From 2439e4bfa111babf4bc07ba20efbf3e36036813e Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 21 Nov 2007 21:19:24 +0100 Subject: drivers/net : move net drivers to drivers/net Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/3c589.c | 519 --- drivers/3c589.h | 435 -- drivers/5701rls.c | 46 - drivers/5701rls.h | 198 - drivers/8390.h | 124 - drivers/Makefile | 33 - drivers/bcm570x.c | 1603 ------- drivers/bcm570x_autoneg.c | 439 -- drivers/bcm570x_autoneg.h | 408 -- drivers/bcm570x_bits.h | 57 - drivers/bcm570x_debug.h | 109 - drivers/bcm570x_lm.h | 434 -- drivers/bcm570x_mm.h | 158 - drivers/bcm570x_queue.h | 387 -- drivers/cs8900.c | 322 -- drivers/cs8900.h | 258 -- drivers/dc2114x.c | 771 ---- drivers/dm9000x.c | 620 --- drivers/dm9000x.h | 119 - drivers/e1000.c | 3016 ------------- drivers/e1000.h | 1758 -------- drivers/eepro100.c | 948 ---- drivers/enc28j60.c | 983 ----- drivers/inca-ip_sw.c | 817 ---- drivers/ks8695eth.c | 238 - drivers/lan91c96.c | 967 ---- drivers/lan91c96.h | 643 --- drivers/macb.c | 587 --- drivers/macb.h | 269 -- drivers/natsemi.c | 882 ---- drivers/ne2000.c | 940 ---- drivers/ne2000.h | 279 -- drivers/net/3c589.c | 519 +++ drivers/net/3c589.h | 435 ++ drivers/net/5701rls.c | 46 + drivers/net/5701rls.h | 198 + drivers/net/8390.h | 124 + drivers/net/Makefile | 33 +- drivers/net/bcm570x.c | 1603 +++++++ drivers/net/bcm570x_autoneg.c | 439 ++ drivers/net/bcm570x_autoneg.h | 408 ++ drivers/net/bcm570x_bits.h | 57 + drivers/net/bcm570x_debug.h | 109 + drivers/net/bcm570x_lm.h | 434 ++ drivers/net/bcm570x_mm.h | 158 + drivers/net/bcm570x_queue.h | 387 ++ drivers/net/cs8900.c | 322 ++ drivers/net/cs8900.h | 258 ++ drivers/net/dc2114x.c | 771 ++++ drivers/net/dm9000x.c | 620 +++ drivers/net/dm9000x.h | 119 + drivers/net/e1000.c | 3016 +++++++++++++ drivers/net/e1000.h | 1758 ++++++++ drivers/net/eepro100.c | 948 ++++ drivers/net/enc28j60.c | 983 +++++ drivers/net/inca-ip_sw.c | 817 ++++ drivers/net/ks8695eth.c | 238 + drivers/net/lan91c96.c | 967 ++++ drivers/net/lan91c96.h | 643 +++ drivers/net/macb.c | 587 +++ drivers/net/macb.h | 269 ++ drivers/net/natsemi.c | 882 ++++ drivers/net/ne2000.c | 940 ++++ drivers/net/ne2000.h | 279 ++ drivers/net/netarm_eth.c | 360 ++ drivers/net/netarm_eth.h | 42 + drivers/net/netconsole.c | 267 ++ drivers/net/nicext.h | 109 + drivers/net/ns7520_eth.c | 859 ++++ drivers/net/ns8382x.c | 863 ++++ drivers/net/ns9750_eth.c | 797 ++++ drivers/net/pcnet.c | 526 +++ drivers/net/plb2800_eth.c | 396 ++ drivers/net/rtl8019.c | 282 ++ drivers/net/rtl8019.h | 117 + drivers/net/rtl8139.c | 547 +++ drivers/net/rtl8169.c | 888 ++++ drivers/net/s3c4510b_eth.c | 246 ++ drivers/net/s3c4510b_eth.h | 302 ++ drivers/net/sk98lin/Makefile | 120 + drivers/net/sk98lin/h/lm80.h | 197 + drivers/net/sk98lin/h/skaddr.h | 425 ++ drivers/net/sk98lin/h/skcsum.h | 261 ++ drivers/net/sk98lin/h/skdebug.h | 119 + drivers/net/sk98lin/h/skdrv1st.h | 264 ++ drivers/net/sk98lin/h/skdrv2nd.h | 561 +++ drivers/net/sk98lin/h/skerror.h | 80 + drivers/net/sk98lin/h/skgedrv.h | 72 + drivers/net/sk98lin/h/skgehw.h | 2336 ++++++++++ drivers/net/sk98lin/h/skgehwt.h | 74 + drivers/net/sk98lin/h/skgei2c.h | 299 ++ drivers/net/sk98lin/h/skgeinit.h | 1113 +++++ drivers/net/sk98lin/h/skgepnm2.h | 462 ++ drivers/net/sk98lin/h/skgepnmi.h | 1114 +++++ drivers/net/sk98lin/h/skgesirq.h | 194 + drivers/net/sk98lin/h/ski2c.h | 292 ++ drivers/net/sk98lin/h/skqueue.h | 147 + drivers/net/sk98lin/h/skrlmt.h | 563 +++ drivers/net/sk98lin/h/sktimer.h | 99 + drivers/net/sk98lin/h/sktypes.h | 87 + drivers/net/sk98lin/h/skversion.h | 52 + drivers/net/sk98lin/h/skvpd.h | 335 ++ drivers/net/sk98lin/h/xmac_ii.h | 1738 ++++++++ drivers/net/sk98lin/skaddr.c | 1879 ++++++++ drivers/net/sk98lin/skcsum.c | 929 ++++ drivers/net/sk98lin/skge.c | 4864 ++++++++++++++++++++ drivers/net/sk98lin/skgehwt.c | 220 + drivers/net/sk98lin/skgeinit.c | 2372 ++++++++++ drivers/net/sk98lin/skgemib.c | 1060 +++++ drivers/net/sk98lin/skgepnmi.c | 8310 +++++++++++++++++++++++++++++++++++ drivers/net/sk98lin/skgesirq.c | 2417 ++++++++++ drivers/net/sk98lin/ski2c.c | 1505 +++++++ drivers/net/sk98lin/sklm80.c | 292 ++ drivers/net/sk98lin/skproc.c | 515 +++ drivers/net/sk98lin/skqueue.c | 242 + drivers/net/sk98lin/skrlmt.c | 3508 +++++++++++++++ drivers/net/sk98lin/sktimer.c | 297 ++ drivers/net/sk98lin/skvpd.c | 1329 ++++++ drivers/net/sk98lin/skxmac2.c | 4396 ++++++++++++++++++ drivers/net/sk98lin/u-boot_compat.h | 98 + drivers/net/sk98lin/uboot_drv.c | 143 + drivers/net/sk98lin/uboot_skb.c | 122 + drivers/net/smc91111.c | 1623 +++++++ drivers/net/smc91111.h | 719 +++ drivers/net/tigon3.c | 5699 ++++++++++++++++++++++++ drivers/net/tigon3.h | 3339 ++++++++++++++ drivers/net/tsec.c | 1590 +++++++ drivers/net/tsec.h | 563 +++ drivers/net/tsi108_eth.c | 1036 +++++ drivers/net/uli526x.c | 996 +++++ drivers/netarm_eth.c | 360 -- drivers/netarm_eth.h | 42 - drivers/netconsole.c | 267 -- drivers/nicext.h | 109 - drivers/ns7520_eth.c | 859 ---- drivers/ns8382x.c | 863 ---- drivers/ns9750_eth.c | 797 ---- drivers/pcnet.c | 526 --- drivers/plb2800_eth.c | 396 -- drivers/rtl8019.c | 282 -- drivers/rtl8019.h | 117 - drivers/rtl8139.c | 547 --- drivers/rtl8169.c | 888 ---- drivers/s3c4510b_eth.c | 246 -- drivers/s3c4510b_eth.h | 302 -- drivers/sk98lin/Makefile | 120 - drivers/sk98lin/h/lm80.h | 197 - drivers/sk98lin/h/skaddr.h | 425 -- drivers/sk98lin/h/skcsum.h | 261 -- drivers/sk98lin/h/skdebug.h | 119 - drivers/sk98lin/h/skdrv1st.h | 264 -- drivers/sk98lin/h/skdrv2nd.h | 561 --- drivers/sk98lin/h/skerror.h | 80 - drivers/sk98lin/h/skgedrv.h | 72 - drivers/sk98lin/h/skgehw.h | 2336 ---------- drivers/sk98lin/h/skgehwt.h | 74 - drivers/sk98lin/h/skgei2c.h | 299 -- drivers/sk98lin/h/skgeinit.h | 1113 ----- drivers/sk98lin/h/skgepnm2.h | 462 -- drivers/sk98lin/h/skgepnmi.h | 1114 ----- drivers/sk98lin/h/skgesirq.h | 194 - drivers/sk98lin/h/ski2c.h | 292 -- drivers/sk98lin/h/skqueue.h | 147 - drivers/sk98lin/h/skrlmt.h | 563 --- drivers/sk98lin/h/sktimer.h | 99 - drivers/sk98lin/h/sktypes.h | 87 - drivers/sk98lin/h/skversion.h | 52 - drivers/sk98lin/h/skvpd.h | 335 -- drivers/sk98lin/h/xmac_ii.h | 1738 -------- drivers/sk98lin/skaddr.c | 1879 -------- drivers/sk98lin/skcsum.c | 929 ---- drivers/sk98lin/skge.c | 4864 -------------------- drivers/sk98lin/skgehwt.c | 220 - drivers/sk98lin/skgeinit.c | 2372 ---------- drivers/sk98lin/skgemib.c | 1060 ----- drivers/sk98lin/skgepnmi.c | 8310 ----------------------------------- drivers/sk98lin/skgesirq.c | 2417 ---------- drivers/sk98lin/ski2c.c | 1505 ------- drivers/sk98lin/sklm80.c | 292 -- drivers/sk98lin/skproc.c | 515 --- drivers/sk98lin/skqueue.c | 242 - drivers/sk98lin/skrlmt.c | 3508 --------------- drivers/sk98lin/sktimer.c | 297 -- drivers/sk98lin/skvpd.c | 1329 ------ drivers/sk98lin/skxmac2.c | 4396 ------------------ drivers/sk98lin/u-boot_compat.h | 98 - drivers/sk98lin/uboot_drv.c | 143 - drivers/sk98lin/uboot_skb.c | 122 - drivers/smc91111.c | 1623 ------- drivers/smc91111.h | 719 --- drivers/tigon3.c | 5699 ------------------------ drivers/tigon3.h | 3339 -------------- drivers/tsec.c | 1590 ------- drivers/tsec.h | 563 --- drivers/tsi108_eth.c | 1036 ----- drivers/uli526x.c | 996 ----- 196 files changed, 87034 insertions(+), 87036 deletions(-) delete mode 100644 drivers/3c589.c delete mode 100644 drivers/3c589.h delete mode 100644 drivers/5701rls.c delete mode 100644 drivers/5701rls.h delete mode 100644 drivers/8390.h delete mode 100644 drivers/bcm570x.c delete mode 100644 drivers/bcm570x_autoneg.c delete mode 100644 drivers/bcm570x_autoneg.h delete mode 100644 drivers/bcm570x_bits.h delete mode 100644 drivers/bcm570x_debug.h delete mode 100644 drivers/bcm570x_lm.h delete mode 100644 drivers/bcm570x_mm.h delete mode 100644 drivers/bcm570x_queue.h delete mode 100644 drivers/cs8900.c delete mode 100644 drivers/cs8900.h delete mode 100644 drivers/dc2114x.c delete mode 100644 drivers/dm9000x.c delete mode 100644 drivers/dm9000x.h delete mode 100644 drivers/e1000.c delete mode 100644 drivers/e1000.h delete mode 100644 drivers/eepro100.c delete mode 100644 drivers/enc28j60.c delete mode 100644 drivers/inca-ip_sw.c delete mode 100644 drivers/ks8695eth.c delete mode 100644 drivers/lan91c96.c delete mode 100644 drivers/lan91c96.h delete mode 100644 drivers/macb.c delete mode 100644 drivers/macb.h delete mode 100644 drivers/natsemi.c delete mode 100644 drivers/ne2000.c delete mode 100644 drivers/ne2000.h create mode 100644 drivers/net/3c589.c create mode 100644 drivers/net/3c589.h create mode 100644 drivers/net/5701rls.c create mode 100644 drivers/net/5701rls.h create mode 100644 drivers/net/8390.h create mode 100644 drivers/net/bcm570x.c create mode 100644 drivers/net/bcm570x_autoneg.c create mode 100644 drivers/net/bcm570x_autoneg.h create mode 100644 drivers/net/bcm570x_bits.h create mode 100644 drivers/net/bcm570x_debug.h create mode 100644 drivers/net/bcm570x_lm.h create mode 100644 drivers/net/bcm570x_mm.h create mode 100644 drivers/net/bcm570x_queue.h create mode 100644 drivers/net/cs8900.c create mode 100644 drivers/net/cs8900.h create mode 100644 drivers/net/dc2114x.c create mode 100644 drivers/net/dm9000x.c create mode 100644 drivers/net/dm9000x.h create mode 100644 drivers/net/e1000.c create mode 100644 drivers/net/e1000.h create mode 100644 drivers/net/eepro100.c create mode 100644 drivers/net/enc28j60.c create mode 100644 drivers/net/inca-ip_sw.c create mode 100644 drivers/net/ks8695eth.c create mode 100644 drivers/net/lan91c96.c create mode 100644 drivers/net/lan91c96.h create mode 100644 drivers/net/macb.c create mode 100644 drivers/net/macb.h create mode 100644 drivers/net/natsemi.c create mode 100644 drivers/net/ne2000.c create mode 100644 drivers/net/ne2000.h create mode 100644 drivers/net/netarm_eth.c create mode 100644 drivers/net/netarm_eth.h create mode 100644 drivers/net/netconsole.c create mode 100644 drivers/net/nicext.h create mode 100644 drivers/net/ns7520_eth.c create mode 100644 drivers/net/ns8382x.c create mode 100644 drivers/net/ns9750_eth.c create mode 100644 drivers/net/pcnet.c create mode 100644 drivers/net/plb2800_eth.c create mode 100644 drivers/net/rtl8019.c create mode 100644 drivers/net/rtl8019.h create mode 100644 drivers/net/rtl8139.c create mode 100644 drivers/net/rtl8169.c create mode 100644 drivers/net/s3c4510b_eth.c create mode 100644 drivers/net/s3c4510b_eth.h create mode 100644 drivers/net/sk98lin/Makefile create mode 100644 drivers/net/sk98lin/h/lm80.h create mode 100644 drivers/net/sk98lin/h/skaddr.h create mode 100644 drivers/net/sk98lin/h/skcsum.h create mode 100644 drivers/net/sk98lin/h/skdebug.h create mode 100644 drivers/net/sk98lin/h/skdrv1st.h create mode 100644 drivers/net/sk98lin/h/skdrv2nd.h create mode 100644 drivers/net/sk98lin/h/skerror.h create mode 100644 drivers/net/sk98lin/h/skgedrv.h create mode 100644 drivers/net/sk98lin/h/skgehw.h create mode 100644 drivers/net/sk98lin/h/skgehwt.h create mode 100644 drivers/net/sk98lin/h/skgei2c.h create mode 100644 drivers/net/sk98lin/h/skgeinit.h create mode 100644 drivers/net/sk98lin/h/skgepnm2.h create mode 100644 drivers/net/sk98lin/h/skgepnmi.h create mode 100644 drivers/net/sk98lin/h/skgesirq.h create mode 100644 drivers/net/sk98lin/h/ski2c.h create mode 100644 drivers/net/sk98lin/h/skqueue.h create mode 100644 drivers/net/sk98lin/h/skrlmt.h create mode 100644 drivers/net/sk98lin/h/sktimer.h create mode 100644 drivers/net/sk98lin/h/sktypes.h create mode 100644 drivers/net/sk98lin/h/skversion.h create mode 100644 drivers/net/sk98lin/h/skvpd.h create mode 100644 drivers/net/sk98lin/h/xmac_ii.h create mode 100644 drivers/net/sk98lin/skaddr.c create mode 100644 drivers/net/sk98lin/skcsum.c create mode 100644 drivers/net/sk98lin/skge.c create mode 100644 drivers/net/sk98lin/skgehwt.c create mode 100644 drivers/net/sk98lin/skgeinit.c create mode 100644 drivers/net/sk98lin/skgemib.c create mode 100644 drivers/net/sk98lin/skgepnmi.c create mode 100644 drivers/net/sk98lin/skgesirq.c create mode 100644 drivers/net/sk98lin/ski2c.c create mode 100644 drivers/net/sk98lin/sklm80.c create mode 100644 drivers/net/sk98lin/skproc.c create mode 100644 drivers/net/sk98lin/skqueue.c create mode 100644 drivers/net/sk98lin/skrlmt.c create mode 100644 drivers/net/sk98lin/sktimer.c create mode 100644 drivers/net/sk98lin/skvpd.c create mode 100644 drivers/net/sk98lin/skxmac2.c create mode 100644 drivers/net/sk98lin/u-boot_compat.h create mode 100644 drivers/net/sk98lin/uboot_drv.c create mode 100644 drivers/net/sk98lin/uboot_skb.c create mode 100644 drivers/net/smc91111.c create mode 100644 drivers/net/smc91111.h create mode 100644 drivers/net/tigon3.c create mode 100644 drivers/net/tigon3.h create mode 100644 drivers/net/tsec.c create mode 100644 drivers/net/tsec.h create mode 100644 drivers/net/tsi108_eth.c create mode 100644 drivers/net/uli526x.c delete mode 100644 drivers/netarm_eth.c delete mode 100644 drivers/netarm_eth.h delete mode 100644 drivers/netconsole.c delete mode 100644 drivers/nicext.h delete mode 100644 drivers/ns7520_eth.c delete mode 100644 drivers/ns8382x.c delete mode 100644 drivers/ns9750_eth.c delete mode 100644 drivers/pcnet.c delete mode 100644 drivers/plb2800_eth.c delete mode 100644 drivers/rtl8019.c delete mode 100644 drivers/rtl8019.h delete mode 100644 drivers/rtl8139.c delete mode 100644 drivers/rtl8169.c delete mode 100644 drivers/s3c4510b_eth.c delete mode 100644 drivers/s3c4510b_eth.h delete mode 100644 drivers/sk98lin/Makefile delete mode 100644 drivers/sk98lin/h/lm80.h delete mode 100644 drivers/sk98lin/h/skaddr.h delete mode 100644 drivers/sk98lin/h/skcsum.h delete mode 100644 drivers/sk98lin/h/skdebug.h delete mode 100644 drivers/sk98lin/h/skdrv1st.h delete mode 100644 drivers/sk98lin/h/skdrv2nd.h delete mode 100644 drivers/sk98lin/h/skerror.h delete mode 100644 drivers/sk98lin/h/skgedrv.h delete mode 100644 drivers/sk98lin/h/skgehw.h delete mode 100644 drivers/sk98lin/h/skgehwt.h delete mode 100644 drivers/sk98lin/h/skgei2c.h delete mode 100644 drivers/sk98lin/h/skgeinit.h delete mode 100644 drivers/sk98lin/h/skgepnm2.h delete mode 100644 drivers/sk98lin/h/skgepnmi.h delete mode 100644 drivers/sk98lin/h/skgesirq.h delete mode 100644 drivers/sk98lin/h/ski2c.h delete mode 100644 drivers/sk98lin/h/skqueue.h delete mode 100644 drivers/sk98lin/h/skrlmt.h delete mode 100644 drivers/sk98lin/h/sktimer.h delete mode 100644 drivers/sk98lin/h/sktypes.h delete mode 100644 drivers/sk98lin/h/skversion.h delete mode 100644 drivers/sk98lin/h/skvpd.h delete mode 100644 drivers/sk98lin/h/xmac_ii.h delete mode 100644 drivers/sk98lin/skaddr.c delete mode 100644 drivers/sk98lin/skcsum.c delete mode 100644 drivers/sk98lin/skge.c delete mode 100644 drivers/sk98lin/skgehwt.c delete mode 100644 drivers/sk98lin/skgeinit.c delete mode 100644 drivers/sk98lin/skgemib.c delete mode 100644 drivers/sk98lin/skgepnmi.c delete mode 100644 drivers/sk98lin/skgesirq.c delete mode 100644 drivers/sk98lin/ski2c.c delete mode 100644 drivers/sk98lin/sklm80.c delete mode 100644 drivers/sk98lin/skproc.c delete mode 100644 drivers/sk98lin/skqueue.c delete mode 100644 drivers/sk98lin/skrlmt.c delete mode 100644 drivers/sk98lin/sktimer.c delete mode 100644 drivers/sk98lin/skvpd.c delete mode 100644 drivers/sk98lin/skxmac2.c delete mode 100644 drivers/sk98lin/u-boot_compat.h delete mode 100644 drivers/sk98lin/uboot_drv.c delete mode 100644 drivers/sk98lin/uboot_skb.c delete mode 100644 drivers/smc91111.c delete mode 100644 drivers/smc91111.h delete mode 100644 drivers/tigon3.c delete mode 100644 drivers/tigon3.h delete mode 100644 drivers/tsec.c delete mode 100644 drivers/tsec.h delete mode 100644 drivers/tsi108_eth.c delete mode 100644 drivers/uli526x.c (limited to 'drivers') diff --git a/drivers/3c589.c b/drivers/3c589.c deleted file mode 100644 index 080b686e21..0000000000 --- a/drivers/3c589.c +++ /dev/null @@ -1,519 +0,0 @@ -/*------------------------------------------------------------------------ - . 3c589.c - . This is a driver for 3Com's 3C589 (Etherlink III) PCMCIA Ethernet device. - . - . (C) Copyright 2002 - . Sysgo Real-Time Solutions, GmbH - . Rolf Offermanns - . - . This program is free software; you can redistribute it and/or modify - . it under the terms of the GNU General Public License as published by - . the Free Software Foundation; either version 2 of the License, or - . (at your option) any later version. - . - . This program is distributed in the hope that it will be useful, - . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - . GNU General Public License for more details. - . - . You should have received a copy of the GNU General Public License - . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - ----------------------------------------------------------------------------*/ - -#include -#include -#include - -#ifdef CONFIG_DRIVER_3C589 - -#include "3c589.h" - - -/* Use power-down feature of the chip */ -#define POWER_DOWN 0 - -#define NO_AUTOPROBE - -static const char version[] = - "Your ad here! :P\n"; - - -#undef EL_DEBUG - -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long int dword; -/*------------------------------------------------------------------------ - . - . Configuration options, for the experienced user to change. - . - -------------------------------------------------------------------------*/ - -/* - . Wait time for memory to be free. This probably shouldn't be - . tuned that much, as waiting for this means nothing else happens - . in the system -*/ -#define MEMORY_WAIT_TIME 16 - - -#if (EL_DEBUG > 2 ) -#define PRINTK3(args...) printf(args) -#else -#define PRINTK3(args...) -#endif - -#if EL_DEBUG > 1 -#define PRINTK2(args...) printf(args) -#else -#define PRINTK2(args...) -#endif - -#ifdef EL_DEBUG -#define PRINTK(args...) printf(args) -#else -#define PRINTK(args...) -#endif - -#define outb(args...) mmio_outb(args) -#define mmio_outb(value, addr) (*((volatile byte *)(addr)) = value) - -#define inb(args...) mmio_inb(args) -#define mmio_inb(addr) (*((volatile byte *)(addr))) - -#define outw(args...) mmio_outw(args) -#define mmio_outw(value, addr) (*((volatile word *)(addr)) = value) - -#define inw(args...) mmio_inw(args) -#define mmio_inw(addr) (*((volatile word *)(addr))) - -#define outsw(args...) mmio_outsw(args) -#define mmio_outsw(r,b,l) ({ int __i; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - mmio_outw( *(__b2 + __i), r); \ - } \ - }) - -#define insw(args...) mmio_insw(args) -#define mmio_insw(r,b,l) ({ int __i ; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = mmio_inw(r); \ - mmio_inw(0); \ - }; \ - }) - -/*------------------------------------------------------------------------ - . - . The internal workings of the driver. If you are changing anything - . here with the 3Com stuff, you should have the datasheet and know - . what you are doing. - . - -------------------------------------------------------------------------*/ -#define EL_BASE_ADDR 0x20000000 - - -/* Offsets from base I/O address. */ -#define EL3_DATA 0x00 -#define EL3_TIMER 0x0a -#define EL3_CMD 0x0e -#define EL3_STATUS 0x0e - -#define EEPROM_READ 0x0080 - -#define EL3WINDOW(win_num) mmio_outw(SelectWindow + (win_num), EL_BASE_ADDR + EL3_CMD) - -/* The top five bits written to EL3_CMD are a command, the lower - 11 bits are the parameter, if applicable. */ -enum c509cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, - TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, - SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11, -}; - -enum c509status { - IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, - TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, - IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 -}; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 -}; - -/* Register window 1 offsets, the window used in normal operation. */ -#define TX_FIFO 0x00 -#define RX_FIFO 0x00 -#define RX_STATUS 0x08 -#define TX_STATUS 0x0B -#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ - - -/* - Read a word from the EEPROM using the regular EEPROM access register. - Assume that we are in register window zero. -*/ -static word read_eeprom(dword ioaddr, int index) -{ - int i; - outw(EEPROM_READ + index, ioaddr + 0xa); - /* Reading the eeprom takes 162 us */ - for (i = 1620; i >= 0; i--) - if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) - break; - return inw(ioaddr + 0xc); -} - -static void el_get_mac_addr( unsigned char *mac_addr ) -{ - int i; - union - { - word w; - unsigned char b[2]; - } wrd; - unsigned char old_window = inw( EL_BASE_ADDR + EL3_STATUS ) >> 13; - GO_WINDOW(0); - VX_BUSY_WAIT; - for (i = 0; i < 3; i++) - { - wrd.w = read_eeprom(EL_BASE_ADDR, 0xa+i); -#ifdef __BIG_ENDIAN - mac_addr[2*i] = wrd.b[0]; - mac_addr[2*i+1] = wrd.b[1]; -#else - mac_addr[2*i] = wrd.b[1]; - mac_addr[2*i+1] = wrd.b[0]; -#endif - } - GO_WINDOW(old_window); - VX_BUSY_WAIT; -} - - -#if EL_DEBUG > 1 -static void print_packet( byte * buf, int length ) -{ - int i; - int remainder; - int lines; - - PRINTK2("Packet of length %d \n", length ); - - lines = length / 16; - remainder = length % 16; - - for ( i = 0; i < lines ; i ++ ) { - int cur; - - for ( cur = 0; cur < 8; cur ++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - PRINTK2("%02x%02x ", a, b ); - } - PRINTK2("\n"); - } - for ( i = 0; i < remainder/2 ; i++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - PRINTK2("%02x%02x ", a, b ); - } - PRINTK2("\n"); -} -#endif /* EL_DEBUG > 1 */ - - -/************************************************************************** -ETH_RESET - Reset adapter -***************************************************************************/ -static void el_reset(bd_t *bd) -{ - /*********************************************************** - Reset 3Com 595 card - *************************************************************/ - /* QUICK HACK - * - adjust timing for 3c589 - * - enable io for PCMCIA */ - outw(0x0004, 0xa0000018); - udelay(100); - outw(0x0041, 0x28010000); - udelay(100); - - /* issue global reset */ - outw(GLOBAL_RESET, BASE + VX_COMMAND); - - /* must wait for at least 1ms */ - udelay(100000000); - - /* set mac addr */ - { - unsigned char *mac_addr = bd->bi_enetaddr; - int i; - - el_get_mac_addr( mac_addr ); - - GO_WINDOW(2); - VX_BUSY_WAIT; - - printf("3C589 MAC Addr.: "); - for (i = 0; i < 6; i++) - { - printf("%02x", mac_addr[i]); - outb(mac_addr[i], BASE + VX_W2_ADDR_0 + i); - VX_BUSY_WAIT; - } - printf("\n\n"); - } - - /* set RX filter */ - outw(SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST, BASE + VX_COMMAND); - VX_BUSY_WAIT; - - - /* set irq mask and read_zero */ - outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | - S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); - VX_BUSY_WAIT; - - outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | - S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); - VX_BUSY_WAIT; - - /* enable TP Linkbeat */ - GO_WINDOW(4); - VX_BUSY_WAIT; - - outw( ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE); - VX_BUSY_WAIT; - - -/* - * Attempt to get rid of any stray interrupts that occured during - * configuration. On the i386 this isn't possible because one may - * already be queued. However, a single stray interrupt is - * unimportant. - */ - - outw(ACK_INTR | 0xff, BASE + VX_COMMAND); - VX_BUSY_WAIT; - - /* enable TX and RX */ - outw( RX_ENABLE, BASE + VX_COMMAND ); - VX_BUSY_WAIT; - - outw( TX_ENABLE, BASE + VX_COMMAND ); - VX_BUSY_WAIT; - - - /* print the diag. regs. */ - PRINTK2("Diag. Regs\n"); - PRINTK2("--> MEDIA_TYPE: %04x\n", inw(BASE + VX_W4_MEDIA_TYPE)); - PRINTK2("--> NET_DIAG: %04x\n", inw(BASE + VX_W4_NET_DIAG)); - PRINTK2("--> FIFO_DIAG: %04x\n", inw(BASE + VX_W4_FIFO_DIAG)); - PRINTK2("--> CTRLR_STATUS: %04x\n", inw(BASE + VX_W4_CTRLR_STATUS)); - PRINTK2("\n\n"); - - /* enter working mode */ - GO_WINDOW(1); - VX_BUSY_WAIT; - - /* wait for another 1ms */ - udelay(100000000); -} - - -/*----------------------------------------------------------------- - . - . The driver can be entered at any of the following entry points. - . - .------------------------------------------------------------------ */ - -extern int eth_init(bd_t *bd); -extern void eth_halt(void); -extern int eth_rx(void); -extern int eth_send(volatile void *packet, int length); - - -/* - ------------------------------------------------------------ - . - . Internal routines - . - ------------------------------------------------------------ -*/ - -int eth_init(bd_t *bd) -{ - el_reset(bd); - return 0; -} - -void eth_halt() { - return; -} - -#define EDEBUG 1 - - -/************************************************************************** -ETH_POLL - Wait for a frame -***************************************************************************/ - -int eth_rx() -{ - word status, rx_status, packet_size; - - VX_BUSY_WAIT; - - status = inw( BASE + VX_STATUS ); - - if ( (status & S_RX_COMPLETE) == 0 ) return 0; /* nothing to do */ - - /* Packet waiting -> check RX_STATUS */ - rx_status = inw( BASE + VX_W1_RX_STATUS ); - - if ( rx_status & ERR_RX ) - { - /* error in packet -> discard */ - PRINTK("[ERROR] Invalid packet -> discarding\n"); - PRINTK("-- error code 0x%02x\n", rx_status & ERR_MASK); - PRINTK("-- rx bytes 0x%04d\n", rx_status & ((1<<11) - 1)); - PRINTK("[ERROR] Invalid packet -> discarding\n"); - outw( RX_DISCARD_TOP_PACK, BASE + VX_COMMAND ); - return 0; - } - - /* correct pack. waiting in fifo */ - packet_size = rx_status & RX_BYTES_MASK; - - PRINTK("Correct packet waiting in fifo, size: %d\n", packet_size); - - { - volatile word *packet_start = (word *)(BASE + VX_W1_RX_PIO_RD_1); - word *RcvBuffer = (word *)(NetRxPackets[0]); - int wcount = 0; - - for (wcount = 0; wcount < (packet_size >> 1); wcount++) - { - *RcvBuffer++ = *(packet_start); - } - - /* handle odd packets */ - if ( packet_size & 1 ) - { - *RcvBuffer++ = *(packet_start); - } - } - - /* fifo should now be empty (besides the padding bytes) */ - if ( ((*((word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK) > 3 ) - { - PRINTK("[ERROR] Fifo not empty after packet read (remaining pkts: %d)\n", - (((*(word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK)); - } - - /* discard packet */ - *((word *)(BASE + VX_COMMAND)) = RX_DISCARD_TOP_PACK; - - /* Pass Packets to upper Layer */ - NetReceive(NetRxPackets[0], packet_size); - return packet_size; -} - - -/************************************************************************** -ETH_TRANSMIT - Transmit a frame -***************************************************************************/ -static char padmap[] = { - 0, 3, 2, 1}; - - -int eth_send(volatile void *packet, int length) { - int pad; - int status; - volatile word *buf = (word *)packet; - int dummy = 0; - - /* padding stuff */ - pad = padmap[length & 3]; - - PRINTK("eth_send(), length: %d\n", length); - /* drop acknowledgements */ - while(( status=inb(EL_BASE_ADDR + VX_W1_TX_STATUS) )& TXS_COMPLETE ) { - if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { - outw(TX_RESET, EL_BASE_ADDR + VX_COMMAND); - outw(TX_ENABLE, EL_BASE_ADDR + VX_COMMAND); - PRINTK("Bad status, resetting and reenabling transmitter\n"); - } - - outb(0x0, EL_BASE_ADDR + VX_W1_TX_STATUS); - } - - - while (inw(EL_BASE_ADDR + VX_W1_FREE_TX) < length + pad + 4) { - /* no room in FIFO */ - if (dummy == 0) - { - PRINTK("No room in FIFO, waiting...\n"); - dummy++; - } - - } - - PRINTK(" ---> FIFO ready\n"); - - - outw(length, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); - - /* Second dword meaningless */ - outw(0x0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); - -#if EL_DEBUG > 1 - print_packet((byte *)buf, length); -#endif - - /* write packet */ - { - unsigned int i, totw; - - totw = ((length + 1) >> 1); - PRINTK("Buffer: (totw = %d)\n", totw); - for (i = 0; i < totw; i++) { - outw( *(buf+i), EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); - udelay(10); - } - if(totw & 1) - { /* pad to double word length */ - outw( 0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); - udelay(10); - } - PRINTK("\n\n"); - } - - /* wait for Tx complete */ - PRINTK("Waiting for Tx to complete...\n"); - while(((status = inw(EL_BASE_ADDR + VX_STATUS)) & S_COMMAND_IN_PROGRESS) != 0) - { - udelay(10); - } - PRINTK(" ---> Tx completed, status = 0x%04x\n", status); - - return length; -} - - -#endif /* CONFIG_DRIVER_3C589 */ diff --git a/drivers/3c589.h b/drivers/3c589.h deleted file mode 100644 index 6735bf9f63..0000000000 --- a/drivers/3c589.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. The name - * of the author may not be used to endorse or promote products derived from - * this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - October 2, 1994 - - Modified by: Andres Vega Garcia - - INRIA - Sophia Antipolis, France - e-mail: avega@sophia.inria.fr - finger: avega@pax.inria.fr - - */ - -/* - * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the - * 3c590 family. - */ - -/* - * Modified by Shusuke Nisiyama - * for etherboot - * Mar. 14, 2000 -*/ - -/* - * Ethernet software status per interface. - */ - -/* - * Some global constants - */ - -#define TX_INIT_RATE 16 -#define TX_INIT_MAX_RATE 64 -#define RX_INIT_LATENCY 64 -#define RX_INIT_EARLY_THRESH 64 -#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */ -#define MIN_RX_EARLY_THRESHL 4 - -#define EEPROMSIZE 0x40 -#define MAX_EEPROMBUSY 1000 -#define VX_LAST_TAG 0xd7 -#define VX_MAX_BOARDS 16 -#define VX_ID_PORT 0x100 - -/* - * some macros to acces long named fields - */ -#define BASE (EL_BASE_ADDR) - -/* - * Commands to read/write EEPROM trough EEPROM command register (Window 0, - * Offset 0xa) - */ -#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ -#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ -#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ -#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ - -#define EEPROM_BUSY (1<<15) - -/* - * Some short functions, worth to let them be a macro - */ - -/************************************************************************** - * * - * These define the EEPROM data structure. They are used in the probe - * function to verify the existence of the adapter after having sent - * the ID_Sequence. - * - * There are others but only the ones we use are defined here. - * - **************************************************************************/ - -#define EEPROM_NODE_ADDR_0 0x0 /* Word */ -#define EEPROM_NODE_ADDR_1 0x1 /* Word */ -#define EEPROM_NODE_ADDR_2 0x2 /* Word */ -#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ -#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ -#define EEPROM_ADDR_CFG 0x8 /* Base addr */ -#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ -#define EEPROM_OEM_ADDR_0 0xa /* Word */ -#define EEPROM_OEM_ADDR_1 0xb /* Word */ -#define EEPROM_OEM_ADDR_2 0xc /* Word */ -#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */ - -#define NO_RX_OVN_ANOMALY (1<<5) - -/************************************************************************** - * * - * These are the registers for the 3Com 3c509 and their bit patterns when * - * applicable. They have been taken out the the "EtherLink III Parallel * - * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * - * from 3com. * - * * - **************************************************************************/ - -#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a - * command reg. */ -#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status - * reg. */ -#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window - * reg. */ -/* - * Window 0 registers. Setup. - */ -/* Write */ -#define VX_W0_EEPROM_DATA 0x0c -#define VX_W0_EEPROM_COMMAND 0x0a -#define VX_W0_RESOURCE_CFG 0x08 -#define VX_W0_ADDRESS_CFG 0x06 -#define VX_W0_CONFIG_CTRL 0x04 - /* Read */ -#define VX_W0_PRODUCT_ID 0x02 -#define VX_W0_MFG_ID 0x00 - - -/* - * Window 1 registers. Operating Set. - */ -/* Write */ -#define VX_W1_TX_PIO_WR_2 0x02 -#define VX_W1_TX_PIO_WR_1 0x00 -/* Read */ -#define VX_W1_FREE_TX 0x0c -#define VX_W1_TX_STATUS 0x0b /* byte */ -#define VX_W1_TIMER 0x0a /* byte */ -#define VX_W1_RX_STATUS 0x08 -#define VX_W1_RX_PIO_RD_2 0x02 -#define VX_W1_RX_PIO_RD_1 0x00 - -/* - * Window 2 registers. Station Address Setup/Read - */ -/* Read/Write */ -#define VX_W2_ADDR_5 0x05 -#define VX_W2_ADDR_4 0x04 -#define VX_W2_ADDR_3 0x03 -#define VX_W2_ADDR_2 0x02 -#define VX_W2_ADDR_1 0x01 -#define VX_W2_ADDR_0 0x00 - -/* - * Window 3 registers. FIFO Management. - */ -/* Read */ -#define VX_W3_INTERNAL_CFG 0x00 -#define VX_W3_RESET_OPT 0x08 -#define VX_W3_FREE_TX 0x0c -#define VX_W3_FREE_RX 0x0a - -/* - * Window 4 registers. Diagnostics. - */ -/* Read/Write */ -#define VX_W4_MEDIA_TYPE 0x0a -#define VX_W4_CTRLR_STATUS 0x08 -#define VX_W4_NET_DIAG 0x06 -#define VX_W4_FIFO_DIAG 0x04 -#define VX_W4_HOST_DIAG 0x02 -#define VX_W4_TX_DIAG 0x00 - -/* - * Window 5 Registers. Results and Internal status. - */ -/* Read */ -#define VX_W5_READ_0_MASK 0x0c -#define VX_W5_INTR_MASK 0x0a -#define VX_W5_RX_FILTER 0x08 -#define VX_W5_RX_EARLY_THRESH 0x06 -#define VX_W5_TX_AVAIL_THRESH 0x02 -#define VX_W5_TX_START_THRESH 0x00 - -/* - * Window 6 registers. Statistics. - */ -/* Read/Write */ -#define TX_TOTAL_OK 0x0c -#define RX_TOTAL_OK 0x0a -#define TX_DEFERRALS 0x08 -#define RX_FRAMES_OK 0x07 -#define TX_FRAMES_OK 0x06 -#define RX_OVERRUNS 0x05 -#define TX_COLLISIONS 0x04 -#define TX_AFTER_1_COLLISION 0x03 -#define TX_AFTER_X_COLLISIONS 0x02 -#define TX_NO_SQE 0x01 -#define TX_CD_LOST 0x00 - -/**************************************** - * - * Register definitions. - * - ****************************************/ - -/* - * Command register. All windows. - * - * 16 bit register. - * 15-11: 5-bit code for command to be executed. - * 10-0: 11-bit arg if any. For commands with no args; - * this can be set to anything. - */ -#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms - * after issuing */ -#define WINDOW_SELECT (unsigned short) (0x1<<11) -#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to - * determine whether - * this is needed. If - * so; wait 800 uSec - * before using trans- - * ceiver. */ -#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on - * power-up */ -#define RX_ENABLE (unsigned short) (0x4<<11) -#define RX_RESET (unsigned short) (0x5<<11) -#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11) -#define TX_ENABLE (unsigned short) (0x9<<11) -#define TX_DISABLE (unsigned short) (0xa<<11) -#define TX_RESET (unsigned short) (0xb<<11) -#define REQ_INTR (unsigned short) (0xc<<11) -/* - * The following C_* acknowledge the various interrupts. Some of them don't - * do anything. See the manual. - */ -#define ACK_INTR (unsigned short) (0x6800) -# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1) -# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2) -# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4) -# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8) -# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10) -# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20) -# define C_INT_RQD (unsigned short) (ACK_INTR|0x40) -# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80) -#define SET_INTR_MASK (unsigned short) (0xe<<11) -#define SET_RD_0_MASK (unsigned short) (0xf<<11) -#define SET_RX_FILTER (unsigned short) (0x10<<11) -# define FIL_INDIVIDUAL (unsigned short) (0x1) -# define FIL_MULTICAST (unsigned short) (0x02) -# define FIL_BRDCST (unsigned short) (0x04) -# define FIL_PROMISC (unsigned short) (0x08) -#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11) -#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11) -#define SET_TX_START_THRESH (unsigned short) (0x13<<11) -#define STATS_ENABLE (unsigned short) (0x15<<11) -#define STATS_DISABLE (unsigned short) (0x16<<11) -#define STOP_TRANSCEIVER (unsigned short) (0x17<<11) - -/* - * Status register. All windows. - * - * 15-13: Window number(0-7). - * 12: Command_in_progress. - * 11: reserved. - * 10: reserved. - * 9: reserved. - * 8: reserved. - * 7: Update Statistics. - * 6: Interrupt Requested. - * 5: RX Early. - * 4: RX Complete. - * 3: TX Available. - * 2: TX Complete. - * 1: Adapter Failure. - * 0: Interrupt Latch. - */ -#define S_INTR_LATCH (unsigned short) (0x1) -#define S_CARD_FAILURE (unsigned short) (0x2) -#define S_TX_COMPLETE (unsigned short) (0x4) -#define S_TX_AVAIL (unsigned short) (0x8) -#define S_RX_COMPLETE (unsigned short) (0x10) -#define S_RX_EARLY (unsigned short) (0x20) -#define S_INT_RQD (unsigned short) (0x40) -#define S_UPD_STATS (unsigned short) (0x80) -#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000) - -#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) - -/* Address Config. Register. - * Window 0/Port 06 - */ - -#define ACF_CONNECTOR_BITS 14 -#define ACF_CONNECTOR_UTP 0 -#define ACF_CONNECTOR_AUI 1 -#define ACF_CONNECTOR_BNC 3 - -#define INTERNAL_CONNECTOR_BITS 20 -#define INTERNAL_CONNECTOR_MASK 0x01700000 - -/* - * FIFO Registers. RX Status. - * - * 15: Incomplete or FIFO empty. - * 14: 1: Error in RX Packet 0: Incomplete or no error. - * 13-11: Type of error. - * 1000 = Overrun. - * 1011 = Run Packet Error. - * 1100 = Alignment Error. - * 1101 = CRC Error. - * 1001 = Oversize Packet Error (>1514 bytes) - * 0010 = Dribble Bits. - * (all other error codes, no errors.) - * - * 10-0: RX Bytes (0-1514) - */ -#define ERR_INCOMPLETE (unsigned short) (0x8000) -#define ERR_RX (unsigned short) (0x4000) -#define ERR_MASK (unsigned short) (0x7800) -#define ERR_OVERRUN (unsigned short) (0x4000) -#define ERR_RUNT (unsigned short) (0x5800) -#define ERR_ALIGNMENT (unsigned short) (0x6000) -#define ERR_CRC (unsigned short) (0x6800) -#define ERR_OVERSIZE (unsigned short) (0x4800) -#define ERR_DRIBBLE (unsigned short) (0x1000) - -/* - * TX Status. - * - * Reports the transmit status of a completed transmission. Writing this - * register pops the transmit completion stack. - * - * Window 1/Port 0x0b. - * - * 7: Complete - * 6: Interrupt on successful transmission requested. - * 5: Jabber Error (TP Only, TX Reset required. ) - * 4: Underrun (TX Reset required. ) - * 3: Maximum Collisions. - * 2: TX Status Overflow. - * 1-0: Undefined. - * - */ -#define TXS_COMPLETE 0x80 -#define TXS_INTR_REQ 0x40 -#define TXS_JABBER 0x20 -#define TXS_UNDERRUN 0x10 -#define TXS_MAX_COLLISION 0x8 -#define TXS_STATUS_OVERFLOW 0x4 - -#define RS_AUI (1<<5) -#define RS_BNC (1<<4) -#define RS_UTP (1<<3) -#define RS_T4 (1<<0) -#define RS_TX (1<<1) -#define RS_FX (1<<2) -#define RS_MII (1<<6) - - -/* - * FIFO Status (Window 4) - * - * Supports FIFO diagnostics - * - * Window 4/Port 0x04.1 - * - * 15: 1=RX receiving (RO). Set when a packet is being received - * into the RX FIFO. - * 14: Reserved - * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt. - * Requires RX Reset or Global Reset command to recover. - * It is generated when you read past the end of a packet - - * reading past what has been received so far will give bad - * data. - * 12: 1=RX status overrun (RO). Set when there are already 8 - * packets in the RX FIFO. While this bit is set, no additional - * packets are received. Requires no action on the part of - * the host. The condition is cleared once a packet has been - * read out of the RX FIFO. - * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there - * may not be an overrun packet yet). While this bit is set, - * no additional packets will be received (some additional - * bytes can still be pending between the wire and the RX - * FIFO). Requires no action on the part of the host. The - * condition is cleared once a few bytes have been read out - * from the RX FIFO. - * 10: 1=TX overrun (RO). Generates adapter failure interrupt. - * Requires TX Reset or Global Reset command to recover. - * Disables Transmitter. - * 9-8: Unassigned. - * 7-0: Built in self test bits for the RX and TX FIFO's. - */ -#define FIFOS_RX_RECEIVING (unsigned short) 0x8000 -#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000 -#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000 -#define FIFOS_RX_OVERRUN (unsigned short) 0x0800 -#define FIFOS_TX_OVERRUN (unsigned short) 0x0400 - -/* - * Misc defines for various things. - */ -#define TAG_ADAPTER 0xd0 -#define ACTIVATE_ADAPTER_TO_CONFIG 0xff -#define ENABLE_DRQ_IRQ 0x0001 -#define MFG_ID 0x506d /* `TCM' */ -#define PROD_ID 0x5090 -#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND) -#define JABBER_GUARD_ENABLE 0x40 -#define LINKBEAT_ENABLE 0x80 -#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE) -#define DISABLE_UTP 0x0 -#define RX_BYTES_MASK (unsigned short) (0x07ff) -#define RX_ERROR 0x4000 -#define RX_INCOMPLETE 0x8000 -#define TX_INDICATE 1<<15 -#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY) - -#define VX_IOSIZE 0x20 - -#define VX_CONNECTORS 8 - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/5701rls.c b/drivers/5701rls.c deleted file mode 100644 index 86950d0f82..0000000000 --- a/drivers/5701rls.c +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* */ -/******************************************************************************/ - -#if INCLUDE_5701_AX_FIX - -#include "bcm570x_mm.h" -#include "5701rls.h" - -LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice) -{ - T3_FWIMG_INFO FwImgInfo; - - FwImgInfo.StartAddress = t3FwStartAddr; - FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText; - FwImgInfo.Text.Offset = t3FwTextAddr; - FwImgInfo.Text.Length = t3FwTextLen; - FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata; - FwImgInfo.ROnlyData.Offset = t3FwRodataAddr; - FwImgInfo.ROnlyData.Length = t3FwRodataLen; - FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData; - FwImgInfo.Data.Offset = t3FwDataAddr; - FwImgInfo.Data.Length = t3FwDataLen; - - if (LM_LoadFirmware(pDevice, - &FwImgInfo, - T3_RX_CPU_ID | T3_TX_CPU_ID, - T3_RX_CPU_ID) != LM_STATUS_SUCCESS) - { - return LM_STATUS_FAILURE; - } - - return LM_STATUS_SUCCESS; -} - -#endif /* INCLUDE_5701_AX_FIX */ diff --git a/drivers/5701rls.h b/drivers/5701rls.h deleted file mode 100644 index 30b127a429..0000000000 --- a/drivers/5701rls.h +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/******************************************************************************/ - -typedef unsigned long U32; -int t3FwReleaseMajor = 0x0; -int t3FwReleaseMinor = 0x0; -int t3FwReleaseFix = 0x0; -U32 t3FwStartAddr = 0x08000000; -U32 t3FwTextAddr = 0x08000000; -int t3FwTextLen = 0x9c0; -U32 t3FwRodataAddr = 0x080009c0; -int t3FwRodataLen = 0x60; -U32 t3FwDataAddr = 0x08000a40; -int t3FwDataLen = 0x20; -U32 t3FwSbssAddr = 0x08000a60; -int t3FwSbssLen = 0xc; -U32 t3FwBssAddr = 0x08000a70; -int t3FwBssLen = 0x10; -U32 t3FwText[(0x9c0/4) + 1] = { -0x0, -0x10000003, 0x0, 0xd, 0xd, -0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, -0x26100000, 0xe000018, 0x0, 0xd, -0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, -0x26100034, 0xe00021c, 0x0, 0xd, -0x0, 0x0, 0x0, 0x27bdffe0, -0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c, -0x241b2105, 0x97850000, 0x97870002, 0x9782002c, -0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014, -0x21400, 0x621825, 0x52c00, 0xafa30010, -0x8f860010, 0xe52825, 0xe000060, 0x24070102, -0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100, -0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, -0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f, -0xaf825d00, 0xe000140, 0x0, 0x8fbf0018, -0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, -0x8f835400, 0x34630400, 0xaf835400, 0xaf825404, -0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008, -0xaf805400, 0x0, 0x0, 0x3c020800, -0x34423000, 0x3c030800, 0x34633000, 0x3c040800, -0x348437ff, 0x3c010800, 0xac220a64, 0x24020040, -0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, -0xac600000, 0x24630004, 0x83102b, 0x5040fffd, -0xac600000, 0x3e00008, 0x0, 0x804821, -0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, -0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b, -0x3c010800, 0xac230a60, 0x14400003, 0x4021, -0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, -0x3c030800, 0x8c630a64, 0x91240000, 0x21140, -0x431021, 0x481021, 0x25080001, 0xa0440000, -0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, -0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c, -0x21140, 0x431021, 0xac440008, 0xac45000c, -0xac460010, 0xac470014, 0xac4a0018, 0x3e00008, -0xac4b001c, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x2000008, -0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3, -0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3, -0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3, -0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x0, 0xa0001e3, -0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3, -0x3c0a0014, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x27bdffe0, -0x1821, 0x1021, 0xafbf0018, 0xafb10014, -0xafb00010, 0x3c010800, 0x220821, 0xac200a70, -0x3c010800, 0x220821, 0xac200a74, 0x3c010800, -0x220821, 0xac200a78, 0x24630001, 0x1860fff5, -0x2442000c, 0x24110001, 0x8f906810, 0x32020004, -0x14400005, 0x24040001, 0x3c020800, 0x8c420a78, -0x18400003, 0x2021, 0xe000182, 0x0, -0x32020001, 0x10400003, 0x0, 0xe000169, -0x0, 0xa000153, 0xaf915028, 0x8fbf0018, -0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, -0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80, -0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800, -0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060, -0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018, -0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810, -0x821004, 0x21027, 0x621824, 0x3e00008, -0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e, -0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec, -0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, -0xaf825cec, 0x8e020000, 0x18400016, 0x0, -0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0, -0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201, -0xac220a74, 0x10400005, 0x0, 0x8e020000, -0x24420001, 0xa0001df, 0xae020000, 0x3c020800, -0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5, -0xafa2001c, 0xe000201, 0x0, 0x1040001f, -0x0, 0x8e020000, 0x8fa3001c, 0x24420001, -0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, -0xa0001df, 0xae020000, 0x3c100800, 0x26100a78, -0x8e020000, 0x18400028, 0x0, 0xe000201, -0x0, 0x14400024, 0x0, 0x8e020000, -0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c, -0x18400006, 0xae020000, 0x31402, 0x221c0, -0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, -0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000, -0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014, -0x8fa6001c, 0x24050008, 0xe000060, 0x3821, -0xa0001df, 0x0, 0xaf825cf8, 0x3c020800, -0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8, -0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, -0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800, -0x248409e8, 0x2821, 0x3021, 0x3821, -0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014, -0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c, -0x8f85680c, 0x21827, 0x3182b, 0x31823, -0x431024, 0x441021, 0xa2282b, 0x10a00006, -0x0, 0x401821, 0x8f82680c, 0x43102b, -0x1440fffd, 0x0, 0x3e00008, 0x0, -0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, -0x64102b, 0x54400002, 0x831023, 0x641023, -0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0, -0x802821, 0x3c040800, 0x24840a00, 0x3021, -0x3821, 0xafbf0018, 0xafa00010, 0xe000060, -0xafa00014, 0xa000216, 0x0, 0x8fbf0018, -0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0, -0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c, -0x3c040800, 0x24840a10, 0x3802821, 0x3021, -0x3821, 0xafa00010, 0xe000060, 0xafa00014, -0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234, -0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020, -0x0, 0x0, 0x0, 0x27bdffe8, -0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003, -0xac200000, 0x8f826810, 0x30422000, 0x10400003, -0x0, 0xe000246, 0x0, 0xa00023a, -0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008, -0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff, -0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024, -0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003, -0x3c074000, 0x851824, 0x8c620010, 0x3c010800, -0xac230a50, 0x30420008, 0x10400005, 0x871025, -0x8cc20000, 0x24420001, 0xacc20000, 0x871025, -0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000, -0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, -0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50, -0x851024, 0x1443ffe8, 0x851824, 0x27bd0008, -0x3e00008, 0x0, 0x0, 0x0 }; -U32 t3FwRodata[(0x60/4) + 1] = { -0x35373031, 0x726c7341, 0x0, -0x0, 0x53774576, 0x656e7430, 0x0, -0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, -0x45766e74, 0x0, 0x0, 0x0, -0x0, 0x66617461, 0x6c457272, 0x0, -0x0, 0x4d61696e, 0x43707542, 0x0, -0x0, 0x0 }; -U32 t3FwData[(0x20/4) + 1] = { -0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0 }; diff --git a/drivers/8390.h b/drivers/8390.h deleted file mode 100644 index f087217ed0..0000000000 --- a/drivers/8390.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - -Ported to U-Boot by Christian Pellegrin - -Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and -eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world -are GPL, so this is, of course, GPL. - -*/ - -/* Generic NS8390 register definitions. */ -/* This file is part of Donald Becker's 8390 drivers, and is distributed - under the same license. Auto-loading of 8390.o only in v2.2 - Paul G. - Some of these names and comments originated from the Crynwr - packet drivers, which are distributed under the GPL. */ - -#ifndef _8390_h -#define _8390_h - -/* Some generic ethernet register configurations. */ -#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ -#define E8390_RX_IRQ_MASK 0x5 -#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ -#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ -#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ -#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ - -/* Register accessed at EN_CMD, the 8390 base addr. */ -#define E8390_STOP 0x01 /* Stop and reset the chip */ -#define E8390_START 0x02 /* Start the chip, clear reset */ -#define E8390_TRANS 0x04 /* Transmit a frame */ -#define E8390_RREAD 0x08 /* Remote read */ -#define E8390_RWRITE 0x10 /* Remote write */ -#define E8390_NODMA 0x20 /* Remote DMA */ -#define E8390_PAGE0 0x00 /* Select page chip registers */ -#define E8390_PAGE1 0x40 /* using the two high-order bits */ -#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ - -/* - * Only generate indirect loads given a machine that needs them. - * - removed AMIGA_PCMCIA from this list, handled as ISA io now - */ - -#define n2k_inb(port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE))) -#define n2k_outb(val,port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = val) - -#define EI_SHIFT(x) (x) - -#define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */ -/* Page 0 register offsets. */ -#define EN0_CLDALO EI_SHIFT(0x01) /* Low byte of current local dma addr RD */ -#define EN0_STARTPG EI_SHIFT(0x01) /* Starting page of ring bfr WR */ -#define EN0_CLDAHI EI_SHIFT(0x02) /* High byte of current local dma addr RD */ -#define EN0_STOPPG EI_SHIFT(0x02) /* Ending page +1 of ring bfr WR */ -#define EN0_BOUNDARY EI_SHIFT(0x03) /* Boundary page of ring bfr RD WR */ -#define EN0_TSR EI_SHIFT(0x04) /* Transmit status reg RD */ -#define EN0_TPSR EI_SHIFT(0x04) /* Transmit starting page WR */ -#define EN0_NCR EI_SHIFT(0x05) /* Number of collision reg RD */ -#define EN0_TCNTLO EI_SHIFT(0x05) /* Low byte of tx byte count WR */ -#define EN0_FIFO EI_SHIFT(0x06) /* FIFO RD */ -#define EN0_TCNTHI EI_SHIFT(0x06) /* High byte of tx byte count WR */ -#define EN0_ISR EI_SHIFT(0x07) /* Interrupt status reg RD WR */ -#define EN0_CRDALO EI_SHIFT(0x08) /* low byte of current remote dma address RD */ -#define EN0_RSARLO EI_SHIFT(0x08) /* Remote start address reg 0 */ -#define EN0_CRDAHI EI_SHIFT(0x09) /* high byte, current remote dma address RD */ -#define EN0_RSARHI EI_SHIFT(0x09) /* Remote start address reg 1 */ -#define EN0_RCNTLO EI_SHIFT(0x0a) /* Remote byte count reg WR */ -#define EN0_RCNTHI EI_SHIFT(0x0b) /* Remote byte count reg WR */ -#define EN0_RSR EI_SHIFT(0x0c) /* rx status reg RD */ -#define EN0_RXCR EI_SHIFT(0x0c) /* RX configuration reg WR */ -#define EN0_TXCR EI_SHIFT(0x0d) /* TX configuration reg WR */ -#define EN0_COUNTER0 EI_SHIFT(0x0d) /* Rcv alignment error counter RD */ -#define EN0_DCFG EI_SHIFT(0x0e) /* Data configuration reg WR */ -#define EN0_COUNTER1 EI_SHIFT(0x0e) /* Rcv CRC error counter RD */ -#define EN0_IMR EI_SHIFT(0x0f) /* Interrupt mask reg WR */ -#define EN0_COUNTER2 EI_SHIFT(0x0f) /* Rcv missed frame error counter RD */ - -/* Bits in EN0_ISR - Interrupt status register */ -#define ENISR_RX 0x01 /* Receiver, no error */ -#define ENISR_TX 0x02 /* Transmitter, no error */ -#define ENISR_RX_ERR 0x04 /* Receiver, with error */ -#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ -#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ -#define ENISR_COUNTERS 0x20 /* Counters need emptying */ -#define ENISR_RDC 0x40 /* remote dma complete */ -#define ENISR_RESET 0x80 /* Reset completed */ -#define ENISR_ALL 0x3f /* Interrupts we will enable */ - -/* Bits in EN0_DCFG - Data config register */ -#define ENDCFG_WTS 0x01 /* word transfer mode selection */ -#define ENDCFG_BOS 0x02 /* byte order selection */ -#define ENDCFG_AUTO_INIT 0x10 /* Auto-init to remove packets from ring */ -#define ENDCFG_FIFO 0x40 /* 8 bytes */ - -/* Page 1 register offsets. */ -#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */ -#define EN1_PHYS_SHIFT(i) EI_SHIFT(i+1) /* Get and set mac address */ -#define EN1_CURPAG EI_SHIFT(0x07) /* Current memory page RD WR */ -#define EN1_MULT EI_SHIFT(0x08) /* Multicast filter mask array (8 bytes) RD WR */ -#define EN1_MULT_SHIFT(i) EI_SHIFT(8+i) /* Get and set multicast filter */ - -/* Bits in received packet status byte and EN0_RSR*/ -#define ENRSR_RXOK 0x01 /* Received a good packet */ -#define ENRSR_CRC 0x02 /* CRC error */ -#define ENRSR_FAE 0x04 /* frame alignment error */ -#define ENRSR_FO 0x08 /* FIFO overrun */ -#define ENRSR_MPA 0x10 /* missed pkt */ -#define ENRSR_PHY 0x20 /* physical/multicast address */ -#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ -#define ENRSR_DEF 0x80 /* deferring */ - -/* Transmitted packet status, EN0_TSR. */ -#define ENTSR_PTX 0x01 /* Packet transmitted without error */ -#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ -#define ENTSR_COL 0x04 /* The transmit collided at least once. */ -#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ -#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ -#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ -#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ -#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ - -#define NIC_RECEIVE_MONITOR_MODE 0x20 - -#endif /* _8390_h */ diff --git a/drivers/Makefile b/drivers/Makefile index c7fc597228..4b6f5f017f 100755 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -51,7 +51,6 @@ COBJS-y += systemace.o COBJS-y += atmel_usart.o COBJS-y += i8042.o COBJS-y += keyboard.o -COBJS-y += netconsole.o COBJS-y += ns16550.o COBJS-y += pc_keyb.o COBJS-y += ps2ser.o @@ -62,38 +61,6 @@ COBJS-y += serial_max3100.o COBJS-y += serial_xuartlite.o COBJS-y += usbtty.o -# -# Network Drivers -# -COBJS-y += 3c589.o -COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o -COBJS-y += cs8900.o -COBJS-y += dc2114x.o -COBJS-y += dm9000x.o -COBJS-y += e1000.o -COBJS-y += eepro100.o -COBJS-y += enc28j60.o -COBJS-y += inca-ip_sw.o -COBJS-y += ks8695eth.o -COBJS-y += lan91c96.o -COBJS-y += macb.o -COBJS-y += natsemi.o -COBJS-y += ne2000.o -COBJS-y += netarm_eth.o -COBJS-y += ns7520_eth.o -COBJS-y += ns8382x.o -COBJS-y += pcnet.o -COBJS-y += plb2800_eth.o -COBJS-y += rtl8019.o -COBJS-y += rtl8139.o -COBJS-y += rtl8169.o -COBJS-y += s3c4510b_eth.o -COBJS-y += smc91111.o -COBJS-y += tigon3.o -COBJS-y += tsec.o -COBJS-y += tsi108_eth.o -COBJS-y += uli526x.o - # # USB Drivers # diff --git a/drivers/bcm570x.c b/drivers/bcm570x.c deleted file mode 100644 index c8f4064224..0000000000 --- a/drivers/bcm570x.c +++ /dev/null @@ -1,1603 +0,0 @@ -/* - * Broadcom BCM570x Ethernet Driver for U-Boot. - * Support 5701, 5702, 5703, and 5704. Single instance driver. - * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com) - */ - -#include - -#if defined(CONFIG_CMD_NET) \ - && (!defined(CONFIG_NET_MULTI)) && defined(CONFIG_BCM570x) - -#ifdef CONFIG_BMW -#include -#endif -#include -#include "bcm570x_mm.h" -#include "bcm570x_autoneg.h" -#include -#include - -/* - * PCI Registers and definitions. - */ -#define PCI_CMD_MASK 0xffff0000 /* mask to save status bits */ -#define PCI_ANY_ID (~0) - -/* - * PCI memory base for Ethernet device as well as device Interrupt. - */ -#define BCM570X_MBAR 0x80100000 -#define BCM570X_ILINE 1 - -#define SECOND_USEC 1000000 -#define MAX_PACKET_SIZE 1600 -#define MAX_UNITS 4 - -/* Globals to this module */ -int initialized = 0; -unsigned int ioBase = 0; -volatile PLM_DEVICE_BLOCK pDevice = NULL; /* 570x softc */ -volatile PUM_DEVICE_BLOCK pUmDevice = NULL; - -/* Used to pass the full-duplex flag, etc. */ -int line_speed[MAX_UNITS] = { 0, 0, 0, 0 }; -static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 }; -static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; -static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; -static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; -static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 }; -static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 }; -static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 }; - -#if JUMBO_FRAMES -/* Jumbo MTU for interfaces. */ -static int mtu[MAX_UNITS] = { 0, 0, 0, 0 }; -#endif - -/* Turn on Wake-on lan for a device unit */ -static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 }; - -#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT -static unsigned int tx_pkt_desc_cnt[MAX_UNITS] = - { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT }; - -#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT -static unsigned int rx_std_desc_cnt[MAX_UNITS] = - { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT }; - -static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 }; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT -#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT -static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] = - { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT }; -#endif -#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS -static unsigned int rx_coalesce_ticks[MAX_UNITS] = - { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK }; - -#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES -static unsigned int rx_max_coalesce_frames[MAX_UNITS] = - { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM }; - -#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS -static unsigned int tx_coalesce_ticks[MAX_UNITS] = - { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK }; - -#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES -static unsigned int tx_max_coalesce_frames[MAX_UNITS] = - { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM }; - -#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS -static unsigned int stats_coalesce_ticks[MAX_UNITS] = - { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK }; - -/* - * Legitimate values for BCM570x device types - */ -typedef enum { - BCM5700VIGIL = 0, - BCM5700A6, - BCM5700T6, - BCM5700A9, - BCM5700T9, - BCM5700, - BCM5701A5, - BCM5701T1, - BCM5701T8, - BCM5701A7, - BCM5701A10, - BCM5701A12, - BCM5701, - BCM5702, - BCM5703, - BCM5703A31, - TC996T, - TC996ST, - TC996SSX, - TC996SX, - TC996BT, - TC997T, - TC997SX, - TC1000T, - TC940BR01, - TC942BR01, - NC6770, - NC7760, - NC7770, - NC7780 -} board_t; - -/* Chip-Rev names for each device-type */ -static struct { - char *name; -} chip_rev[] = { - { - "BCM5700VIGIL"}, { - "BCM5700A6"}, { - "BCM5700T6"}, { - "BCM5700A9"}, { - "BCM5700T9"}, { - "BCM5700"}, { - "BCM5701A5"}, { - "BCM5701T1"}, { - "BCM5701T8"}, { - "BCM5701A7"}, { - "BCM5701A10"}, { - "BCM5701A12"}, { - "BCM5701"}, { - "BCM5702"}, { - "BCM5703"}, { - "BCM5703A31"}, { - "TC996T"}, { - "TC996ST"}, { - "TC996SSX"}, { - "TC996SX"}, { - "TC996BT"}, { - "TC997T"}, { - "TC997SX"}, { - "TC1000T"}, { - "TC940BR01"}, { - "TC942BR01"}, { - "NC6770"}, { - "NC7760"}, { - "NC7770"}, { - "NC7780"}, { - 0} -}; - -/* indexed by board_t, above */ -static struct { - char *name; -} board_info[] = { - { - "Broadcom Vigil B5700 1000Base-T"}, { - "Broadcom BCM5700 1000Base-T"}, { - "Broadcom BCM5700 1000Base-SX"}, { - "Broadcom BCM5700 1000Base-SX"}, { - "Broadcom BCM5700 1000Base-T"}, { - "Broadcom BCM5700"}, { - "Broadcom BCM5701 1000Base-T"}, { - "Broadcom BCM5701 1000Base-T"}, { - "Broadcom BCM5701 1000Base-T"}, { - "Broadcom BCM5701 1000Base-SX"}, { - "Broadcom BCM5701 1000Base-T"}, { - "Broadcom BCM5701 1000Base-T"}, { - "Broadcom BCM5701"}, { - "Broadcom BCM5702 1000Base-T"}, { - "Broadcom BCM5703 1000Base-T"}, { - "Broadcom BCM5703 1000Base-SX"}, { - "3Com 3C996 10/100/1000 Server NIC"}, { - "3Com 3C996 10/100/1000 Server NIC"}, { - "3Com 3C996 Gigabit Fiber-SX Server NIC"}, { - "3Com 3C996 Gigabit Fiber-SX Server NIC"}, { - "3Com 3C996B Gigabit Server NIC"}, { - "3Com 3C997 Gigabit Server NIC"}, { - "3Com 3C997 Gigabit Fiber-SX Server NIC"}, { - "3Com 3C1000 Gigabit NIC"}, { - "3Com 3C940 Gigabit LOM (21X21)"}, { - "3Com 3C942 Gigabit LOM (31X31)"}, { - "Compaq NC6770 Gigabit Server Adapter"}, { - "Compaq NC7760 Gigabit Server Adapter"}, { - "Compaq NC7770 Gigabit Server Adapter"}, { - "Compaq NC7780 Gigabit Server Adapter"}, { -0},}; - -/* PCI Devices which use the 570x chipset */ -struct pci_device_table { - unsigned short vendor_id, device_id; /* Vendor/DeviceID */ - unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ - unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ - unsigned long board_id; /* Data private to the driver */ - int io_size, min_latency; -} bcm570xDevices[] = { - { - 0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, { - 0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, { - 0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, { - 0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, { - 0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, { - 0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, { - 0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, { - 0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, { - 0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, { - 0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, { - 0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, { - 0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, { - 0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, { - 0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, { - 0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, { - 0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, { - 0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, { - 0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, { - 0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, { - 0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, { - 0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, { - 0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, { - 0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, { - 0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, { - 0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, { - 0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, { - 0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, { - 0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, { - 0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, { - 0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, { - 0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, { - 0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, { - 0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, { - 0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, { - 0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32} -}; - -#define n570xDevices (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0])) - -/* - * Allocate a packet buffer from the bcm570x packet pool. - */ -void *bcm570xPktAlloc (int u, int pksize) -{ - return malloc (pksize); -} - -/* - * Free a packet previously allocated from the bcm570x packet - * buffer pool. - */ -void bcm570xPktFree (int u, void *p) -{ - free (p); -} - -int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice) -{ - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - void *skb; - int queue_rx = 0; - int ret = 0; - - while ((pUmPacket = (PUM_PACKET) - QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) { - - pPacket = (PLM_PACKET) pUmPacket; - - /* reuse an old skb */ - if (pUmPacket->skbuff) { - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, - pPacket); - queue_rx = 1; - continue; - } - if ((skb = bcm570xPktAlloc (pUmDevice->index, - pPacket->u.Rx.RxBufferSize + 2)) == - 0) { - QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container, - pPacket); - printf ("NOTICE: Out of RX memory.\n"); - ret = 1; - break; - } - - pUmPacket->skbuff = skb; - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - queue_rx = 1; - } - - if (queue_rx) { - LM_QueueRxPackets (pDevice); - } - - return ret; -} - -/* - * Probe, Map, and Init 570x device. - */ -int eth_init (bd_t * bis) -{ - int i, rv, devFound = FALSE; - pci_dev_t devbusfn; - unsigned short status; - - /* Find PCI device, if it exists, configure ... */ - for (i = 0; i < n570xDevices; i++) { - devbusfn = pci_find_device (bcm570xDevices[i].vendor_id, - bcm570xDevices[i].device_id, 0); - if (devbusfn == -1) { - continue; /* No device of that vendor/device ID */ - } else { - - /* Set ILINE */ - pci_write_config_byte (devbusfn, - PCI_INTERRUPT_LINE, - BCM570X_ILINE); - - /* - * 0x10 - 0x14 define one 64-bit MBAR. - * 0x14 is the higher-order address bits of the BAR. - */ - pci_write_config_dword (devbusfn, - PCI_BASE_ADDRESS_1, 0); - - ioBase = BCM570X_MBAR; - - pci_write_config_dword (devbusfn, - PCI_BASE_ADDRESS_0, ioBase); - - /* - * Enable PCI memory, IO, and Master -- don't - * reset any status bits in doing so. - */ - pci_read_config_word (devbusfn, PCI_COMMAND, &status); - - status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - - pci_write_config_word (devbusfn, PCI_COMMAND, status); - - printf - ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n", - board_info[bcm570xDevices[i].board_id].name, - PCI_BUS (devbusfn), PCI_DEV (devbusfn), - PCI_FUNC (devbusfn), ioBase); - - /* Allocate once, but always clear on init */ - if (!pDevice) { - pDevice = malloc (sizeof (UM_DEVICE_BLOCK)); - pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK)); - } - - /* Configure pci dev structure */ - pUmDevice->pdev = devbusfn; - pUmDevice->index = 0; - pUmDevice->tx_pkt = 0; - pUmDevice->rx_pkt = 0; - devFound = TRUE; - break; - } - } - - if (!devFound) { - printf - ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n"); - return -1; - } - - /* Setup defaults for chip */ - pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; - - if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) { - pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; - } else { - - if (rx_checksum[i]) { - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_RX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_RX_UDP_CHECKSUM; - } - - if (tx_checksum[i]) { - pDevice->TaskToOffload |= - LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_TX_UDP_CHECKSUM; - pDevice->NoTxPseudoHdrChksum = TRUE; - } - } - - /* Set Device PCI Memory base address */ - pDevice->pMappedMemBase = (PLM_UINT8) ioBase; - - /* Pull down adapter info */ - if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) { - printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv); - return -2; - } - - /* Lock not needed */ - pUmDevice->do_global_lock = 0; - - if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) { - /* The 5700 chip works best without interleaved register */ - /* accesses on certain machines. */ - pUmDevice->do_global_lock = 1; - } - - /* Setup timer delays */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - pDevice->UseTaggedStatus = TRUE; - pUmDevice->timer_interval = CFG_HZ; - } else { - pUmDevice->timer_interval = CFG_HZ / 50; - } - - /* Grab name .... */ - pUmDevice->name = - (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name) - + 1); - strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name); - - memcpy (pDevice->NodeAddress, bis->bi_enetaddr, 6); - LM_SetMacAddress (pDevice, bis->bi_enetaddr); - /* Init queues .. */ - QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container, - MAX_RX_PACKET_DESC_COUNT); - pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0; - - /* delay for 4 seconds */ - pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval; - - pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval; - - /* Sometimes we get spurious ints. after reset when link is down. */ - /* This field tells the isr to service the int. even if there is */ - /* no status block update. */ - pUmDevice->adapter_just_inited = - (3 * CFG_HZ) / pUmDevice->timer_interval; - - /* Initialize 570x */ - if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) { - printf ("ERROR: Adapter initialization failed.\n"); - return ERROR; - } - - /* Enable chip ISR */ - LM_EnableInterrupt (pDevice); - - /* Clear MC table */ - LM_MulticastClear (pDevice); - - /* Enable Multicast */ - LM_SetReceiveMask (pDevice, - pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST); - - pUmDevice->opened = 1; - pUmDevice->tx_full = 0; - pUmDevice->tx_pkt = 0; - pUmDevice->rx_pkt = 0; - printf ("eth%d: %s @0x%lx,", - pDevice->index, pUmDevice->name, (unsigned long)ioBase); - printf ("node addr "); - for (i = 0; i < 6; i++) { - printf ("%2.2x", pDevice->NodeAddress[i]); - } - printf ("\n"); - - printf ("eth%d: ", pDevice->index); - printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name); - - if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID) - printf ("Broadcom BCM5400 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) - printf ("Broadcom BCM5401 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID) - printf ("Broadcom BCM5411 Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) - printf ("Broadcom BCM5701 Integrated Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) - printf ("Broadcom BCM5703 Integrated Copper "); - else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID) - printf ("Broadcom BCM8002 SerDes "); - else if (pDevice->EnableTbi) - printf ("Agilent HDMP-1636 SerDes "); - else - printf ("Unknown "); - printf ("transceiver found\n"); - - printf ("eth%d: %s, MTU: %d,", - pDevice->index, pDevice->BusSpeedStr, 1500); - - if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i]) - printf ("Rx Checksum ON\n"); - else - printf ("Rx Checksum OFF\n"); - initialized++; - - return 0; -} - -/* Ethernet Interrupt service routine */ -void eth_isr (void) -{ - LM_UINT32 oldtag, newtag; - int i; - - pUmDevice->interrupt = 1; - - if (pDevice->UseTaggedStatus) { - if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) || - pUmDevice->adapter_just_inited) { - MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1); - oldtag = pDevice->pStatusBlkVirt->StatusTag; - - for (i = 0;; i++) { - pDevice->pStatusBlkVirt->Status &= - ~STATUS_BLOCK_UPDATED; - LM_ServiceInterrupts (pDevice); - newtag = pDevice->pStatusBlkVirt->StatusTag; - if ((newtag == oldtag) || (i > 50)) { - MB_REG_WR (pDevice, - Mailbox.Interrupt[0].Low, - newtag << 24); - if (pDevice->UndiFix) { - REG_WR (pDevice, Grc.LocalCtrl, - pDevice-> - GrcLocalCtrl | 0x2); - } - break; - } - oldtag = newtag; - } - } - } else { - while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { - unsigned int dummy; - - pDevice->pMemView->Mailbox.Interrupt[0].Low = 1; - pDevice->pStatusBlkVirt->Status &= - ~STATUS_BLOCK_UPDATED; - LM_ServiceInterrupts (pDevice); - pDevice->pMemView->Mailbox.Interrupt[0].Low = 0; - dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low; - } - } - - /* Allocate new RX buffers */ - if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) { - bcm570xReplenishRxBuffers (pUmDevice); - } - - /* Queue packets */ - if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) { - LM_QueueRxPackets (pDevice); - } - - if (pUmDevice->tx_queued) { - pUmDevice->tx_queued = 0; - } - - if (pUmDevice->tx_full) { - if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) { - printf - ("NOTICE: tx was previously blocked, restarting MUX\n"); - pUmDevice->tx_full = 0; - } - } - - pUmDevice->interrupt = 0; - -} - -int eth_send (volatile void *packet, int length) -{ - int status = 0; -#if ET_DEBUG - unsigned char *ptr = (unsigned char *)packet; -#endif - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - - /* Link down, return */ - while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) { -#if 0 - printf ("eth%d: link down - check cable or link partner.\n", - pUmDevice->index); -#endif - eth_isr (); - - /* Wait to see link for one-half a second before sending ... */ - udelay (1500000); - - } - - /* Clear sent flag */ - pUmDevice->tx_pkt = 0; - - /* Previously blocked */ - if (pUmDevice->tx_full) { - printf ("eth%d: tx blocked.\n", pUmDevice->index); - return 0; - } - - pPacket = (PLM_PACKET) - QQ_PopHead (&pDevice->TxPacketFreeQ.Container); - - if (pPacket == 0) { - pUmDevice->tx_full = 1; - printf ("bcm570xEndSend: TX full!\n"); - return 0; - } - - if (pDevice->SendBdLeft.counter == 0) { - pUmDevice->tx_full = 1; - printf ("bcm570xEndSend: no more TX descriptors!\n"); - QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); - return 0; - } - - if (length <= 0) { - printf ("eth: bad packet size: %d\n", length); - goto out; - } - - /* Get packet buffers and fragment list */ - pUmPacket = (PUM_PACKET) pPacket; - /* Single DMA Descriptor transmit. - * Fragments may be provided, but one DMA descriptor max is - * used to send the packet. - */ - if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) { - if (pUmPacket->skbuff == NULL) { - /* Packet was discarded */ - printf ("TX: failed (1)\n"); - status = 1; - } else { - printf ("TX: failed (2)\n"); - status = 2; - } - QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); - return status; - } - - /* Copy packet to DMA buffer */ - memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE); - memcpy ((void *)pUmPacket->skbuff, (void *)packet, length); - pPacket->PacketSize = length; - pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW; - pPacket->u.Tx.FragCount = 1; - /* We've already provided a frame ready for transmission */ - pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM; - - if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) { - /* - * A lower level send failure will push the packet descriptor back - * in the free queue, so just deal with the VxWorks clusters. - */ - if (pUmPacket->skbuff == NULL) { - printf ("TX failed (1)!\n"); - /* Packet was discarded */ - status = 3; - } else { - /* A resource problem ... */ - printf ("TX failed (2)!\n"); - status = 4; - } - - if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) { - printf ("TX: emptyQ!\n"); - pUmDevice->tx_full = 1; - } - } - - while (pUmDevice->tx_pkt == 0) { - /* Service TX */ - eth_isr (); - } -#if ET_DEBUG - printf ("eth_send: 0x%x, %d bytes\n" - "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n", - (int)pPacket, length, - ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], - ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], - ptr[13], ptr[14], ptr[15]); -#endif - pUmDevice->tx_pkt = 0; - QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); - - /* Done with send */ - out: - return status; -} - -/* Ethernet receive */ -int eth_rx (void) -{ - PLM_PACKET pPacket = NULL; - PUM_PACKET pUmPacket = NULL; - void *skb; - int size = 0; - - while (TRUE) { - - bcm570x_service_isr: - /* Pull down packet if it is there */ - eth_isr (); - - /* Indicate RX packets called */ - if (pUmDevice->rx_pkt) { - /* printf("eth_rx: got a packet...\n"); */ - pUmDevice->rx_pkt = 0; - } else { - /* printf("eth_rx: waiting for packet...\n"); */ - goto bcm570x_service_isr; - } - - pPacket = (PLM_PACKET) - QQ_PopHead (&pDevice->RxPacketReceivedQ.Container); - - if (pPacket == 0) { - printf ("eth_rx: empty packet!\n"); - goto bcm570x_service_isr; - } - - pUmPacket = (PUM_PACKET) pPacket; -#if ET_DEBUG - printf ("eth_rx: packet @0x%x\n", (int)pPacket); -#endif - /* If the packet generated an error, reuse buffer */ - if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) || - ((size = pPacket->PacketSize) > pDevice->RxMtu)) { - - /* reuse skb */ - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, - pPacket); - printf ("eth_rx: error in packet dma!\n"); - goto bcm570x_service_isr; - } - - /* Set size and address */ - skb = pUmPacket->skbuff; - size = pPacket->PacketSize; - - /* Pass the packet up to the protocol - * layers. - */ - NetReceive (skb, size); - - /* Free packet buffer */ - bcm570xPktFree (pUmDevice->index, skb); - pUmPacket->skbuff = NULL; - - /* Reuse SKB */ - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - - return 0; /* Got a packet, bail ... */ - } - return size; -} - -/* Shut down device */ -void eth_halt (void) -{ - int i; - if (initialized) - if (pDevice && pUmDevice && pUmDevice->opened) { - printf ("\neth%d:%s,", pUmDevice->index, - pUmDevice->name); - printf ("HALT,"); - /* stop device */ - LM_Halt (pDevice); - printf ("POWER DOWN,"); - LM_SetPowerState (pDevice, LM_POWER_STATE_D3); - - /* Free the memory allocated by the device in tigon3 */ - for (i = 0; i < pUmDevice->mem_list_num; i++) { - if (pUmDevice->mem_list[i]) { - /* sanity check */ - if (pUmDevice->dma_list[i]) { /* cache-safe memory */ - free (pUmDevice->mem_list[i]); - } else { - free (pUmDevice->mem_list[i]); /* normal memory */ - } - } - } - pUmDevice->opened = 0; - free (pDevice); - pDevice = NULL; - pUmDevice = NULL; - initialized = 0; - printf ("done - offline.\n"); - } -} - -/* - * - * Middle Module: Interface between the HW driver (tigon3 modules) and - * the native (SENS) driver. These routines implement the system - * interface for tigon3 on VxWorks. - */ - -/* Middle module dependency - size of a packet descriptor */ -int MM_Packet_Desc_Size = sizeof (UM_PACKET); - -LM_STATUS -MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice, - LM_UINT32 Offset, LM_UINT32 * pValue32) -{ - UM_DEVICE_BLOCK *pUmDevice; - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32) -{ - UM_DEVICE_BLOCK *pUmDevice; - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_write_config_dword (pUmDevice->pdev, Offset, Value32); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice, - LM_UINT32 Offset, LM_UINT16 * pValue16) -{ - UM_DEVICE_BLOCK *pUmDevice; - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16) -{ - UM_DEVICE_BLOCK *pUmDevice; - pUmDevice = (UM_DEVICE_BLOCK *) pDevice; - pci_write_config_word (pUmDevice->pdev, Offset, Value16); - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, - PLM_VOID * pMemoryBlockVirt, - PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached) -{ - PLM_VOID pvirt; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - dma_addr_t mapping; - - pvirt = malloc (BlockSize); - mapping = (dma_addr_t) (pvirt); - if (!pvirt) - return LM_STATUS_FAILURE; - - pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; - pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping; - pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; - memset (pvirt, 0, BlockSize); - - *pMemoryBlockVirt = (PLM_VOID) pvirt; - MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping); - - return LM_STATUS_SUCCESS; -} - -LM_STATUS -MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, - PLM_VOID * pMemoryBlockVirt) -{ - PLM_VOID pvirt; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - - pvirt = malloc (BlockSize); - - if (!pvirt) - return LM_STATUS_FAILURE; - - pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; - pUmDevice->dma_list[pUmDevice->mem_list_num] = 0; - pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; - memset (pvirt, 0, BlockSize); - *pMemoryBlockVirt = pvirt; - - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice) -{ - printf ("BCM570x PCI Memory base address @0x%x\n", - (unsigned int)pDevice->pMappedMemBase); - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice) -{ - int i; - void *skb; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PUM_PACKET pUmPacket = NULL; - PLM_PACKET pPacket = NULL; - - for (i = 0; i < pDevice->RxPacketDescCnt; i++) { - pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container); - pUmPacket = (PUM_PACKET) pPacket; - - if (pPacket == 0) { - printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n"); - } - - skb = bcm570xPktAlloc (pUmDevice->index, - pPacket->u.Rx.RxBufferSize + 2); - - if (skb == 0) { - pUmPacket->skbuff = 0; - QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container, - pPacket); - printf ("MM_InitializeUmPackets: out of buffer.\n"); - continue; - } - - pUmPacket->skbuff = skb; - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - } - - pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8; - - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - int index = pDevice->index; - - if (auto_speed[index] == 0) - pDevice->DisableAutoNeg = TRUE; - else - pDevice->DisableAutoNeg = FALSE; - - if (line_speed[index] == 0) { - pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; - pDevice->DisableAutoNeg = FALSE; - } else { - if (line_speed[index] == 1000) { - if (pDevice->EnableTbi) { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX; - } else if (full_duplex[index]) { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX; - } else { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS; - } - if (!pDevice->EnableTbi) - pDevice->DisableAutoNeg = FALSE; - } else if (line_speed[index] == 100) { - if (full_duplex[index]) { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX; - } else { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS; - } - } else if (line_speed[index] == 10) { - if (full_duplex[index]) { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX; - } else { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; - } - } else { - pDevice->RequestedMediaType = - LM_REQUESTED_MEDIA_TYPE_AUTO; - pDevice->DisableAutoNeg = FALSE; - } - - } - pDevice->FlowControlCap = 0; - if (rx_flow_control[index] != 0) { - pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - if (tx_flow_control[index] != 0) { - pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; - } - if ((auto_flow_control[index] != 0) && - (pDevice->DisableAutoNeg == FALSE)) { - - pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE; - if ((tx_flow_control[index] == 0) && - (rx_flow_control[index] == 0)) { - pDevice->FlowControlCap |= - LM_FLOW_CONTROL_TRANSMIT_PAUSE | - LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - } - - /* Default MTU for now */ - pUmDevice->mtu = 1500; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - if (pUmDevice->mtu > 1500) { - pDevice->RxMtu = pUmDevice->mtu; - pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; - } else { - pDevice->RxJumboDescCnt = 0; - } - pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index]; -#else - pDevice->RxMtu = pUmDevice->mtu; -#endif - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - pDevice->UseTaggedStatus = TRUE; - pUmDevice->timer_interval = CFG_HZ; - } else { - pUmDevice->timer_interval = CFG_HZ / 50; - } - - pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index]; - pDevice->RxStdDescCnt = rx_std_desc_cnt[index]; - /* Note: adaptive coalescence really isn't adaptive in this driver */ - pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index]; - if (!pUmDevice->rx_adaptive_coalesce) { - pDevice->RxCoalescingTicks = rx_coalesce_ticks[index]; - if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS) - pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS; - pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks; - - pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index]; - if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES) - pDevice->RxMaxCoalescedFrames = - MAX_RX_MAX_COALESCED_FRAMES; - pUmDevice->rx_curr_coalesce_frames = - pDevice->RxMaxCoalescedFrames; - pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index]; - if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS) - pDevice->StatsCoalescingTicks = - MAX_STATS_COALESCING_TICKS; - } else { - pUmDevice->rx_curr_coalesce_frames = - DEFAULT_RX_MAX_COALESCED_FRAMES; - pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS; - } - pDevice->TxCoalescingTicks = tx_coalesce_ticks[index]; - if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS) - pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS; - pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index]; - if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES) - pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES; - - if (enable_wol[index]) { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET; - pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET; - } - pDevice->NicSendBd = TRUE; - - /* Don't update status blocks during interrupt */ - pDevice->RxCoalescingTicksDuringInt = 0; - pDevice->TxCoalescingTicksDuringInt = 0; - - return LM_STATUS_SUCCESS; - -} - -LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - printf ("Start TX DMA: dev=%d packet @0x%x\n", - (int)pUmDevice->index, (unsigned int)pPacket); - - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - printf ("Complete TX DMA: dev=%d packet @0x%x\n", - (int)pUmDevice->index, (unsigned int)pPacket); - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status) -{ - char buf[128]; - char lcd[4]; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - LM_FLOW_CONTROL flow_control; - - pUmDevice->delayed_link_ind = 0; - memset (lcd, 0x0, 4); - - if (Status == LM_STATUS_LINK_DOWN) { - sprintf (buf, "eth%d: %s: NIC Link is down\n", - pUmDevice->index, pUmDevice->name); - lcd[0] = 'L'; - lcd[1] = 'N'; - lcd[2] = 'K'; - lcd[3] = '?'; - } else if (Status == LM_STATUS_LINK_ACTIVE) { - sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name); - - if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) { - strcat (buf, "1000 Mbps "); - lcd[0] = '1'; - lcd[1] = 'G'; - lcd[2] = 'B'; - } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) { - strcat (buf, "100 Mbps "); - lcd[0] = '1'; - lcd[1] = '0'; - lcd[2] = '0'; - } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { - strcat (buf, "10 Mbps "); - lcd[0] = '1'; - lcd[1] = '0'; - lcd[2] = ' '; - } - if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) { - strcat (buf, "full duplex"); - lcd[3] = 'F'; - } else { - strcat (buf, "half duplex"); - lcd[3] = 'H'; - } - strcat (buf, " link up"); - - flow_control = pDevice->FlowControl & - (LM_FLOW_CONTROL_RECEIVE_PAUSE | - LM_FLOW_CONTROL_TRANSMIT_PAUSE); - - if (flow_control) { - if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) { - strcat (buf, ", receive "); - if (flow_control & - LM_FLOW_CONTROL_TRANSMIT_PAUSE) - strcat (buf, " & transmit "); - } else { - strcat (buf, ", transmit "); - } - strcat (buf, "flow control ON"); - } else { - strcat (buf, ", flow control OFF"); - } - strcat (buf, "\n"); - printf ("%s", buf); - } -#if 0 - sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]); -#endif - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PUM_PACKET pUmPacket; - void *skb; - - pUmPacket = (PUM_PACKET) pPacket; - - if ((skb = pUmPacket->skbuff)) - bcm570xPktFree (pUmDevice->index, skb); - - pUmPacket->skbuff = 0; - - return LM_STATUS_SUCCESS; -} - -unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo) -{ - return get_timer (0); -} - -/* - * Transform an MBUF chain into a single MBUF. - * This routine will fail if the amount of data in the - * chain overflows a transmit buffer. In that case, - * the incoming MBUF chain will be freed. This routine can - * also fail by not being able to allocate a new MBUF (including - * cluster and mbuf headers). In that case the failure is - * non-fatal. The incoming cluster chain is not freed, giving - * the caller the choice of whether to try a retransmit later. - */ -LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - void *skbnew; - int len = 0; - - if (len == 0) - return (LM_STATUS_SUCCESS); - - if (len > MAX_PACKET_SIZE) { - printf ("eth%d: xmit frame discarded, too big!, size = %d\n", - pUmDevice->index, len); - return (LM_STATUS_FAILURE); - } - - skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE); - - if (skbnew == NULL) { - pUmDevice->tx_full = 1; - printf ("eth%d: out of transmit buffers", pUmDevice->index); - return (LM_STATUS_FAILURE); - } - - /* New packet values */ - pUmPacket->skbuff = skbnew; - pUmPacket->lm_packet.u.Tx.FragCount = 1; - - return (LM_STATUS_SUCCESS); -} - -LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - pUmDevice->rx_pkt = 1; - return LM_STATUS_SUCCESS; -} - -LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice) -{ - PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; - PLM_PACKET pPacket; - PUM_PACKET pUmPacket; - void *skb; - while (TRUE) { - - pPacket = (PLM_PACKET) - QQ_PopHead (&pDevice->TxPacketXmittedQ.Container); - - if (pPacket == 0) - break; - - pUmPacket = (PUM_PACKET) pPacket; - skb = (void *)pUmPacket->skbuff; - - /* - * Free MBLK if we transmitted a fragmented packet or a - * non-fragmented packet straight from the VxWorks - * buffer pool. If packet was copied to a local transmit - * buffer, then there's no MBUF to free, just free - * the transmit buffer back to the cluster pool. - */ - - if (skb) - bcm570xPktFree (pUmDevice->index, skb); - - pUmPacket->skbuff = 0; - QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket); - pUmDevice->tx_pkt = 1; - } - if (pUmDevice->tx_full) { - if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >= - (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1)) - pUmDevice->tx_full = 0; - } - return LM_STATUS_SUCCESS; -} - -/* - * Scan an MBUF chain until we reach fragment number "frag" - * Return its length and physical address. - */ -void MM_MapTxDma - (PLM_DEVICE_BLOCK pDevice, - struct _LM_PACKET *pPacket, - T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) { - PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; - *len = pPacket->PacketSize; - MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff); -} - -/* - * Convert an mbuf address, a CPU local virtual address, - * to a physical address as seen from a PCI device. Store the - * result at paddr. - */ -void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice, - struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr) -{ - PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; - MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff); -} - -void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr) -{ -#if (BITS_PER_LONG == 64) - paddr->High = ((unsigned long)addr) >> 32; - paddr->Low = ((unsigned long)addr) & 0xffffffff; -#else - paddr->High = 0; - paddr->Low = (unsigned long)addr; -#endif -} - -void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr) -{ - unsigned long baddr = (unsigned long)addr; -#if (BITS_PER_LONG == 64) - set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32); -#else - set_64bit_addr (paddr, baddr, 0); -#endif -} - -/* - * This combination of `inline' and `extern' has almost the effect of a - * macro. The way to use it is to put a function definition in a header - * file with these keywords, and put another copy of the definition - * (lacking `inline' and `extern') in a library file. The definition in - * the header file will cause most calls to the function to be inlined. - * If any uses of the function remain, they will refer to the single copy - * in the library. - */ -void atomic_set (atomic_t * entry, int val) -{ - entry->counter = val; -} - -int atomic_read (atomic_t * entry) -{ - return entry->counter; -} - -void atomic_inc (atomic_t * entry) -{ - if (entry) - entry->counter++; -} - -void atomic_dec (atomic_t * entry) -{ - if (entry) - entry->counter--; -} - -void atomic_sub (int a, atomic_t * entry) -{ - if (entry) - entry->counter -= a; -} - -void atomic_add (int a, atomic_t * entry) -{ - if (entry) - entry->counter += a; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -void QQ_InitQueue (PQQ_CONTAINER pQueue, unsigned int QueueSize) -{ - pQueue->Head = 0; - pQueue->Tail = 0; - pQueue->Size = QueueSize + 1; - atomic_set (&pQueue->EntryCnt, 0); -} /* QQ_InitQueue */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -char QQ_Full (PQQ_CONTAINER pQueue) -{ - unsigned int NewHead; - - NewHead = (pQueue->Head + 1) % pQueue->Size; - - return (NewHead == pQueue->Tail); -} /* QQ_Full */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -char QQ_Empty (PQQ_CONTAINER pQueue) -{ - return (pQueue->Head == pQueue->Tail); -} /* QQ_Empty */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -unsigned int QQ_GetSize (PQQ_CONTAINER pQueue) -{ - return pQueue->Size; -} /* QQ_GetSize */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue) -{ - return atomic_read (&pQueue->EntryCnt); -} /* QQ_GetEntryCnt */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* TRUE entry was added successfully. */ -/* FALSE queue is full. */ -/******************************************************************************/ -char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) -{ - unsigned int Head; - - Head = (pQueue->Head + 1) % pQueue->Size; - -#if !defined(QQ_NO_OVERFLOW_CHECK) - if (Head == pQueue->Tail) { - return 0; - } /* if */ -#endif /* QQ_NO_OVERFLOW_CHECK */ - - pQueue->Array[pQueue->Head] = pEntry; - wmb (); - pQueue->Head = Head; - atomic_inc (&pQueue->EntryCnt); - - return -1; -} /* QQ_PushHead */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* TRUE entry was added successfully. */ -/* FALSE queue is full. */ -/******************************************************************************/ -char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) -{ - unsigned int Tail; - - Tail = pQueue->Tail; - if (Tail == 0) { - Tail = pQueue->Size; - } /* if */ - Tail--; - -#if !defined(QQ_NO_OVERFLOW_CHECK) - if (Tail == pQueue->Head) { - return 0; - } /* if */ -#endif /* QQ_NO_OVERFLOW_CHECK */ - - pQueue->Array[Tail] = pEntry; - wmb (); - pQueue->Tail = Tail; - atomic_inc (&pQueue->EntryCnt); - - return -1; -} /* QQ_PushTail */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue) -{ - unsigned int Head; - PQQ_ENTRY Entry; - - Head = pQueue->Head; - -#if !defined(QQ_NO_UNDERFLOW_CHECK) - if (Head == pQueue->Tail) { - return (PQQ_ENTRY) 0; - } /* if */ -#endif /* QQ_NO_UNDERFLOW_CHECK */ - - if (Head == 0) { - Head = pQueue->Size; - } /* if */ - Head--; - - Entry = pQueue->Array[Head]; - membar (); - - pQueue->Head = Head; - atomic_dec (&pQueue->EntryCnt); - - return Entry; -} /* QQ_PopHead */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue) -{ - unsigned int Tail; - PQQ_ENTRY Entry; - - Tail = pQueue->Tail; - -#if !defined(QQ_NO_UNDERFLOW_CHECK) - if (Tail == pQueue->Head) { - return (PQQ_ENTRY) 0; - } /* if */ -#endif /* QQ_NO_UNDERFLOW_CHECK */ - - Entry = pQueue->Array[Tail]; - membar (); - pQueue->Tail = (Tail + 1) % pQueue->Size; - atomic_dec (&pQueue->EntryCnt); - - return Entry; -} /* QQ_PopTail */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -PQQ_ENTRY QQ_GetHead (PQQ_CONTAINER pQueue, unsigned int Idx) -{ - if (Idx >= atomic_read (&pQueue->EntryCnt)) { - return (PQQ_ENTRY) 0; - } - - if (pQueue->Head > Idx) { - Idx = pQueue->Head - Idx; - } else { - Idx = pQueue->Size - (Idx - pQueue->Head); - } - Idx--; - - return pQueue->Array[Idx]; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -PQQ_ENTRY QQ_GetTail (PQQ_CONTAINER pQueue, unsigned int Idx) -{ - if (Idx >= atomic_read (&pQueue->EntryCnt)) { - return (PQQ_ENTRY) 0; - } - - Idx += pQueue->Tail; - if (Idx >= pQueue->Size) { - Idx = Idx - pQueue->Size; - } - - return pQueue->Array[Idx]; -} - -#endif diff --git a/drivers/bcm570x_autoneg.c b/drivers/bcm570x_autoneg.c deleted file mode 100644 index 9023796aa0..0000000000 --- a/drivers/bcm570x_autoneg.c +++ /dev/null @@ -1,439 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/******************************************************************************/ -#if !defined(CONFIG_NET_MULTI) -#if INCLUDE_TBI_SUPPORT -#include "bcm570x_autoneg.h" -#include "bcm570x_mm.h" - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -void -MM_AnTxConfig( - PAN_STATE_INFO pAnInfo) -{ - PLM_DEVICE_BLOCK pDevice; - - pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; - - REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT); - - pDevice->MacMode |= MAC_MODE_SEND_CONFIGS; - REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); -} - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -void -MM_AnTxIdle( - PAN_STATE_INFO pAnInfo) -{ - PLM_DEVICE_BLOCK pDevice; - - pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; - - pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS; - REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); -} - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -char -MM_AnRxConfig( - PAN_STATE_INFO pAnInfo, - unsigned short *pRxConfig) -{ - PLM_DEVICE_BLOCK pDevice; - LM_UINT32 Value32; - char Retcode; - - Retcode = AN_FALSE; - - pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; - - Value32 = REG_RD(pDevice, MacCtrl.Status); - if(Value32 & MAC_STATUS_RECEIVING_CFG) - { - Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg); - *pRxConfig = (unsigned short) Value32; - - Retcode = AN_TRUE; - } - - return Retcode; -} - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -void -AutonegInit( - PAN_STATE_INFO pAnInfo) -{ - unsigned long j; - - for(j = 0; j < sizeof(AN_STATE_INFO); j++) - { - ((unsigned char *) pAnInfo)[j] = 0; - } - - /* Initialize the default advertisement register. */ - pAnInfo->mr_adv_full_duplex = 1; - pAnInfo->mr_adv_sym_pause = 1; - pAnInfo->mr_adv_asym_pause = 1; - pAnInfo->mr_an_enable = 1; -} - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -AUTONEG_STATUS -Autoneg8023z( - PAN_STATE_INFO pAnInfo) -{ - unsigned short RxConfig; - unsigned long Delta_us; - AUTONEG_STATUS AnRet; - - /* Get the current time. */ - if(pAnInfo->State == AN_STATE_UNKNOWN) - { - pAnInfo->RxConfig.AsUSHORT = 0; - pAnInfo->CurrentTime_us = 0; - pAnInfo->LinkTime_us = 0; - pAnInfo->AbilityMatchCfg = 0; - pAnInfo->AbilityMatchCnt = 0; - pAnInfo->AbilityMatch = AN_FALSE; - pAnInfo->IdleMatch = AN_FALSE; - pAnInfo->AckMatch = AN_FALSE; - } - - /* Increment the timer tick. This function is called every microsecon. */ -/* pAnInfo->CurrentTime_us++; */ - - /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */ - /* corresponding conditions are satisfied. */ - if(MM_AnRxConfig(pAnInfo, &RxConfig)) - { - if(RxConfig != pAnInfo->AbilityMatchCfg) - { - pAnInfo->AbilityMatchCfg = RxConfig; - pAnInfo->AbilityMatch = AN_FALSE; - pAnInfo->AbilityMatchCnt = 0; - } - else - { - pAnInfo->AbilityMatchCnt++; - if(pAnInfo->AbilityMatchCnt > 1) - { - pAnInfo->AbilityMatch = AN_TRUE; - pAnInfo->AbilityMatchCfg = RxConfig; - } - } - - if(RxConfig & AN_CONFIG_ACK) - { - pAnInfo->AckMatch = AN_TRUE; - } - else - { - pAnInfo->AckMatch = AN_FALSE; - } - - pAnInfo->IdleMatch = AN_FALSE; - } - else - { - pAnInfo->IdleMatch = AN_TRUE; - - pAnInfo->AbilityMatchCfg = 0; - pAnInfo->AbilityMatchCnt = 0; - pAnInfo->AbilityMatch = AN_FALSE; - pAnInfo->AckMatch = AN_FALSE; - - RxConfig = 0; - } - - /* Save the last Config. */ - pAnInfo->RxConfig.AsUSHORT = RxConfig; - - /* Default return code. */ - AnRet = AUTONEG_STATUS_OK; - - /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */ - switch(pAnInfo->State) - { - case AN_STATE_UNKNOWN: - if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an) - { - pAnInfo->CurrentTime_us = 0; - pAnInfo->State = AN_STATE_AN_ENABLE; - } - - /* Fall through.*/ - - case AN_STATE_AN_ENABLE: - pAnInfo->mr_an_complete = AN_FALSE; - pAnInfo->mr_page_rx = AN_FALSE; - - if(pAnInfo->mr_an_enable) - { - pAnInfo->LinkTime_us = 0; - pAnInfo->AbilityMatchCfg = 0; - pAnInfo->AbilityMatchCnt = 0; - pAnInfo->AbilityMatch = AN_FALSE; - pAnInfo->IdleMatch = AN_FALSE; - pAnInfo->AckMatch = AN_FALSE; - - pAnInfo->State = AN_STATE_AN_RESTART_INIT; - } - else - { - pAnInfo->State = AN_STATE_DISABLE_LINK_OK; - } - break; - - case AN_STATE_AN_RESTART_INIT: - pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; - pAnInfo->mr_np_loaded = AN_FALSE; - - pAnInfo->TxConfig.AsUSHORT = 0; - MM_AnTxConfig(pAnInfo); - - AnRet = AUTONEG_STATUS_TIMER_ENABLED; - - pAnInfo->State = AN_STATE_AN_RESTART; - - /* Fall through.*/ - - case AN_STATE_AN_RESTART: - /* Get the current time and compute the delta with the saved */ - /* link timer. */ - Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; - if(Delta_us > AN_LINK_TIMER_INTERVAL_US) - { - pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT; - } - else - { - AnRet = AUTONEG_STATUS_TIMER_ENABLED; - } - break; - - case AN_STATE_DISABLE_LINK_OK: - AnRet = AUTONEG_STATUS_DONE; - break; - - case AN_STATE_ABILITY_DETECT_INIT: - /* Note: in the state diagram, this variable is set to */ - /* mr_adv_ability<12>. Is this right?. */ - pAnInfo->mr_toggle_tx = AN_FALSE; - - /* Send the config as advertised in the advertisement register. */ - pAnInfo->TxConfig.AsUSHORT = 0; - pAnInfo->TxConfig.D5_FD = pAnInfo->mr_adv_full_duplex; - pAnInfo->TxConfig.D6_HD = pAnInfo->mr_adv_half_duplex; - pAnInfo->TxConfig.D7_PS1 = pAnInfo->mr_adv_sym_pause; - pAnInfo->TxConfig.D8_PS2 = pAnInfo->mr_adv_asym_pause; - pAnInfo->TxConfig.D12_RF1 = pAnInfo->mr_adv_remote_fault1; - pAnInfo->TxConfig.D13_RF2 = pAnInfo->mr_adv_remote_fault2; - pAnInfo->TxConfig.D15_NP = pAnInfo->mr_adv_next_page; - - MM_AnTxConfig(pAnInfo); - - pAnInfo->State = AN_STATE_ABILITY_DETECT; - - break; - - case AN_STATE_ABILITY_DETECT: - if(pAnInfo->AbilityMatch == AN_TRUE && - pAnInfo->RxConfig.AsUSHORT != 0) - { - pAnInfo->State = AN_STATE_ACK_DETECT_INIT; - } - - break; - - case AN_STATE_ACK_DETECT_INIT: - pAnInfo->TxConfig.D14_ACK = 1; - MM_AnTxConfig(pAnInfo); - - pAnInfo->State = AN_STATE_ACK_DETECT; - - /* Fall through. */ - - case AN_STATE_ACK_DETECT: - if(pAnInfo->AckMatch == AN_TRUE) - { - if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) == - (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK)) - { - pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT; - } - else - { - pAnInfo->State = AN_STATE_AN_ENABLE; - } - } - else if(pAnInfo->AbilityMatch == AN_TRUE && - pAnInfo->RxConfig.AsUSHORT == 0) - { - pAnInfo->State = AN_STATE_AN_ENABLE; - } - - break; - - case AN_STATE_COMPLETE_ACK_INIT: - /* Make sure invalid bits are not set. */ - if(pAnInfo->RxConfig.bits.D0 || pAnInfo->RxConfig.bits.D1 || - pAnInfo->RxConfig.bits.D2 || pAnInfo->RxConfig.bits.D3 || - pAnInfo->RxConfig.bits.D4 || pAnInfo->RxConfig.bits.D9 || - pAnInfo->RxConfig.bits.D10 || pAnInfo->RxConfig.bits.D11) - { - AnRet = AUTONEG_STATUS_FAILED; - break; - } - - /* Set up the link partner advertisement register. */ - pAnInfo->mr_lp_adv_full_duplex = pAnInfo->RxConfig.D5_FD; - pAnInfo->mr_lp_adv_half_duplex = pAnInfo->RxConfig.D6_HD; - pAnInfo->mr_lp_adv_sym_pause = pAnInfo->RxConfig.D7_PS1; - pAnInfo->mr_lp_adv_asym_pause = pAnInfo->RxConfig.D8_PS2; - pAnInfo->mr_lp_adv_remote_fault1 = pAnInfo->RxConfig.D12_RF1; - pAnInfo->mr_lp_adv_remote_fault2 = pAnInfo->RxConfig.D13_RF2; - pAnInfo->mr_lp_adv_next_page = pAnInfo->RxConfig.D15_NP; - - pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; - - pAnInfo->mr_toggle_tx = !pAnInfo->mr_toggle_tx; - pAnInfo->mr_toggle_rx = pAnInfo->RxConfig.bits.D11; - pAnInfo->mr_np_rx = pAnInfo->RxConfig.D15_NP; - pAnInfo->mr_page_rx = AN_TRUE; - - pAnInfo->State = AN_STATE_COMPLETE_ACK; - AnRet = AUTONEG_STATUS_TIMER_ENABLED; - - break; - - case AN_STATE_COMPLETE_ACK: - if(pAnInfo->AbilityMatch == AN_TRUE && - pAnInfo->RxConfig.AsUSHORT == 0) - { - pAnInfo->State = AN_STATE_AN_ENABLE; - break; - } - - Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; - - if(Delta_us > AN_LINK_TIMER_INTERVAL_US) - { - if(pAnInfo->mr_adv_next_page == 0 || - pAnInfo->mr_lp_adv_next_page == 0) - { - pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; - } - else - { - if(pAnInfo->TxConfig.bits.D15 == 0 && - pAnInfo->mr_np_rx == 0) - { - pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; - } - else - { - AnRet = AUTONEG_STATUS_FAILED; - } - } - } - - break; - - case AN_STATE_IDLE_DETECT_INIT: - pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; - - MM_AnTxIdle(pAnInfo); - - pAnInfo->State = AN_STATE_IDLE_DETECT; - - AnRet = AUTONEG_STATUS_TIMER_ENABLED; - - break; - - case AN_STATE_IDLE_DETECT: - if(pAnInfo->AbilityMatch == AN_TRUE && - pAnInfo->RxConfig.AsUSHORT == 0) - { - pAnInfo->State = AN_STATE_AN_ENABLE; - break; - } - - Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; - if(Delta_us > AN_LINK_TIMER_INTERVAL_US) - { -#if 0 -/* if(pAnInfo->IdleMatch == AN_TRUE) */ -/* { */ -#endif - pAnInfo->State = AN_STATE_LINK_OK; -#if 0 -/* } */ -/* else */ -/* { */ -/* AnRet = AUTONEG_STATUS_FAILED; */ -/* break; */ -/* } */ -#endif - } - - break; - - case AN_STATE_LINK_OK: - pAnInfo->mr_an_complete = AN_TRUE; - pAnInfo->mr_link_ok = AN_TRUE; - AnRet = AUTONEG_STATUS_DONE; - - break; - - case AN_STATE_NEXT_PAGE_WAIT_INIT: - break; - - case AN_STATE_NEXT_PAGE_WAIT: - break; - - default: - AnRet = AUTONEG_STATUS_FAILED; - break; - } - - return AnRet; -} -#endif /* INCLUDE_TBI_SUPPORT */ - -#endif /* !defined(CONFIG_NET_MULTI) */ diff --git a/drivers/bcm570x_autoneg.h b/drivers/bcm570x_autoneg.h deleted file mode 100644 index 7830944b8a..0000000000 --- a/drivers/bcm570x_autoneg.h +++ /dev/null @@ -1,408 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/******************************************************************************/ - - -#ifndef AUTONEG_H -#define AUTONEG_H - - -/******************************************************************************/ -/* Constants. */ -/******************************************************************************/ - -#define AN_LINK_TIMER_INTERVAL_US 9000 /* 10ms */ - -/* TRUE, FALSE */ -#define AN_TRUE 1 -#define AN_FALSE 0 - - -/******************************************************************************/ -/* Main data structure for keeping track of 802.3z auto-negotation state */ -/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */ -/******************************************************************************/ - -typedef struct -{ - /* Current auto-negotiation state. */ - unsigned long State; - #define AN_STATE_UNKNOWN 0 - #define AN_STATE_AN_ENABLE 1 - #define AN_STATE_AN_RESTART_INIT 2 - #define AN_STATE_AN_RESTART 3 - #define AN_STATE_DISABLE_LINK_OK 4 - #define AN_STATE_ABILITY_DETECT_INIT 5 - #define AN_STATE_ABILITY_DETECT 6 - #define AN_STATE_ACK_DETECT_INIT 7 - #define AN_STATE_ACK_DETECT 8 - #define AN_STATE_COMPLETE_ACK_INIT 9 - #define AN_STATE_COMPLETE_ACK 10 - #define AN_STATE_IDLE_DETECT_INIT 11 - #define AN_STATE_IDLE_DETECT 12 - #define AN_STATE_LINK_OK 13 - #define AN_STATE_NEXT_PAGE_WAIT_INIT 14 - #define AN_STATE_NEXT_PAGE_WAIT 16 - - /* Link timer. */ - unsigned long LinkTime_us; - - /* Current time. */ - unsigned long CurrentTime_us; - - /* Need these values for consistency check. */ - unsigned short AbilityMatchCfg; - - /* Ability, idle, and ack match functions. */ - unsigned long AbilityMatchCnt; - char AbilityMatch; - char IdleMatch; - char AckMatch; - - /* Tx config data */ - union - { - /* The TxConfig register is arranged as follows: */ - /* */ - /* MSB LSB */ - /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ - /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ - /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ - struct - { -#ifdef BIG_ENDIAN_HOST - unsigned int D7:1; /* PS1 */ - unsigned int D6:1; /* HD */ - unsigned int D5:1; /* FD */ - unsigned int D4:1; - unsigned int D3:1; - unsigned int D2:1; - unsigned int D1:1; - unsigned int D0:1; - unsigned int D15:1; /* NP */ - unsigned int D14:1; /* ACK */ - unsigned int D13:1; /* RF2 */ - unsigned int D12:1; /* RF1 */ - unsigned int D11:1; - unsigned int D10:1; - unsigned int D9:1; - unsigned int D8:1; /* PS2 */ -#else /* BIG_ENDIAN_HOST */ - unsigned int D8:1; /* PS2 */ - unsigned int D9:1; - unsigned int D10:1; - unsigned int D11:1; - unsigned int D12:1; /* RF1 */ - unsigned int D13:1; /* RF2 */ - unsigned int D14:1; /* ACK */ - unsigned int D15:1; /* NP */ - unsigned int D0:1; - unsigned int D1:1; - unsigned int D2:1; - unsigned int D3:1; - unsigned int D4:1; - unsigned int D5:1; /* FD */ - unsigned int D6:1; /* HD */ - unsigned int D7:1; /* PS1 */ -#endif - } bits; - - unsigned short AsUSHORT; - - #define D8_PS2 bits.D8 - #define D12_RF1 bits.D12 - #define D13_RF2 bits.D13 - #define D14_ACK bits.D14 - #define D15_NP bits.D15 - #define D5_FD bits.D5 - #define D6_HD bits.D6 - #define D7_PS1 bits.D7 - } TxConfig; - - /* Rx config data */ - union - { - /* The RxConfig register is arranged as follows: */ - /* */ - /* MSB LSB */ - /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ - /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ - /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ - struct - { -#ifdef BIG_ENDIAN_HOST - unsigned int D7:1; /* PS1 */ - unsigned int D6:1; /* HD */ - unsigned int D5:1; /* FD */ - unsigned int D4:1; - unsigned int D3:1; - unsigned int D2:1; - unsigned int D1:1; - unsigned int D0:1; - unsigned int D15:1; /* NP */ - unsigned int D14:1; /* ACK */ - unsigned int D13:1; /* RF2 */ - unsigned int D12:1; /* RF1 */ - unsigned int D11:1; - unsigned int D10:1; - unsigned int D9:1; - unsigned int D8:1; /* PS2 */ -#else /* BIG_ENDIAN_HOST */ - unsigned int D8:1; /* PS2 */ - unsigned int D9:1; - unsigned int D10:1; - unsigned int D11:1; - unsigned int D12:1; /* RF1 */ - unsigned int D13:1; /* RF2 */ - unsigned int D14:1; /* ACK */ - unsigned int D15:1; /* NP */ - unsigned int D0:1; - unsigned int D1:1; - unsigned int D2:1; - unsigned int D3:1; - unsigned int D4:1; - unsigned int D5:1; /* FD */ - unsigned int D6:1; /* HD */ - unsigned int D7:1; /* PS1 */ -#endif - } bits; - - unsigned short AsUSHORT; - } RxConfig; - - #define AN_CONFIG_NP 0x0080 - #define AN_CONFIG_ACK 0x0040 - #define AN_CONFIG_RF2 0x0020 - #define AN_CONFIG_RF1 0x0010 - #define AN_CONFIG_PS2 0x0001 - #define AN_CONFIG_PS1 0x8000 - #define AN_CONFIG_HD 0x4000 - #define AN_CONFIG_FD 0x2000 - - - /* Management registers. */ - - /* Control register. */ - union - { - struct - { - unsigned int an_enable:1; - unsigned int loopback:1; - unsigned int reset:1; - unsigned int restart_an:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_an_enable Mr0.bits.an_enable - #define mr_loopback Mr0.bits.loopback - #define mr_main_reset Mr0.bits.reset - #define mr_restart_an Mr0.bits.restart_an - } Mr0; - - /* Status register. */ - union - { - struct - { - unsigned int an_complete:1; - unsigned int link_ok:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_an_complete Mr1.bits.an_complete - #define mr_link_ok Mr1.bits.link_ok - } Mr1; - - /* Advertisement register. */ - union - { - struct - { - unsigned int reserved_4:5; - unsigned int full_duplex:1; - unsigned int half_duplex:1; - unsigned int sym_pause:1; - unsigned int asym_pause:1; - unsigned int reserved_11:3; - unsigned int remote_fault1:1; - unsigned int remote_fault2:1; - unsigned int reserved_14:1; - unsigned int next_page:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_adv_full_duplex Mr4.bits.full_duplex - #define mr_adv_half_duplex Mr4.bits.half_duplex - #define mr_adv_sym_pause Mr4.bits.sym_pause - #define mr_adv_asym_pause Mr4.bits.asym_pause - #define mr_adv_remote_fault1 Mr4.bits.remote_fault1 - #define mr_adv_remote_fault2 Mr4.bits.remote_fault2 - #define mr_adv_next_page Mr4.bits.next_page - } Mr4; - - /* Link partner advertisement register. */ - union - { - struct - { - unsigned int reserved_4:5; - unsigned int lp_full_duplex:1; - unsigned int lp_half_duplex:1; - unsigned int lp_sym_pause:1; - unsigned int lp_asym_pause:1; - unsigned int reserved_11:3; - unsigned int lp_remote_fault1:1; - unsigned int lp_remote_fault2:1; - unsigned int lp_ack:1; - unsigned int lp_next_page:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_lp_adv_full_duplex Mr5.bits.lp_full_duplex - #define mr_lp_adv_half_duplex Mr5.bits.lp_half_duplex - #define mr_lp_adv_sym_pause Mr5.bits.lp_sym_pause - #define mr_lp_adv_asym_pause Mr5.bits.lp_asym_pause - #define mr_lp_adv_remote_fault1 Mr5.bits.lp_remote_fault1 - #define mr_lp_adv_remote_fault2 Mr5.bits.lp_remote_fault2 - #define mr_lp_adv_next_page Mr5.bits.lp_next_page - } Mr5; - - /* Auto-negotiation expansion register. */ - union - { - struct - { - unsigned int reserved_0:1; - unsigned int page_received:1; - unsigned int next_pageable:1; - unsigned int reserved_15:13; - } bits; - - unsigned short AsUSHORT; - } Mr6; - - /* Auto-negotiation next page transmit register. */ - union - { - struct - { - unsigned int code_field:11; - unsigned int toggle:1; - unsigned int ack2:1; - unsigned int message_page:1; - unsigned int reserved_14:1; - unsigned int next_page:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_np_tx Mr7.AsUSHORT - } Mr7; - - /* Auto-negotiation link partner ability register. */ - union - { - struct - { - unsigned int code_field:11; - unsigned int toggle:1; - unsigned int ack2:1; - unsigned int message_page:1; - unsigned int ack:1; - unsigned int next_page:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_lp_np_rx Mr8.AsUSHORT - } Mr8; - - /* Extended status register. */ - union - { - struct - { - unsigned int reserved_11:12; - unsigned int base1000_t_hd:1; - unsigned int base1000_t_fd:1; - unsigned int base1000_x_hd:1; - unsigned int base1000_x_fd:1; - } bits; - - unsigned short AsUSHORT; - } Mr15; - - /* Miscellaneous state variables. */ - union - { - struct - { - unsigned int toggle_tx:1; - unsigned int toggle_rx:1; - unsigned int np_rx:1; - unsigned int page_rx:1; - unsigned int np_loaded:1; - } bits; - - unsigned short AsUSHORT; - - #define mr_toggle_tx MrMisc.bits.toggle_tx - #define mr_toggle_rx MrMisc.bits.toggle_rx - #define mr_np_rx MrMisc.bits.np_rx - #define mr_page_rx MrMisc.bits.page_rx - #define mr_np_loaded MrMisc.bits.np_loaded - } MrMisc; - - - /* Implement specifics */ - - /* Pointer to the operating system specific data structure. */ - void *pContext; -} AN_STATE_INFO, *PAN_STATE_INFO; - - -/******************************************************************************/ -/* Return code of Autoneg8023z. */ -/******************************************************************************/ - -typedef enum -{ - AUTONEG_STATUS_OK = 0, - AUTONEG_STATUS_DONE = 1, - AUTONEG_STATUS_TIMER_ENABLED = 2, - AUTONEG_STATUS_FAILED = 0xfffffff -} AUTONEG_STATUS, *PAUTONEG_STATUS; - - -/******************************************************************************/ -/* Function prototypes. */ -/******************************************************************************/ - -AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo); -void AutonegInit(PAN_STATE_INFO pAnInfo); - - -/******************************************************************************/ -/* The following functions are defined in the os-dependent module. */ -/******************************************************************************/ - -void MM_AnTxConfig(PAN_STATE_INFO pAnInfo); -void MM_AnTxIdle(PAN_STATE_INFO pAnInfo); -char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig); - - -#endif /* AUTONEG_H */ diff --git a/drivers/bcm570x_bits.h b/drivers/bcm570x_bits.h deleted file mode 100644 index 615d61e98b..0000000000 --- a/drivers/bcm570x_bits.h +++ /dev/null @@ -1,57 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* 02/25/00 Hav Khauv Initial version. */ -/******************************************************************************/ - -#ifndef BITS_H -#define BITS_H - - -/******************************************************************************/ -/* Bit Mask definitions */ -/******************************************************************************/ -#define BIT_NONE 0x00 -#define BIT_0 0x01 -#define BIT_1 0x02 -#define BIT_2 0x04 -#define BIT_3 0x08 -#define BIT_4 0x10 -#define BIT_5 0x20 -#define BIT_6 0x40 -#define BIT_7 0x80 -#define BIT_8 0x0100 -#define BIT_9 0x0200 -#define BIT_10 0x0400 -#define BIT_11 0x0800 -#define BIT_12 0x1000 -#define BIT_13 0x2000 -#define BIT_14 0x4000 -#define BIT_15 0x8000 -#define BIT_16 0x010000 -#define BIT_17 0x020000 -#define BIT_18 0x040000 -#define BIT_19 0x080000 -#define BIT_20 0x100000 -#define BIT_21 0x200000 -#define BIT_22 0x400000 -#define BIT_23 0x800000 -#define BIT_24 0x01000000 -#define BIT_25 0x02000000 -#define BIT_26 0x04000000 -#define BIT_27 0x08000000 -#define BIT_28 0x10000000 -#define BIT_29 0x20000000 -#define BIT_30 0x40000000 -#define BIT_31 0x80000000 - -#endif /* BITS_H */ diff --git a/drivers/bcm570x_debug.h b/drivers/bcm570x_debug.h deleted file mode 100644 index 88e209b0fb..0000000000 --- a/drivers/bcm570x_debug.h +++ /dev/null @@ -1,109 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* 02/25/00 Hav Khauv Initial version. */ -/******************************************************************************/ - -#ifndef DEBUG_H -#define DEBUG_H - -#ifdef VXWORKS -#include -#endif - -/******************************************************************************/ -/* Debug macros */ -/******************************************************************************/ - -/* Code path for controlling output debug messages. */ -/* Define your code path here. */ -#define CP_INIT 0x010000 -#define CP_SEND 0x020000 -#define CP_RCV 0x040000 -#define CP_INT 0x080000 -#define CP_UINIT 0x100000 -#define CP_RESET 0x200000 - -#define CP_ALL (CP_INIT | CP_SEND | CP_RCV | CP_INT | \ - CP_RESET | CP_UINIT) - -#define CP_MASK 0xffff0000 - - -/* Debug message levels. */ -#define LV_VERBOSE 0x03 -#define LV_INFORM 0x02 -#define LV_WARN 0x01 -#define LV_FATAL 0x00 - -#define LV_MASK 0xffff - - -/* Code path and messsage level combined. These are the first argument of */ -/* the DbgMessage macro. */ -#define INIT_V (CP_INIT | LV_VERBOSE) -#define INIT_I (CP_INIT | LV_INFORM) -#define INIT_W (CP_INIT | LV_WARN) -#define SEND_V (CP_SEND | LV_VERBOSE) -#define SEND_I (CP_SEND | LV_INFORM) -#define SEND_W (CP_SEND | LV_WARN) -#define RCV_V (CP_RCV | LV_VERBOSE) -#define RCV_I (CP_RCV | LV_INFORM) -#define RCV_W (CP_RCV | LV_WARN) -#define INT_V (CP_INT | LV_VERBOSE) -#define INT_I (CP_INT | LV_INFORM) -#define INT_W (CP_INT | LV_WARN) -#define UINIT_V (CP_UINIT | LV_VERBOSE) -#define UINIT_I (CP_UINIT | LV_INFORM) -#define UINIT_W (CP_UINIT | LV_WARN) -#define RESET_V (CP_RESET | LV_VERBOSE) -#define RESET_I (CP_RESET | LV_INFORM) -#define RESET_W (CP_RESET | LV_WARN) -#define CPALL_V (CP_ALL | LV_VERBOSE) -#define CPALL_I (CP_ALL | LV_INFORM) -#define CPALL_W (CP_ALL | LV_WARN) - - -/* All code path message levels. */ -#define FATAL (CP_ALL | LV_FATAL) -#define WARN (CP_ALL | LV_WARN) -#define INFORM (CP_ALL | LV_INFORM) -#define VERBOSE (CP_ALL | LV_VERBOSE) - - -/* These constants control the message output. */ -/* Set your debug message output level and code path here. */ -#ifndef DBG_MSG_CP -#define DBG_MSG_CP CP_ALL /* Where to output messages. */ -#endif - -#ifndef DBG_MSG_LV -#define DBG_MSG_LV LV_VERBOSE /* Level of message output. */ -#endif - -/* DbgMessage macro. */ -#if DBG -#define DbgMessage(CNTRL, MESSAGE) \ - if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \ - printf MESSAGE -#define DbgBreak() DbgBreakPoint() -#undef STATIC -#define STATIC -#else -#define DbgMessage(CNTRL, MESSAGE) -#define DbgBreak() -#undef STATIC -#define STATIC static -#endif /* DBG */ - - -#endif /* DEBUG_H */ diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h deleted file mode 100644 index 2ea6ca8fa9..0000000000 --- a/drivers/bcm570x_lm.h +++ /dev/null @@ -1,434 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* 02/25/00 Hav Khauv Initial version. */ -/******************************************************************************/ - -#ifndef LM_H -#define LM_H - -#include "bcm570x_queue.h" -#include "bcm570x_bits.h" - -/******************************************************************************/ -/* Basic types. */ -/******************************************************************************/ - -typedef char LM_CHAR, *PLM_CHAR; -typedef unsigned int LM_UINT, *PLM_UINT; -typedef unsigned char LM_UINT8, *PLM_UINT8; -typedef unsigned short LM_UINT16, *PLM_UINT16; -typedef unsigned int LM_UINT32, *PLM_UINT32; -typedef unsigned int LM_COUNTER, *PLM_COUNTER; -typedef void LM_VOID, *PLM_VOID; -typedef char LM_BOOL, *PLM_BOOL; - -/* 64bit value. */ -typedef struct { -#ifdef BIG_ENDIAN_HOST - LM_UINT32 High; - LM_UINT32 Low; -#else /* BIG_ENDIAN_HOST */ - LM_UINT32 Low; - LM_UINT32 High; -#endif /* !BIG_ENDIAN_HOST */ -} LM_UINT64, *PLM_UINT64; - -typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS; - -/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */ -#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize) \ - { \ - LM_UINT32 OrgLow; \ - \ - OrgLow = (pAddr)->Low; \ - (pAddr)->Low += IncSize; \ - if((pAddr)->Low < OrgLow) { \ - (pAddr)->High++; /* Wrap around. */ \ - } \ - } - -#ifndef NULL -#define NULL ((void *) 0) -#endif /* NULL */ - -#ifndef OFFSETOF -#define OFFSETOF(_s, _m) (MM_UINT_PTR(&(((_s *) 0)->_m))) -#endif /* OFFSETOF */ - -/******************************************************************************/ -/* Simple macros. */ -/******************************************************************************/ - -#define IS_ETH_BROADCAST(_pEthAddr) \ - (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff)) - -#define IS_ETH_MULTICAST(_pEthAddr) \ - (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01)) - -#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2) \ - ((((unsigned char *) (_pEtherAddr1))[0] == \ - ((unsigned char *) (_pEtherAddr2))[0]) && \ - (((unsigned char *) (_pEtherAddr1))[1] == \ - ((unsigned char *) (_pEtherAddr2))[1]) && \ - (((unsigned char *) (_pEtherAddr1))[2] == \ - ((unsigned char *) (_pEtherAddr2))[2]) && \ - (((unsigned char *) (_pEtherAddr1))[3] == \ - ((unsigned char *) (_pEtherAddr2))[3]) && \ - (((unsigned char *) (_pEtherAddr1))[4] == \ - ((unsigned char *) (_pEtherAddr2))[4]) && \ - (((unsigned char *) (_pEtherAddr1))[5] == \ - ((unsigned char *) (_pEtherAddr2))[5])) - -#define COPY_ETH_ADDRESS(_Src, _Dst) \ - ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0]; \ - ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1]; \ - ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2]; \ - ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3]; \ - ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4]; \ - ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5]; - -/******************************************************************************/ -/* Constants. */ -/******************************************************************************/ - -#define ETHERNET_ADDRESS_SIZE 6 -#define ETHERNET_PACKET_HEADER_SIZE 14 -#define MIN_ETHERNET_PACKET_SIZE 64 /* with 4 byte crc. */ -#define MAX_ETHERNET_PACKET_SIZE 1518 /* with 4 byte crc. */ -#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60 -#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514 -#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536 /* A nice even number. */ - -#ifndef LM_MAX_MC_TABLE_SIZE -#define LM_MAX_MC_TABLE_SIZE 32 -#endif /* LM_MAX_MC_TABLE_SIZE */ -#define LM_MC_ENTRY_SIZE (ETHERNET_ADDRESS_SIZE+1) -#define LM_MC_INSTANCE_COUNT_INDEX (LM_MC_ENTRY_SIZE-1) - -/* Receive filter masks. */ -#define LM_ACCEPT_UNICAST 0x0001 -#define LM_ACCEPT_MULTICAST 0x0002 -#define LM_ACCEPT_ALL_MULTICAST 0x0004 -#define LM_ACCEPT_BROADCAST 0x0008 -#define LM_ACCEPT_ERROR_PACKET 0x0010 - -#define LM_PROMISCUOUS_MODE 0x10000 - -/******************************************************************************/ -/* PCI registers. */ -/******************************************************************************/ - -#define PCI_VENDOR_ID_REG 0x00 -#define PCI_DEVICE_ID_REG 0x02 - -#define PCI_COMMAND_REG 0x04 -#define PCI_IO_SPACE_ENABLE 0x0001 -#define PCI_MEM_SPACE_ENABLE 0x0002 -#define PCI_BUSMASTER_ENABLE 0x0004 -#define PCI_MEMORY_WRITE_INVALIDATE 0x0010 -#define PCI_PARITY_ERROR_ENABLE 0x0040 -#define PCI_SYSTEM_ERROR_ENABLE 0x0100 -#define PCI_FAST_BACK_TO_BACK_ENABLE 0x0200 - -#define PCI_STATUS_REG 0x06 -#define PCI_REV_ID_REG 0x08 - -#define PCI_CACHE_LINE_SIZE_REG 0x0c - -#define PCI_IO_BASE_ADDR_REG 0x10 -#define PCI_IO_BASE_ADDR_MASK 0xfffffff0 - -#define PCI_MEM_BASE_ADDR_LOW 0x10 -#define PCI_MEM_BASE_ADDR_HIGH 0x14 - -#define PCI_SUBSYSTEM_VENDOR_ID_REG 0x2c -#define PCI_SUBSYSTEM_ID_REG 0x2e -#define PCI_INT_LINE_REG 0x3c - -#define PCIX_CAP_REG 0x40 -#define PCIX_ENABLE_RELAXED_ORDERING BIT_17 - -/******************************************************************************/ -/* Fragment structure. */ -/******************************************************************************/ - -typedef struct { - LM_UINT32 FragSize; - LM_PHYSICAL_ADDRESS FragBuf; -} LM_FRAG, *PLM_FRAG; - -typedef struct { - /* FragCount is initialized for the caller to the maximum array size, on */ - /* return FragCount is the number of the actual fragments in the array. */ - LM_UINT32 FragCount; - - /* Total buffer size. */ - LM_UINT32 TotalSize; - - /* Fragment array buffer. */ - LM_FRAG Fragments[1]; -} LM_FRAG_LIST, *PLM_FRAG_LIST; - -#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \ - typedef struct { \ - LM_FRAG_LIST FragList; \ - LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1]; \ - } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME - -/******************************************************************************/ -/* Status codes. */ -/******************************************************************************/ - -#define LM_STATUS_SUCCESS 0 -#define LM_STATUS_FAILURE 1 - -#define LM_STATUS_INTERRUPT_ACTIVE 2 -#define LM_STATUS_INTERRUPT_NOT_ACTIVE 3 - -#define LM_STATUS_LINK_ACTIVE 4 -#define LM_STATUS_LINK_DOWN 5 -#define LM_STATUS_LINK_SETTING_MISMATCH 6 - -#define LM_STATUS_TOO_MANY_FRAGMENTS 7 -#define LM_STATUS_TRANSMIT_ABORTED 8 -#define LM_STATUS_TRANSMIT_ERROR 9 -#define LM_STATUS_RECEIVE_ABORTED 10 -#define LM_STATUS_RECEIVE_ERROR 11 -#define LM_STATUS_INVALID_PACKET_SIZE 12 -#define LM_STATUS_OUT_OF_MAP_REGISTERS 13 -#define LM_STATUS_UNKNOWN_ADAPTER 14 - -typedef LM_UINT LM_STATUS, *PLM_STATUS; - -/******************************************************************************/ -/* Requested media type. */ -/******************************************************************************/ - -#define LM_REQUESTED_MEDIA_TYPE_AUTO 0 -#define LM_REQUESTED_MEDIA_TYPE_BNC 1 -#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO 2 -#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS 3 -#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX 4 -#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS 5 -#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX 6 -#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS 7 -#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX 8 -#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS 9 -#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX 10 -#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS 11 -#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX 12 -#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK 0xfffe -#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK 0xffff - -typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE; - -/******************************************************************************/ -/* Media type. */ -/******************************************************************************/ - -#define LM_MEDIA_TYPE_UNKNOWN -1 -#define LM_MEDIA_TYPE_AUTO 0 -#define LM_MEDIA_TYPE_UTP 1 -#define LM_MEDIA_TYPE_BNC 2 -#define LM_MEDIA_TYPE_AUI 3 -#define LM_MEDIA_TYPE_FIBER 4 - -typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE; - -/******************************************************************************/ -/* Line speed. */ -/******************************************************************************/ - -#define LM_LINE_SPEED_UNKNOWN 0 -#define LM_LINE_SPEED_10MBPS 1 -#define LM_LINE_SPEED_100MBPS 2 -#define LM_LINE_SPEED_1000MBPS 3 - -typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED; - -/******************************************************************************/ -/* Duplex mode. */ -/******************************************************************************/ - -#define LM_DUPLEX_MODE_UNKNOWN 0 -#define LM_DUPLEX_MODE_HALF 1 -#define LM_DUPLEX_MODE_FULL 2 - -typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE; - -/******************************************************************************/ -/* Power state. */ -/******************************************************************************/ - -#define LM_POWER_STATE_D0 0 -#define LM_POWER_STATE_D1 1 -#define LM_POWER_STATE_D2 2 -#define LM_POWER_STATE_D3 3 - -typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE; - -/******************************************************************************/ -/* Task offloading. */ -/******************************************************************************/ - -#define LM_TASK_OFFLOAD_NONE 0x0000 -#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM 0x0001 -#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM 0x0002 -#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM 0x0004 -#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM 0x0008 -#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM 0x0010 -#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM 0x0020 -#define LM_TASK_OFFLOAD_TCP_SEGMENTATION 0x0040 - -typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD; - -/******************************************************************************/ -/* Flow control. */ -/******************************************************************************/ - -#define LM_FLOW_CONTROL_NONE 0x00 -#define LM_FLOW_CONTROL_RECEIVE_PAUSE 0x01 -#define LM_FLOW_CONTROL_TRANSMIT_PAUSE 0x02 -#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \ - LM_FLOW_CONTROL_TRANSMIT_PAUSE) - -/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE. If the */ -/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */ -/* bits are set, then flow control is enabled regardless of link partner's */ -/* flow control capability. */ -#define LM_FLOW_CONTROL_AUTO_PAUSE 0x80000000 - -typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL; - -/******************************************************************************/ -/* Wake up mode. */ -/******************************************************************************/ - -#define LM_WAKE_UP_MODE_NONE 0 -#define LM_WAKE_UP_MODE_MAGIC_PACKET 1 -#define LM_WAKE_UP_MODE_NWUF 2 -#define LM_WAKE_UP_MODE_LINK_CHANGE 4 - -typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE; - -/******************************************************************************/ -/* Counters. */ -/******************************************************************************/ - -#define LM_COUNTER_FRAMES_XMITTED_OK 0 -#define LM_COUNTER_FRAMES_RECEIVED_OK 1 -#define LM_COUNTER_ERRORED_TRANSMIT_COUNT 2 -#define LM_COUNTER_ERRORED_RECEIVE_COUNT 3 -#define LM_COUNTER_RCV_CRC_ERROR 4 -#define LM_COUNTER_ALIGNMENT_ERROR 5 -#define LM_COUNTER_SINGLE_COLLISION_FRAMES 6 -#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES 7 -#define LM_COUNTER_FRAMES_DEFERRED 8 -#define LM_COUNTER_MAX_COLLISIONS 9 -#define LM_COUNTER_RCV_OVERRUN 10 -#define LM_COUNTER_XMIT_UNDERRUN 11 -#define LM_COUNTER_UNICAST_FRAMES_XMIT 12 -#define LM_COUNTER_MULTICAST_FRAMES_XMIT 13 -#define LM_COUNTER_BROADCAST_FRAMES_XMIT 14 -#define LM_COUNTER_UNICAST_FRAMES_RCV 15 -#define LM_COUNTER_MULTICAST_FRAMES_RCV 16 -#define LM_COUNTER_BROADCAST_FRAMES_RCV 17 - -typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE; - -/******************************************************************************/ -/* Forward definition. */ -/******************************************************************************/ - -typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK; -typedef struct _LM_PACKET *PLM_PACKET; - -/******************************************************************************/ -/* Function prototypes. */ -/******************************************************************************/ - -LM_STATUS LM_GetAdapterInfo (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_InitializeAdapter (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_DisableInterrupt (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_EnableInterrupt (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); -LM_STATUS LM_ServiceInterrupts (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask); -LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); -LM_STATUS LM_MulticastDel (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); -LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_SetMacAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress); -LM_STATUS LM_LoopbackAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress); - -LM_UINT32 LM_GetCrcCounter (PLM_DEVICE_BLOCK pDevice); - -LM_WAKE_UP_MODE LM_PMCapabilities (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_NwufAdd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, - LM_UINT8 * pByteMask, LM_UINT8 * pPattern); -LM_STATUS LM_NwufRemove (PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, - LM_UINT8 * pByteMask, LM_UINT8 * pPattern); -LM_STATUS LM_SetPowerState (PLM_DEVICE_BLOCK pDevice, - LM_POWER_STATE PowerLevel); - -LM_VOID LM_ReadPhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, - PLM_UINT32 pData32); -LM_VOID LM_WritePhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, - LM_UINT32 Data32); - -LM_STATUS LM_ControlLoopBack (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control); -LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice); -int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration); - -/******************************************************************************/ -/* These are the OS specific functions called by LMAC. */ -/******************************************************************************/ - -LM_STATUS MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT16 * pValue16); -LM_STATUS MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT16 Value16); -LM_STATUS MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT32 * pValue32); -LM_STATUS MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, - LM_UINT32 Value32); -LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_MapIoBase (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); -LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); -LM_STATUS MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, - PLM_VOID * pMemoryBlockVirt); -LM_STATUS MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, - LM_UINT32 BlockSize, - PLM_VOID * pMemoryBlockVirt, - PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, - LM_BOOL Cached); -LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status); -LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice); -LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); -LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); -LM_STATUS LM_MbufWorkAround (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_SetLinkSpeed (PLM_DEVICE_BLOCK pDevice, - LM_REQUESTED_MEDIA_TYPE RequestedMediaType); - -#if INCLUDE_5703_A0_FIX -LM_STATUS LM_Load5703DmaWFirmware (PLM_DEVICE_BLOCK pDevice); -#endif - -#endif /* LM_H */ diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h deleted file mode 100644 index ff5302f47c..0000000000 --- a/drivers/bcm570x_mm.h +++ /dev/null @@ -1,158 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/******************************************************************************/ - -#ifndef MM_H -#define MM_H - -#define __raw_readl readl -#define __raw_writel writel - -#define BIG_ENDIAN_HOST 1 -#define readl(addr) (*(volatile unsigned int*)(addr)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) - -/* Define memory barrier function here if needed */ -#define wmb() -#define membar() -#include -#include -#include "bcm570x_lm.h" -#include "bcm570x_queue.h" -#include "tigon3.h" -#include - -#define FALSE 0 -#define TRUE 1 -#define ERROR -1 - -#if DBG -#define STATIC -#else -#define STATIC static -#endif - -extern int MM_Packet_Desc_Size; - -#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size - -DECLARE_QUEUE_TYPE (UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT + 1); - -#define MAX_MEM 16 - -/* Synch */ -typedef int mutex_t; -typedef int spinlock_t; - -/* Embedded device control */ -typedef struct _UM_DEVICE_BLOCK { - LM_DEVICE_BLOCK lm_dev; - pci_dev_t pdev; - char *name; - void *mem_list[MAX_MEM]; - dma_addr_t dma_list[MAX_MEM]; - int mem_size_list[MAX_MEM]; - int mem_list_num; - int mtu; - int index; - int opened; - int delayed_link_ind; /* Delay link status during initial load */ - int adapter_just_inited; /* the first few seconds after init. */ - int spurious_int; /* new -- unsupported */ - int timer_interval; - int adaptive_expiry; - int crc_counter_expiry; /* new -- unsupported */ - int poll_tib_expiry; /* new -- unsupported */ - int tx_full; - int tx_queued; - int line_speed; /* in Mbps, 0 if link is down */ - UM_RX_PACKET_Q rx_out_of_buf_q; - int rx_out_of_buf; - int rx_low_buf_thresh; /* changed to rx_buf_repl_thresh */ - int rx_buf_repl_panic_thresh; - int rx_buf_align; /* new -- unsupported */ - int do_global_lock; - mutex_t global_lock; - mutex_t undi_lock; - long undi_flags; - volatile int interrupt; - int tasklet_pending; - int tasklet_busy; /* new -- unsupported */ - int rx_pkt; - int tx_pkt; -#ifdef NICE_SUPPORT /* unsupported, this is a linux ioctl */ - void (*nice_rx) (void *, void *); - void *nice_ctx; -#endif /* NICE_SUPPORT */ - int rx_adaptive_coalesce; - unsigned int rx_last_cnt; - unsigned int tx_last_cnt; - unsigned int rx_curr_coalesce_frames; - unsigned int rx_curr_coalesce_ticks; - unsigned int tx_curr_coalesce_frames; /* new -- unsupported */ -#if TIGON3_DEBUG /* new -- unsupported */ - uint tx_zc_count; - uint tx_chksum_count; - uint tx_himem_count; - uint rx_good_chksum_count; -#endif - unsigned int rx_bad_chksum_count; /* new -- unsupported */ - unsigned int rx_misc_errors; /* new -- unsupported */ -} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK; - -/* Physical/PCI DMA address */ -typedef union { - dma_addr_t dma_map; -} dma_map_t; - -/* Packet */ -typedef struct - _UM_PACKET { - LM_PACKET lm_packet; - void *skbuff; /* Address of packet buffer */ -} UM_PACKET, *PUM_PACKET; - -#define MM_ACQUIRE_UNDI_LOCK(_pDevice) -#define MM_RELEASE_UNDI_LOCK(_pDevice) -#define MM_ACQUIRE_INT_LOCK(_pDevice) -#define MM_RELEASE_INT_LOCK(_pDevice) -#define MM_UINT_PTR(_ptr) ((unsigned long) (_ptr)) - -/* Macro for setting 64bit address struct */ -#define set_64bit_addr(paddr, low, high) \ - (paddr)->Low = low; \ - (paddr)->High = high; - -/* Assume that PCI controller's view of host memory is same as host */ - -#define MEM_TO_PCI_PHYS(addr) (addr) - -extern void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr); -extern void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr); -extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice, - struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr, - LM_UINT32 * len, int frag); -extern void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice, - struct _LM_PACKET *pPacket, - T3_64BIT_HOST_ADDR * paddr); - -/* BSP needs to provide sysUsecDelay and sysSerialPrintString */ -extern void sysSerialPrintString (char *s); -#define MM_Wait(usec) udelay(usec) - -/* Define memory barrier function here if needed */ -#define wmb() - -#if 0 -#define cpu_to_le32(val) LONGSWAP(val) -#endif -#endif /* MM_H */ diff --git a/drivers/bcm570x_queue.h b/drivers/bcm570x_queue.h deleted file mode 100644 index 336b3caa4a..0000000000 --- a/drivers/bcm570x_queue.h +++ /dev/null @@ -1,387 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* Queue functions. */ -/* void QQ_InitQueue(PQQ_CONTAINER pQueue) */ -/* char QQ_Full(PQQ_CONTAINER pQueue) */ -/* char QQ_Empty(PQQ_CONTAINER pQueue) */ -/* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) */ -/* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) */ -/* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ -/* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ -/* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) */ -/* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) */ -/* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) */ -/* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) */ -/* */ -/* */ -/* History: */ -/* 02/25/00 Hav Khauv Initial version. */ -/******************************************************************************/ - -#ifndef BCM_QUEUE_H -#define BCM_QUEUE_H -#ifndef EMBEDDED -#define EMBEDDED 1 -#endif - -/******************************************************************************/ -/* Queue definitions. */ -/******************************************************************************/ - -/* Entry for queueing. */ -typedef void *PQQ_ENTRY; - -/* Linux Atomic Ops support */ -typedef struct { int counter; } atomic_t; - - -/* - * This combination of `inline' and `extern' has almost the effect of a - * macro. The way to use it is to put a function definition in a header - * file with these keywords, and put another copy of the definition - * (lacking `inline' and `extern') in a library file. The definition in - * the header file will cause most calls to the function to be inlined. - * If any uses of the function remain, they will refer to the single copy - * in the library. - */ -extern __inline void -atomic_set(atomic_t* entry, int val) -{ - entry->counter = val; -} -extern __inline int -atomic_read(atomic_t* entry) -{ - return entry->counter; -} -extern __inline void -atomic_inc(atomic_t* entry) -{ - if(entry) - entry->counter++; -} - -extern __inline void -atomic_dec(atomic_t* entry) -{ - if(entry) - entry->counter--; -} - -extern __inline void -atomic_sub(int a, atomic_t* entry) -{ - if(entry) - entry->counter -= a; -} -extern __inline void -atomic_add(int a, atomic_t* entry) -{ - if(entry) - entry->counter += a; -} - - -/* Queue header -- base type. */ -typedef struct { - unsigned int Head; - unsigned int Tail; - unsigned int Size; - atomic_t EntryCnt; - PQQ_ENTRY Array[1]; -} QQ_CONTAINER, *PQQ_CONTAINER; - - -/* Declare queue type macro. */ -#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \ - \ - typedef struct { \ - QQ_CONTAINER Container; \ - PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \ - } _QUEUE_TYPE, *P##_QUEUE_TYPE - - -/******************************************************************************/ -/* Compilation switches. */ -/******************************************************************************/ - -#if DBG -#undef QQ_NO_OVERFLOW_CHECK -#undef QQ_NO_UNDERFLOW_CHECK -#endif /* DBG */ - -#ifdef QQ_USE_MACROS -/* notdone */ -#else - -#ifdef QQ_NO_INLINE -#define __inline -#endif /* QQ_NO_INLINE */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline void -QQ_InitQueue( -PQQ_CONTAINER pQueue, -unsigned int QueueSize) { - pQueue->Head = 0; - pQueue->Tail = 0; - pQueue->Size = QueueSize+1; - atomic_set(&pQueue->EntryCnt, 0); -} /* QQ_InitQueue */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline char -QQ_Full( -PQQ_CONTAINER pQueue) { - unsigned int NewHead; - - NewHead = (pQueue->Head + 1) % pQueue->Size; - - return(NewHead == pQueue->Tail); -} /* QQ_Full */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline char -QQ_Empty( -PQQ_CONTAINER pQueue) { - return(pQueue->Head == pQueue->Tail); -} /* QQ_Empty */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline unsigned int -QQ_GetSize( -PQQ_CONTAINER pQueue) { - return pQueue->Size; -} /* QQ_GetSize */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline unsigned int -QQ_GetEntryCnt( -PQQ_CONTAINER pQueue) { - return atomic_read(&pQueue->EntryCnt); -} /* QQ_GetEntryCnt */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* TRUE entry was added successfully. */ -/* FALSE queue is full. */ -/******************************************************************************/ -extern __inline char -QQ_PushHead( -PQQ_CONTAINER pQueue, -PQQ_ENTRY pEntry) { - unsigned int Head; - - Head = (pQueue->Head + 1) % pQueue->Size; - -#if !defined(QQ_NO_OVERFLOW_CHECK) - if(Head == pQueue->Tail) { - return 0; - } /* if */ -#endif /* QQ_NO_OVERFLOW_CHECK */ - - pQueue->Array[pQueue->Head] = pEntry; - wmb(); - pQueue->Head = Head; - atomic_inc(&pQueue->EntryCnt); - - return -1; -} /* QQ_PushHead */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* TRUE entry was added successfully. */ -/* FALSE queue is full. */ -/******************************************************************************/ -extern __inline char -QQ_PushTail( -PQQ_CONTAINER pQueue, -PQQ_ENTRY pEntry) { - unsigned int Tail; - - Tail = pQueue->Tail; - if(Tail == 0) { - Tail = pQueue->Size; - } /* if */ - Tail--; - -#if !defined(QQ_NO_OVERFLOW_CHECK) - if(Tail == pQueue->Head) { - return 0; - } /* if */ -#endif /* QQ_NO_OVERFLOW_CHECK */ - - pQueue->Array[Tail] = pEntry; - wmb(); - pQueue->Tail = Tail; - atomic_inc(&pQueue->EntryCnt); - - return -1; -} /* QQ_PushTail */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline PQQ_ENTRY -QQ_PopHead( -PQQ_CONTAINER pQueue) { - unsigned int Head; - PQQ_ENTRY Entry; - - Head = pQueue->Head; - -#if !defined(QQ_NO_UNDERFLOW_CHECK) - if(Head == pQueue->Tail) { - return (PQQ_ENTRY) 0; - } /* if */ -#endif /* QQ_NO_UNDERFLOW_CHECK */ - - if(Head == 0) { - Head = pQueue->Size; - } /* if */ - Head--; - - Entry = pQueue->Array[Head]; -#ifdef EMBEDDED - membar(); -#else - mb(); -#endif - pQueue->Head = Head; - atomic_dec(&pQueue->EntryCnt); - - return Entry; -} /* QQ_PopHead */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline PQQ_ENTRY -QQ_PopTail( -PQQ_CONTAINER pQueue) { - unsigned int Tail; - PQQ_ENTRY Entry; - - Tail = pQueue->Tail; - -#if !defined(QQ_NO_UNDERFLOW_CHECK) - if(Tail == pQueue->Head) { - return (PQQ_ENTRY) 0; - } /* if */ -#endif /* QQ_NO_UNDERFLOW_CHECK */ - - Entry = pQueue->Array[Tail]; -#ifdef EMBEDDED - membar(); -#else - mb(); -#endif - pQueue->Tail = (Tail + 1) % pQueue->Size; - atomic_dec(&pQueue->EntryCnt); - - return Entry; -} /* QQ_PopTail */ - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline PQQ_ENTRY -QQ_GetHead( - PQQ_CONTAINER pQueue, - unsigned int Idx) -{ - if(Idx >= atomic_read(&pQueue->EntryCnt)) - { - return (PQQ_ENTRY) 0; - } - - if(pQueue->Head > Idx) - { - Idx = pQueue->Head - Idx; - } - else - { - Idx = pQueue->Size - (Idx - pQueue->Head); - } - Idx--; - - return pQueue->Array[Idx]; -} - - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -extern __inline PQQ_ENTRY -QQ_GetTail( - PQQ_CONTAINER pQueue, - unsigned int Idx) -{ - if(Idx >= atomic_read(&pQueue->EntryCnt)) - { - return (PQQ_ENTRY) 0; - } - - Idx += pQueue->Tail; - if(Idx >= pQueue->Size) - { - Idx = Idx - pQueue->Size; - } - - return pQueue->Array[Idx]; -} - -#endif /* QQ_USE_MACROS */ - - -#endif /* QUEUE_H */ diff --git a/drivers/cs8900.c b/drivers/cs8900.c deleted file mode 100644 index 80c4ba21a6..0000000000 --- a/drivers/cs8900.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Cirrus Logic CS8900A Ethernet - * - * (C) 2003 Wolfgang Denk, wd@denx.de - * Extension to synchronize ethaddr environment variable - * against value in EEPROM - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Marius Groeger - * - * Copyright (C) 1999 Ben Williamson - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is loaded into SRAM in bootstrap mode, where it waits - * for commands on UART1 to read and write memory, jump to code etc. - * A design goal for this program is to be entirely independent of the - * target board. Anything with a CL-PS7111 or EP7211 should be able to run - * this code in bootstrap mode. All the board specifics can be handled on - * the host. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include "cs8900.h" -#include - -#ifdef CONFIG_DRIVER_CS8900 - -#if defined(CONFIG_CMD_NET) - -#undef DEBUG - -/* packet page register access functions */ - -#ifdef CS8900_BUS32 -/* we don't need 16 bit initialisation on 32 bit bus */ -#define get_reg_init_bus(x) get_reg((x)) -#else -static unsigned short get_reg_init_bus (int regno) -{ - /* force 16 bit busmode */ - volatile unsigned char c; - - c = CS8900_BUS16_0; - c = CS8900_BUS16_1; - c = CS8900_BUS16_0; - c = CS8900_BUS16_1; - c = CS8900_BUS16_0; - - CS8900_PPTR = regno; - return (unsigned short) CS8900_PDATA; -} -#endif - -static unsigned short get_reg (int regno) -{ - CS8900_PPTR = regno; - return (unsigned short) CS8900_PDATA; -} - - -static void put_reg (int regno, unsigned short val) -{ - CS8900_PPTR = regno; - CS8900_PDATA = val; -} - -static void eth_reset (void) -{ - int tmo; - unsigned short us; - - /* reset NIC */ - put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset); - - /* wait for 200ms */ - udelay (200000); - /* Wait until the chip is reset */ - - tmo = get_timer (0) + 1 * CFG_HZ; - while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) - && tmo < get_timer (0)) - /*NOP*/; -} - -static void eth_reginit (void) -{ - /* receive only error free packets addressed to this card */ - put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); - /* do not generate any interrupts on receive operations */ - put_reg (PP_RxCFG, 0); - /* do not generate any interrupts on transmit operations */ - put_reg (PP_TxCFG, 0); - /* do not generate any interrupts on buffer operations */ - put_reg (PP_BufCFG, 0); - /* enable transmitter/receiver mode */ - put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); -} - -void cs8900_get_enetaddr (uchar * addr) -{ - int i; - unsigned char env_enetaddr[6]; - char *tmp = getenv ("ethaddr"); - char *end; - - for (i=0; i<6; i++) { - env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; - if (tmp) - tmp = (*end) ? end+1 : end; - } - - /* verify chip id */ - if (get_reg_init_bus (PP_ChipID) != 0x630e) - return; - eth_reset (); - if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == - (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) { - - /* Load the MAC from EEPROM */ - for (i = 0; i < 6 / 2; i++) { - unsigned int Addr; - - Addr = get_reg (PP_IA + i * 2); - addr[i * 2] = Addr & 0xFF; - addr[i * 2 + 1] = Addr >> 8; - } - - if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 && - memcmp(env_enetaddr, addr, 6) != 0) { - printf ("\nWarning: MAC addresses don't match:\n"); - printf ("\tHW MAC address: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - addr[0], addr[1], - addr[2], addr[3], - addr[4], addr[5] ); - printf ("\t\"ethaddr\" value: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - env_enetaddr[0], env_enetaddr[1], - env_enetaddr[2], env_enetaddr[3], - env_enetaddr[4], env_enetaddr[5]) ; - debug ("### Set MAC addr from environment\n"); - memcpy (addr, env_enetaddr, 6); - } - if (!tmp) { - char ethaddr[20]; - sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", - addr[0], addr[1], - addr[2], addr[3], - addr[4], addr[5]) ; - debug ("### Set environment from HW MAC addr = \"%s\"\n", ethaddr); - setenv ("ethaddr", ethaddr); - } - - } -} - -void eth_halt (void) -{ - /* disable transmitter/receiver mode */ - put_reg (PP_LineCTL, 0); - - /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ - get_reg_init_bus (PP_ChipID); -} - -int eth_init (bd_t * bd) -{ - - /* verify chip id */ - if (get_reg_init_bus (PP_ChipID) != 0x630e) { - printf ("CS8900 Ethernet chip not found?!\n"); - return 0; - } - - eth_reset (); - /* set the ethernet address */ - put_reg (PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); - put_reg (PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); - put_reg (PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); - - eth_reginit (); - return 0; -} - -/* Get a data block via Ethernet */ -extern int eth_rx (void) -{ - int i; - unsigned short rxlen; - unsigned short *addr; - unsigned short status; - - status = get_reg (PP_RER); - - if ((status & PP_RER_RxOK) == 0) - return 0; - - status = CS8900_RTDATA; /* stat */ - rxlen = CS8900_RTDATA; /* len */ - -#ifdef DEBUG - if (rxlen > PKTSIZE_ALIGN + PKTALIGN) - printf ("packet too big!\n"); -#endif - for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0; - i--) - *addr++ = CS8900_RTDATA; - if (rxlen & 1) - *addr++ = CS8900_RTDATA; - - /* Pass the packet up to the protocol layers. */ - NetReceive (NetRxPackets[0], rxlen); - - return rxlen; -} - -/* Send a data block via Ethernet. */ -extern int eth_send (volatile void *packet, int length) -{ - volatile unsigned short *addr; - int tmo; - unsigned short s; - -retry: - /* initiate a transmit sequence */ - CS8900_TxCMD = PP_TxCmd_TxStart_Full; - CS8900_TxLEN = length; - - /* Test to see if the chip has allocated memory for the packet */ - if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { - /* Oops... this should not happen! */ -#ifdef DEBUG - printf ("cs: unable to send packet; retrying...\n"); -#endif - for (tmo = get_timer (0) + 5 * CFG_HZ; get_timer (0) < tmo;) - /*NOP*/; - eth_reset (); - eth_reginit (); - goto retry; - } - - /* Write the contents of the packet */ - /* assume even number of bytes */ - for (addr = packet; length > 0; length -= 2) - CS8900_RTDATA = *addr++; - - /* wait for transfer to succeed */ - tmo = get_timer (0) + 5 * CFG_HZ; - while ((s = get_reg (PP_TER) & ~0x1F) == 0) { - if (get_timer (0) >= tmo) - break; - } - - /* nothing */ ; - if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { -#ifdef DEBUG - printf ("\ntransmission error %#x\n", s); -#endif - } - - return 0; -} - -static void cs8900_e2prom_ready(void) -{ - while(get_reg(PP_SelfST) & SI_BUSY); -} - -/***********************************************************/ -/* read a 16-bit word out of the EEPROM */ -/***********************************************************/ - -int cs8900_e2prom_read(unsigned char addr, unsigned short *value) -{ - cs8900_e2prom_ready(); - put_reg(PP_EECMD, EEPROM_READ_CMD | addr); - cs8900_e2prom_ready(); - *value = get_reg(PP_EEData); - - return 0; -} - - -/***********************************************************/ -/* write a 16-bit word into the EEPROM */ -/***********************************************************/ - -int cs8900_e2prom_write(unsigned char addr, unsigned short value) -{ - cs8900_e2prom_ready(); - put_reg(PP_EECMD, EEPROM_WRITE_EN); - cs8900_e2prom_ready(); - put_reg(PP_EEData, value); - put_reg(PP_EECMD, EEPROM_WRITE_CMD | addr); - cs8900_e2prom_ready(); - put_reg(PP_EECMD, EEPROM_WRITE_DIS); - cs8900_e2prom_ready(); - - return 0; -} - -#endif /* COMMANDS & CFG_NET */ - -#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/cs8900.h b/drivers/cs8900.h deleted file mode 100644 index f886d103c1..0000000000 --- a/drivers/cs8900.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Cirrus Logic CS8900A Ethernet - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Marius Groeger - * - * Copyright (C) 1999 Ben Williamson - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is loaded into SRAM in bootstrap mode, where it waits - * for commands on UART1 to read and write memory, jump to code etc. - * A design goal for this program is to be entirely independent of the - * target board. Anything with a CL-PS7111 or EP7211 should be able to run - * this code in bootstrap mode. All the board specifics can be handled on - * the host. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#ifdef CONFIG_DRIVER_CS8900 - -/* although the registers are 16 bit, they are 32-bit aligned on the - EDB7111. so we have to read them as 32-bit registers and ignore the - upper 16-bits. i'm not sure if this holds for the EDB7211. */ - -#ifdef CS8900_BUS16 - /* 16 bit aligned registers, 16 bit wide */ - #define CS8900_REG u16 - #define CS8900_OFF 0x02 - #define CS8900_BUS16_0 *(volatile u8 *)(CS8900_BASE+0x00) - #define CS8900_BUS16_1 *(volatile u8 *)(CS8900_BASE+0x01) -#elif defined(CS8900_BUS32) - /* 32 bit aligned registers, 16 bit wide (we ignore upper 16 bits) */ - #define CS8900_REG u32 - #define CS8900_OFF 0x04 -#else - #error unknown bussize ... -#endif - -#define CS8900_RTDATA *(volatile CS8900_REG *)(CS8900_BASE+0x00*CS8900_OFF) -#define CS8900_TxCMD *(volatile CS8900_REG *)(CS8900_BASE+0x02*CS8900_OFF) -#define CS8900_TxLEN *(volatile CS8900_REG *)(CS8900_BASE+0x03*CS8900_OFF) -#define CS8900_ISQ *(volatile CS8900_REG *)(CS8900_BASE+0x04*CS8900_OFF) -#define CS8900_PPTR *(volatile CS8900_REG *)(CS8900_BASE+0x05*CS8900_OFF) -#define CS8900_PDATA *(volatile CS8900_REG *)(CS8900_BASE+0x06*CS8900_OFF) - - -#define ISQ_RxEvent 0x04 -#define ISQ_TxEvent 0x08 -#define ISQ_BufEvent 0x0C -#define ISQ_RxMissEvent 0x10 -#define ISQ_TxColEvent 0x12 -#define ISQ_EventMask 0x3F - -/* packet page register offsets */ - -/* bus interface registers */ -#define PP_ChipID 0x0000 /* Chip identifier - must be 0x630E */ -#define PP_ChipRev 0x0002 /* Chip revision, model codes */ - -#define PP_IntReg 0x0022 /* Interrupt configuration */ -#define PP_IntReg_IRQ0 0x0000 /* Use INTR0 pin */ -#define PP_IntReg_IRQ1 0x0001 /* Use INTR1 pin */ -#define PP_IntReg_IRQ2 0x0002 /* Use INTR2 pin */ -#define PP_IntReg_IRQ3 0x0003 /* Use INTR3 pin */ - -/* status and control registers */ - -#define PP_RxCFG 0x0102 /* Receiver configuration */ -#define PP_RxCFG_Skip1 0x0040 /* Skip (i.e. discard) current frame */ -#define PP_RxCFG_Stream 0x0080 /* Enable streaming mode */ -#define PP_RxCFG_RxOK 0x0100 /* RxOK interrupt enable */ -#define PP_RxCFG_RxDMAonly 0x0200 /* Use RxDMA for all frames */ -#define PP_RxCFG_AutoRxDMA 0x0400 /* Select RxDMA automatically */ -#define PP_RxCFG_BufferCRC 0x0800 /* Include CRC characters in frame */ -#define PP_RxCFG_CRC 0x1000 /* Enable interrupt on CRC error */ -#define PP_RxCFG_RUNT 0x2000 /* Enable interrupt on RUNT frames */ -#define PP_RxCFG_EXTRA 0x4000 /* Enable interrupt on frames with extra data */ - -#define PP_RxCTL 0x0104 /* Receiver control */ -#define PP_RxCTL_IAHash 0x0040 /* Accept frames that match hash */ -#define PP_RxCTL_Promiscuous 0x0080 /* Accept any frame */ -#define PP_RxCTL_RxOK 0x0100 /* Accept well formed frames */ -#define PP_RxCTL_Multicast 0x0200 /* Accept multicast frames */ -#define PP_RxCTL_IA 0x0400 /* Accept frame that matches IA */ -#define PP_RxCTL_Broadcast 0x0800 /* Accept broadcast frames */ -#define PP_RxCTL_CRC 0x1000 /* Accept frames with bad CRC */ -#define PP_RxCTL_RUNT 0x2000 /* Accept runt frames */ -#define PP_RxCTL_EXTRA 0x4000 /* Accept frames that are too long */ - -#define PP_TxCFG 0x0106 /* Transmit configuration */ -#define PP_TxCFG_CRS 0x0040 /* Enable interrupt on loss of carrier */ -#define PP_TxCFG_SQE 0x0080 /* Enable interrupt on Signal Quality Error */ -#define PP_TxCFG_TxOK 0x0100 /* Enable interrupt on successful xmits */ -#define PP_TxCFG_Late 0x0200 /* Enable interrupt on "out of window" */ -#define PP_TxCFG_Jabber 0x0400 /* Enable interrupt on jabber detect */ -#define PP_TxCFG_Collision 0x0800 /* Enable interrupt if collision */ -#define PP_TxCFG_16Collisions 0x8000 /* Enable interrupt if > 16 collisions */ - -#define PP_TxCmd 0x0108 /* Transmit command status */ -#define PP_TxCmd_TxStart_5 0x0000 /* Start after 5 bytes in buffer */ -#define PP_TxCmd_TxStart_381 0x0040 /* Start after 381 bytes in buffer */ -#define PP_TxCmd_TxStart_1021 0x0080 /* Start after 1021 bytes in buffer */ -#define PP_TxCmd_TxStart_Full 0x00C0 /* Start after all bytes loaded */ -#define PP_TxCmd_Force 0x0100 /* Discard any pending packets */ -#define PP_TxCmd_OneCollision 0x0200 /* Abort after a single collision */ -#define PP_TxCmd_NoCRC 0x1000 /* Do not add CRC */ -#define PP_TxCmd_NoPad 0x2000 /* Do not pad short packets */ - -#define PP_BufCFG 0x010A /* Buffer configuration */ -#define PP_BufCFG_SWI 0x0040 /* Force interrupt via software */ -#define PP_BufCFG_RxDMA 0x0080 /* Enable interrupt on Rx DMA */ -#define PP_BufCFG_TxRDY 0x0100 /* Enable interrupt when ready for Tx */ -#define PP_BufCFG_TxUE 0x0200 /* Enable interrupt in Tx underrun */ -#define PP_BufCFG_RxMiss 0x0400 /* Enable interrupt on missed Rx packets */ -#define PP_BufCFG_Rx128 0x0800 /* Enable Rx interrupt after 128 bytes */ -#define PP_BufCFG_TxCol 0x1000 /* Enable int on Tx collision ctr overflow */ -#define PP_BufCFG_Miss 0x2000 /* Enable int on Rx miss ctr overflow */ -#define PP_BufCFG_RxDest 0x8000 /* Enable int on Rx dest addr match */ - -#define PP_LineCTL 0x0112 /* Line control */ -#define PP_LineCTL_Rx 0x0040 /* Enable receiver */ -#define PP_LineCTL_Tx 0x0080 /* Enable transmitter */ -#define PP_LineCTL_AUIonly 0x0100 /* AUI interface only */ -#define PP_LineCTL_AutoAUI10BT 0x0200 /* Autodetect AUI or 10BaseT interface */ -#define PP_LineCTL_ModBackoffE 0x0800 /* Enable modified backoff algorithm */ -#define PP_LineCTL_PolarityDis 0x1000 /* Disable Rx polarity autodetect */ -#define PP_LineCTL_2partDefDis 0x2000 /* Disable two-part defferal */ -#define PP_LineCTL_LoRxSquelch 0x4000 /* Reduce receiver squelch threshold */ - -#define PP_SelfCTL 0x0114 /* Chip self control */ -#define PP_SelfCTL_Reset 0x0040 /* Self-clearing reset */ -#define PP_SelfCTL_SWSuspend 0x0100 /* Initiate suspend mode */ -#define PP_SelfCTL_HWSleepE 0x0200 /* Enable SLEEP input */ -#define PP_SelfCTL_HWStandbyE 0x0400 /* Enable standby mode */ -#define PP_SelfCTL_HC0E 0x1000 /* use HCB0 for LINK LED */ -#define PP_SelfCTL_HC1E 0x2000 /* use HCB1 for BSTATUS LED */ -#define PP_SelfCTL_HCB0 0x4000 /* control LINK LED if HC0E set */ -#define PP_SelfCTL_HCB1 0x8000 /* control BSTATUS LED if HC1E set */ - -#define PP_BusCTL 0x0116 /* Bus control */ -#define PP_BusCTL_ResetRxDMA 0x0040 /* Reset RxDMA pointer */ -#define PP_BusCTL_DMAextend 0x0100 /* Extend DMA cycle */ -#define PP_BusCTL_UseSA 0x0200 /* Assert MEMCS16 on address decode */ -#define PP_BusCTL_MemoryE 0x0400 /* Enable memory mode */ -#define PP_BusCTL_DMAburst 0x0800 /* Limit DMA access burst */ -#define PP_BusCTL_IOCHRDYE 0x1000 /* Set IOCHRDY high impedence */ -#define PP_BusCTL_RxDMAsize 0x2000 /* Set DMA buffer size 64KB */ -#define PP_BusCTL_EnableIRQ 0x8000 /* Generate interrupt on interrupt event */ - -#define PP_TestCTL 0x0118 /* Test control */ -#define PP_TestCTL_DisableLT 0x0080 /* Disable link status */ -#define PP_TestCTL_ENDECloop 0x0200 /* Internal loopback */ -#define PP_TestCTL_AUIloop 0x0400 /* AUI loopback */ -#define PP_TestCTL_DisBackoff 0x0800 /* Disable backoff algorithm */ -#define PP_TestCTL_FDX 0x4000 /* Enable full duplex mode */ - -#define PP_ISQ 0x0120 /* Interrupt Status Queue */ - -#define PP_RER 0x0124 /* Receive event */ -#define PP_RER_IAHash 0x0040 /* Frame hash match */ -#define PP_RER_Dribble 0x0080 /* Frame had 1-7 extra bits after last byte */ -#define PP_RER_RxOK 0x0100 /* Frame received with no errors */ -#define PP_RER_Hashed 0x0200 /* Frame address hashed OK */ -#define PP_RER_IA 0x0400 /* Frame address matched IA */ -#define PP_RER_Broadcast 0x0800 /* Broadcast frame */ -#define PP_RER_CRC 0x1000 /* Frame had CRC error */ -#define PP_RER_RUNT 0x2000 /* Runt frame */ -#define PP_RER_EXTRA 0x4000 /* Frame was too long */ - -#define PP_TER 0x0128 /* Transmit event */ -#define PP_TER_CRS 0x0040 /* Carrier lost */ -#define PP_TER_SQE 0x0080 /* Signal Quality Error */ -#define PP_TER_TxOK 0x0100 /* Packet sent without error */ -#define PP_TER_Late 0x0200 /* Out of window */ -#define PP_TER_Jabber 0x0400 /* Stuck transmit? */ -#define PP_TER_NumCollisions 0x7800 /* Number of collisions */ -#define PP_TER_16Collisions 0x8000 /* > 16 collisions */ - -#define PP_BER 0x012C /* Buffer event */ -#define PP_BER_SWint 0x0040 /* Software interrupt */ -#define PP_BER_RxDMAFrame 0x0080 /* Received framed DMAed */ -#define PP_BER_Rdy4Tx 0x0100 /* Ready for transmission */ -#define PP_BER_TxUnderrun 0x0200 /* Transmit underrun */ -#define PP_BER_RxMiss 0x0400 /* Received frame missed */ -#define PP_BER_Rx128 0x0800 /* 128 bytes received */ -#define PP_BER_RxDest 0x8000 /* Received framed passed address filter */ - -#define PP_RxMiss 0x0130 /* Receiver miss counter */ - -#define PP_TxCol 0x0132 /* Transmit collision counter */ - -#define PP_LineSTAT 0x0134 /* Line status */ -#define PP_LineSTAT_LinkOK 0x0080 /* Line is connected and working */ -#define PP_LineSTAT_AUI 0x0100 /* Connected via AUI */ -#define PP_LineSTAT_10BT 0x0200 /* Connected via twisted pair */ -#define PP_LineSTAT_Polarity 0x1000 /* Line polarity OK (10BT only) */ -#define PP_LineSTAT_CRS 0x4000 /* Frame being received */ - -#define PP_SelfSTAT 0x0136 /* Chip self status */ -#define PP_SelfSTAT_33VActive 0x0040 /* supply voltage is 3.3V */ -#define PP_SelfSTAT_InitD 0x0080 /* Chip initialization complete */ -#define PP_SelfSTAT_SIBSY 0x0100 /* EEPROM is busy */ -#define PP_SelfSTAT_EEPROM 0x0200 /* EEPROM present */ -#define PP_SelfSTAT_EEPROM_OK 0x0400 /* EEPROM checks out */ -#define PP_SelfSTAT_ELPresent 0x0800 /* External address latch logic available */ -#define PP_SelfSTAT_EEsize 0x1000 /* Size of EEPROM */ - -#define PP_BusSTAT 0x0138 /* Bus status */ -#define PP_BusSTAT_TxBid 0x0080 /* Tx error */ -#define PP_BusSTAT_TxRDY 0x0100 /* Ready for Tx data */ - -#define PP_TDR 0x013C /* AUI Time Domain Reflectometer */ - -/* initiate transmit registers */ - -#define PP_TxCommand 0x0144 /* Tx Command */ -#define PP_TxLength 0x0146 /* Tx Length */ - - -/* address filter registers */ - -#define PP_LAF 0x0150 /* Logical address filter (6 bytes) */ -#define PP_IA 0x0158 /* Individual address (MAC) */ - -/* EEPROM Kram */ -#define SI_BUSY 0x0100 -#define PP_SelfST 0x0136 /* Self State register */ -#define PP_EECMD 0x0040 /* NVR Interface Command register */ -#define PP_EEData 0x0042 /* NVR Interface Data Register */ -#define EEPROM_WRITE_EN 0x00F0 -#define EEPROM_WRITE_DIS 0x0000 -#define EEPROM_WRITE_CMD 0x0100 -#define EEPROM_READ_CMD 0x0200 -#define EEPROM_ERASE_CMD 0x0300 - -extern int cs8900_e2prom_read(uchar, ushort *); -extern int cs8900_e2prom_write(uchar, ushort); - -#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c deleted file mode 100644 index d5275dceb0..0000000000 --- a/drivers/dc2114x.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_TULIP) - -#include -#include -#include - -#undef DEBUG_SROM -#undef DEBUG_SROM2 - -#undef UPDATE_SROM - -/* PCI Registers. - */ -#define PCI_CFDA_PSM 0x43 - -#define CFRV_RN 0x000000f0 /* Revision Number */ - -#define WAKEUP 0x00 /* Power Saving Wakeup */ -#define SLEEP 0x80 /* Power Saving Sleep Mode */ - -#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */ - -/* Ethernet chip registers. - */ -#define DE4X5_BMR 0x000 /* Bus Mode Register */ -#define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */ -#define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */ -#define DE4X5_TRBA 0x020 /* TX Ring Base Address Reg */ -#define DE4X5_STS 0x028 /* Status Register */ -#define DE4X5_OMR 0x030 /* Operation Mode Register */ -#define DE4X5_SICR 0x068 /* SIA Connectivity Register */ -#define DE4X5_APROM 0x048 /* Ethernet Address PROM */ - -/* Register bits. - */ -#define BMR_SWR 0x00000001 /* Software Reset */ -#define STS_TS 0x00700000 /* Transmit Process State */ -#define STS_RS 0x000e0000 /* Receive Process State */ -#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ -#define OMR_SR 0x00000002 /* Start/Stop Receive */ -#define OMR_PS 0x00040000 /* Port Select */ -#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ -#define OMR_PM 0x00000080 /* Pass All Multicast */ - -/* Descriptor bits. - */ -#define R_OWN 0x80000000 /* Own Bit */ -#define RD_RER 0x02000000 /* Receive End Of Ring */ -#define RD_LS 0x00000100 /* Last Descriptor */ -#define RD_ES 0x00008000 /* Error Summary */ -#define TD_TER 0x02000000 /* Transmit End Of Ring */ -#define T_OWN 0x80000000 /* Own Bit */ -#define TD_LS 0x40000000 /* Last Segment */ -#define TD_FS 0x20000000 /* First Segment */ -#define TD_ES 0x00008000 /* Error Summary */ -#define TD_SET 0x08000000 /* Setup Packet */ - -/* The EEPROM commands include the alway-set leading bit. */ -#define SROM_WRITE_CMD 5 -#define SROM_READ_CMD 6 -#define SROM_ERASE_CMD 7 - -#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */ -#define SROM_RD 0x00004000 /* Read from Boot ROM */ -#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x4801 -#define EE_WRITE_1 0x4805 -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ -#define SROM_SR 0x00000800 /* Select Serial ROM when set */ - -#define DT_IN 0x00000004 /* Serial Data In */ -#define DT_CLK 0x00000002 /* Serial ROM Clock */ -#define DT_CS 0x00000001 /* Serial ROM Chip Select */ - -#define POLL_DEMAND 1 - -#ifdef CONFIG_TULIP_FIX_DAVICOM -#define RESET_DM9102(dev) {\ - unsigned long i;\ - i=INL(dev, 0x0);\ - udelay(1000);\ - OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ - udelay(1000);\ -} -#else -#define RESET_DE4X5(dev) {\ - int i;\ - i=INL(dev, DE4X5_BMR);\ - udelay(1000);\ - OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ - udelay(1000);\ - OUTL(dev, i, DE4X5_BMR);\ - udelay(1000);\ - for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\ - udelay(1000);\ -} -#endif - -#define START_DE4X5(dev) {\ - s32 omr; \ - omr = INL(dev, DE4X5_OMR);\ - omr |= OMR_ST | OMR_SR;\ - OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\ -} - -#define STOP_DE4X5(dev) {\ - s32 omr; \ - omr = INL(dev, DE4X5_OMR);\ - omr &= ~(OMR_ST|OMR_SR);\ - OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ -} - -#define NUM_RX_DESC PKTBUFSRX -#ifndef CONFIG_TULIP_FIX_DAVICOM - #define NUM_TX_DESC 1 /* Number of TX descriptors */ -#else - #define NUM_TX_DESC 4 -#endif -#define RX_BUFF_SZ PKTSIZE_ALIGN - -#define TOUT_LOOP 1000000 - -#define SETUP_FRAME_LEN 192 -#define ETH_ALEN 6 - -struct de4x5_desc { - volatile s32 status; - u32 des1; - u32 buf; - u32 next; -}; - -static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring */ -static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring */ -static int rx_new; /* RX descriptor ring pointer */ -static int tx_new; /* TX descriptor ring pointer */ - -static char rxRingSize; -static char txRingSize; - -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) -static void sendto_srom(struct eth_device* dev, u_int command, u_long addr); -static int getfrom_srom(struct eth_device* dev, u_long addr); -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr,int cmd,int cmd_len); -static int do_read_eeprom(struct eth_device *dev,u_long ioaddr,int location,int addr_len); -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ -#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value); -static void update_srom(struct eth_device *dev, bd_t *bis); -#endif -#ifndef CONFIG_TULIP_FIX_DAVICOM -static int read_srom(struct eth_device *dev, u_long ioaddr, int index); -static void read_hw_addr(struct eth_device* dev, bd_t * bis); -#endif /* CONFIG_TULIP_FIX_DAVICOM */ -static void send_setup_frame(struct eth_device* dev, bd_t * bis); - -static int dc21x4x_init(struct eth_device* dev, bd_t* bis); -static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length); -static int dc21x4x_recv(struct eth_device* dev); -static void dc21x4x_halt(struct eth_device* dev); -#ifdef CONFIG_TULIP_SELECT_MEDIA -extern void dc21x4x_select_media(struct eth_device* dev); -#endif - -#if defined(CONFIG_E500) -#define phys_to_bus(a) (a) -#else -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) -#endif - -static int INL(struct eth_device* dev, u_long addr) -{ - return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); -} - -static void OUTL(struct eth_device* dev, int command, u_long addr) -{ - *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); -} - -static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, -#ifdef CONFIG_TULIP_FIX_DAVICOM - { PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DAVICOM_DM9102A }, -#endif - { } -}; - -int dc21x4x_initialize(bd_t *bis) -{ - int idx=0; - int card_number = 0; - unsigned int cfrv; - unsigned char timer; - pci_dev_t devbusfn; - unsigned int iobase; - unsigned short status; - struct eth_device* dev; - - while(1) { - devbusfn = pci_find_devices(supported, idx++); - if (devbusfn == -1) { - break; - } - - /* Get the chip configuration revision register. */ - pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); - -#ifndef CONFIG_TULIP_FIX_DAVICOM - if ((cfrv & CFRV_RN) < DC2114x_BRK ) { - printf("Error: The chip is not DC21143.\n"); - continue; - } -#endif - - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - status |= -#ifdef CONFIG_TULIP_USE_IO - PCI_COMMAND_IO | -#else - PCI_COMMAND_MEMORY | -#endif - PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, status); - - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_IO)) { - printf("Error: Can not enable I/O access.\n"); - continue; - } - - if (!(status & PCI_COMMAND_IO)) { - printf("Error: Can not enable I/O access.\n"); - continue; - } - - if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } - - /* Check the latency timer for values >= 0x60. */ - pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); - - if (timer < 0x60) { - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60); - } - -#ifdef CONFIG_TULIP_USE_IO - /* read BAR for memory space access */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); - iobase &= PCI_BASE_ADDRESS_IO_MASK; -#else - /* read BAR for memory space access */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); - iobase &= PCI_BASE_ADDRESS_MEM_MASK; -#endif - debug ("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); - - dev = (struct eth_device*) malloc(sizeof *dev); - -#ifdef CONFIG_TULIP_FIX_DAVICOM - sprintf(dev->name, "Davicom#%d", card_number); -#else - sprintf(dev->name, "dc21x4x#%d", card_number); -#endif - -#ifdef CONFIG_TULIP_USE_IO - dev->iobase = pci_io_to_phys(devbusfn, iobase); -#else - dev->iobase = pci_mem_to_phys(devbusfn, iobase); -#endif - dev->priv = (void*) devbusfn; - dev->init = dc21x4x_init; - dev->halt = dc21x4x_halt; - dev->send = dc21x4x_send; - dev->recv = dc21x4x_recv; - - /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); - - udelay(10 * 1000); - -#ifndef CONFIG_TULIP_FIX_DAVICOM - read_hw_addr(dev, bis); -#endif - eth_register(dev); - - card_number++; - } - - return card_number; -} - -static int dc21x4x_init(struct eth_device* dev, bd_t* bis) -{ - int i; - int devbusfn = (int) dev->priv; - - /* Ensure we're not sleeping. */ - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); - -#ifdef CONFIG_TULIP_FIX_DAVICOM - RESET_DM9102(dev); -#else - RESET_DE4X5(dev); -#endif - - if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { - printf("Error: Cannot reset ethernet controller.\n"); - return 0; - } - -#ifdef CONFIG_TULIP_SELECT_MEDIA - dc21x4x_select_media(dev); -#else - OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); -#endif - - for (i = 0; i < NUM_RX_DESC; i++) { - rx_ring[i].status = cpu_to_le32(R_OWN); - rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); - rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i])); -#ifdef CONFIG_TULIP_FIX_DAVICOM - rx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &rx_ring[(i+1) % NUM_RX_DESC])); -#else - rx_ring[i].next = 0; -#endif - } - - for (i=0; i < NUM_TX_DESC; i++) { - tx_ring[i].status = 0; - tx_ring[i].des1 = 0; - tx_ring[i].buf = 0; - -#ifdef CONFIG_TULIP_FIX_DAVICOM - tx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &tx_ring[(i+1) % NUM_TX_DESC])); -#else - tx_ring[i].next = 0; -#endif - } - - rxRingSize = NUM_RX_DESC; - txRingSize = NUM_TX_DESC; - - /* Write the end of list marker to the descriptor lists. */ - rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); - tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER); - - /* Tell the adapter where the TX/RX rings are located. */ - OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA); - OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA); - - START_DE4X5(dev); - - tx_new = 0; - rx_new = 0; - - send_setup_frame(dev, bis); - - return 1; -} - -static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length) -{ - int status = -1; - int i; - - if (length <= 0) { - printf("%s: bad packet size: %d\n", dev->name, length); - goto Done; - } - - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx error buffer not ready\n", dev->name); - goto Done; - } - } - - tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet)); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); - tx_ring[tx_new].status = cpu_to_le32(T_OWN); - - OUTL(dev, POLL_DEMAND, DE4X5_TPD); - - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf(".%s: tx buffer not ready\n", dev->name); - goto Done; - } - } - - if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) { -#if 0 /* test-only */ - printf("TX error status = 0x%08X\n", - le32_to_cpu(tx_ring[tx_new].status)); -#endif - tx_ring[tx_new].status = 0x0; - goto Done; - } - - status = length; - - Done: - tx_new = (tx_new+1) % NUM_TX_DESC; - return status; -} - -static int dc21x4x_recv(struct eth_device* dev) -{ - s32 status; - int length = 0; - - for ( ; ; ) { - status = (s32)le32_to_cpu(rx_ring[rx_new].status); - - if (status & R_OWN) { - break; - } - - if (status & RD_LS) { - /* Valid frame status. - */ - if (status & RD_ES) { - - /* There was an error. - */ - printf("RX error status = 0x%08X\n", status); - } else { - /* A valid frame received. - */ - length = (le32_to_cpu(rx_ring[rx_new].status) >> 16); - - /* Pass the packet up to the protocol - * layers. - */ - NetReceive(NetRxPackets[rx_new], length - 4); - } - - /* Change buffer ownership for this frame, back - * to the adapter. - */ - rx_ring[rx_new].status = cpu_to_le32(R_OWN); - } - - /* Update entry information. - */ - rx_new = (rx_new + 1) % rxRingSize; - } - - return length; -} - -static void dc21x4x_halt(struct eth_device* dev) -{ - int devbusfn = (int) dev->priv; - - STOP_DE4X5(dev); - OUTL(dev, 0, DE4X5_SICR); - - pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); -} - -static void send_setup_frame(struct eth_device* dev, bd_t *bis) -{ - int i; - char setup_frame[SETUP_FRAME_LEN]; - char *pa = &setup_frame[0]; - - memset(pa, 0xff, SETUP_FRAME_LEN); - - for (i = 0; i < ETH_ALEN; i++) { - *(pa + (i & 1)) = dev->enetaddr[i]; - if (i & 0x01) { - pa += 4; - } - } - - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx error buffer not ready\n", dev->name); - goto Done; - } - } - - tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0])); - tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN); - tx_ring[tx_new].status = cpu_to_le32(T_OWN); - - OUTL(dev, POLL_DEMAND, DE4X5_TPD); - - for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx buffer not ready\n", dev->name); - goto Done; - } - } - - if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { - printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status)); - } - tx_new = (tx_new+1) % NUM_TX_DESC; - -Done: - return; -} - -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) -/* SROM Read and write routines. - */ -static void -sendto_srom(struct eth_device* dev, u_int command, u_long addr) -{ - OUTL(dev, command, addr); - udelay(1); -} - -static int -getfrom_srom(struct eth_device* dev, u_long addr) -{ - s32 tmp; - - tmp = INL(dev, addr); - udelay(1); - - return tmp; -} - -/* Note: this routine returns extra data bits for size detection. */ -static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - int read_cmd = location | (SROM_READ_CMD << addr_len); - - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM read at %d ", location); -#endif - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr); - udelay(10); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); - } - - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); -#endif - - for (i = 16; i > 0; i--) { - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - udelay(10); -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev, ioaddr) & 15); -#endif - retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); - sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); - udelay(10); - } - - /* Terminate the EEPROM access. */ - sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM2 - printf(" EEPROM value at %d is %5.5x.\n", location, retval); -#endif - - return retval; -} -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ - -/* This executes a generic EEPROM command, typically a write or write - * enable. It returns the data output from the EEPROM, and thus may - * also be used for reads. - */ -#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) -static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len) -{ - unsigned retval = 0; - -#ifdef DEBUG_SROM - printf(" EEPROM op 0x%x: ", cmd); -#endif - - sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); - - /* Shift the command bits out. */ - do { - short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; - sendto_srom(dev,dataval, ioaddr); - udelay(10); - -#ifdef DEBUG_SROM2 - printf("%X", getfrom_srom(dev,ioaddr) & 15); -#endif - - sendto_srom(dev,dataval | DT_CLK, ioaddr); - udelay(10); - retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0); - } while (--cmd_len >= 0); - sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr); - - /* Terminate the EEPROM access. */ - sendto_srom(dev,SROM_RD | SROM_SR, ioaddr); - -#ifdef DEBUG_SROM - printf(" EEPROM result is 0x%5.5x.\n", retval); -#endif - - return retval; -} -#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ - -#ifndef CONFIG_TULIP_FIX_DAVICOM -static int read_srom(struct eth_device *dev, u_long ioaddr, int index) -{ - int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; - - return do_eeprom_cmd(dev, ioaddr, - (((SROM_READ_CMD << ee_addr_size) | index) << 16) - | 0xffff, 3 + ee_addr_size + 16); -} -#endif /* CONFIG_TULIP_FIX_DAVICOM */ - -#ifdef UPDATE_SROM -static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value) -{ - int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; - int i; - unsigned short newval; - - udelay(10*1000); /* test-only */ - -#ifdef DEBUG_SROM - printf("ee_addr_size=%d.\n", ee_addr_size); - printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); -#endif - - /* Enable programming modes. */ - do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size); - - /* Do the actual write. */ - do_eeprom_cmd(dev, ioaddr, - (((SROM_WRITE_CMD<enetaddr[0]); - int i, j = 0; - - for (i = 0; i < (ETH_ALEN >> 1); i++) { - tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i)); - *p = le16_to_cpu(tmp); - j += *p++; - } - - if ((j == 0) || (j == 0x2fffd)) { - memset (dev->enetaddr, 0, ETH_ALEN); - debug ("Warning: can't read HW address from SROM.\n"); - goto Done; - } - - return; - -Done: -#ifdef UPDATE_SROM - update_srom(dev, bis); -#endif - return; -} -#endif /* CONFIG_TULIP_FIX_DAVICOM */ - -#ifdef UPDATE_SROM -static void update_srom(struct eth_device *dev, bd_t *bis) -{ - int i; - static unsigned short eeprom[0x40] = { - 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ - 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ - 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ - 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ - 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ - 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ - }; - - /* Ethernet Addr... */ - eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff); - eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff); - eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff); - - for (i=0; i<0x40; i++) - { - write_srom(dev, DE4X5_APROM, i, eeprom[i]); - } -} -#endif /* UPDATE_SROM */ - -#endif diff --git a/drivers/dm9000x.c b/drivers/dm9000x.c deleted file mode 100644 index 6131b5c357..0000000000 --- a/drivers/dm9000x.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - dm9000.c: Version 1.2 12/15/2003 - - A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. - Copyright (C) 1997 Sten Wang - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. - -V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match - 06/22/2001 Support DM9801 progrmming - E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 - E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 - R17 = (R17 & 0xfff0) | NF + 3 - E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 - R17 = (R17 & 0xfff0) | NF - -v1.00 modify by simon 2001.9.5 - change for kernel 2.4.x - -v1.1 11/09/2001 fix force mode bug - -v1.2 03/18/2003 Weilun Huang : - Fixed phy reset. - Added tx/rx 32 bit mode. - Cleaned up for kernel merge. - --------------------------------------- - - 12/15/2003 Initial port to u-boot by Sascha Hauer - -TODO: Homerun NIC and longrun NIC are not functional, only internal at the - moment. -*/ - -#include -#include -#include -#include - -#ifdef CONFIG_DRIVER_DM9000 - -#include "dm9000x.h" - -/* Board/System/Debug information/definition ---------------- */ - -#define DM9801_NOISE_FLOOR 0x08 -#define DM9802_NOISE_FLOOR 0x05 - -/* #define CONFIG_DM9000_DEBUG */ - -#ifdef CONFIG_DM9000_DEBUG -#define DM9000_DBG(fmt,args...) printf(fmt ,##args) -#else /* */ -#define DM9000_DBG(fmt,args...) -#endif /* */ -enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD = - 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO = - 8, DM9000_1M_HPNA = 0x10 -}; -enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2 -}; - -/* Structure/enum declaration ------------------------------- */ -typedef struct board_info { - u32 runt_length_counter; /* counter: RX length < 64byte */ - u32 long_length_counter; /* counter: RX length > 1514byte */ - u32 reset_counter; /* counter: RESET */ - u32 reset_tx_timeout; /* RESET caused by TX Timeout */ - u32 reset_rx_status; /* RESET caused by RX Statsus wrong */ - u16 tx_pkt_cnt; - u16 queue_start_addr; - u16 dbug_cnt; - u8 phy_addr; - u8 device_wait_reset; /* device state */ - u8 nic_type; /* NIC type */ - unsigned char srom[128]; -} board_info_t; -board_info_t dmfe_info; - -/* For module input parameter */ -static int media_mode = DM9000_AUTO; -static u8 nfloor = 0; - -/* function declaration ------------------------------------- */ -int eth_init(bd_t * bd); -int eth_send(volatile void *, int); -int eth_rx(void); -void eth_halt(void); -static int dm9000_probe(void); -static u16 phy_read(int); -static void phy_write(int, u16); -u16 read_srom_word(int); -static u8 DM9000_ior(int); -static void DM9000_iow(int reg, u8 value); - -/* DM9000 network board routine ---------------------------- */ - -#define DM9000_outb(d,r) ( *(volatile u8 *)r = d ) -#define DM9000_outw(d,r) ( *(volatile u16 *)r = d ) -#define DM9000_outl(d,r) ( *(volatile u32 *)r = d ) -#define DM9000_inb(r) (*(volatile u8 *)r) -#define DM9000_inw(r) (*(volatile u16 *)r) -#define DM9000_inl(r) (*(volatile u32 *)r) - -#ifdef CONFIG_DM9000_DEBUG -static void -dump_regs(void) -{ - DM9000_DBG("\n"); - DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0)); - DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1)); - DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2)); - DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3)); - DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4)); - DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5)); - DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6)); - DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(ISR)); - DM9000_DBG("\n"); -} -#endif /* */ - -/* - Search DM9000 board, allocate space and register it -*/ -int -dm9000_probe(void) -{ - u32 id_val; - id_val = DM9000_ior(DM9000_VIDL); - id_val |= DM9000_ior(DM9000_VIDH) << 8; - id_val |= DM9000_ior(DM9000_PIDL) << 16; - id_val |= DM9000_ior(DM9000_PIDH) << 24; - if (id_val == DM9000_ID) { - printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE, - id_val); - return 0; - } else { - printf("dm9000 not found at 0x%08x id: 0x%08x\n", - CONFIG_DM9000_BASE, id_val); - return -1; - } -} - -/* Set PHY operationg mode -*/ -static void -set_PHY_mode(void) -{ - u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000; - if (!(media_mode & DM9000_AUTO)) { - switch (media_mode) { - case DM9000_10MHD: - phy_reg4 = 0x21; - phy_reg0 = 0x0000; - break; - case DM9000_10MFD: - phy_reg4 = 0x41; - phy_reg0 = 0x1100; - break; - case DM9000_100MHD: - phy_reg4 = 0x81; - phy_reg0 = 0x2000; - break; - case DM9000_100MFD: - phy_reg4 = 0x101; - phy_reg0 = 0x3100; - break; - } - phy_write(4, phy_reg4); /* Set PHY media mode */ - phy_write(0, phy_reg0); /* Tmp */ - } - DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */ - DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */ -} - -/* - Init HomeRun DM9801 -*/ -static void -program_dm9801(u16 HPNA_rev) -{ - __u16 reg16, reg17, reg24, reg25; - if (!nfloor) - nfloor = DM9801_NOISE_FLOOR; - reg16 = phy_read(16); - reg17 = phy_read(17); - reg24 = phy_read(24); - reg25 = phy_read(25); - switch (HPNA_rev) { - case 0xb900: /* DM9801 E3 */ - reg16 |= 0x1000; - reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000; - break; - case 0xb901: /* DM9801 E4 */ - reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200; - reg17 = (reg17 & 0xfff0) + nfloor + 3; - break; - case 0xb902: /* DM9801 E5 */ - case 0xb903: /* DM9801 E6 */ - default: - reg16 |= 0x1000; - reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200; - reg17 = (reg17 & 0xfff0) + nfloor; - } - phy_write(16, reg16); - phy_write(17, reg17); - phy_write(25, reg25); -} - -/* - Init LongRun DM9802 -*/ -static void -program_dm9802(void) -{ - __u16 reg25; - if (!nfloor) - nfloor = DM9802_NOISE_FLOOR; - reg25 = phy_read(25); - reg25 = (reg25 & 0xff00) + nfloor; - phy_write(25, reg25); -} - -/* Identify NIC type -*/ -static void -identify_nic(void) -{ - struct board_info *db = &dmfe_info; /* Point a board information structure */ - u16 phy_reg3; - DM9000_iow(DM9000_NCR, NCR_EXT_PHY); - phy_reg3 = phy_read(3); - switch (phy_reg3 & 0xfff0) { - case 0xb900: - if (phy_read(31) == 0x4404) { - db->nic_type = HOMERUN_NIC; - program_dm9801(phy_reg3); - DM9000_DBG("found homerun NIC\n"); - } else { - db->nic_type = LONGRUN_NIC; - DM9000_DBG("found longrun NIC\n"); - program_dm9802(); - } - break; - default: - db->nic_type = FASTETHER_NIC; - break; - } - DM9000_iow(DM9000_NCR, 0); -} - -/* General Purpose dm9000 reset routine */ -static void -dm9000_reset(void) -{ - DM9000_DBG("resetting\n"); - DM9000_iow(DM9000_NCR, NCR_RST); - udelay(1000); /* delay 1ms */ -} - -/* Initilize dm9000 board -*/ -int -eth_init(bd_t * bd) -{ - int i, oft, lnk; - DM9000_DBG("eth_init()\n"); - - /* RESET device */ - dm9000_reset(); - dm9000_probe(); - - /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ - identify_nic(); - - /* GPIO0 on pre-activate PHY */ - DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */ - - /* Set PHY */ - set_PHY_mode(); - - /* Program operating register */ - DM9000_iow(DM9000_NCR, 0x0); /* only intern phy supported by now */ - DM9000_iow(DM9000_TCR, 0); /* TX Polling clear */ - DM9000_iow(DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ - DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); /* Flow Control : High/Low Water */ - DM9000_iow(DM9000_FCR, 0x0); /* SH FIXME: This looks strange! Flow Control */ - DM9000_iow(DM9000_SMCR, 0); /* Special Mode */ - DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */ - DM9000_iow(DM9000_ISR, 0x0f); /* Clear interrupt status */ - - /* Set Node address */ - for (i = 0; i < 6; i++) - ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i); - - if (is_zero_ether_addr(bd->bi_enetaddr) || - is_multicast_ether_addr(bd->bi_enetaddr)) { - /* try reading from environment */ - u8 i; - char *s, *e; - s = getenv ("ethaddr"); - for (i = 0; i < 6; ++i) { - bd->bi_enetaddr[i] = s ? - simple_strtoul (s, &e, 16) : 0; - if (s) - s = (*e) ? e + 1 : e; - } - } - - printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0], - bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3], - bd->bi_enetaddr[4], bd->bi_enetaddr[5]); - for (i = 0, oft = 0x10; i < 6; i++, oft++) - DM9000_iow(oft, bd->bi_enetaddr[i]); - for (i = 0, oft = 0x16; i < 8; i++, oft++) - DM9000_iow(oft, 0xff); - - /* read back mac, just to be sure */ - for (i = 0, oft = 0x10; i < 6; i++, oft++) - DM9000_DBG("%02x:", DM9000_ior(oft)); - DM9000_DBG("\n"); - - /* Activate DM9000 */ - DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */ - DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */ - i = 0; - while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */ - udelay(1000); - i++; - if (i == 10000) { - printf("could not establish link\n"); - return 0; - } - } - - /* see what we've got */ - lnk = phy_read(17) >> 12; - printf("operating at "); - switch (lnk) { - case 1: - printf("10M half duplex "); - break; - case 2: - printf("10M full duplex "); - break; - case 4: - printf("100M half duplex "); - break; - case 8: - printf("100M full duplex "); - break; - default: - printf("unknown: %d ", lnk); - break; - } - printf("mode\n"); - return 0; -} - -/* - Hardware start transmission. - Send a packet to media from the upper layer. -*/ -int -eth_send(volatile void *packet, int length) -{ - char *data_ptr; - u32 tmplen, i; - int tmo; - DM9000_DBG("eth_send: length: %d\n", length); - for (i = 0; i < length; i++) { - if (i % 8 == 0) - DM9000_DBG("\nSend: 02x: ", i); - DM9000_DBG("%02x ", ((unsigned char *) packet)[i]); - } DM9000_DBG("\n"); - - /* Move data to DM9000 TX RAM */ - data_ptr = (char *) packet; - DM9000_outb(DM9000_MWCMD, DM9000_IO); - -#ifdef CONFIG_DM9000_USE_8BIT - /* Byte mode */ - for (i = 0; i < length; i++) - DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - tmplen = (length + 1) / 2; - for (i = 0; i < tmplen; i++) - DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmplen = (length + 3) / 4; - for (i = 0; i < tmplen; i++) - DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); - -#endif /* */ - - /* Set TX length to DM9000 */ - DM9000_iow(DM9000_TXPLL, length & 0xff); - DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff); - - /* Issue TX polling command */ - DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ - - /* wait for end of transmission */ - tmo = get_timer(0) + 5 * CFG_HZ; - while (DM9000_ior(DM9000_TCR) & TCR_TXREQ) { - if (get_timer(0) >= tmo) { - printf("transmission timeout\n"); - break; - } - } - DM9000_DBG("transmit done\n\n"); - return 0; -} - -/* - Stop the interface. - The interface is stopped when it is brought. -*/ -void -eth_halt(void) -{ - DM9000_DBG("eth_halt\n"); - - /* RESET devie */ - phy_write(0, 0x8000); /* PHY RESET */ - DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */ - DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */ - DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */ -} - -/* - Received a packet and pass to upper layer -*/ -int -eth_rx(void) -{ - u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; - u16 RxStatus, RxLen = 0; - u32 tmplen, i; -#ifdef CONFIG_DM9000_USE_32BIT - u32 tmpdata; -#endif - - /* Check packet ready or not */ - DM9000_ior(DM9000_MRCMDX); /* Dummy read */ - rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */ - if (rxbyte == 0) - return 0; - - /* Status check: this byte must be 0 or 1 */ - if (rxbyte > 1) { - DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */ - DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ - DM9000_DBG("rx status check: %d\n", rxbyte); - } - DM9000_DBG("receiving packet\n"); - - /* A packet ready now & Get status/length */ - DM9000_outb(DM9000_MRCMD, DM9000_IO); - -#ifdef CONFIG_DM9000_USE_8BIT - RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); - RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - RxStatus = DM9000_inw(DM9000_DATA); - RxLen = DM9000_inw(DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmpdata = DM9000_inl(DM9000_DATA); - RxStatus = tmpdata; - RxLen = tmpdata >> 16; - -#endif /* */ - DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); - - /* Move data from DM9000 */ - /* Read received packet from RX SRAM */ -#ifdef CONFIG_DM9000_USE_8BIT - for (i = 0; i < RxLen; i++) - rdptr[i] = DM9000_inb(DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_16BIT - tmplen = (RxLen + 1) / 2; - for (i = 0; i < tmplen; i++) - ((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA); - -#endif /* */ -#ifdef CONFIG_DM9000_USE_32BIT - tmplen = (RxLen + 3) / 4; - for (i = 0; i < tmplen; i++) - ((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA); - -#endif /* */ - if ((RxStatus & 0xbf00) || (RxLen < 0x40) - || (RxLen > DM9000_PKT_MAX)) { - if (RxStatus & 0x100) { - printf("rx fifo error\n"); - } - if (RxStatus & 0x200) { - printf("rx crc error\n"); - } - if (RxStatus & 0x8000) { - printf("rx length error\n"); - } - if (RxLen > DM9000_PKT_MAX) { - printf("rx length too big\n"); - dm9000_reset(); - } - } else { - - /* Pass to upper layer */ - DM9000_DBG("passing packet to upper layer\n"); - NetReceive(NetRxPackets[0], RxLen); - return RxLen; - } - return 0; -} - -/* - Read a word data from SROM -*/ -u16 -read_srom_word(int offset) -{ - DM9000_iow(DM9000_EPAR, offset); - DM9000_iow(DM9000_EPCR, 0x4); - udelay(8000); - DM9000_iow(DM9000_EPCR, 0x0); - return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8)); -} - -void -write_srom_word(int offset, u16 val) -{ - DM9000_iow(DM9000_EPAR, offset); - DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff)); - DM9000_iow(DM9000_EPDRL, (val & 0xff)); - DM9000_iow(DM9000_EPCR, 0x12); - udelay(8000); - DM9000_iow(DM9000_EPCR, 0); -} - - -/* - Read a byte from I/O port -*/ -static u8 -DM9000_ior(int reg) -{ - DM9000_outb(reg, DM9000_IO); - return DM9000_inb(DM9000_DATA); -} - -/* - Write a byte to I/O port -*/ -static void -DM9000_iow(int reg, u8 value) -{ - DM9000_outb(reg, DM9000_IO); - DM9000_outb(value, DM9000_DATA); -} - -/* - Read a word from phyxcer -*/ -static u16 -phy_read(int reg) -{ - u16 val; - - /* Fill the phyxcer register into REG_0C */ - DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); - DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */ - udelay(100); /* Wait read complete */ - DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */ - val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL); - - /* The read data keeps on REG_0D & REG_0E */ - DM9000_DBG("phy_read(%d): %d\n", reg, val); - return val; -} - -/* - Write a word to phyxcer -*/ -static void -phy_write(int reg, u16 value) -{ - - /* Fill the phyxcer register into REG_0C */ - DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); - - /* Fill the written data into REG_0D & REG_0E */ - DM9000_iow(DM9000_EPDRL, (value & 0xff)); - DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff)); - DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */ - udelay(500); /* Wait write complete */ - DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */ - DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value); -} -#endif /* CONFIG_DRIVER_DM9000 */ diff --git a/drivers/dm9000x.h b/drivers/dm9000x.h deleted file mode 100644 index f47ff8cb34..0000000000 --- a/drivers/dm9000x.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * dm9000 Ethernet - */ - -#ifdef CONFIG_DRIVER_DM9000 - -#define DM9000_ID 0x90000A46 -#define DM9000_PKT_MAX 1536 /* Received packet max size */ -#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */ - -/* although the registers are 16 bit, they are 32-bit aligned. - */ - -#define DM9000_NCR 0x00 -#define DM9000_NSR 0x01 -#define DM9000_TCR 0x02 -#define DM9000_TSR1 0x03 -#define DM9000_TSR2 0x04 -#define DM9000_RCR 0x05 -#define DM9000_RSR 0x06 -#define DM9000_ROCR 0x07 -#define DM9000_BPTR 0x08 -#define DM9000_FCTR 0x09 -#define DM9000_FCR 0x0A -#define DM9000_EPCR 0x0B -#define DM9000_EPAR 0x0C -#define DM9000_EPDRL 0x0D -#define DM9000_EPDRH 0x0E -#define DM9000_WCR 0x0F - -#define DM9000_PAR 0x10 -#define DM9000_MAR 0x16 - -#define DM9000_GPCR 0x1e -#define DM9000_GPR 0x1f -#define DM9000_TRPAL 0x22 -#define DM9000_TRPAH 0x23 -#define DM9000_RWPAL 0x24 -#define DM9000_RWPAH 0x25 - -#define DM9000_VIDL 0x28 -#define DM9000_VIDH 0x29 -#define DM9000_PIDL 0x2A -#define DM9000_PIDH 0x2B - -#define DM9000_CHIPR 0x2C -#define DM9000_SMCR 0x2F - -#define DM9000_PHY 0x40 /* PHY address 0x01 */ - -#define DM9000_MRCMDX 0xF0 -#define DM9000_MRCMD 0xF2 -#define DM9000_MRRL 0xF4 -#define DM9000_MRRH 0xF5 -#define DM9000_MWCMDX 0xF6 -#define DM9000_MWCMD 0xF8 -#define DM9000_MWRL 0xFA -#define DM9000_MWRH 0xFB -#define DM9000_TXPLL 0xFC -#define DM9000_TXPLH 0xFD -#define DM9000_ISR 0xFE -#define DM9000_IMR 0xFF - -#define NCR_EXT_PHY (1<<7) -#define NCR_WAKEEN (1<<6) -#define NCR_FCOL (1<<4) -#define NCR_FDX (1<<3) -#define NCR_LBK (3<<1) -#define NCR_RST (1<<0) - -#define NSR_SPEED (1<<7) -#define NSR_LINKST (1<<6) -#define NSR_WAKEST (1<<5) -#define NSR_TX2END (1<<3) -#define NSR_TX1END (1<<2) -#define NSR_RXOV (1<<1) - -#define TCR_TJDIS (1<<6) -#define TCR_EXCECM (1<<5) -#define TCR_PAD_DIS2 (1<<4) -#define TCR_CRC_DIS2 (1<<3) -#define TCR_PAD_DIS1 (1<<2) -#define TCR_CRC_DIS1 (1<<1) -#define TCR_TXREQ (1<<0) - -#define TSR_TJTO (1<<7) -#define TSR_LC (1<<6) -#define TSR_NC (1<<5) -#define TSR_LCOL (1<<4) -#define TSR_COL (1<<3) -#define TSR_EC (1<<2) - -#define RCR_WTDIS (1<<6) -#define RCR_DIS_LONG (1<<5) -#define RCR_DIS_CRC (1<<4) -#define RCR_ALL (1<<3) -#define RCR_RUNT (1<<2) -#define RCR_PRMSC (1<<1) -#define RCR_RXEN (1<<0) - -#define RSR_RF (1<<7) -#define RSR_MF (1<<6) -#define RSR_LCS (1<<5) -#define RSR_RWTO (1<<4) -#define RSR_PLE (1<<3) -#define RSR_AE (1<<2) -#define RSR_CE (1<<1) -#define RSR_FOE (1<<0) - -#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 ) -#define FCTR_LWOT(ot) ( ot & 0xf ) - -#define IMR_PAR (1<<7) -#define IMR_ROOM (1<<3) -#define IMR_ROM (1<<2) -#define IMR_PTM (1<<1) -#define IMR_PRM (1<<0) - -#endif diff --git a/drivers/e1000.c b/drivers/e1000.c deleted file mode 100644 index f0741da82b..0000000000 --- a/drivers/e1000.c +++ /dev/null @@ -1,3016 +0,0 @@ -/************************************************************************** -Inter Pro 1000 for ppcboot/das-u-boot -Drivers are port from Intel's Linux driver e1000-4.3.15 -and from Etherboot pro 1000 driver by mrakes at vivato dot net -tested on both gig copper and gig fiber boards -***************************************************************************/ -/******************************************************************************* - - - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ -/* - * Copyright (C) Archway Digital Solutions. - * - * written by Chrsitopher Li or - * 2/9/2002 - * - * Copyright (C) Linux Networx. - * Massive upgrade to work with the new intel gigabit NICs. - * - */ - -#include "e1000.h" - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_E1000) - -#define TOUT_LOOP 100000 - -#undef virt_to_bus -#define virt_to_bus(x) ((unsigned long)x) -#define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) -#define mdelay(n) udelay((n)*1000) - -#define E1000_DEFAULT_PBA 0x00000030 - -/* NIC specific static variables go here */ - -static char tx_pool[128 + 16]; -static char rx_pool[128 + 16]; -static char packet[2096]; - -static struct e1000_tx_desc *tx_base; -static struct e1000_rx_desc *rx_base; - -static int tx_tail; -static int rx_tail, rx_last; - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_COPPER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_FIBER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_COPPER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_LOM}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_COPPER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM}, -}; - -/* Function forward declarations */ -static int e1000_setup_link(struct eth_device *nic); -static int e1000_setup_fiber_link(struct eth_device *nic); -static int e1000_setup_copper_link(struct eth_device *nic); -static int e1000_phy_setup_autoneg(struct e1000_hw *hw); -static void e1000_config_collision_dist(struct e1000_hw *hw); -static int e1000_config_mac_to_phy(struct e1000_hw *hw); -static int e1000_config_fc_after_link_up(struct e1000_hw *hw); -static int e1000_check_for_link(struct eth_device *nic); -static int e1000_wait_autoneg(struct e1000_hw *hw); -static void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, - uint16_t * duplex); -static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, - uint16_t * phy_data); -static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, - uint16_t phy_data); -static void e1000_phy_hw_reset(struct e1000_hw *hw); -static int e1000_phy_reset(struct e1000_hw *hw); -static int e1000_detect_gig_phy(struct e1000_hw *hw); - -#define E1000_WRITE_REG(a, reg, value) (writel((value), ((a)->hw_addr + E1000_##reg))) -#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_##reg)) -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) (\ - writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2)))) -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + E1000_##reg + ((offset) << 2))) -#define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);} - -#ifndef CONFIG_AP1000 /* remove for warnings */ -/****************************************************************************** - * Raises the EEPROM's clock input. - * - * hw - Struct containing variables accessed by shared code - * eecd - EECD's current value - *****************************************************************************/ -static void -e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t * eecd) -{ - /* Raise the clock input to the EEPROM (by setting the SK bit), and then - * wait 50 microseconds. - */ - *eecd = *eecd | E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, *eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); -} - -/****************************************************************************** - * Lowers the EEPROM's clock input. - * - * hw - Struct containing variables accessed by shared code - * eecd - EECD's current value - *****************************************************************************/ -static void -e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t * eecd) -{ - /* Lower the clock input to the EEPROM (by clearing the SK bit), and then - * wait 50 microseconds. - */ - *eecd = *eecd & ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, *eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); -} - -/****************************************************************************** - * Shift data bits out to the EEPROM. - * - * hw - Struct containing variables accessed by shared code - * data - data to send to the EEPROM - * count - number of bits to shift out - *****************************************************************************/ -static void -e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count) -{ - uint32_t eecd; - uint32_t mask; - - /* We need to shift "count" bits out to the EEPROM. So, value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - */ - mask = 0x01 << (count - 1); - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - do { - /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", - * and then raising and then lowering the clock (the SK bit controls - * the clock input to the EEPROM). A "0" is shifted out to the EEPROM - * by setting "DI" to "0" and then raising and then lowering the clock. - */ - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - - udelay(50); - - e1000_raise_ee_clk(hw, &eecd); - e1000_lower_ee_clk(hw, &eecd); - - mask = mask >> 1; - - } while (mask); - - /* We leave the "DI" bit set to "0" when we leave this routine. */ - eecd &= ~E1000_EECD_DI; - E1000_WRITE_REG(hw, EECD, eecd); -} - -/****************************************************************************** - * Shift data bits in from the EEPROM - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw) -{ - uint32_t eecd; - uint32_t i; - uint16_t data; - - /* In order to read a register from the EEPROM, we need to shift 16 bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the "DO" - * bit. During this "shifting in" process the "DI" bit should always be - * clear.. - */ - - eecd = E1000_READ_REG(hw, EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < 16; i++) { - data = data << 1; - e1000_raise_ee_clk(hw, &eecd); - - eecd = E1000_READ_REG(hw, EECD); - - eecd &= ~(E1000_EECD_DI); - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_ee_clk(hw, &eecd); - } - - return data; -} - -/****************************************************************************** - * Prepares EEPROM for access - * - * hw - Struct containing variables accessed by shared code - * - * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This - * function should be called before issuing a command to the EEPROM. - *****************************************************************************/ -static void -e1000_setup_eeprom(struct e1000_hw *hw) -{ - uint32_t eecd; - - eecd = E1000_READ_REG(hw, EECD); - - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_SK | E1000_EECD_DI); - E1000_WRITE_REG(hw, EECD, eecd); - - /* Set CS */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); -} - -/****************************************************************************** - * Returns EEPROM to a "standby" state - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static void -e1000_standby_eeprom(struct e1000_hw *hw) -{ - uint32_t eecd; - - eecd = E1000_READ_REG(hw, EECD); - - /* Deselct EEPROM */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); - - /* Clock high */ - eecd |= E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); - - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); - - /* Clock low */ - eecd &= ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); -} - -/****************************************************************************** - * Reads a 16 bit word from the EEPROM. - * - * hw - Struct containing variables accessed by shared code - * offset - offset of word in the EEPROM to read - * data - word read from the EEPROM - *****************************************************************************/ -static int -e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t * data) -{ - uint32_t eecd; - uint32_t i = 0; - int large_eeprom = FALSE; - - /* Request EEPROM Access */ - if (hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - if (eecd & E1000_EECD_SIZE) - large_eeprom = TRUE; - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { - i++; - udelay(10); - eecd = E1000_READ_REG(hw, EECD); - } - if (!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } - } - - /* Prepare the EEPROM for reading */ - e1000_setup_eeprom(hw); - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3); - e1000_shift_out_ee_bits(hw, offset, (large_eeprom) ? 8 : 6); - - /* Read the data */ - *data = e1000_shift_in_ee_bits(hw); - - /* End this read operation */ - e1000_standby_eeprom(hw); - - /* Stop requesting EEPROM access */ - if (hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - } - - return 0; -} - -#if 0 -static void -e1000_eeprom_cleanup(struct e1000_hw *hw) -{ - uint32_t eecd; - - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); - E1000_WRITE_REG(hw, EECD, eecd); - e1000_raise_ee_clk(hw, &eecd); - e1000_lower_ee_clk(hw, &eecd); -} - -static uint16_t -e1000_wait_eeprom_done(struct e1000_hw *hw) -{ - uint32_t eecd; - uint32_t i; - - e1000_standby_eeprom(hw); - for (i = 0; i < 200; i++) { - eecd = E1000_READ_REG(hw, EECD); - if (eecd & E1000_EECD_DO) - return (TRUE); - udelay(5); - } - return (FALSE); -} - -static int -e1000_write_eeprom(struct e1000_hw *hw, uint16_t Reg, uint16_t Data) -{ - uint32_t eecd; - int large_eeprom = FALSE; - int i = 0; - - /* Request EEPROM Access */ - if (hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - if (eecd & E1000_EECD_SIZE) - large_eeprom = TRUE; - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { - i++; - udelay(5); - eecd = E1000_READ_REG(hw, EECD); - } - if (!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - return FALSE; - } - } - e1000_setup_eeprom(hw); - e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); - e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); - e1000_standby_eeprom(hw); - e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); - e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 8 : 6); - e1000_shift_out_ee_bits(hw, Data, 16); - if (!e1000_wait_eeprom_done(hw)) { - return FALSE; - } - e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); - e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); - e1000_eeprom_cleanup(hw); - - /* Stop requesting EEPROM access */ - if (hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - } - i = 0; - eecd = E1000_READ_REG(hw, EECD); - while (((eecd & E1000_EECD_GNT)) && (i < 500)) { - i++; - udelay(10); - eecd = E1000_READ_REG(hw, EECD); - } - if ((eecd & E1000_EECD_GNT)) { - DEBUGOUT("Could not release EEPROM grant\n"); - } - return TRUE; -} -#endif - -/****************************************************************************** - * Verifies that the EEPROM has a valid checksum - * - * hw - Struct containing variables accessed by shared code - * - * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is - * valid. - *****************************************************************************/ -static int -e1000_validate_eeprom_checksum(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint16_t checksum = 0; - uint16_t i, eeprom_data; - - DEBUGFUNC(); - - for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if (e1000_read_eeprom(hw, i, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - - if (checksum == (uint16_t) EEPROM_SUM) { - return 0; - } else { - DEBUGOUT("EEPROM Checksum Invalid\n"); - return -E1000_ERR_EEPROM; - } -} -#endif /* #ifndef CONFIG_AP1000 */ - -/****************************************************************************** - * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the - * second function of dual function devices - * - * nic - Struct containing variables accessed by shared code - *****************************************************************************/ -static int -e1000_read_mac_addr(struct eth_device *nic) -{ -#ifndef CONFIG_AP1000 - struct e1000_hw *hw = nic->priv; - uint16_t offset; - uint16_t eeprom_data; - int i; - - DEBUGFUNC(); - - for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { - offset = i >> 1; - if (e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - nic->enetaddr[i] = eeprom_data & 0xff; - nic->enetaddr[i + 1] = (eeprom_data >> 8) & 0xff; - } - if ((hw->mac_type == e1000_82546) && - (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { - /* Invert the last bit if this is the second device */ - nic->enetaddr[5] += 1; - } -#else - /* - * The AP1000's e1000 has no eeprom; the MAC address is stored in the - * environment variables. Currently this does not support the addition - * of a PMC e1000 card, which is certainly a possibility, so this should - * be updated to properly use the env variable only for the onboard e1000 - */ - - int ii; - char *s, *e; - - DEBUGFUNC(); - - s = getenv ("ethaddr"); - if (s == NULL){ - return -E1000_ERR_EEPROM; - } - else{ - for(ii = 0; ii < 6; ii++) { - nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0; - if (s){ - s = (*e) ? e + 1 : e; - } - } - } -#endif - return 0; -} - -/****************************************************************************** - * Initializes receive address filters. - * - * hw - Struct containing variables accessed by shared code - * - * Places the MAC address in receive address register 0 and clears the rest - * of the receive addresss registers. Clears the multicast table. Assumes - * the receiver is in reset when the routine is called. - *****************************************************************************/ -static void -e1000_init_rx_addrs(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t i; - uint32_t addr_low; - uint32_t addr_high; - - DEBUGFUNC(); - - /* Setup the receive address. */ - DEBUGOUT("Programming MAC Address into RAR[0]\n"); - addr_low = (nic->enetaddr[0] | - (nic->enetaddr[1] << 8) | - (nic->enetaddr[2] << 16) | (nic->enetaddr[3] << 24)); - - addr_high = (nic->enetaddr[4] | (nic->enetaddr[5] << 8) | E1000_RAH_AV); - - E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low); - E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high); - - /* Zero out the other 15 receive addresses. */ - DEBUGOUT("Clearing RAR[1-15]\n"); - for (i = 1; i < E1000_RAR_ENTRIES; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); - E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); - } -} - -/****************************************************************************** - * Clears the VLAN filer table - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static void -e1000_clear_vfta(struct e1000_hw *hw) -{ - uint32_t offset; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); -} - -/****************************************************************************** - * Set the mac type member in the hw struct. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -static int -e1000_set_mac_type(struct e1000_hw *hw) -{ - DEBUGFUNC(); - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - switch (hw->revision_id) { - case E1000_82542_2_0_REV_ID: - hw->mac_type = e1000_82542_rev2_0; - break; - case E1000_82542_2_1_REV_ID: - hw->mac_type = e1000_82542_rev2_1; - break; - default: - /* Invalid 82542 revision ID */ - return -E1000_ERR_MAC_TYPE; - } - break; - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - hw->mac_type = e1000_82543; - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - hw->mac_type = e1000_82544; - break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - hw->mac_type = e1000_82540; - break; - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - hw->mac_type = e1000_82545; - break; - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - hw->mac_type = e1000_82546; - break; - default: - /* Should never have loaded on this device */ - return -E1000_ERR_MAC_TYPE; - } - return E1000_SUCCESS; -} - -/****************************************************************************** - * Reset the transmit and receive units; mask and clear all interrupts. - * - * hw - Struct containing variables accessed by shared code - *****************************************************************************/ -void -e1000_reset_hw(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t ctrl_ext; - uint32_t icr; - uint32_t manc; - - DEBUGFUNC(); - - /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - pci_write_config_word(hw->pdev, PCI_COMMAND, - hw-> - pci_cmd_word & ~PCI_COMMAND_INVALIDATE); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC with - * the global reset. - */ - E1000_WRITE_REG(hw, RCTL, 0); - E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ - hw->tbi_compatibility_on = FALSE; - - /* Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - mdelay(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); - -#if 0 - if (hw->mac_type > e1000_82543) - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); - else -#endif - E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); - - /* 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 */ - mdelay(2); - } else { - /* Wait for EEPROM reload (it happens automatically) */ - mdelay(4); - /* Dissable HW ARPs on ASF enabled adapters */ - manc = E1000_READ_REG(hw, MANC); - manc &= ~(E1000_MANC_ARP_EN); - E1000_WRITE_REG(hw, MANC, manc); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, IMC, 0xffffffff); - - /* Clear any pending interrupt events. */ - icr = E1000_READ_REG(hw, ICR); - - /* If MWI was previously enabled, reenable it. */ - if (hw->mac_type == e1000_82542_rev2_0) { - pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); - } -} - -/****************************************************************************** - * Performs basic configuration of the adapter. - * - * hw - Struct containing variables accessed by shared code - * - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes the receive address registers, - * multicast table, and VLAN filter table. Calls routines to setup link - * configuration and flow control settings. Clears all on-chip counters. Leaves - * the transmit and receive units disabled and uninitialized. - *****************************************************************************/ -static int -e1000_init_hw(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t ctrl, status; - uint32_t i; - int32_t ret_val; - uint16_t pcix_cmd_word; - uint16_t pcix_stat_hi_word; - uint16_t cmd_mmrbc; - uint16_t stat_mmrbc; - e1000_bus_type bus_type = e1000_bus_type_unknown; - - DEBUGFUNC(); -#if 0 - /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if (ret_val < 0) { - DEBUGOUT("Error Initializing Identification LED\n"); - return ret_val; - } -#endif - /* 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; - } - - /* Disabling VLAN filtering. */ - DEBUGOUT("Initializing the IEEE VLAN\n"); - E1000_WRITE_REG(hw, VET, 0); - - e1000_clear_vfta(hw); - - /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - pci_write_config_word(hw->pdev, PCI_COMMAND, - hw-> - pci_cmd_word & ~PCI_COMMAND_INVALIDATE); - E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); - E1000_WRITE_FLUSH(hw); - mdelay(5); - } - - /* Setup the receive address. This involves initializing all of the Receive - * Address Registers (RARs 0 - 15). - */ - e1000_init_rx_addrs(nic); - - /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if (hw->mac_type == e1000_82542_rev2_0) { - E1000_WRITE_REG(hw, RCTL, 0); - E1000_WRITE_FLUSH(hw); - mdelay(1); - pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); - } - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < E1000_MC_TBL_SIZE; i++) - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - -#if 0 - /* Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. - */ - if (hw->dma_fairness) { - ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); - } -#endif - if (hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - bus_type = (status & E1000_STATUS_PCIX_MODE) ? - e1000_bus_type_pcix : e1000_bus_type_pci; - } - /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if (bus_type == e1000_bus_type_pcix) { - pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, - &pcix_cmd_word); - pci_read_config_word(hw->pdev, 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; - pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, - pcix_cmd_word); - } - } - - /* Call a subroutine to configure the link and setup flow control. */ - ret_val = e1000_setup_link(nic); - - /* Set the transmit descriptor write-back policy */ - if (hw->mac_type > e1000_82544) { - ctrl = E1000_READ_REG(hw, TXDCTL); - ctrl = - (ctrl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - E1000_WRITE_REG(hw, TXDCTL, ctrl); - } -#if 0 - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs(hw); -#endif - - return ret_val; -} - -/****************************************************************************** - * Configures flow control and link settings. - * - * hw - Struct containing variables accessed by shared code - * - * Determines which flow control settings to use. Calls the apropriate media- - * specific link configuration function. Configures the flow control settings. - * Assuming the adapter has a valid link partner, a valid link should be - * established. Assumes the hardware has previously been reset and the - * transmitter and receiver are not enabled. - *****************************************************************************/ -static int -e1000_setup_link(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t ctrl_ext; - int32_t ret_val; - uint16_t eeprom_data; - - DEBUGFUNC(); - -#ifndef CONFIG_AP1000 - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - if (e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } -#else - /* we have to hardcode the proper value for our hardware. */ - /* this value is for the 82540EM pci card used for prototyping, and it works. */ - eeprom_data = 0xb220; -#endif - - if (hw->fc == e1000_fc_default) { - if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = e1000_fc_none; - else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == - EEPROM_WORD0F_ASM_DIR) - hw->fc = e1000_fc_tx_pause; - else - hw->fc = e1000_fc_full; - } - - /* We want to save off the original Flow Control configuration just - * in case we get disconnected and then reconnected into a different - * hub or switch with different Flow Control capabilities. - */ - if (hw->mac_type == e1000_82542_rev2_0) - hw->fc &= (~e1000_fc_tx_pause); - - if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) - hw->fc &= (~e1000_fc_rx_pause); - - hw->original_fc = hw->fc; - - DEBUGOUT("After fix-ups FlowControl is now = %x\n", hw->fc); - - /* Take the 4 bits from EEPROM word 0x0F that determine the initial - * polarity value for the SW controlled pins, and setup the - * Extended Device Control reg with that info. - * This is needed because one of the SW controlled pins is used for - * signal detection. So this should be done before e1000_setup_pcs_link() - * or e1000_phy_setup() is called. - */ - if (hw->mac_type == e1000_82543) { - ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << - SWDPIO__EXT_SHIFT); - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - } - - /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_fiber) ? - e1000_setup_fiber_link(nic) : e1000_setup_copper_link(nic); - if (ret_val < 0) { - return ret_val; - } - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - DEBUGOUT - ("Initializing the Flow Control address, type and timer regs\n"); - - E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); - E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); - E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames in not enabled, then these - * registers will be set to 0. - */ - if (!(hw->fc & e1000_fc_tx_pause)) { - E1000_WRITE_REG(hw, FCRTL, 0); - E1000_WRITE_REG(hw, FCRTH, 0); - } else { - /* We need to set up the Receive Threshold high and low water marks - * as well as (optionally) enabling the transmission of XON frames. - */ - if (hw->fc_send_xon) { - E1000_WRITE_REG(hw, FCRTL, - (hw->fc_low_water | E1000_FCRTL_XONE)); - E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); - } else { - E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water); - E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); - } - } - return ret_val; -} - -/****************************************************************************** - * Sets up link for a fiber based adapter - * - * hw - Struct containing variables accessed by shared code - * - * Manipulates Physical Coding Sublayer functions in order to configure - * link. Assumes the hardware has been previously reset and the transmitter - * and receiver are not enabled. - *****************************************************************************/ -static int -e1000_setup_fiber_link(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t ctrl; - uint32_t status; - uint32_t txcw = 0; - uint32_t i; - uint32_t signal; - int32_t ret_val; - - DEBUGFUNC(); - /* On adapters with a MAC newer that 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 - */ - ctrl = E1000_READ_REG(hw, CTRL); - if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) - signal = E1000_CTRL_SWDPIN1; - else - signal = 0; - - printf("signal for %s is %x (ctrl %08x)!!!!\n", nic->name, signal, - ctrl); - /* Take the link out of reset */ - ctrl &= ~(E1000_CTRL_LRST); - - e1000_config_collision_dist(hw); - - /* Check for a software override of the flow control settings, and setup - * the device accordingly. If auto-negotiation is enabled, then software - * will have to set the "PAUSE" bits to the correct value in the Tranmsit - * Config Word Register (TXCW) and re-start auto-negotiation. However, if - * auto-negotiation is disabled, then software will have to manually - * configure the two flow control enable bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, but - * not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do - * not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - */ - switch (hw->fc) { - case e1000_fc_none: - /* Flow control is completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* RX Flow control is enabled and TX Flow control is disabled by a - * software over-ride. Since there really isn't a way to advertise - * that we are capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later, we will - * disable the adapter's ability to send PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* TX Flow control is enabled, and RX Flow control is disabled, by a - * software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* Flow control (both RX and TX) is enabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - break; - } - - /* Since auto-negotiation is enabled, take the link out of reset (the link - * will be in reset, because we previously reset the chip). This will - * restart auto-negotiation. If auto-neogtiation is successful then the - * link-up status bit will be set and the flow control enable bits (RFCE - * and TFCE) will be set according to their negotiated value. - */ - DEBUGOUT("Auto-negotiation enabled (%#x)\n", txcw); - - E1000_WRITE_REG(hw, TXCW, txcw); - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - hw->txcw = txcw; - mdelay(1); - - /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" - * 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). - */ - if ((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { - DEBUGOUT("Looking for Link\n"); - for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { - mdelay(10); - status = E1000_READ_REG(hw, STATUS); - 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(nic); - if (ret_val < 0) { - DEBUGOUT("Error while checking for link\n"); - return ret_val; - } - hw->autoneg_failed = 0; - } else { - hw->autoneg_failed = 0; - DEBUGOUT("Valid Link Found\n"); - } - } else { - DEBUGOUT("No Signal Detected\n"); - return -E1000_ERR_NOLINK; - } - return 0; -} - -/****************************************************************************** -* Detects which PHY is present and the speed and duplex -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int -e1000_setup_copper_link(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t ctrl; - int32_t ret_val; - uint16_t i; - uint16_t phy_data; - - DEBUGFUNC(); - - ctrl = E1000_READ_REG(hw, CTRL); - /* With 82543, we need to force speed and duplex on the MAC equal to what - * the PHY speed and duplex configuration is. In addition, we need to - * perform a hardware reset on the PHY to take it out of reset. - */ - if (hw->mac_type > e1000_82543) { - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, CTRL, ctrl); - } else { - ctrl |= - (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); - E1000_WRITE_REG(hw, CTRL, ctrl); - e1000_phy_hw_reset(hw); - } - - /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if (ret_val < 0) { - DEBUGOUT("Error, did not detect valid phy.\n"); - return ret_val; - } - DEBUGOUT("Phy ID = %x \n", hw->phy_id); - - /* 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; - -#if 0 - /* 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; - } -#else - phy_data |= M88E1000_PSCR_AUTO_X_MODE; -#endif - -#if 0 - /* 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; -#else - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; -#endif - 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 (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; - /* 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; - } - - /* 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; - } - - /* 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. - */ - /* 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; - - 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 (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; - } -#if 0 - /* 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"); - return ret_val; - } - } -#else - /* If we do not wait for autonegtation to complete I - * do not see a valid link status. - */ - ret_val = e1000_wait_autoneg(hw); - if (ret_val < 0) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); - return ret_val; - } -#endif - - /* 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 (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 - * if we are on 82543. If we - * are on newer silicon, we only need to configure - * collision distance in the Transmit Control Register. - * 2) Set up flow control on the MAC to that established with - * the link partner. - */ - if (hw->mac_type >= e1000_82544) { - e1000_config_collision_dist(hw); - } else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val < 0) { - DEBUGOUT - ("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val < 0) { - DEBUGOUT("Error Configuring Flow Control\n"); - return ret_val; - } - DEBUGOUT("Valid link established!!!\n"); - return 0; - } - udelay(10); - } - - DEBUGOUT("Unable to establish link!!!\n"); - return -E1000_ERR_NOLINK; -} - -/****************************************************************************** -* Configures PHY autoneg and flow control advertisement settings -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int -e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - uint16_t mii_autoneg_adv_reg; - uint16_t mii_1000t_ctrl_reg; - - DEBUGFUNC(); - - /* 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; - } - - /* 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; - } - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - DEBUGOUT("autoneg_advertised %x\n", hw->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_HALF) { - DEBUGOUT("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_FULL) { - DEBUGOUT("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_HALF) { - DEBUGOUT("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_FULL) { - DEBUGOUT("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { - DEBUGOUT - ("Advertise 1000mb Half duplex requested, request denied!\n"); - } - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { - DEBUGOUT("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc) { - case e1000_fc_none: /* 0 */ - /* Flow control (RX & TX) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_rx_pause: /* 1 */ - /* RX Flow control is enabled, and TX Flow control is - * disabled, by a software over-ride. - */ - /* Since there really isn't a way to advertise that we are - * capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - *hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_tx_pause: /* 2 */ - /* TX Flow control is enabled, and RX Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case e1000_fc_full: /* 3 */ - /* Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - 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; - } - - DEBUGOUT("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; -} - -/****************************************************************************** -* Sets the collision distance in the Transmit Control register -* -* hw - Struct containing variables accessed by shared code -* -* Link should have been established previously. Reads the speed and duplex -* information from the Device Status register. -******************************************************************************/ -static void -e1000_config_collision_dist(struct e1000_hw *hw) -{ - uint32_t tctl; - - tctl = E1000_READ_REG(hw, TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - E1000_WRITE_REG(hw, TCTL, tctl); - E1000_WRITE_FLUSH(hw); -} - -/****************************************************************************** -* Sets MAC speed and duplex settings to reflect the those in the PHY -* -* hw - Struct containing variables accessed by shared code -* mii_reg - data to write to the MII control register -* -* The contents of the PHY register containing the needed information need to -* be passed in. -******************************************************************************/ -static int -e1000_config_mac_to_phy(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint16_t phy_data; - - DEBUGFUNC(); - - /* Read the Device Control Register and set the bits to Force Speed - * and Duplex. - */ - ctrl = E1000_READ_REG(hw, CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); - - /* Set up duplex in the Device Control and Transmit Control - * registers depending on negotiated values. - */ - if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if (phy_data & M88E1000_PSSR_DPLX) - ctrl |= E1000_CTRL_FD; - else - ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); - - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - /* Write the configured values back to the Device Control Reg. */ - E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; -} - -/****************************************************************************** - * Forces the MAC's flow control settings. - * - * hw - Struct containing variables accessed by shared code - * - * Sets the TFCE and RFCE bits in the device control register to reflect - * the adapter settings. TFCE and RFCE need to be explicitly set by - * software when a Copper PHY is used because autonegotiation is managed - * by the PHY rather than the MAC. Software must also configure these - * bits when link is forced on a fiber connection. - *****************************************************************************/ -static int -e1000_force_mac_fc(struct e1000_hw *hw) -{ - uint32_t ctrl; - - DEBUGFUNC(); - - /* Get the current configuration of the Device Control Register */ - ctrl = E1000_READ_REG(hw, CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and TX flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - - switch (hw->fc) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - /* Disable TX Flow Control for 82542 (rev 2.0) */ - if (hw->mac_type == e1000_82542_rev2_0) - ctrl &= (~E1000_CTRL_TFCE); - - E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; -} - -/****************************************************************************** - * Configures flow control settings after link is established - * - * hw - Struct containing variables accessed by shared code - * - * Should be called immediately after a valid link has been established. - * Forces MAC flow control settings if link was forced. When in MII/GMII mode - * and autonegotiation is enabled, the MAC flow control settings will be set - * based on the flow control negotiated by the PHY. In TBI mode, the TFCE - * and RFCE bits will be automaticaly set to the negotiated flow control mode. - *****************************************************************************/ -static int -e1000_config_fc_after_link_up(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t mii_status_reg; - uint16_t mii_nway_adv_reg; - uint16_t mii_nway_lp_ability_reg; - uint16_t speed; - uint16_t duplex; - - DEBUGFUNC(); - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if ((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) { - ret_val = e1000_force_mac_fc(hw); - if (ret_val < 0) { - DEBUGOUT("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if (hw->media_type == e1000_media_type_copper) { - /* Read the MII Status Register and check to see if AutoNeg - * 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 (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement Register - * (Address 4) and the Auto_Negotiation Base Page Ability - * 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; - } - - /* Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - */ - /* Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | e1000_fc_full - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* Now we need to check if the user selected RX ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->original_fc == e1000_fc_full) { - hw->fc = e1000_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); - } else { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT - ("Flow Control = RX PAUSE frames only.\r\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = e1000_fc_tx_pause; - DEBUGOUT - ("Flow Control = TX PAUSE frames only.\r\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT - ("Flow Control = RX PAUSE frames only.\r\n"); - } - /* Per the IEEE spec, at this point flow control should be - * disabled. However, we want to consider that we could - * be connected to a legacy switch that doesn't advertise - * desired flow control, but can be forced on the link - * partner. So if we advertised no flow control, that is - * what we will resolve to. If we advertised some kind of - * receive capability (Rx Pause Only or Full Flow Control) - * and the link partner advertised none, we will configure - * ourselves to enable Rx Flow Control only. We can do - * this safely for two reasons: If the link partner really - * didn't want flow control enabled, and we enable Rx, no - * harm done since we won't be receiving any PAUSE frames - * anyway. If the intent on the link partner was to have - * flow control enabled, then by us enabling RX only, we - * can at least receive pause frames and process them. - * This is a good idea because in most cases, since we are - * predominantly a server NIC, more times than not we will - * be asked to delay transmission of packets than asking - * our link partner to pause transmission of frames. - */ - else if (hw->original_fc == e1000_fc_none || - hw->original_fc == e1000_fc_tx_pause) { - hw->fc = e1000_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); - } else { - hw->fc = e1000_fc_rx_pause; - DEBUGOUT - ("Flow Control = RX PAUSE frames only.\r\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - e1000_get_speed_and_duplex(hw, &speed, &duplex); - - if (duplex == HALF_DUPLEX) - hw->fc = e1000_fc_none; - - /* 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) { - DEBUGOUT - ("Error forcing flow control settings\n"); - return ret_val; - } - } else { - DEBUGOUT - ("Copper PHY and Auto Neg has not completed.\r\n"); - } - } - return 0; -} - -/****************************************************************************** - * Checks to see if the link status of the hardware has changed. - * - * hw - Struct containing variables accessed by shared code - * - * Called by any function that needs to check the link status of the adapter. - *****************************************************************************/ -static int -e1000_check_for_link(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - uint32_t rxcw; - uint32_t ctrl; - uint32_t status; - uint32_t rctl; - uint32_t signal; - int32_t ret_val; - uint16_t phy_data; - uint16_t lp_capability; - - DEBUGFUNC(); - - /* On adapters with a MAC newer that 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 - */ - ctrl = E1000_READ_REG(hw, CTRL); - if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) - signal = E1000_CTRL_SWDPIN1; - else - signal = 0; - - status = E1000_READ_REG(hw, STATUS); - rxcw = E1000_READ_REG(hw, RXCW); - DEBUGOUT("ctrl: %#08x status %#08x rxcw %#08x\n", ctrl, status, rxcw); - - /* If we have a copper PHY then we only want to go out to the PHY - * registers to see if Auto-Neg has completed and/or if our link - * status has changed. The get_link_status flag will be set if we - * receive a Link Status Change interrupt or we have Rx Sequence - * Errors. - */ - if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * 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 (phy_data & MII_SR_LINK_STATUS) { - hw->get_link_status = FALSE; - } else { - /* No link detected */ - return -E1000_ERR_NOLINK; - } - - /* 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 - * configuration. So we only need to configure Collision - * Distance in the MAC. Otherwise, we need to force - * speed/duplex on the MAC to the current PHY speed/duplex - * settings. - */ - if (hw->mac_type >= e1000_82544) - e1000_config_collision_dist(hw); - else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val < 0) { - DEBUGOUT - ("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - - /* Configure Flow Control now that Auto-Neg has completed. First, we - * 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) { - DEBUGOUT("Error configuring flow control\n"); - return ret_val; - } - - /* At this point we know that we are on copper and we have - * auto-negotiated link. These are conditions for checking the link - * parter capability register. We use the link partner capability to - * determine if TBI Compatibility needs to be turned on or off. If - * the link partner advertises any speed in addition to Gigabit, then - * we assume that they are GMII-based, and TBI compatibility is not - * needed. If no other speeds are advertised, we assume the link - * 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 (lp_capability & (NWAY_LPAR_10T_HD_CAPS | - NWAY_LPAR_10T_FD_CAPS | - NWAY_LPAR_100TX_HD_CAPS | - NWAY_LPAR_100TX_FD_CAPS | - NWAY_LPAR_100T4_CAPS)) { - /* If our link partner advertises anything in addition to - * gigabit, we do not need to enable TBI compatibility. - */ - if (hw->tbi_compatibility_on) { - /* If we previously were in the mode, turn it off. */ - rctl = E1000_READ_REG(hw, RCTL); - rctl &= ~E1000_RCTL_SBP; - E1000_WRITE_REG(hw, RCTL, rctl); - hw->tbi_compatibility_on = FALSE; - } - } else { - /* If TBI compatibility is was previously off, turn it on. For - * compatibility with a TBI link partner, we will store bad - * packets. Some frames have an additional byte on the end and - * will look like CRC errors to to the hardware. - */ - if (!hw->tbi_compatibility_on) { - hw->tbi_compatibility_on = TRUE; - rctl = E1000_READ_REG(hw, RCTL); - rctl |= E1000_RCTL_SBP; - E1000_WRITE_REG(hw, RCTL, rctl); - } - } - } - } - /* If we don't have link (auto-negotiation failed or link partner cannot - * auto-negotiate), the cable is plugged in (we have signal), and our - * link partner is not trying to auto-negotiate with us (we are receiving - * idles or data), we need to force link up. We also need to give - * auto-negotiation time to complete, in case the cable was just plugged - * in. The autoneg_failed flag does this. - */ - else if ((hw->media_type == e1000_media_type_fiber) && - (!(status & E1000_STATUS_LU)) && - ((ctrl & E1000_CTRL_SWDPIN1) == signal) && - (!(rxcw & E1000_RXCW_C))) { - if (hw->autoneg_failed == 0) { - hw->autoneg_failed = 1; - return 0; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - 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) { - DEBUGOUT("Error configuring flow control\n"); - return ret_val; - } - } - /* If we are forcing link and we are receiving /C/ ordered sets, re-enable - * auto-negotiation in the TXCW register and disable forced link in the - * Device Control register in an attempt to auto-negotiate with our link - * partner. - */ - else if ((hw->media_type == e1000_media_type_fiber) && - (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - DEBUGOUT - ("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); - E1000_WRITE_REG(hw, TXCW, hw->txcw); - E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); - } - return 0; -} - -/****************************************************************************** - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - *****************************************************************************/ -static void -e1000_get_speed_and_duplex(struct e1000_hw *hw, - uint16_t * speed, uint16_t * duplex) -{ - uint32_t status; - - DEBUGFUNC(); - - if (hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if (status & E1000_STATUS_SPEED_1000) { - *speed = SPEED_1000; - DEBUGOUT("1000 Mbs, "); - } else if (status & E1000_STATUS_SPEED_100) { - *speed = SPEED_100; - DEBUGOUT("100 Mbs, "); - } else { - *speed = SPEED_10; - DEBUGOUT("10 Mbs, "); - } - - if (status & E1000_STATUS_FD) { - *duplex = FULL_DUPLEX; - DEBUGOUT("Full Duplex\r\n"); - } else { - *duplex = HALF_DUPLEX; - DEBUGOUT(" Half Duplex\r\n"); - } - } else { - DEBUGOUT("1000 Mbs, Full Duplex\r\n"); - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - } -} - -/****************************************************************************** -* Blocks until autoneg completes or times out (~4.5 seconds) -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int -e1000_wait_autoneg(struct e1000_hw *hw) -{ - uint16_t i; - uint16_t phy_data; - - DEBUGFUNC(); - DEBUGOUT("Waiting for Auto-Neg to complete.\n"); - - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { - /* 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 (phy_data & MII_SR_AUTONEG_COMPLETE) { - DEBUGOUT("Auto-Neg complete.\n"); - return 0; - } - mdelay(100); - } - DEBUGOUT("Auto-Neg timedout.\n"); - return -E1000_ERR_TIMEOUT; -} - -/****************************************************************************** -* Raises the Management Data Clock -* -* hw - Struct containing variables accessed by shared code -* ctrl - Device control register's current value -******************************************************************************/ -static void -e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) -{ - /* Raise the clock input to the Management Data Clock (by setting the MDC - * bit), and then delay 2 microseconds. - */ - E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - udelay(2); -} - -/****************************************************************************** -* Lowers the Management Data Clock -* -* hw - Struct containing variables accessed by shared code -* ctrl - Device control register's current value -******************************************************************************/ -static void -e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) -{ - /* Lower the clock input to the Management Data Clock (by clearing the MDC - * bit), and then delay 2 microseconds. - */ - E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - udelay(2); -} - -/****************************************************************************** -* Shifts data bits out to the PHY -* -* hw - Struct containing variables accessed by shared code -* data - Data to send out to the PHY -* count - Number of bits to shift out -* -* Bits are shifted out in MSB to LSB order. -******************************************************************************/ -static void -e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count) -{ - uint32_t ctrl; - uint32_t mask; - - /* We need to shift "count" number of bits out to the PHY. So, the value - * in the "data" parameter will be shifted out to the PHY one bit at a - * time. In order to do this, "data" must be broken down into bits. - */ - mask = 0x01; - mask <<= (count - 1); - - ctrl = E1000_READ_REG(hw, CTRL); - - /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ - ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - - while (mask) { - /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and - * then raising and lowering the Management Data Clock. A "0" is - * shifted out to the PHY by setting the MDIO bit to "0" and then - * raising and lowering the clock. - */ - if (data & mask) - ctrl |= E1000_CTRL_MDIO; - else - ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - udelay(2); - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - mask = mask >> 1; - } -} - -/****************************************************************************** -* Shifts data bits in from the PHY -* -* hw - Struct containing variables accessed by shared code -* -* Bits are shifted in in MSB to LSB order. -******************************************************************************/ -static uint16_t -e1000_shift_in_mdi_bits(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint16_t data = 0; - uint8_t i; - - /* In order to read a register from the PHY, we need to shift in a total - * of 18 bits from the PHY. The first two bit (turnaround) times are used - * to avoid contention on the MDIO pin when a read operation is performed. - * These two bits are ignored by us and thrown away. Bits are "shifted in" - * by raising the input to the Management Data Clock (setting the MDC bit), - * and then reading the value of the MDIO bit. - */ - ctrl = E1000_READ_REG(hw, CTRL); - - /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */ - ctrl &= ~E1000_CTRL_MDIO_DIR; - ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - /* Raise and Lower the clock before reading in the data. This accounts for - * the turnaround bits. The first clock occurred when we clocked out the - * last bit of the Register Address. - */ - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - for (data = 0, i = 0; i < 16; i++) { - data = data << 1; - e1000_raise_mdi_clk(hw, &ctrl); - ctrl = E1000_READ_REG(hw, CTRL); - /* Check to see if we shifted in a "1". */ - if (ctrl & E1000_CTRL_MDIO) - data |= 1; - e1000_lower_mdi_clk(hw, &ctrl); - } - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - return data; -} - -/***************************************************************************** -* Reads the value from a PHY register -* -* hw - Struct containing variables accessed by shared code -* reg_addr - address of the PHY register to read -******************************************************************************/ -static int -e1000_read_phy_reg(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; - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - DEBUGOUT("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, and register address in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - E1000_WRITE_REG(hw, MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed */ - for (i = 0; i < 64; i++) { - udelay(10); - mdic = E1000_READ_REG(hw, MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (uint16_t) mdic; - } else { - /* We must first send a preamble through the MDIO pin to signal the - * beginning of an MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the next few fields that are required for a read - * operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine five different times. The format of - * a MII read instruction consists of a shift out of 14 bits and is - * defined as follows: - * - * followed by a shift in of 18 bits. This first two bits shifted in - * are TurnAround bits used to avoid contention on the MDIO pin when a - * READ operation is performed. These two bits are thrown away - * followed by a shift in of 16 bits which contains the desired data. - */ - mdic = ((reg_addr) | (phy_addr << 5) | - (PHY_OP_READ << 10) | (PHY_SOF << 12)); - - e1000_shift_out_mdi_bits(hw, mdic, 14); - - /* Now that we've shifted out the read command to the MII, we need to - * "shift in" the 16-bit value (18 total bits) of the requested PHY - * register address. - */ - *phy_data = e1000_shift_in_mdi_bits(hw); - } - return 0; -} - -/****************************************************************************** -* Writes a value to a PHY register -* -* hw - Struct containing variables accessed by shared code -* reg_addr - address of the PHY register to write -* data - data to write to the PHY -******************************************************************************/ -static int -e1000_write_phy_reg(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; - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - DEBUGOUT("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, register address, and data intended - * for the PHY register in the MDI Control register. The MAC will take - * care of interfacing with the PHY to send the desired data. - */ - mdic = (((uint32_t) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - E1000_WRITE_REG(hw, MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed */ - for (i = 0; i < 64; i++) { - udelay(10); - mdic = E1000_READ_REG(hw, MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } else { - /* We'll need to use the SW defined pins to shift the write command - * out to the PHY. We first send a preamble to the PHY to signal the - * beginning of the MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the remaining required fields that will indicate a - * write operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine for each field in the command. The - * format of a MII write instruction is as follows: - * . - */ - mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | - (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); - mdic <<= 16; - mdic |= (uint32_t) phy_data; - - e1000_shift_out_mdi_bits(hw, mdic, 32); - } - return 0; -} - -/****************************************************************************** -* Returns the PHY to the power-on reset state -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static void -e1000_phy_hw_reset(struct e1000_hw *hw) -{ - uint32_t ctrl; - uint32_t ctrl_ext; - - DEBUGFUNC(); - - DEBUGOUT("Resetting Phy...\n"); - - if (hw->mac_type > e1000_82543) { - /* Read the device control register and assert the E1000_CTRL_PHY_RST - * bit. Then, take it out of reset. - */ - ctrl = E1000_READ_REG(hw, CTRL); - E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(hw); - mdelay(10); - E1000_WRITE_REG(hw, CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - } else { - /* Read the Extended Device Control Register, assert the PHY_RESET_DIR - * bit to put the PHY into reset. Then, take it out of reset. - */ - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; - ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - mdelay(10); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - } - udelay(150); -} - -/****************************************************************************** -* Resets the PHY -* -* hw - Struct containing variables accessed by shared code -* -* Sets bit 15 of the MII Control regiser -******************************************************************************/ -static int -e1000_phy_reset(struct e1000_hw *hw) -{ - uint16_t phy_data; - - DEBUGFUNC(); - - 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); - return 0; -} - -/****************************************************************************** -* Probes the expected PHY address for known PHY IDs -* -* hw - Struct containing variables accessed by shared code -******************************************************************************/ -static int -e1000_detect_gig_phy(struct e1000_hw *hw) -{ - uint16_t phy_id_high, phy_id_low; - int match = FALSE; - - DEBUGFUNC(); - - /* 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; - } - hw->phy_id = (uint32_t) (phy_id_high << 16); - udelay(2); - if (e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); - - switch (hw->mac_type) { - case e1000_82543: - if (hw->phy_id == M88E1000_E_PHY_ID) - match = TRUE; - break; - case e1000_82544: - if (hw->phy_id == M88E1000_I_PHY_ID) - match = TRUE; - break; - case e1000_82540: - case e1000_82545: - case e1000_82546: - if (hw->phy_id == M88E1011_I_PHY_ID) - match = TRUE; - break; - default: - DEBUGOUT("Invalid MAC type %d\n", hw->mac_type); - return -E1000_ERR_CONFIG; - } - if (match) { - DEBUGOUT("PHY ID 0x%X detected\n", hw->phy_id); - return 0; - } - DEBUGOUT("Invalid PHY ID 0x%X\n", hw->phy_id); - return -E1000_ERR_PHY; -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * - * e1000_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - **/ - -static int -e1000_sw_init(struct eth_device *nic, int cardnum) -{ - struct e1000_hw *hw = (typeof(hw)) nic->priv; - int result; - - /* PCI config space info */ - pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id); - pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id); - pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID, - &hw->subsystem_vendor_id); - pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id); - - pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id); - pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word); - - /* identify the MAC */ - result = e1000_set_mac_type(hw); - if (result) { - E1000_ERR("Unknown MAC Type\n"); - return result; - } - - /* lan a vs. lan b settings */ - if (hw->mac_type == e1000_82546) - /*this also works w/ multiple 82546 cards */ - /*but not if they're intermingled /w other e1000s */ - hw->lan_loc = (cardnum % 2) ? e1000_lan_b : e1000_lan_a; - else - hw->lan_loc = e1000_lan_a; - - /* flow control settings */ - hw->fc_high_water = E1000_FC_HIGH_THRESH; - hw->fc_low_water = E1000_FC_LOW_THRESH; - hw->fc_pause_time = E1000_FC_PAUSE_TIME; - hw->fc_send_xon = 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) { - DEBUGOUT("fiber interface\n"); - hw->media_type = e1000_media_type_fiber; - } else { - DEBUGOUT("copper interface\n"); - hw->media_type = e1000_media_type_copper; - } - } else { - hw->media_type = e1000_media_type_fiber; - } - - if (hw->mac_type < e1000_82543) - hw->report_tx_early = 0; - else - hw->report_tx_early = 1; - - hw->tbi_compatibility_en = TRUE; -#if 0 - hw->wait_autoneg_complete = FALSE; - hw->adaptive_ifs = TRUE; - - /* Copper options */ - if (hw->media_type == e1000_media_type_copper) { - hw->mdix = AUTO_ALL_MODES; - hw->disable_polarity_correction = FALSE; - } -#endif - return E1000_SUCCESS; -} - -void -fill_rx(struct e1000_hw *hw) -{ - struct e1000_rx_desc *rd; - - rx_last = rx_tail; - rd = rx_base + rx_tail; - rx_tail = (rx_tail + 1) % 8; - memset(rd, 0, 16); - rd->buffer_addr = cpu_to_le64((u32) & packet); - E1000_WRITE_REG(hw, RDT, rx_tail); -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ - -static void -e1000_configure_tx(struct e1000_hw *hw) -{ - unsigned long ptr; - unsigned long tctl; - unsigned long tipg; - - ptr = (u32) tx_pool; - if (ptr & 0xf) - ptr = (ptr + 0x10) & (~0xf); - - tx_base = (typeof(tx_base)) ptr; - - E1000_WRITE_REG(hw, TDBAL, (u32) tx_base); - E1000_WRITE_REG(hw, TDBAH, 0); - - E1000_WRITE_REG(hw, TDLEN, 128); - - /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG(hw, TDH, 0); - E1000_WRITE_REG(hw, TDT, 0); - tx_tail = 0; - - /* Set the default values for the Tx Inter Packet Gap timer */ - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - tipg = DEFAULT_82542_TIPG_IPGT; - tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - break; - default: - if (hw->media_type == e1000_media_type_fiber) - tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; - } - E1000_WRITE_REG(hw, TIPG, tipg); -#if 0 - /* Set the Tx Interrupt Delay register */ - E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); - if (hw->mac_type >= e1000_82540) - E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); -#endif - /* Program the Transmit Control Register */ - tctl = E1000_READ_REG(hw, TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - E1000_WRITE_REG(hw, TCTL, tctl); - - e1000_config_collision_dist(hw); -#if 0 - /* Setup Transmit Descriptor Settings for this adapter */ - adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE; - - if (adapter->hw.report_tx_early == 1) - adapter->txd_cmd |= E1000_TXD_CMD_RS; - else - adapter->txd_cmd |= E1000_TXD_CMD_RPS; -#endif -} - -/** - * e1000_setup_rctl - configure the receive control register - * @adapter: Board private structure - **/ -static void -e1000_setup_rctl(struct e1000_hw *hw) -{ - uint32_t rctl; - - rctl = E1000_READ_REG(hw, RCTL); - - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF; /* | - (hw.mc_filter_type << E1000_RCTL_MO_SHIFT); */ - - if (hw->tbi_compatibility_on == 1) - rctl |= E1000_RCTL_SBP; - else - rctl &= ~E1000_RCTL_SBP; - - rctl &= ~(E1000_RCTL_SZ_4096); -#if 0 - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: -#endif - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); -#if 0 - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; - break; - } -#endif - E1000_WRITE_REG(hw, RCTL, rctl); -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void -e1000_configure_rx(struct e1000_hw *hw) -{ - unsigned long ptr; - unsigned long rctl; -#if 0 - unsigned long rxcsum; -#endif - rx_tail = 0; - /* make sure receives are disabled while setting up the descriptors */ - rctl = E1000_READ_REG(hw, RCTL); - E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); -#if 0 - /* set the Receive Delay Timer Register */ - - E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); -#endif - if (hw->mac_type >= e1000_82540) { -#if 0 - E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); -#endif - /* Set the interrupt throttling rate. Value is calculated - * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) - E1000_WRITE_REG(hw, ITR, DEFAULT_ITR); - } - - /* Setup the Base and Length of the Rx Descriptor Ring */ - ptr = (u32) rx_pool; - if (ptr & 0xf) - ptr = (ptr + 0x10) & (~0xf); - rx_base = (typeof(rx_base)) ptr; - E1000_WRITE_REG(hw, RDBAL, (u32) rx_base); - E1000_WRITE_REG(hw, RDBAH, 0); - - E1000_WRITE_REG(hw, RDLEN, 128); - - /* Setup the HW Rx Head and Tail Descriptor Pointers */ - E1000_WRITE_REG(hw, RDH, 0); - E1000_WRITE_REG(hw, RDT, 0); -#if 0 - /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if ((adapter->hw.mac_type >= e1000_82543) && (adapter->rx_csum == TRUE)) { - rxcsum = E1000_READ_REG(hw, RXCSUM); - rxcsum |= E1000_RXCSUM_TUOFL; - E1000_WRITE_REG(hw, RXCSUM, rxcsum); - } -#endif - /* Enable Receives */ - - E1000_WRITE_REG(hw, RCTL, rctl); - fill_rx(hw); -} - -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int -e1000_poll(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - struct e1000_rx_desc *rd; - /* return true if there's an ethernet packet ready to read */ - rd = rx_base + rx_last; - if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD) - return 0; - /*DEBUGOUT("recv: packet len=%d \n", rd->length); */ - NetReceive((uchar *)packet, le32_to_cpu(rd->length)); - fill_rx(hw); - return 1; -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static int -e1000_transmit(struct eth_device *nic, volatile void *packet, int length) -{ - struct e1000_hw *hw = nic->priv; - struct e1000_tx_desc *txp; - int i = 0; - - txp = tx_base + tx_tail; - tx_tail = (tx_tail + 1) % 8; - - txp->buffer_addr = cpu_to_le64(virt_to_bus(packet)); - txp->lower.data = cpu_to_le32(E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | length); - txp->upper.data = 0; - E1000_WRITE_REG(hw, TDT, tx_tail); - - while (!(le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)) { - if (i++ > TOUT_LOOP) { - DEBUGOUT("e1000: tx timeout\n"); - return 0; - } - udelay(10); /* give the nic a chance to write to the register */ - } - return 1; -} - -/*reset function*/ -static inline int -e1000_reset(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - - e1000_reset_hw(hw); - if (hw->mac_type >= e1000_82544) { - E1000_WRITE_REG(hw, WUC, 0); - } - return e1000_init_hw(nic); -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void -e1000_disable(struct eth_device *nic) -{ - struct e1000_hw *hw = nic->priv; - - /* Turn off the ethernet interface */ - E1000_WRITE_REG(hw, RCTL, 0); - E1000_WRITE_REG(hw, TCTL, 0); - - /* Clear the transmit ring */ - E1000_WRITE_REG(hw, TDH, 0); - E1000_WRITE_REG(hw, TDT, 0); - - /* Clear the receive ring */ - E1000_WRITE_REG(hw, RDH, 0); - E1000_WRITE_REG(hw, RDT, 0); - - /* put the card in its initial state */ -#if 0 - E1000_WRITE_REG(hw, CTRL, E1000_CTRL_RST); -#endif - mdelay(10); - -} - -/************************************************************************** -INIT - set up ethernet interface(s) -***************************************************************************/ -static int -e1000_init(struct eth_device *nic, bd_t * bis) -{ - struct e1000_hw *hw = nic->priv; - int ret_val = 0; - - ret_val = e1000_reset(nic); - if (ret_val < 0) { - if ((ret_val == -E1000_ERR_NOLINK) || - (ret_val == -E1000_ERR_TIMEOUT)) { - E1000_ERR("Valid Link not detected\n"); - } else { - E1000_ERR("Hardware Initialization Failed\n"); - } - return 0; - } - e1000_configure_tx(hw); - e1000_setup_rctl(hw); - e1000_configure_rx(hw); - return 1; -} - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -You should omit the last argument struct pci_device * for a non-PCI NIC -***************************************************************************/ -int -e1000_initialize(bd_t * bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *nic = NULL; - struct e1000_hw *hw = NULL; - u32 iobase; - int idx = 0; - u32 PciCommandWord; - - while (1) { /* Find PCI device(s) */ - if ((devno = pci_find_devices(supported, idx++)) < 0) { - break; - } - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); - iobase &= ~0xf; /* Mask the bits that say "this is an io addr" */ - DEBUGOUT("e1000#%d: iobase 0x%08x\n", card_number, iobase); - - pci_write_config_dword(devno, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword(devno, PCI_COMMAND, &PciCommandWord); - if (!(PciCommandWord & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEM access.\n"); - continue; - } else if (!(PciCommandWord & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } - - nic = (struct eth_device *) malloc(sizeof (*nic)); - hw = (struct e1000_hw *) malloc(sizeof (*hw)); - hw->pdev = devno; - nic->priv = hw; - nic->iobase = bus_to_phys(devno, iobase); - - sprintf(nic->name, "e1000#%d", card_number); - - /* Are these variables needed? */ -#if 0 - hw->fc = e1000_fc_none; - hw->original_fc = e1000_fc_none; -#else - hw->fc = e1000_fc_default; - hw->original_fc = e1000_fc_default; -#endif - hw->autoneg_failed = 0; - hw->get_link_status = TRUE; - hw->hw_addr = (typeof(hw->hw_addr)) iobase; - hw->mac_type = e1000_undefined; - - /* MAC and Phy settings */ - if (e1000_sw_init(nic, card_number) < 0) { - free(hw); - free(nic); - return 0; - } -#ifndef CONFIG_AP1000 - if (e1000_validate_eeprom_checksum(nic) < 0) { - printf("The EEPROM Checksum Is Not Valid\n"); - free(hw); - free(nic); - return 0; - } -#endif - e1000_read_mac_addr(nic); - - E1000_WRITE_REG(hw, PBA, E1000_DEFAULT_PBA); - - printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n", - nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2], - nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); - - nic->init = e1000_init; - nic->recv = e1000_poll; - nic->send = e1000_transmit; - nic->halt = e1000_disable; - - eth_register(nic); - - card_number++; - } - return 1; -} - -#endif diff --git a/drivers/e1000.h b/drivers/e1000.h deleted file mode 100644 index 0fbdc90b1f..0000000000 --- a/drivers/e1000.h +++ /dev/null @@ -1,1758 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* e1000_hw.h - * Structures, enums, and macros for the MAC - */ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include -#include -#include -#include -#include - -#define E1000_ERR(args...) printf("e1000: " args) - -#ifdef E1000_DEBUG -#define E1000_DBG(args...) printf("e1000: " args) -#define DEBUGOUT(fmt,args...) printf(fmt ,##args) -#define DEBUGFUNC() printf("%s\n", __FUNCTION__); -#else -#define E1000_DBG(args...) -#define DEBUGFUNC() -#define DEBUGOUT(fmt,args...) -#endif - -/* Forward declarations of structures used by the shared code */ -struct e1000_hw; -struct e1000_hw_stats; - -typedef enum { - FALSE = 0, - TRUE = 1 -} boolean_t; - -/* Enumerated types specific to the e1000 hardware */ -/* Media Access Controlers */ -typedef enum { - e1000_undefined = 0, - e1000_82542_rev2_0, - e1000_82542_rev2_1, - e1000_82543, - e1000_82544, - e1000_82540, - e1000_82545, - e1000_82546, - e1000_num_macs -} e1000_mac_type; - -/* Media Types */ -typedef enum { - e1000_media_type_copper = 0, - e1000_media_type_fiber = 1, - e1000_num_media_types -} e1000_media_type; - -typedef enum { - e1000_10_half = 0, - e1000_10_full = 1, - e1000_100_half = 2, - e1000_100_full = 3 -} e1000_speed_duplex_type; - -typedef enum { - e1000_lan_a = 0, - e1000_lan_b = 1 -} e1000_lan_loc; - -/* Flow Control Settings */ -typedef enum { - e1000_fc_none = 0, - e1000_fc_rx_pause = 1, - e1000_fc_tx_pause = 2, - e1000_fc_full = 3, - e1000_fc_default = 0xFF -} e1000_fc_type; - -/* PCI bus types */ -typedef enum { - e1000_bus_type_unknown = 0, - e1000_bus_type_pci, - e1000_bus_type_pcix -} e1000_bus_type; - -/* PCI bus speeds */ -typedef enum { - e1000_bus_speed_unknown = 0, - e1000_bus_speed_33, - e1000_bus_speed_66, - e1000_bus_speed_100, - e1000_bus_speed_133, - e1000_bus_speed_reserved -} e1000_bus_speed; - -/* PCI bus widths */ -typedef enum { - e1000_bus_width_unknown = 0, - e1000_bus_width_32, - e1000_bus_width_64 -} e1000_bus_width; - -/* PHY status info structure and supporting enums */ -typedef enum { - e1000_cable_length_50 = 0, - e1000_cable_length_50_80, - e1000_cable_length_80_110, - e1000_cable_length_110_140, - e1000_cable_length_140, - e1000_cable_length_undefined = 0xFF -} e1000_cable_length; - -typedef enum { - e1000_10bt_ext_dist_enable_normal = 0, - e1000_10bt_ext_dist_enable_lower, - e1000_10bt_ext_dist_enable_undefined = 0xFF -} e1000_10bt_ext_dist_enable; - -typedef enum { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -} e1000_rev_polarity; - -typedef enum { - e1000_polarity_reversal_enabled = 0, - e1000_polarity_reversal_disabled, - e1000_polarity_reversal_undefined = 0xFF -} e1000_polarity_reversal; - -typedef enum { - e1000_auto_x_mode_manual_mdi = 0, - e1000_auto_x_mode_manual_mdix, - e1000_auto_x_mode_auto1, - e1000_auto_x_mode_auto2, - e1000_auto_x_mode_undefined = 0xFF -} e1000_auto_x_mode; - -typedef enum { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -} e1000_1000t_rx_status; - -struct e1000_phy_info { - e1000_cable_length cable_length; - e1000_10bt_ext_dist_enable extended_10bt_distance; - e1000_rev_polarity cable_polarity; - e1000_polarity_reversal polarity_correction; - e1000_auto_x_mode mdix_mode; - e1000_1000t_rx_status local_rx; - e1000_1000t_rx_status remote_rx; -}; - -struct e1000_phy_stats { - uint32_t idle_errors; - uint32_t receive_errors; -}; - -/* Error Codes */ -#define E1000_SUCCESS 0 -#define E1000_ERR_EEPROM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_TYPE 5 -#define E1000_ERR_NOLINK 6 -#define E1000_ERR_TIMEOUT 7 - -/* PCI Device IDs */ -#define E1000_DEV_ID_82542 0x1000 -#define E1000_DEV_ID_82543GC_FIBER 0x1001 -#define E1000_DEV_ID_82543GC_COPPER 0x1004 -#define E1000_DEV_ID_82544EI_COPPER 0x1008 -#define E1000_DEV_ID_82544EI_FIBER 0x1009 -#define E1000_DEV_ID_82544GC_COPPER 0x100C -#define E1000_DEV_ID_82544GC_LOM 0x100D -#define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82540EM_LOM 0x1015 -#define E1000_DEV_ID_82545EM_COPPER 0x100F -#define E1000_DEV_ID_82545EM_FIBER 0x1011 -#define E1000_DEV_ID_82546EB_COPPER 0x1010 -#define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define NUM_DEV_IDS 13 - -#define NODE_ADDRESS_SIZE 6 -#define ETH_LENGTH_OF_ADDRESS 6 - -/* MAC decode size is 128K - This is the size of BAR0 */ -#define MAC_DECODE_SIZE (128 * 1024) - -#define E1000_82542_2_0_REV_ID 2 -#define E1000_82542_2_1_REV_ID 3 - -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* The sizes (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* With FCS */ -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ -#define ETHERNET_FCS_SIZE 4 -#define MAXIMUM_ETHERNET_PACKET_SIZE \ - (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define MINIMUM_ETHERNET_PACKET_SIZE \ - (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define CRC_LENGTH ETHERNET_FCS_SIZE -#define MAX_JUMBO_FRAME_SIZE 0x3F00 - -/* 802.1q VLAN Packet Sizes */ -#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ - -/* Ethertype field values */ -#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ -#define ETHERNET_IP_TYPE 0x0800 /* IP packets */ -#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */ - -/* Packet Header defines */ -#define IP_PROTOCOL_TCP 6 -#define IP_PROTOCOL_UDP 0x11 - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - */ -#define POLL_IMS_ENABLE_MASK ( \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ) - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* The 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. - */ -#define E1000_RAR_ENTRIES 16 - -#define MIN_NUMBER_OF_DESCRIPTORS 8 -#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 - -/* Receive Descriptor */ -struct e1000_rx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ - uint16_t length; /* Length of data DMAed into data buffer */ - uint16_t csum; /* Packet checksum */ - uint8_t status; /* Descriptor status */ - uint8_t errors; /* Descriptor Errors */ - uint16_t special; -}; - -/* Receive Decriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ -#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ -#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */ -#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */ - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Transmit Descriptor */ -struct e1000_tx_desc { - uint64_t buffer_addr; /* Address of the descriptor's data buffer */ - union { - uint32_t data; - struct { - uint16_t length; /* Data buffer length */ - uint8_t cso; /* Checksum offset */ - uint8_t cmd; /* Descriptor control */ - } flags; - } lower; - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t css; /* Checksum start */ - uint16_t special; - } fields; - } upper; -}; - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - uint32_t ip_config; - struct { - uint8_t ipcss; /* IP checksum start */ - uint8_t ipcso; /* IP checksum offset */ - uint16_t ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - uint32_t tcp_config; - struct { - uint8_t tucss; /* TCP checksum start */ - uint8_t tucso; /* TCP checksum offset */ - uint16_t tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - uint32_t cmd_and_length; /* */ - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t hdr_len; /* Header length */ - uint16_t mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - uint64_t buffer_addr; /* Address of the descriptor's buffer address */ - union { - uint32_t data; - struct { - uint16_t length; /* Data buffer length */ - uint8_t typ_len_ext; /* */ - uint8_t cmd; /* */ - } flags; - } lower; - union { - uint32_t data; - struct { - uint8_t status; /* Descriptor status */ - uint8_t popts; /* Packet Options */ - uint16_t special; /* */ - } fields; - } upper; -}; - -/* Filters */ -#define E1000_NUM_UNICAST 16 /* Unicast filter entries */ -#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - -/* Receive Address Register */ -struct e1000_rar { - volatile uint32_t low; /* receive address low */ - volatile uint32_t high; /* receive address high */ -}; - -/* The number of entries in the Multicast Table Array (MTA). */ -#define E1000_NUM_MTA_REGISTERS 128 - -/* IPv4 Address Table Entry */ -struct e1000_ipv4_at_entry { - volatile uint32_t ipv4_addr; /* IP Address (RW) */ - volatile uint32_t reserved; -}; - -/* Four wakeup IP addresses are supported */ -#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 -#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX -#define E1000_IP6AT_SIZE 1 - -/* IPv6 Address Table Entry */ -struct e1000_ipv6_at_entry { - volatile uint8_t ipv6_addr[16]; -}; - -/* Flexible Filter Length Table Entry */ -struct e1000_fflt_entry { - volatile uint32_t length; /* Flexible Filter Length (RW) */ - volatile uint32_t reserved; -}; - -/* Flexible Filter Mask Table Entry */ -struct e1000_ffmt_entry { - volatile uint32_t mask; /* Flexible Filter Mask (RW) */ - volatile uint32_t reserved; -}; - -/* Flexible Filter Value Table Entry */ -struct e1000_ffvt_entry { - volatile uint32_t value; /* Flexible Filter Value (RW) */ - volatile uint32_t reserved; -}; - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - -#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX -#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX - -/* Register Set. (82543, 82544) - * - * Registers are defined to be 32 bits and should be accessed as 32 bit values. - * These registers are physically located on the NIC, but are mapped into the - * host memory address space. - * - * RW - register is both readable and writable - * RO - register is read only - * WO - register is write only - * R/clr - register is read only and is cleared when read - * A - register array - */ -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_RCTL 0x00100 /* RX Control - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ -#define E1000_TCTL 0x00400 /* TX Control - RW */ -#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ -#define E1000_TBT 0x00448 /* TX Burst Timer - RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ -#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ -#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ -#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */ -#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */ -#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */ -#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */ -#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ -#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ -#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ -#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ -#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ -#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ -#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */ -#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */ -#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */ -#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ -#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ -#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ -#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ -#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ -#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ -#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ -#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ - -/* Register Set (82542) - * - * Some of the 82542 registers are located at different offsets than they are - * in more current versions of the 8254x. Despite the difference in location, - * the registers function in the same manner. - */ -#define E1000_82542_CTRL E1000_CTRL -#define E1000_82542_STATUS E1000_STATUS -#define E1000_82542_EECD E1000_EECD -#define E1000_82542_EERD E1000_EERD -#define E1000_82542_CTRL_EXT E1000_CTRL_EXT -#define E1000_82542_MDIC E1000_MDIC -#define E1000_82542_FCAL E1000_FCAL -#define E1000_82542_FCAH E1000_FCAH -#define E1000_82542_FCT E1000_FCT -#define E1000_82542_VET E1000_VET -#define E1000_82542_RA 0x00040 -#define E1000_82542_ICR E1000_ICR -#define E1000_82542_ITR E1000_ITR -#define E1000_82542_ICS E1000_ICS -#define E1000_82542_IMS E1000_IMS -#define E1000_82542_IMC E1000_IMC -#define E1000_82542_RCTL E1000_RCTL -#define E1000_82542_RDTR 0x00108 -#define E1000_82542_RDBAL 0x00110 -#define E1000_82542_RDBAH 0x00114 -#define E1000_82542_RDLEN 0x00118 -#define E1000_82542_RDH 0x00120 -#define E1000_82542_RDT 0x00128 -#define E1000_82542_FCRTH 0x00160 -#define E1000_82542_FCRTL 0x00168 -#define E1000_82542_FCTTV E1000_FCTTV -#define E1000_82542_TXCW E1000_TXCW -#define E1000_82542_RXCW E1000_RXCW -#define E1000_82542_MTA 0x00200 -#define E1000_82542_TCTL E1000_TCTL -#define E1000_82542_TIPG E1000_TIPG -#define E1000_82542_TDBAL 0x00420 -#define E1000_82542_TDBAH 0x00424 -#define E1000_82542_TDLEN 0x00428 -#define E1000_82542_TDH 0x00430 -#define E1000_82542_TDT 0x00438 -#define E1000_82542_TIDV 0x00440 -#define E1000_82542_TBT E1000_TBT -#define E1000_82542_AIT E1000_AIT -#define E1000_82542_VFTA 0x00600 -#define E1000_82542_LEDCTL E1000_LEDCTL -#define E1000_82542_PBA E1000_PBA -#define E1000_82542_RXDCTL E1000_RXDCTL -#define E1000_82542_RADV E1000_RADV -#define E1000_82542_RSRPD E1000_RSRPD -#define E1000_82542_TXDMAC E1000_TXDMAC -#define E1000_82542_TXDCTL E1000_TXDCTL -#define E1000_82542_TADV E1000_TADV -#define E1000_82542_TSPMT E1000_TSPMT -#define E1000_82542_CRCERRS E1000_CRCERRS -#define E1000_82542_ALGNERRC E1000_ALGNERRC -#define E1000_82542_SYMERRS E1000_SYMERRS -#define E1000_82542_RXERRC E1000_RXERRC -#define E1000_82542_MPC E1000_MPC -#define E1000_82542_SCC E1000_SCC -#define E1000_82542_ECOL E1000_ECOL -#define E1000_82542_MCC E1000_MCC -#define E1000_82542_LATECOL E1000_LATECOL -#define E1000_82542_COLC E1000_COLC -#define E1000_82542_DC E1000_DC -#define E1000_82542_TNCRS E1000_TNCRS -#define E1000_82542_SEC E1000_SEC -#define E1000_82542_CEXTERR E1000_CEXTERR -#define E1000_82542_RLEC E1000_RLEC -#define E1000_82542_XONRXC E1000_XONRXC -#define E1000_82542_XONTXC E1000_XONTXC -#define E1000_82542_XOFFRXC E1000_XOFFRXC -#define E1000_82542_XOFFTXC E1000_XOFFTXC -#define E1000_82542_FCRUC E1000_FCRUC -#define E1000_82542_PRC64 E1000_PRC64 -#define E1000_82542_PRC127 E1000_PRC127 -#define E1000_82542_PRC255 E1000_PRC255 -#define E1000_82542_PRC511 E1000_PRC511 -#define E1000_82542_PRC1023 E1000_PRC1023 -#define E1000_82542_PRC1522 E1000_PRC1522 -#define E1000_82542_GPRC E1000_GPRC -#define E1000_82542_BPRC E1000_BPRC -#define E1000_82542_MPRC E1000_MPRC -#define E1000_82542_GPTC E1000_GPTC -#define E1000_82542_GORCL E1000_GORCL -#define E1000_82542_GORCH E1000_GORCH -#define E1000_82542_GOTCL E1000_GOTCL -#define E1000_82542_GOTCH E1000_GOTCH -#define E1000_82542_RNBC E1000_RNBC -#define E1000_82542_RUC E1000_RUC -#define E1000_82542_RFC E1000_RFC -#define E1000_82542_ROC E1000_ROC -#define E1000_82542_RJC E1000_RJC -#define E1000_82542_MGTPRC E1000_MGTPRC -#define E1000_82542_MGTPDC E1000_MGTPDC -#define E1000_82542_MGTPTC E1000_MGTPTC -#define E1000_82542_TORL E1000_TORL -#define E1000_82542_TORH E1000_TORH -#define E1000_82542_TOTL E1000_TOTL -#define E1000_82542_TOTH E1000_TOTH -#define E1000_82542_TPR E1000_TPR -#define E1000_82542_TPT E1000_TPT -#define E1000_82542_PTC64 E1000_PTC64 -#define E1000_82542_PTC127 E1000_PTC127 -#define E1000_82542_PTC255 E1000_PTC255 -#define E1000_82542_PTC511 E1000_PTC511 -#define E1000_82542_PTC1023 E1000_PTC1023 -#define E1000_82542_PTC1522 E1000_PTC1522 -#define E1000_82542_MPTC E1000_MPTC -#define E1000_82542_BPTC E1000_BPTC -#define E1000_82542_TSCTC E1000_TSCTC -#define E1000_82542_TSCTFC E1000_TSCTFC -#define E1000_82542_RXCSUM E1000_RXCSUM -#define E1000_82542_WUC E1000_WUC -#define E1000_82542_WUFC E1000_WUFC -#define E1000_82542_WUS E1000_WUS -#define E1000_82542_MANC E1000_MANC -#define E1000_82542_IPAV E1000_IPAV -#define E1000_82542_IP4AT E1000_IP4AT -#define E1000_82542_IP6AT E1000_IP6AT -#define E1000_82542_WUPL E1000_WUPL -#define E1000_82542_WUPM E1000_WUPM -#define E1000_82542_FFLT E1000_FFLT -#define E1000_82542_FFMT E1000_FFMT -#define E1000_82542_FFVT E1000_FFVT - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - uint64_t crcerrs; - uint64_t algnerrc; - uint64_t symerrs; - uint64_t rxerrc; - uint64_t mpc; - uint64_t scc; - uint64_t ecol; - uint64_t mcc; - uint64_t latecol; - uint64_t colc; - uint64_t dc; - uint64_t tncrs; - uint64_t sec; - uint64_t cexterr; - uint64_t rlec; - uint64_t xonrxc; - uint64_t xontxc; - uint64_t xoffrxc; - uint64_t xofftxc; - uint64_t fcruc; - uint64_t prc64; - uint64_t prc127; - uint64_t prc255; - uint64_t prc511; - uint64_t prc1023; - uint64_t prc1522; - uint64_t gprc; - uint64_t bprc; - uint64_t mprc; - uint64_t gptc; - uint64_t gorcl; - uint64_t gorch; - uint64_t gotcl; - uint64_t gotch; - uint64_t rnbc; - uint64_t ruc; - uint64_t rfc; - uint64_t roc; - uint64_t rjc; - uint64_t mgprc; - uint64_t mgpdc; - uint64_t mgptc; - uint64_t torl; - uint64_t torh; - uint64_t totl; - uint64_t toth; - uint64_t tpr; - uint64_t tpt; - uint64_t ptc64; - uint64_t ptc127; - uint64_t ptc255; - uint64_t ptc511; - uint64_t ptc1023; - uint64_t ptc1522; - uint64_t mptc; - uint64_t bptc; - uint64_t tsctc; - uint64_t tsctfc; -}; - -/* Structure containing variables used by the shared code (e1000_hw.c) */ -struct e1000_hw { - pci_dev_t pdev; - uint8_t *hw_addr; - e1000_mac_type mac_type; - e1000_media_type media_type; - e1000_lan_loc lan_loc; - e1000_fc_type fc; -#if 0 - e1000_bus_speed bus_speed; - e1000_bus_width bus_width; - e1000_bus_type bus_type; - uint32_t io_base; -#endif - uint32_t phy_id; - uint32_t phy_addr; - uint32_t original_fc; - uint32_t txcw; - uint32_t autoneg_failed; -#if 0 - uint32_t max_frame_size; - uint32_t min_frame_size; - uint32_t mc_filter_type; - uint32_t num_mc_addrs; - uint32_t collision_delta; - uint32_t tx_packet_delta; - uint32_t ledctl_default; - uint32_t ledctl_mode1; - uint32_t ledctl_mode2; -#endif - uint16_t autoneg_advertised; - uint16_t pci_cmd_word; - uint16_t fc_high_water; - uint16_t fc_low_water; - uint16_t fc_pause_time; -#if 0 - uint16_t current_ifs_val; - uint16_t ifs_min_val; - uint16_t ifs_max_val; - uint16_t ifs_step_size; - uint16_t ifs_ratio; -#endif - uint16_t device_id; - uint16_t vendor_id; - uint16_t subsystem_id; - uint16_t subsystem_vendor_id; - uint8_t revision_id; -#if 0 - uint8_t autoneg; - uint8_t mdix; - uint8_t forced_speed_duplex; - uint8_t wait_autoneg_complete; - uint8_t dma_fairness; -#endif -#if 0 - uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; - boolean_t disable_polarity_correction; -#endif - boolean_t get_link_status; - boolean_t tbi_compatibility_en; - boolean_t tbi_compatibility_on; - boolean_t fc_send_xon; - boolean_t report_tx_early; -#if 0 - boolean_t adaptive_ifs; - boolean_t ifs_params_forced; - boolean_t in_ifs_mode; -#endif -}; - -#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ -#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ - -/* Register Bit Masks */ -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ -#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ -#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ -#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ -#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ -#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ -#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ -#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ -#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ -#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ - -/* Constants used to intrepret the masked PCI-X bus speed. */ -#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ -#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ -#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ - -/* EEPROM/Flash Control */ -#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */ -#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ -#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 -#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ -#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ -#define E1000_EECD_FWE_SHIFT 4 -#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ -#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ - -/* EEPROM Read */ -#define E1000_EERD_START 0x00000001 /* Start Read */ -#define E1000_EERD_DONE 0x00000010 /* Read Done */ -#define E1000_EERD_ADDR_SHIFT 8 -#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */ -#define E1000_EERD_DATA_SHIFT 16 -#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ - -/* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN -#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ -#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ -#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA -#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define E1000_CTRL_EXT_SWDPIN6 0x00000040 /* SWDPIN 6 value */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define E1000_CTRL_EXT_SWDPIN7 0x00000080 /* SWDPIN 7 value */ -#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ -#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define E1000_CTRL_EXT_SWDPIO6 0x00000400 /* SWDPIN 6 Input or output */ -#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ -#define E1000_CTRL_EXT_SWDPIO7 0x00000800 /* SWDPIN 7 Input or output */ -#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 -#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 -#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 -#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 -#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 - -/* MDI Control */ -#define E1000_MDIC_DATA_MASK 0x0000FFFF -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_MASK 0x03E00000 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_INT_EN 0x20000000 -#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_MODE_LINK_10_1000 0x0 -#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_ACTIVITY 0x3 -#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 -#define E1000_LEDCTL_MODE_LINK_10 0x5 -#define E1000_LEDCTL_MODE_LINK_100 0x6 -#define E1000_LEDCTL_MODE_LINK_1000 0x7 -#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 -#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 -#define E1000_LEDCTL_MODE_COLLISION 0xA -#define E1000_LEDCTL_MODE_BUS_SPEED 0xB -#define E1000_LEDCTL_MODE_BUS_SIZE 0xC -#define E1000_LEDCTL_MODE_PAUSED 0xD -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Receive Address */ -#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 - -/* 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 - -/* 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 - -/* 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 - -/* 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 */ -/* 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 */ -/* 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 */ - -/* Receive Descriptor */ -#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ -#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ -#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */ -#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */ -#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */ - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Receive Descriptor Control */ -#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ -#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ -#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ -#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ - -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ -#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ -#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ -#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_CC 0x10000000 /* Receive config change */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ -#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ - -/* Transmit Control */ -#define E1000_TCTL_RST 0x00000001 /* software reset */ -#define E1000_TCTL_EN 0x00000002 /* enable tx */ -#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ -#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ - -/* Receive Checksum Control */ -#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ -#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ -#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ -#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */ -#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */ -#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */ -#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */ -#define E1000_WUS_BC 0x00000010 /* Broadcast Received */ -#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */ -#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */ -#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */ -#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */ -#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */ -#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */ -#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */ -#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ -#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ -#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ -#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ -#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ -#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery - * Filtering */ -#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ -#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ -#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ -#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ -#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ -#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ -#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ - -#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ -#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ - -/* Wake Up Packet Length */ -#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ - -#define E1000_MDALIGN 4096 - -/* EEPROM Commands */ -#define EEPROM_READ_OPCODE 0x6 /* EERPOM read opcode */ -#define EEPROM_WRITE_OPCODE 0x5 /* EERPOM write opcode */ -#define EEPROM_ERASE_OPCODE 0x7 /* EERPOM erase opcode */ -#define EEPROM_EWEN_OPCODE 0x13 /* EERPOM erase/write enable */ -#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ - -/* 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_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -/* Mask bits for fields in Word 0x03 of the EEPROM */ -#define EEPROM_COMPAT_SERVER 0x0400 -#define EEPROM_COMPAT_CLIENT 0x0200 - -/* Mask bits for fields in Word 0x0a of the EEPROM */ -#define EEPROM_WORD0A_ILOS 0x0010 -#define EEPROM_WORD0A_SWDPIO 0x01E0 -#define EEPROM_WORD0A_LRST 0x0200 -#define EEPROM_WORD0A_FD 0x0400 -#define EEPROM_WORD0A_66MHZ 0x0800 - -/* Mask bits for fields in Word 0x0f of the EEPROM */ -#define EEPROM_WORD0F_PAUSE_MASK 0x3000 -#define EEPROM_WORD0F_PAUSE 0x1000 -#define EEPROM_WORD0F_ASM_DIR 0x2000 -#define EEPROM_WORD0F_ANE 0x0800 -#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 - -/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ -#define EEPROM_SUM 0xBABA - -/* EEPROM Map defines (WORD OFFSETS)*/ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_PBA_BYTE_1 8 - -/* EEPROM Map Sizes (Byte Counts) */ -#define PBA_SIZE 4 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 16 -#define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 64 -#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_GB_HDX_COLLISION_DISTANCE 512 -#define E1000_COLD_SHIFT 12 - -/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82542_TIPG_IPGT 10 -#define DEFAULT_82543_TIPG_IPGT_FIBER 9 -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF -#define E1000_TIPG_IPGR1_MASK 0x000FFC00 -#define E1000_TIPG_IPGR2_MASK 0x3FF00000 - -#define DEFAULT_82542_TIPG_IPGR1 2 -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82542_TIPG_IPGR2 10 -#define DEFAULT_82543_TIPG_IPGR2 6 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define E1000_TXDMAC_DPP 0x00000001 - -/* Adaptive IFS defines */ -#define TX_THRESHOLD_START 8 -#define TX_THRESHOLD_INCREMENT 10 -#define TX_THRESHOLD_DECREMENT 1 -#define TX_THRESHOLD_STOP 190 -#define TX_THRESHOLD_DISABLE 0 -#define TX_THRESHOLD_TIMER_MS 10000 -#define MIN_NUM_XMITS 1000 -#define IFS_MAX 80 -#define IFS_STEP 10 -#define IFS_MIN 40 -#define IFS_RATIO 4 - -/* PBA constants */ -#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ -#define E1000_PBA_24K 0x0018 -#define E1000_PBA_40K 0x0028 -#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* The historical defaults for the flow control values are given below. */ -#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ -#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ -#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ - -/* Flow Control High-Watermark: 43464 bytes */ -#define E1000_FC_HIGH_THRESH 0xA9C8 -/* Flow Control Low-Watermark: 43456 bytes */ -#define E1000_FC_LOW_THRESH 0xA9C0 -/* Flow Control Pause Time: 858 usec */ -#define E1000_FC_PAUSE_TIME 0x0680 - -/* PCIX Config space */ -#define PCIX_COMMAND_REGISTER 0xE6 -#define PCIX_STATUS_REGISTER_LO 0xE8 -#define PCIX_STATUS_REGISTER_HI 0xEA - -#define PCIX_COMMAND_MMRBC_MASK 0x000C -#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -#define PCIX_STATUS_HI_MMRBC_4K 0x3 -#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 - */ -#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 - */ -#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 - */ -#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 - */ -#define ILOS_SHIFT 3 - -#define RECEIVE_BUFFER_ALIGN_SIZE (256) - -/* The number of milliseconds we wait for auto-negotiation to complete */ -#define LINK_UP_TIMEOUT 500 - -#define E1000_TX_BUFFER_SIZE ((uint32_t)1514) - -/* The carrier extension symbol, as received by the NIC. */ -#define CARRIER_EXTENSION 0x0F - -/* TBI_ACCEPT macro definition: - * - * This macro requires: - * adapter = a pointer to struct e1000_hw - * status = the 8 bit status field of the RX descriptor with EOP set - * error = the 8 bit error field of the RX descriptor with EOP set - * length = the sum of all the length fields of the RX descriptors that - * make up the current frame - * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. - * - * This macro is a conditional that should be used in the interrupt - * handler's Rx processing routine when RxErrors have been detected. - * - * Typical use: - * ... - * if (TBI_ACCEPT) { - * accept_frame = TRUE; - * e1000_tbi_adjust_stats(adapter, MacAddress); - * frame_length--; - * } else { - * accept_frame = FALSE; - * } - * ... - */ - -#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \ - ((adapter)->tbi_compatibility_on && \ - (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ - ((last_byte) == CARRIER_EXTENSION) && \ - (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= ((adapter)->max_frame_size + 1))) : \ - (((length) > (adapter)->min_frame_size) && \ - ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1))))) - -/* Structures, enums, and macros for the PHY */ - -/* Bit definitions for the Management Data IO (MDIO) and Management Data - * Clock (MDC) pins in the Device Control Register. - */ -#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 -#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 -#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 -#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 -#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 -#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 -#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR -#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA - -/* PHY 1000 MII Register/Bit Definitions */ -/* PHY Registers defined by IEEE */ -#define PHY_CTRL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Regiser */ -#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ -#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ -#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ -#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ -#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ -#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ - -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ - -/* 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 */ -#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ -#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ -#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ -#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ -#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ - -/* PHY Status Register */ -#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ -#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ -#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ -#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ -#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ -#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ -#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ -#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ -#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ -#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ -#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ -#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ -#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ -#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ -#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ - -/* Autoneg Advertisement Register */ -#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ -#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ -#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ -#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ -#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ -#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ -#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ -#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ -#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ -#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Link Partner Ability Register (Base Page) */ -#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ -#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ -#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ -#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ -#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ -#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ -#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ -#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ -#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ -#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ -#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Autoneg Expansion Register */ -#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ -#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ -#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ -#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0100 /* LP is 100TX Full Duplex Capable */ - -/* Next Page TX Register */ -#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* Link Partner Next Page Register */ -#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ -#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* 1000BASE-T Control Register */ -#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ -#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ -#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ -#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ - /* 0=DTE device */ -#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ - /* 0=Configure PHY as Slave */ -#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ - /* 0=Automatic Master/Slave config */ -#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ - -/* 1000BASE-T Status Register */ -#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ -#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ -#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ -#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ -#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 - -/* Extended Status Register */ -#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ -#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ -#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ -#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ - -#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ -#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ - -#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ - /* (0=enable, 1=disable) */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 - /* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 - /* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5 -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; - * 3=110-140M;4=>140M */ -#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ -#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ -#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 -#define M88E1000_PSSR_MDIX_SHIFT 6 -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* M88E1000 Extended PHY Specific Control Register */ -#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ -#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. - * Will assert lost lock and bring - * link down if idle not seen - * within 1ms in 1000BASE-T - */ -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 -#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - -/* Bit definitions for valid PHY IDs. */ -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID -#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID - -/* Miscellaneous PHY bit definitions. */ -#define PHY_PREAMBLE 0xFFFFFFFF -#define PHY_SOF 0x01 -#define PHY_OP_READ 0x02 -#define PHY_OP_WRITE 0x01 -#define PHY_TURNAROUND 0x02 -#define PHY_PREAMBLE_SIZE 32 -#define MII_CR_SPEED_1000 0x0040 -#define MII_CR_SPEED_100 0x2000 -#define MII_CR_SPEED_10 0x0000 -#define E1000_PHY_ADDRESS 0x01 -#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ -#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ -#define REG4_SPEED_MASK 0x01E0 -#define REG9_SPEED_MASK 0x0300 -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 -#define ADVERTISE_1000_FULL 0x0020 -#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ - -#endif /* _E1000_HW_H_ */ diff --git a/drivers/eepro100.c b/drivers/eepro100.c deleted file mode 100644 index 738146e661..0000000000 --- a/drivers/eepro100.c +++ /dev/null @@ -1,948 +0,0 @@ -/* - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_EEPRO100) - - /* Ethernet chip registers. - */ -#define SCBStatus 0 /* Rx/Command Unit Status *Word* */ -#define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ -#define SCBCmd 2 /* Rx/Command Unit Command *Word* */ -#define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */ -#define SCBPointer 4 /* General purpose pointer. */ -#define SCBPort 8 /* Misc. commands and operands. */ -#define SCBflash 12 /* Flash memory control. */ -#define SCBeeprom 14 /* EEPROM memory control. */ -#define SCBCtrlMDI 16 /* MDI interface control. */ -#define SCBEarlyRx 20 /* Early receive byte count. */ -#define SCBGenControl 28 /* 82559 General Control Register */ -#define SCBGenStatus 29 /* 82559 General Status register */ - - /* 82559 SCB status word defnitions - */ -#define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ -#define SCB_STATUS_FR 0x4000 /* frame received */ -#define SCB_STATUS_CNA 0x2000 /* CU left active state */ -#define SCB_STATUS_RNR 0x1000 /* receiver left ready state */ -#define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */ -#define SCB_STATUS_SWI 0x0400 /* software generated interrupt */ -#define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */ - -#define SCB_INTACK_MASK 0xFD00 /* all the above */ - -#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) -#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) - - /* System control block commands - */ -/* CU Commands */ -#define CU_NOP 0x0000 -#define CU_START 0x0010 -#define CU_RESUME 0x0020 -#define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */ -#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ -#define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */ -#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ - -/* RUC Commands */ -#define RUC_NOP 0x0000 -#define RUC_START 0x0001 -#define RUC_RESUME 0x0002 -#define RUC_ABORT 0x0004 -#define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */ -#define RUC_RESUMENR 0x0007 - -#define CU_CMD_MASK 0x00f0 -#define RU_CMD_MASK 0x0007 - -#define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */ -#define SCB_SWI 0x0200 /* 1 - cause device to interrupt */ - -#define CU_STATUS_MASK 0x00C0 -#define RU_STATUS_MASK 0x003C - -#define RU_STATUS_IDLE (0<<2) -#define RU_STATUS_SUS (1<<2) -#define RU_STATUS_NORES (2<<2) -#define RU_STATUS_READY (4<<2) -#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) -#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) -#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) - - /* 82559 Port interface commands. - */ -#define I82559_RESET 0x00000000 /* Software reset */ -#define I82559_SELFTEST 0x00000001 /* 82559 Selftest command */ -#define I82559_SELECTIVE_RESET 0x00000002 -#define I82559_DUMP 0x00000003 -#define I82559_DUMP_WAKEUP 0x00000007 - - /* 82559 Eeprom interface. - */ -#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ -#define EE_CS 0x02 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ -#define EE_ENB (0x4800 | EE_CS) -#define EE_CMD_BITS 3 -#define EE_DATA_BITS 16 - - /* The EEPROM commands include the alway-set leading bit. - */ -#define EE_EWENB_CMD (4 << addr_len) -#define EE_WRITE_CMD (5 << addr_len) -#define EE_READ_CMD (6 << addr_len) -#define EE_ERASE_CMD (7 << addr_len) - - /* Receive frame descriptors. - */ -struct RxFD { - volatile u16 status; - volatile u16 control; - volatile u32 link; /* struct RxFD * */ - volatile u32 rx_buf_addr; /* void * */ - volatile u32 count; - - volatile u8 data[PKTSIZE_ALIGN]; -}; - -#define RFD_STATUS_C 0x8000 /* completion of received frame */ -#define RFD_STATUS_OK 0x2000 /* frame received with no errors */ - -#define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */ -#define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */ -#define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */ -#define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */ - -#define RFD_COUNT_MASK 0x3fff -#define RFD_COUNT_F 0x4000 -#define RFD_COUNT_EOF 0x8000 - -#define RFD_RX_CRC 0x0800 /* crc error */ -#define RFD_RX_ALIGNMENT 0x0400 /* alignment error */ -#define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */ -#define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */ -#define RFD_RX_SHORT 0x0080 /* short frame error */ -#define RFD_RX_LENGTH 0x0020 -#define RFD_RX_ERROR 0x0010 /* receive error */ -#define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */ -#define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */ -#define RFD_RX_TCO 0x0001 /* TCO indication */ - - /* Transmit frame descriptors - */ -struct TxFD { /* Transmit frame descriptor set. */ - volatile u16 status; - volatile u16 command; - volatile u32 link; /* void * */ - volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ - volatile s32 count; - - volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ - volatile s32 tx_buf_size0; /* Length of Tx frame. */ - volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ - volatile s32 tx_buf_size1; /* Length of Tx frame. */ -}; - -#define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */ -#define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ -#define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ -#define TxCB_CMD_I 0x2000 /* generate interrupt on completion */ -#define TxCB_CMD_S 0x4000 /* suspend on completion */ -#define TxCB_CMD_EL 0x8000 /* last command block in CBL */ - -#define TxCB_COUNT_MASK 0x3fff -#define TxCB_COUNT_EOF 0x8000 - - /* The Speedo3 Rx and Tx frame/buffer descriptors. - */ -struct descriptor { /* A generic descriptor. */ - volatile u16 status; - volatile u16 command; - volatile u32 link; /* struct descriptor * */ - - unsigned char params[0]; -}; - -#define CFG_CMD_EL 0x8000 -#define CFG_CMD_SUSPEND 0x4000 -#define CFG_CMD_INT 0x2000 -#define CFG_CMD_IAS 0x0001 /* individual address setup */ -#define CFG_CMD_CONFIGURE 0x0002 /* configure */ - -#define CFG_STATUS_C 0x8000 -#define CFG_STATUS_OK 0x2000 - - /* Misc. - */ -#define NUM_RX_DESC PKTBUFSRX -#define NUM_TX_DESC 1 /* Number of TX descriptors */ - -#define TOUT_LOOP 1000000 - -#define ETH_ALEN 6 - -static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ -static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ -static int rx_next; /* RX descriptor ring pointer */ -static int tx_next; /* TX descriptor ring pointer */ -static int tx_threshold; - -/* - * The parameters for a CmdConfigure operation. - * There are so many options that it would be difficult to document - * each bit. We mostly use the default or recommended settings. - */ -static const char i82557_config_cmd[] = { - 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ - 0, 0x2E, 0, 0x60, 0, - 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ - 0x3f, 0x05, -}; -static const char i82558_config_cmd[] = { - 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ - 0, 0x2E, 0, 0x60, 0x08, 0x88, - 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ - 0x31, 0x05, -}; - -static void init_rx_ring (struct eth_device *dev); -static void purge_tx_ring (struct eth_device *dev); - -static void read_hw_addr (struct eth_device *dev, bd_t * bis); - -static int eepro100_init (struct eth_device *dev, bd_t * bis); -static int eepro100_send (struct eth_device *dev, volatile void *packet, - int length); -static int eepro100_recv (struct eth_device *dev); -static void eepro100_halt (struct eth_device *dev); - -#if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460) -#define bus_to_phys(a) (a) -#define phys_to_bus(a) (a) -#else -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) -#endif - -static inline int INW (struct eth_device *dev, u_long addr) -{ - return le16_to_cpu (*(volatile u16 *) (addr + dev->iobase)); -} - -static inline void OUTW (struct eth_device *dev, int command, u_long addr) -{ - *(volatile u16 *) ((addr + dev->iobase)) = cpu_to_le16 (command); -} - -static inline void OUTL (struct eth_device *dev, int command, u_long addr) -{ - *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command); -} - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) -static inline int INL (struct eth_device *dev, u_long addr) -{ - return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase)); -} - -static int get_phyreg (struct eth_device *dev, unsigned char addr, - unsigned char reg, unsigned short *value) -{ - int cmd; - int timeout = 50; - - /* read requested data */ - cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL (dev, cmd, SCBCtrlMDI); - - do { - udelay(1000); - cmd = INL (dev, SCBCtrlMDI); - } while (!(cmd & (1 << 28)) && (--timeout)); - - if (timeout == 0) - return -1; - - *value = (unsigned short) (cmd & 0xffff); - - return 0; -} - -static int set_phyreg (struct eth_device *dev, unsigned char addr, - unsigned char reg, unsigned short value) -{ - int cmd; - int timeout = 50; - - /* write requested data */ - cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - OUTL (dev, cmd | value, SCBCtrlMDI); - - while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) - udelay(1000); - - if (timeout == 0) - return -1; - - return 0; -} - -/* Check if given phyaddr is valid, i.e. there is a PHY connected. - * Do this by checking model value field from ID2 register. - */ -static struct eth_device* verify_phyaddr (char *devname, unsigned char addr) -{ - struct eth_device *dev; - unsigned short value; - unsigned char model; - - dev = eth_get_dev_by_name(devname); - if (dev == NULL) { - printf("%s: no such device\n", devname); - return NULL; - } - - /* read id2 register */ - if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) { - printf("%s: mii read timeout!\n", devname); - return NULL; - } - - /* get model */ - model = (unsigned char)((value >> 4) & 0x003f); - - if (model == 0) { - printf("%s: no PHY at address %d\n", devname, addr); - return NULL; - } - - return dev; -} - -static int eepro100_miiphy_read (char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) -{ - struct eth_device *dev; - - dev = verify_phyaddr(devname, addr); - if (dev == NULL) - return -1; - - if (get_phyreg(dev, addr, reg, value) != 0) { - printf("%s: mii read timeout!\n", devname); - return -1; - } - - return 0; -} - -static int eepro100_miiphy_write (char *devname, unsigned char addr, - unsigned char reg, unsigned short value) -{ - struct eth_device *dev; - - dev = verify_phyaddr(devname, addr); - if (dev == NULL) - return -1; - - if (set_phyreg(dev, addr, reg, value) != 0) { - printf("%s: mii write timeout!\n", devname); - return -1; - } - - return 0; -} - -#endif - -/* Wait for the chip get the command. -*/ -static int wait_for_eepro100 (struct eth_device *dev) -{ - int i; - - for (i = 0; INW (dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { - if (i >= TOUT_LOOP) { - return 0; - } - } - - return 1; -} - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, - {} -}; - -int eepro100_initialize (bd_t * bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase, status; - int idx = 0; - - while (1) { - /* Find PCI device - */ - if ((devno = pci_find_devices (supported, idx++)) < 0) { - break; - } - - pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); - iobase &= ~0xf; - -#ifdef DEBUG - printf ("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", - iobase); -#endif - - pci_write_config_dword (devno, - PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - /* Check if I/O accesses and Bus Mastering are enabled. - */ - pci_read_config_dword (devno, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf ("Error: Can not enable MEM access.\n"); - continue; - } - - if (!(status & PCI_COMMAND_MASTER)) { - printf ("Error: Can not enable Bus Mastering.\n"); - continue; - } - - dev = (struct eth_device *) malloc (sizeof *dev); - - sprintf (dev->name, "i82559#%d", card_number); - dev->priv = (void *) devno; /* this have to come before bus_to_phys() */ - dev->iobase = bus_to_phys (iobase); - dev->init = eepro100_init; - dev->halt = eepro100_halt; - dev->send = eepro100_send; - dev->recv = eepro100_recv; - - eth_register (dev); - -#if defined (CONFIG_MII) || defined(CONFIG_CMD_MII) - /* register mii command access routines */ - miiphy_register(dev->name, - eepro100_miiphy_read, eepro100_miiphy_write); -#endif - - card_number++; - - /* Set the latency timer for value. - */ - pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); - - udelay (10 * 1000); - - read_hw_addr (dev, bis); - } - - return card_number; -} - - -static int eepro100_init (struct eth_device *dev, bd_t * bis) -{ - int i, status = 0; - int tx_cur; - struct descriptor *ias_cmd, *cfg_cmd; - - /* Reset the ethernet controller - */ - OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); - udelay (20); - - OUTL (dev, I82559_RESET, SCBPort); - udelay (20); - - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); - - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); - - /* Initialize Rx and Tx rings. - */ - init_rx_ring (dev); - purge_tx_ring (dev); - - /* Tell the adapter where the RX ring is located. - */ - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - - OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); - OUTW (dev, SCB_M | RUC_START, SCBCmd); - - /* Send the Configure frame */ - tx_cur = tx_next; - tx_next = ((tx_next + 1) % NUM_TX_DESC); - - cfg_cmd = (struct descriptor *) &tx_ring[tx_cur]; - cfg_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_CONFIGURE)); - cfg_cmd->status = 0; - cfg_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); - - memcpy (cfg_cmd->params, i82558_config_cmd, - sizeof (i82558_config_cmd)); - - if (!wait_for_eepro100 (dev)) { - printf ("Error---CFG_CMD_CONFIGURE: Can not reset ethernet controller.\n"); - goto Done; - } - - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); - - for (i = 0; - !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", dev->name); - goto Done; - } - } - - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); - goto Done; - } - - /* Send the Individual Address Setup frame - */ - tx_cur = tx_next; - tx_next = ((tx_next + 1) % NUM_TX_DESC); - - ias_cmd = (struct descriptor *) &tx_ring[tx_cur]; - ias_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_IAS)); - ias_cmd->status = 0; - ias_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); - - memcpy (ias_cmd->params, dev->enetaddr, 6); - - /* Tell the adapter where the TX ring is located. - */ - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); - - for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", - dev->name); - goto Done; - } - } - - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); - goto Done; - } - - status = 1; - - Done: - return status; -} - -static int eepro100_send (struct eth_device *dev, volatile void *packet, int length) -{ - int i, status = -1; - int tx_cur; - - if (length <= 0) { - printf ("%s: bad packet size: %d\n", dev->name, length); - goto Done; - } - - tx_cur = tx_next; - tx_next = (tx_next + 1) % NUM_TX_DESC; - - tx_ring[tx_cur].command = cpu_to_le16 ( TxCB_CMD_TRANSMIT | - TxCB_CMD_SF | - TxCB_CMD_S | - TxCB_CMD_EL ); - tx_ring[tx_cur].status = 0; - tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); - tx_ring[tx_cur].link = - cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); - tx_ring[tx_cur].tx_desc_addr = - cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_cur].tx_buf_addr0)); - tx_ring[tx_cur].tx_buf_addr0 = - cpu_to_le32 (phys_to_bus ((u_long) packet)); - tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); - - if (!wait_for_eepro100 (dev)) { - printf ("%s: Tx error ethernet controller not ready.\n", - dev->name); - goto Done; - } - - /* Send the packet. - */ - OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); - OUTW (dev, SCB_M | CU_START, SCBCmd); - - for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); - i++) { - if (i >= TOUT_LOOP) { - printf ("%s: Tx error buffer not ready\n", dev->name); - goto Done; - } - } - - if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { - printf ("TX error status = 0x%08X\n", - le16_to_cpu (tx_ring[tx_cur].status)); - goto Done; - } - - status = length; - - Done: - return status; -} - -static int eepro100_recv (struct eth_device *dev) -{ - u16 status, stat; - int rx_prev, length = 0; - - stat = INW (dev, SCBStatus); - OUTW (dev, stat & SCB_STATUS_RNR, SCBStatus); - - for (;;) { - status = le16_to_cpu (rx_ring[rx_next].status); - - if (!(status & RFD_STATUS_C)) { - break; - } - - /* Valid frame status. - */ - if ((status & RFD_STATUS_OK)) { - /* A valid frame received. - */ - length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; - - /* Pass the packet up to the protocol - * layers. - */ - NetReceive (rx_ring[rx_next].data, length); - } else { - /* There was an error. - */ - printf ("RX error status = 0x%08X\n", status); - } - - rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); - rx_ring[rx_next].status = 0; - rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); - - rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; - rx_ring[rx_prev].control = 0; - - /* Update entry information. - */ - rx_next = (rx_next + 1) % NUM_RX_DESC; - } - - if (stat & SCB_STATUS_RNR) { - - printf ("%s: Receiver is not ready, restart it !\n", dev->name); - - /* Reinitialize Rx ring. - */ - init_rx_ring (dev); - - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not restart ethernet controller.\n"); - goto Done; - } - - OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); - OUTW (dev, SCB_M | RUC_START, SCBCmd); - } - - Done: - return length; -} - -static void eepro100_halt (struct eth_device *dev) -{ - /* Reset the ethernet controller - */ - OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); - udelay (20); - - OUTL (dev, I82559_RESET, SCBPort); - udelay (20); - - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); - - if (!wait_for_eepro100 (dev)) { - printf ("Error: Can not reset ethernet controller.\n"); - goto Done; - } - OUTL (dev, 0, SCBPointer); - OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); - - Done: - return; -} - - /* SROM Read. - */ -static int read_eeprom (struct eth_device *dev, int location, int addr_len) -{ - unsigned short retval = 0; - int read_cmd = location | EE_READ_CMD; - int i; - - OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); - OUTW (dev, EE_ENB, SCBeeprom); - - /* Shift the read command bits out. */ - for (i = 12; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - - OUTW (dev, EE_ENB | dataval, SCBeeprom); - udelay (1); - OUTW (dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay (1); - } - OUTW (dev, EE_ENB, SCBeeprom); - - for (i = 15; i >= 0; i--) { - OUTW (dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); - udelay (1); - retval = (retval << 1) | - ((INW (dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); - OUTW (dev, EE_ENB, SCBeeprom); - udelay (1); - } - - /* Terminate the EEPROM access. */ - OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); - return retval; -} - -#ifdef CONFIG_EEPRO100_SROM_WRITE -int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, unsigned short data) -{ - unsigned short dataval; - int enable_cmd = 0x3f | EE_EWENB_CMD; - int write_cmd = location | EE_WRITE_CMD; - int i; - unsigned long datalong, tmplong; - - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB, SCBeeprom); - - /* Shift the enable command bits out. */ - for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) - { - dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - } - - OUTW(dev, EE_ENB, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB, SCBeeprom); - - - /* Shift the write command bits out. */ - for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) - { - dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - } - - /* Write the data */ - datalong= (unsigned long) ((((data) & 0x00ff) << 8) | ( (data) >> 8)); - - for (i = 0; i< EE_DATA_BITS; i++) - { - /* Extract and move data bit to bit DI */ - dataval = ((datalong & 0x8000)>>13) ? EE_DATA_WRITE : 0; - - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); - udelay(1); - OUTW(dev, EE_ENB | dataval, SCBeeprom); - udelay(1); - - datalong = datalong << 1; /* Adjust significant data bit*/ - } - - /* Finish up command (toggle CS) */ - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - udelay(1); /* delay for more than 250 ns */ - OUTW(dev, EE_ENB, SCBeeprom); - - /* Wait for programming ready (D0 = 1) */ - tmplong = 10; - do - { - dataval = INW(dev, SCBeeprom); - if (dataval & EE_DATA_READ) - break; - udelay(10000); - } - while (-- tmplong); - - if (tmplong == 0) - { - printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n"); - return -1; - } - - /* Terminate the EEPROM access. */ - OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); - - return 0; -} -#endif - -static void init_rx_ring (struct eth_device *dev) -{ - int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - rx_ring[i].status = 0; - rx_ring[i].control = - (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; - rx_ring[i].link = - cpu_to_le32 (phys_to_bus - ((u32) & rx_ring[(i + 1) % NUM_RX_DESC])); - rx_ring[i].rx_buf_addr = 0xffffffff; - rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); - } - - rx_next = 0; -} - -static void purge_tx_ring (struct eth_device *dev) -{ - int i; - - tx_next = 0; - tx_threshold = 0x01208000; - - for (i = 0; i < NUM_TX_DESC; i++) { - tx_ring[i].status = 0; - tx_ring[i].command = 0; - tx_ring[i].link = 0; - tx_ring[i].tx_desc_addr = 0; - tx_ring[i].count = 0; - - tx_ring[i].tx_buf_addr0 = 0; - tx_ring[i].tx_buf_size0 = 0; - tx_ring[i].tx_buf_addr1 = 0; - tx_ring[i].tx_buf_size1 = 0; - } -} - -static void read_hw_addr (struct eth_device *dev, bd_t * bis) -{ - u16 eeprom[0x40]; - u16 sum = 0; - int i, j; - int addr_len = read_eeprom (dev, 0, 6) == 0xffff ? 8 : 6; - - for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom (dev, i, addr_len); - - eeprom[i] = value; - sum += value; - if (i < 3) { - dev->enetaddr[j++] = value; - dev->enetaddr[j++] = value >> 8; - } - } - - if (sum != 0xBABA) { - memset (dev->enetaddr, 0, ETH_ALEN); -#ifdef DEBUG - printf ("%s: Invalid EEPROM checksum %#4.4x, " - "check settings before activating this device!\n", - dev->name, sum); -#endif - } -} - -#endif diff --git a/drivers/enc28j60.c b/drivers/enc28j60.c deleted file mode 100644 index 98303aceee..0000000000 --- a/drivers/enc28j60.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#ifdef CONFIG_ENC28J60 -#include -#include -#include - -/* - * Control Registers in Bank 0 - */ - -#define CTL_REG_ERDPTL 0x00 -#define CTL_REG_ERDPTH 0x01 -#define CTL_REG_EWRPTL 0x02 -#define CTL_REG_EWRPTH 0x03 -#define CTL_REG_ETXSTL 0x04 -#define CTL_REG_ETXSTH 0x05 -#define CTL_REG_ETXNDL 0x06 -#define CTL_REG_ETXNDH 0x07 -#define CTL_REG_ERXSTL 0x08 -#define CTL_REG_ERXSTH 0x09 -#define CTL_REG_ERXNDL 0x0A -#define CTL_REG_ERXNDH 0x0B -#define CTL_REG_ERXRDPTL 0x0C -#define CTL_REG_ERXRDPTH 0x0D -#define CTL_REG_ERXWRPTL 0x0E -#define CTL_REG_ERXWRPTH 0x0F -#define CTL_REG_EDMASTL 0x10 -#define CTL_REG_EDMASTH 0x11 -#define CTL_REG_EDMANDL 0x12 -#define CTL_REG_EDMANDH 0x13 -#define CTL_REG_EDMADSTL 0x14 -#define CTL_REG_EDMADSTH 0x15 -#define CTL_REG_EDMACSL 0x16 -#define CTL_REG_EDMACSH 0x17 -/* these are common in all banks */ -#define CTL_REG_EIE 0x1B -#define CTL_REG_EIR 0x1C -#define CTL_REG_ESTAT 0x1D -#define CTL_REG_ECON2 0x1E -#define CTL_REG_ECON1 0x1F - -/* - * Control Registers in Bank 1 - */ - -#define CTL_REG_EHT0 0x00 -#define CTL_REG_EHT1 0x01 -#define CTL_REG_EHT2 0x02 -#define CTL_REG_EHT3 0x03 -#define CTL_REG_EHT4 0x04 -#define CTL_REG_EHT5 0x05 -#define CTL_REG_EHT6 0x06 -#define CTL_REG_EHT7 0x07 -#define CTL_REG_EPMM0 0x08 -#define CTL_REG_EPMM1 0x09 -#define CTL_REG_EPMM2 0x0A -#define CTL_REG_EPMM3 0x0B -#define CTL_REG_EPMM4 0x0C -#define CTL_REG_EPMM5 0x0D -#define CTL_REG_EPMM6 0x0E -#define CTL_REG_EPMM7 0x0F -#define CTL_REG_EPMCSL 0x10 -#define CTL_REG_EPMCSH 0x11 -#define CTL_REG_EPMOL 0x14 -#define CTL_REG_EPMOH 0x15 -#define CTL_REG_EWOLIE 0x16 -#define CTL_REG_EWOLIR 0x17 -#define CTL_REG_ERXFCON 0x18 -#define CTL_REG_EPKTCNT 0x19 - -/* - * Control Registers in Bank 2 - */ - -#define CTL_REG_MACON1 0x00 -#define CTL_REG_MACON2 0x01 -#define CTL_REG_MACON3 0x02 -#define CTL_REG_MACON4 0x03 -#define CTL_REG_MABBIPG 0x04 -#define CTL_REG_MAIPGL 0x06 -#define CTL_REG_MAIPGH 0x07 -#define CTL_REG_MACLCON1 0x08 -#define CTL_REG_MACLCON2 0x09 -#define CTL_REG_MAMXFLL 0x0A -#define CTL_REG_MAMXFLH 0x0B -#define CTL_REG_MAPHSUP 0x0D -#define CTL_REG_MICON 0x11 -#define CTL_REG_MICMD 0x12 -#define CTL_REG_MIREGADR 0x14 -#define CTL_REG_MIWRL 0x16 -#define CTL_REG_MIWRH 0x17 -#define CTL_REG_MIRDL 0x18 -#define CTL_REG_MIRDH 0x19 - -/* - * Control Registers in Bank 3 - */ - -#define CTL_REG_MAADR1 0x00 -#define CTL_REG_MAADR0 0x01 -#define CTL_REG_MAADR3 0x02 -#define CTL_REG_MAADR2 0x03 -#define CTL_REG_MAADR5 0x04 -#define CTL_REG_MAADR4 0x05 -#define CTL_REG_EBSTSD 0x06 -#define CTL_REG_EBSTCON 0x07 -#define CTL_REG_EBSTCSL 0x08 -#define CTL_REG_EBSTCSH 0x09 -#define CTL_REG_MISTAT 0x0A -#define CTL_REG_EREVID 0x12 -#define CTL_REG_ECOCON 0x15 -#define CTL_REG_EFLOCON 0x17 -#define CTL_REG_EPAUSL 0x18 -#define CTL_REG_EPAUSH 0x19 - - -/* - * PHY Register - */ - -#define PHY_REG_PHID1 0x02 -#define PHY_REG_PHID2 0x03 -/* taken from the Linux driver */ -#define PHY_REG_PHCON1 0x00 -#define PHY_REG_PHCON2 0x10 -#define PHY_REG_PHLCON 0x14 - -/* - * Receive Filter Register (ERXFCON) bits - */ - -#define ENC_RFR_UCEN 0x80 -#define ENC_RFR_ANDOR 0x40 -#define ENC_RFR_CRCEN 0x20 -#define ENC_RFR_PMEN 0x10 -#define ENC_RFR_MPEN 0x08 -#define ENC_RFR_HTEN 0x04 -#define ENC_RFR_MCEN 0x02 -#define ENC_RFR_BCEN 0x01 - -/* - * ECON1 Register Bits - */ - -#define ENC_ECON1_TXRST 0x80 -#define ENC_ECON1_RXRST 0x40 -#define ENC_ECON1_DMAST 0x20 -#define ENC_ECON1_CSUMEN 0x10 -#define ENC_ECON1_TXRTS 0x08 -#define ENC_ECON1_RXEN 0x04 -#define ENC_ECON1_BSEL1 0x02 -#define ENC_ECON1_BSEL0 0x01 - -/* - * ECON2 Register Bits - */ -#define ENC_ECON2_AUTOINC 0x80 -#define ENC_ECON2_PKTDEC 0x40 -#define ENC_ECON2_PWRSV 0x20 -#define ENC_ECON2_VRPS 0x08 - -/* - * EIR Register Bits - */ -#define ENC_EIR_PKTIF 0x40 -#define ENC_EIR_DMAIF 0x20 -#define ENC_EIR_LINKIF 0x10 -#define ENC_EIR_TXIF 0x08 -#define ENC_EIR_WOLIF 0x04 -#define ENC_EIR_TXERIF 0x02 -#define ENC_EIR_RXERIF 0x01 - -/* - * ESTAT Register Bits - */ - -#define ENC_ESTAT_INT 0x80 -#define ENC_ESTAT_LATECOL 0x10 -#define ENC_ESTAT_RXBUSY 0x04 -#define ENC_ESTAT_TXABRT 0x02 -#define ENC_ESTAT_CLKRDY 0x01 - -/* - * EIE Register Bits - */ - -#define ENC_EIE_INTIE 0x80 -#define ENC_EIE_PKTIE 0x40 -#define ENC_EIE_DMAIE 0x20 -#define ENC_EIE_LINKIE 0x10 -#define ENC_EIE_TXIE 0x08 -#define ENC_EIE_WOLIE 0x04 -#define ENC_EIE_TXERIE 0x02 -#define ENC_EIE_RXERIE 0x01 - -/* - * MACON1 Register Bits - */ -#define ENC_MACON1_LOOPBK 0x10 -#define ENC_MACON1_TXPAUS 0x08 -#define ENC_MACON1_RXPAUS 0x04 -#define ENC_MACON1_PASSALL 0x02 -#define ENC_MACON1_MARXEN 0x01 - - -/* - * MACON2 Register Bits - */ -#define ENC_MACON2_MARST 0x80 -#define ENC_MACON2_RNDRST 0x40 -#define ENC_MACON2_MARXRST 0x08 -#define ENC_MACON2_RFUNRST 0x04 -#define ENC_MACON2_MATXRST 0x02 -#define ENC_MACON2_TFUNRST 0x01 - -/* - * MACON3 Register Bits - */ -#define ENC_MACON3_PADCFG2 0x80 -#define ENC_MACON3_PADCFG1 0x40 -#define ENC_MACON3_PADCFG0 0x20 -#define ENC_MACON3_TXCRCEN 0x10 -#define ENC_MACON3_PHDRLEN 0x08 -#define ENC_MACON3_HFRMEN 0x04 -#define ENC_MACON3_FRMLNEN 0x02 -#define ENC_MACON3_FULDPX 0x01 - -/* - * MICMD Register Bits - */ -#define ENC_MICMD_MIISCAN 0x02 -#define ENC_MICMD_MIIRD 0x01 - -/* - * MISTAT Register Bits - */ -#define ENC_MISTAT_NVALID 0x04 -#define ENC_MISTAT_SCAN 0x02 -#define ENC_MISTAT_BUSY 0x01 - -/* - * PHID1 and PHID2 values - */ -#define ENC_PHID1_VALUE 0x0083 -#define ENC_PHID2_VALUE 0x1400 -#define ENC_PHID2_MASK 0xFC00 - - -#define ENC_SPI_SLAVE_CS 0x00010000 /* pin P1.16 */ -#define ENC_RESET 0x00020000 /* pin P1.17 */ - -#define FAILSAFE_VALUE 5000 - -/* - * Controller memory layout: - * - * 0x0000 - 0x17ff 6k bytes receive buffer - * 0x1800 - 0x1fff 2k bytes transmit buffer - */ -/* Use the lower memory for receiver buffer. See errata pt. 5 */ -#define ENC_RX_BUF_START 0x0000 -#define ENC_TX_BUF_START 0x1800 -/* taken from the Linux driver */ -#define ENC_RX_BUF_END 0x17ff -#define ENC_TX_BUF_END 0x1fff - -/* maximum frame length */ -#define ENC_MAX_FRM_LEN 1518 - -#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS) -#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS) -#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8); - - -static unsigned char encReadReg (unsigned char regNo); -static void encWriteReg (unsigned char regNo, unsigned char data); -static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c); -static void encReadBuff (unsigned short length, unsigned char *pBuff); -static void encWriteBuff (unsigned short length, unsigned char *pBuff); -static void encBitSet (unsigned char regNo, unsigned char data); -static void encBitClr (unsigned char regNo, unsigned char data); -static void encReset (void); -static void encInit (unsigned char *pEthAddr); -static unsigned short phyRead (unsigned char addr); -static void phyWrite(unsigned char, unsigned short); -static void encPoll (void); -static void encRx (void); - -#define m_nic_read(reg) encReadReg(reg) -#define m_nic_write(reg, data) encWriteReg(reg, data) -#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count) -#define m_nic_read_data(len, buf) encReadBuff((len), (buf)) -#define m_nic_write_data(len, buf) encWriteBuff((len), (buf)) - -/* bit field set */ -#define m_nic_bfs(reg, data) encBitSet(reg, data) - -/* bit field clear */ -#define m_nic_bfc(reg, data) encBitClr(reg, data) - -static unsigned char bank = 0; /* current bank in enc28j60 */ -static unsigned char next_pointer_lsb; -static unsigned char next_pointer_msb; - -static unsigned char buffer[ENC_MAX_FRM_LEN]; -static int rxResetCounter = 0; - -#define RX_RESET_COUNTER 1000; - -/*----------------------------------------------------------------------------- - * Always returns 0 - */ -int eth_init (bd_t * bis) -{ - unsigned char estatVal; - - /* configure GPIO */ - (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS; - (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET; - - /* CS and RESET active low */ - PUT32 (IO1SET, ENC_SPI_SLAVE_CS); - PUT32 (IO1SET, ENC_RESET); - - spi_init (); - - /* taken from the Linux driver - dangerous stuff here! */ - /* Wait for CLKRDY to become set (i.e., check that we can communicate with - the ENC) */ - do - { - estatVal = m_nic_read(CTL_REG_ESTAT); - } while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY)); - - /* initialize controller */ - encReset (); - encInit (bis->bi_enetaddr); - - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ - - return 0; -} - -int eth_send (volatile void *packet, int length) -{ - /* check frame length, etc. */ - /* TODO: */ - - /* switch to bank 0 */ - m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); - - /* set EWRPT */ - m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff)); - m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8)); - - /* set ETXND */ - m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF); - m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8); - - /* set ETXST */ - m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF); - m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8); - - /* write packet */ - m_nic_write_data (length, (unsigned char *) packet); - - /* taken from the Linux driver */ - /* Verify that the internal transmit logic has not been altered by excessive - collisions. See Errata B4 12 and 14. - */ - if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) { - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST); - m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST); - } - m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF)); - - /* set ECON1.TXRTS */ - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS); - - return 0; -} - - -/***************************************************************************** - * This function resets the receiver only. This function may be called from - * interrupt-context. - */ -static void encReceiverReset (void) -{ - unsigned char econ1; - - econ1 = m_nic_read (CTL_REG_ECON1); - if ((econ1 & ENC_ECON1_RXRST) == 0) { - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST); - rxResetCounter = RX_RESET_COUNTER; - } -} - -/***************************************************************************** - * receiver reset timer - */ -static void encReceiverResetCallback (void) -{ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST); - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ -} - -/*----------------------------------------------------------------------------- - * Check for received packets. Call NetReceive for each packet. The return - * value is ignored by the caller. - */ -int eth_rx (void) -{ - if (rxResetCounter > 0 && --rxResetCounter == 0) { - encReceiverResetCallback (); - } - - encPoll (); - - return 0; -} - -void eth_halt (void) -{ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */ -} - -/*****************************************************************************/ - -static void encPoll (void) -{ - unsigned char eir_reg; - volatile unsigned char estat_reg; - unsigned char pkt_cnt; - -#ifdef CONFIG_USE_IRQ - /* clear global interrupt enable bit in enc28j60 */ - m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE); -#endif - estat_reg = m_nic_read (CTL_REG_ESTAT); - - eir_reg = m_nic_read (CTL_REG_EIR); - - if (eir_reg & ENC_EIR_TXIF) { - /* clear TXIF bit in EIR */ - m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF); - } - - /* We have to use pktcnt and not pktif bit, see errata pt. 6 */ - - /* move to bank 1 */ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); - - /* read pktcnt */ - pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); - - if (pkt_cnt > 0) { - if ((eir_reg & ENC_EIR_PKTIF) == 0) { - /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */ - } - encRx (); - /* clear PKTIF bit in EIR, this should not need to be done but it - seems like we get problems if we do not */ - m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF); - } - - if (eir_reg & ENC_EIR_RXERIF) { - printf ("encPoll: rx error\n"); - m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF); - } - if (eir_reg & ENC_EIR_TXERIF) { - printf ("encPoll: tx error\n"); - m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF); - } - -#ifdef CONFIG_USE_IRQ - /* set global interrupt enable bit in enc28j60 */ - m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); -#endif -} - -static void encRx (void) -{ - unsigned short pkt_len; - unsigned short copy_len; - unsigned short status; - unsigned char eir_reg; - unsigned char pkt_cnt = 0; - unsigned short rxbuf_rdpt; - - /* switch to bank 0 */ - m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); - - m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); - m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); - - do { - m_nic_read_data (6, buffer); - next_pointer_lsb = buffer[0]; - next_pointer_msb = buffer[1]; - pkt_len = buffer[2]; - pkt_len |= (unsigned short) buffer[3] << 8; - status = buffer[4]; - status |= (unsigned short) buffer[5] << 8; - - if (pkt_len <= ENC_MAX_FRM_LEN) - copy_len = pkt_len; - else - copy_len = 0; - - if ((status & (1L << 7)) == 0) /* check Received Ok bit */ - copy_len = 0; - - /* taken from the Linux driver */ - /* check if next pointer is resonable */ - if ((((unsigned int)next_pointer_msb << 8) | - (unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START) - copy_len = 0; - - if (copy_len > 0) { - m_nic_read_data (copy_len, buffer); - } - - /* advance read pointer to next pointer */ - m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); - m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); - - /* decrease packet counter */ - m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC); - - /* taken from the Linux driver */ - /* Only odd values should be written to ERXRDPTL, - * see errata B4 pt.13 - */ - rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1; - if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 | - m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt > - (m_nic_read(CTL_REG_ERXNDH) << 8 | - m_nic_read(CTL_REG_ERXNDL)))) { - m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL)); - m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH)); - } else { - m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF); - m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8); - } - - /* move to bank 1 */ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); - - /* read pktcnt */ - pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); - - /* switch to bank 0 */ - m_nic_bfc (CTL_REG_ECON1, - (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); - - if (copy_len == 0) { - eir_reg = m_nic_read (CTL_REG_EIR); - encReceiverReset (); - printf ("eth_rx: copy_len=0\n"); - continue; - } - - NetReceive ((unsigned char *) buffer, pkt_len); - - eir_reg = m_nic_read (CTL_REG_EIR); - } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */ -} - -static void encWriteReg (unsigned char regNo, unsigned char data) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0x40 | regNo); /* write in regNo */ - spi_write (data); - - enc_disable (); - enc_enable (); - - spi_write (0x1f); /* write reg 0x1f */ - - enc_disable (); - spi_unlock (); -} - -static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c) -{ - unsigned char readback; - int i; - - spi_lock (); - - for (i = 0; i < c; i++) { - enc_cfg_spi (); - enc_enable (); - - spi_write (0x40 | regNo); /* write in regNo */ - spi_write (data); - - enc_disable (); - enc_enable (); - - spi_write (0x1f); /* write reg 0x1f */ - - enc_disable (); - - spi_unlock (); /* we must unlock spi first */ - - readback = encReadReg (regNo); - - spi_lock (); - - if (readback == data) - break; - } - spi_unlock (); - - if (i == c) { - printf ("enc28j60: write reg %d failed\n", regNo); - } -} - -static unsigned char encReadReg (unsigned char regNo) -{ - unsigned char rxByte; - - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0x1f); /* read reg 0x1f */ - - bank = spi_read () & 0x3; - - enc_disable (); - enc_enable (); - - spi_write (regNo); - rxByte = spi_read (); - - /* check if MAC or MII register */ - if (((bank == 2) && (regNo <= 0x1a)) || - ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) { - /* ignore first byte and read another byte */ - rxByte = spi_read (); - } - - enc_disable (); - spi_unlock (); - - return rxByte; -} - -static void encReadBuff (unsigned short length, unsigned char *pBuff) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0x20 | 0x1a); /* read buffer memory */ - - while (length--) { - if (pBuff != NULL) - *pBuff++ = spi_read (); - else - spi_write (0); - } - - enc_disable (); - spi_unlock (); -} - -static void encWriteBuff (unsigned short length, unsigned char *pBuff) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0x60 | 0x1a); /* write buffer memory */ - - spi_write (0x00); /* control byte */ - - while (length--) - spi_write (*pBuff++); - - enc_disable (); - spi_unlock (); -} - -static void encBitSet (unsigned char regNo, unsigned char data) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0x80 | regNo); /* bit field set */ - spi_write (data); - - enc_disable (); - spi_unlock (); -} - -static void encBitClr (unsigned char regNo, unsigned char data) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0xA0 | regNo); /* bit field clear */ - spi_write (data); - - enc_disable (); - spi_unlock (); -} - -static void encReset (void) -{ - spi_lock (); - enc_cfg_spi (); - enc_enable (); - - spi_write (0xff); /* soft reset */ - - enc_disable (); - spi_unlock (); - - /* sleep 1 ms. See errata pt. 2 */ - udelay (1000); -} - -static void encInit (unsigned char *pEthAddr) -{ - unsigned short phid1 = 0; - unsigned short phid2 = 0; - - /* switch to bank 0 */ - m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); - - /* - * Setup the buffer space. The reset values are valid for the - * other pointers. - */ - /* We shall not write to ERXST, see errata pt. 5. Instead we - have to make sure that ENC_RX_BUS_START is 0. */ - m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1); - m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1); - - /* taken from the Linux driver */ - m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1); - m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1); - - m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1); - m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1); - - next_pointer_lsb = (ENC_RX_BUF_START & 0xFF); - next_pointer_msb = (ENC_RX_BUF_START >> 8); - - /* verify identification */ - phid1 = phyRead (PHY_REG_PHID1); - phid2 = phyRead (PHY_REG_PHID2); - - if (phid1 != ENC_PHID1_VALUE - || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) { - printf ("ERROR: failed to identify controller\n"); - printf ("phid1 = %x, phid2 = %x\n", - phid1, (phid2 & ENC_PHID2_MASK)); - printf ("should be phid1 = %x, phid2 = %x\n", - ENC_PHID1_VALUE, ENC_PHID2_VALUE); - } - - /* - * --- MAC Initialization --- - */ - - /* Pull MAC out of Reset */ - - /* switch to bank 2 */ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* enable MAC to receive frames */ - /* added some bits from the Linux driver */ - m_nic_write_retry (CTL_REG_MACON1 - ,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS) - ,10); - - /* configure pad, tx-crc and duplex */ - /* added a bit from the Linux driver */ - m_nic_write_retry (CTL_REG_MACON3 - ,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN) - ,10); - - /* added 4 new lines from the Linux driver */ - /* Allow infinite deferals if the medium is continously busy */ - m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10); - - /* Late collisions occur beyond 63 bytes */ - m_nic_write_retry(CTL_REG_MACLCON2, 63, 10); - - /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */ - m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10); - - /* - * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended - * 0x0c for half-duplex. Nothing for full-duplex - */ - m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10); - - /* set maximum frame length */ - m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10); - m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10); - - /* - * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex - * and 0x15 for full duplex. - */ - m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10); - - /* set MAC address */ - - /* switch to bank 3 */ - m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1)); - - m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1); - m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1); - m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1); - m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1); - m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1); - m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1); - - /* - * PHY Initialization taken from the Linux driver - */ - - /* Prevent automatic loopback of data beeing transmitted by setting - ENC_PHCON2_HDLDIS */ - phyWrite(PHY_REG_PHCON2, (1<<8)); - - /* LEDs configuration - * LEDA: LACFG = 0100 -> display link status - * LEDB: LBCFG = 0111 -> display TX & RX activity - * STRCH = 1 -> LED pulses - */ - phyWrite(PHY_REG_PHLCON, 0x0472); - - /* Reset PDPXMD-bit => half duplex */ - phyWrite(PHY_REG_PHCON1, 0); - - /* - * Receive settings - */ - -#ifdef CONFIG_USE_IRQ - /* enable interrupts */ - m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE); - m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE); - m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE); - m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE); - m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); -#endif -} - -/***************************************************************************** - * - * Description: - * Read PHY registers. - * - * NOTE! This function will change to Bank 2. - * - * Params: - * [in] addr address of the register to read - * - * Returns: - * The value in the register - */ -static unsigned short phyRead (unsigned char addr) -{ - unsigned short ret = 0; - - /* move to bank 2 */ - m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* write address to MIREGADR */ - m_nic_write (CTL_REG_MIREGADR, addr); - - /* set MICMD.MIIRD */ - m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD); - - /* taken from the Linux driver */ - /* move to bank 3 */ - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* poll MISTAT.BUSY bit until operation is complete */ - while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { - static int cnt = 0; - - if (cnt++ >= 1000) { - /* GJ - this seems extremely dangerous! */ - /* printf("#"); */ - cnt = 0; - } - } - - /* taken from the Linux driver */ - /* move to bank 2 */ - m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* clear MICMD.MIIRD */ - m_nic_write (CTL_REG_MICMD, 0); - - ret = (m_nic_read (CTL_REG_MIRDH) << 8); - ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF); - - return ret; -} - -/***************************************************************************** - * - * Taken from the Linux driver. - * Description: - * Write PHY registers. - * - * NOTE! This function will change to Bank 3. - * - * Params: - * [in] addr address of the register to write to - * [in] data to be written - * - * Returns: - * None - */ -static void phyWrite(unsigned char addr, unsigned short data) -{ - /* move to bank 2 */ - m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* write address to MIREGADR */ - m_nic_write(CTL_REG_MIREGADR, addr); - - m_nic_write(CTL_REG_MIWRL, data & 0xff); - m_nic_write(CTL_REG_MIWRH, data >> 8); - - /* move to bank 3 */ - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); - m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); - - /* poll MISTAT.BUSY bit until operation is complete */ - while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { - static int cnt = 0; - - if(cnt++ >= 1000) { - cnt = 0; - } - } -} - -#endif /* CONFIG_ENC28J60 */ diff --git a/drivers/inca-ip_sw.c b/drivers/inca-ip_sw.c deleted file mode 100644 index e4aaed6afb..0000000000 --- a/drivers/inca-ip_sw.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * INCA-IP internal switch ethernet driver. - * - * (C) Copyright 2003-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - - -#include - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_INCA_IP_SWITCH) - -#include -#include -#include -#include - - -#define NUM_RX_DESC PKTBUFSRX -#define NUM_TX_DESC 3 -#define TOUT_LOOP 1000000 - - -#define DELAY udelay(10000) - /* Sometimes the store word instruction hangs while writing to one - * of the Switch registers. Moving the instruction into a separate - * function somehow makes the problem go away. - */ -static void SWORD(volatile u32 * reg, u32 value) -{ - *reg = value; -} - -#define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value; -#define DMA_READ_REG(reg, value) value = (u32)*((volatile u32*)reg) -#define SW_WRITE_REG(reg, value) \ - SWORD(reg, value);\ - DELAY;\ - SWORD(reg, value); - -#define SW_READ_REG(reg, value) \ - value = (u32)*((volatile u32*)reg);\ - DELAY;\ - value = (u32)*((volatile u32*)reg); - -#define INCA_DMA_TX_POLLING_TIME 0x07 -#define INCA_DMA_RX_POLLING_TIME 0x07 - -#define INCA_DMA_TX_HOLD 0x80000000 -#define INCA_DMA_TX_EOP 0x40000000 -#define INCA_DMA_TX_SOP 0x20000000 -#define INCA_DMA_TX_ICPT 0x10000000 -#define INCA_DMA_TX_IEOP 0x08000000 - -#define INCA_DMA_RX_C 0x80000000 -#define INCA_DMA_RX_SOP 0x40000000 -#define INCA_DMA_RX_EOP 0x20000000 - -#define INCA_SWITCH_PHY_SPEED_10H 0x1 -#define INCA_SWITCH_PHY_SPEED_10F 0x5 -#define INCA_SWITCH_PHY_SPEED_100H 0x2 -#define INCA_SWITCH_PHY_SPEED_100F 0x6 - -/************************ Auto MDIX settings ************************/ -#define INCA_IP_AUTO_MDIX_LAN_PORTS_DIR INCA_IP_Ports_P1_DIR -#define INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL INCA_IP_Ports_P1_ALTSEL -#define INCA_IP_AUTO_MDIX_LAN_PORTS_OUT INCA_IP_Ports_P1_OUT -#define INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX 16 - -#define WAIT_SIGNAL_RETRIES 100 -#define WAIT_LINK_RETRIES 100 -#define LINK_RETRY_DELAY 2000 /* ms */ -/********************************************************************/ - -typedef struct -{ - union { - struct { - volatile u32 HOLD :1; - volatile u32 ICpt :1; - volatile u32 IEop :1; - volatile u32 offset :3; - volatile u32 reserved0 :4; - volatile u32 NFB :22; - }field; - - volatile u32 word; - }params; - - volatile u32 nextRxDescPtr; - - volatile u32 RxDataPtr; - - union { - struct { - volatile u32 C :1; - volatile u32 Sop :1; - volatile u32 Eop :1; - volatile u32 reserved3 :12; - volatile u32 NBT :17; - }field; - - volatile u32 word; - }status; - -} inca_rx_descriptor_t; - - -typedef struct -{ - union { - struct { - volatile u32 HOLD :1; - volatile u32 Eop :1; - volatile u32 Sop :1; - volatile u32 ICpt :1; - volatile u32 IEop :1; - volatile u32 reserved0 :5; - volatile u32 NBA :22; - }field; - - volatile u32 word; - }params; - - volatile u32 nextTxDescPtr; - - volatile u32 TxDataPtr; - - volatile u32 C :1; - volatile u32 reserved3 :31; - -} inca_tx_descriptor_t; - - -static inca_rx_descriptor_t rx_ring[NUM_RX_DESC] __attribute__ ((aligned(16))); -static inca_tx_descriptor_t tx_ring[NUM_TX_DESC] __attribute__ ((aligned(16))); - -static int tx_new, rx_new, tx_hold, rx_hold; -static int tx_old_hold = -1; -static int initialized = 0; - - -static int inca_switch_init(struct eth_device *dev, bd_t * bis); -static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length); -static int inca_switch_recv(struct eth_device *dev); -static void inca_switch_halt(struct eth_device *dev); -static void inca_init_switch_chip(void); -static void inca_dma_init(void); -static int inca_amdix(void); - - -int inca_switch_initialize(bd_t * bis) -{ - struct eth_device *dev; - -#if 0 - printf("Entered inca_switch_initialize()\n"); -#endif - - if (!(dev = (struct eth_device *) malloc (sizeof *dev))) { - printf("Failed to allocate memory\n"); - return 0; - } - memset(dev, 0, sizeof(*dev)); - - inca_dma_init(); - - inca_init_switch_chip(); - -#if defined(CONFIG_INCA_IP_SWITCH_AMDIX) - inca_amdix(); -#endif - - sprintf(dev->name, "INCA-IP Switch"); - dev->init = inca_switch_init; - dev->halt = inca_switch_halt; - dev->send = inca_switch_send; - dev->recv = inca_switch_recv; - - eth_register(dev); - -#if 0 - printf("Leaving inca_switch_initialize()\n"); -#endif - - return 1; -} - - -static int inca_switch_init(struct eth_device *dev, bd_t * bis) -{ - int i; - u32 v, regValue; - u16 wTmp; - -#if 0 - printf("Entering inca_switch_init()\n"); -#endif - - /* Set MAC address. - */ - wTmp = (u16)dev->enetaddr[0]; - regValue = (wTmp << 8) | dev->enetaddr[1]; - - SW_WRITE_REG(INCA_IP_Switch_PMAC_SA1, regValue); - - wTmp = (u16)dev->enetaddr[2]; - regValue = (wTmp << 8) | dev->enetaddr[3]; - regValue = regValue << 16; - wTmp = (u16)dev->enetaddr[4]; - regValue |= (wTmp<<8) | dev->enetaddr[5]; - - SW_WRITE_REG(INCA_IP_Switch_PMAC_SA2, regValue); - - /* Initialize the descriptor rings. - */ - for (i = 0; i < NUM_RX_DESC; i++) { - inca_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_ring[i]); - memset(rx_desc, 0, sizeof(rx_ring[i])); - - /* Set maximum size of receive buffer. - */ - rx_desc->params.field.NFB = PKTSIZE_ALIGN; - - /* Set the offset of the receive buffer. Zero means - * that the offset mechanism is not used. - */ - rx_desc->params.field.offset = 0; - - /* Check if it is the last descriptor. - */ - if (i == (NUM_RX_DESC - 1)) { - /* Let the last descriptor point to the first - * one. - */ - rx_desc->nextRxDescPtr = KSEG1ADDR((u32)rx_ring); - } else { - /* Set the address of the next descriptor. - */ - rx_desc->nextRxDescPtr = (u32)KSEG1ADDR(&rx_ring[i+1]); - } - - rx_desc->RxDataPtr = (u32)KSEG1ADDR(NetRxPackets[i]); - } - -#if 0 - printf("rx_ring = 0x%08X 0x%08X\n", (u32)rx_ring, (u32)&rx_ring[0]); - printf("tx_ring = 0x%08X 0x%08X\n", (u32)tx_ring, (u32)&tx_ring[0]); -#endif - - for (i = 0; i < NUM_TX_DESC; i++) { - inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[i]); - - memset(tx_desc, 0, sizeof(tx_ring[i])); - - tx_desc->params.word = 0; - tx_desc->params.field.HOLD = 1; - tx_desc->C = 1; - - /* Check if it is the last descriptor. - */ - if (i == (NUM_TX_DESC - 1)) { - /* Let the last descriptor point to the - * first one. - */ - tx_desc->nextTxDescPtr = KSEG1ADDR((u32)tx_ring); - } else { - /* Set the address of the next descriptor. - */ - tx_desc->nextTxDescPtr = (u32)KSEG1ADDR(&tx_ring[i+1]); - } - } - - /* Initialize RxDMA. - */ - DMA_READ_REG(INCA_IP_DMA_DMA_RXISR, v); -#if 0 - printf("RX status = 0x%08X\n", v); -#endif - - /* Writing to the FRDA of CHANNEL. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXFRDA0, (u32)rx_ring); - - /* Writing to the COMMAND REG. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_INIT); - - /* Initialize TxDMA. - */ - DMA_READ_REG(INCA_IP_DMA_DMA_TXISR, v); -#if 0 - printf("TX status = 0x%08X\n", v); -#endif - - /* Writing to the FRDA of CHANNEL. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXFRDA0, (u32)tx_ring); - - tx_new = rx_new = 0; - - tx_hold = NUM_TX_DESC - 1; - rx_hold = NUM_RX_DESC - 1; - -#if 0 - rx_ring[rx_hold].params.field.HOLD = 1; -#endif - /* enable spanning tree forwarding, enable the CPU port */ - /* ST_PT: - * CPS (CPU port status) 0x3 (forwarding) - * LPS (LAN port status) 0x3 (forwarding) - * PPS (PC port status) 0x3 (forwarding) - */ - SW_WRITE_REG(INCA_IP_Switch_ST_PT,0x3f); - -#if 0 - printf("Leaving inca_switch_init()\n"); -#endif - - return 0; -} - - -static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length) -{ - int i; - int res = -1; - u32 command; - u32 regValue; - inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[tx_new]); - -#if 0 - printf("Entered inca_switch_send()\n"); -#endif - - if (length <= 0) { - printf ("%s: bad packet size: %d\n", dev->name, length); - goto Done; - } - - for(i = 0; tx_desc->C == 0; i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx error buffer not ready\n", dev->name); - goto Done; - } - } - - if (tx_old_hold >= 0) { - KSEG1ADDR(&tx_ring[tx_old_hold])->params.field.HOLD = 1; - } - tx_old_hold = tx_hold; - - tx_desc->params.word = - (INCA_DMA_TX_SOP | INCA_DMA_TX_EOP | INCA_DMA_TX_HOLD); - - tx_desc->C = 0; - tx_desc->TxDataPtr = (u32)packet; - tx_desc->params.field.NBA = length; - - KSEG1ADDR(&tx_ring[tx_hold])->params.field.HOLD = 0; - - tx_hold = tx_new; - tx_new = (tx_new + 1) % NUM_TX_DESC; - - - if (! initialized) { - command = INCA_IP_DMA_DMA_TXCCR0_INIT; - initialized = 1; - } else { - command = INCA_IP_DMA_DMA_TXCCR0_HR; - } - - DMA_READ_REG(INCA_IP_DMA_DMA_TXCCR0, regValue); - regValue |= command; -#if 0 - printf("regValue = 0x%x\n", regValue); -#endif - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, regValue); - -#if 1 - for(i = 0; KSEG1ADDR(&tx_ring[tx_hold])->C == 0; i++) { - if (i >= TOUT_LOOP) { - printf("%s: tx buffer not ready\n", dev->name); - goto Done; - } - } -#endif - res = length; -Done: -#if 0 - printf("Leaving inca_switch_send()\n"); -#endif - return res; -} - - -static int inca_switch_recv(struct eth_device *dev) -{ - int length = 0; - inca_rx_descriptor_t * rx_desc; - -#if 0 - printf("Entered inca_switch_recv()\n"); -#endif - - for (;;) { - rx_desc = KSEG1ADDR(&rx_ring[rx_new]); - - if (rx_desc->status.field.C == 0) { - break; - } - -#if 0 - rx_ring[rx_new].params.field.HOLD = 1; -#endif - - if (! rx_desc->status.field.Eop) { - printf("Partly received packet!!!\n"); - break; - } - - length = rx_desc->status.field.NBT; - rx_desc->status.word &= - ~(INCA_DMA_RX_EOP | INCA_DMA_RX_SOP | INCA_DMA_RX_C); -#if 0 -{ - int i; - for (i=0;iparams.field.HOLD = 0; - - rx_hold = rx_new; - - rx_new = (rx_new + 1) % NUM_RX_DESC; - } - -#if 0 - printf("Leaving inca_switch_recv()\n"); -#endif - - return length; -} - - -static void inca_switch_halt(struct eth_device *dev) -{ -#if 0 - printf("Entered inca_switch_halt()\n"); -#endif - -#if 1 - initialized = 0; -#endif -#if 1 - /* Disable forwarding to the CPU port. - */ - SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf); - - /* Close RxDMA channel. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); - - /* Close TxDMA channel. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_TXCCR0_OFF); - - -#endif -#if 0 - printf("Leaving inca_switch_halt()\n"); -#endif -} - - -static void inca_init_switch_chip(void) -{ - u32 regValue; - - /* To workaround a problem with collision counter - * (see Errata sheet). - */ - SW_WRITE_REG(INCA_IP_Switch_PC_TX_CTL, 0x00000001); - SW_WRITE_REG(INCA_IP_Switch_LAN_TX_CTL, 0x00000001); - -#if 1 - /* init MDIO configuration: - * MDS (Poll speed): 0x01 (4ms) - * PHY_LAN_ADDR: 0x06 - * PHY_PC_ADDR: 0x05 - * UEP (Use External PHY): 0x00 (Internal PHY is used) - * PS (Port Select): 0x00 (PT/UMM for LAN) - * PT (PHY Test): 0x00 (no test mode) - * UMM (Use MDIO Mode): 0x00 (state machine is disabled) - */ - SW_WRITE_REG(INCA_IP_Switch_MDIO_CFG, 0x4c50); - - /* init PHY: - * SL (Auto Neg. Speed for LAN) - * SP (Auto Neg. Speed for PC) - * LL (Link Status for LAN) - * LP (Link Status for PC) - * DL (Duplex Status for LAN) - * DP (Duplex Status for PC) - * PL (Auto Neg. Pause Status for LAN) - * PP (Auto Neg. Pause Status for PC) - */ - SW_WRITE_REG (INCA_IP_Switch_EPHY, 0xff); - - /* MDIO_ACC: - * RA (Request/Ack) 0x01 (Request) - * RW (Read/Write) 0x01 (Write) - * PHY_ADDR 0x05 (PC) - * REG_ADDR 0x00 (PHY_BCR: basic control register) - * PHY_DATA 0x8000 - * Reset - software reset - * LB (loop back) - normal - * SS (speed select) - 10 Mbit/s - * ANE (auto neg. enable) - enable - * PD (power down) - normal - * ISO (isolate) - normal - * RAN (restart auto neg.) - normal - * DM (duplex mode) - half duplex - * CT (collision test) - enable - */ - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0a09000); - - /* MDIO_ACC: - * RA (Request/Ack) 0x01 (Request) - * RW (Read/Write) 0x01 (Write) - * PHY_ADDR 0x06 (LAN) - * REG_ADDR 0x00 (PHY_BCR: basic control register) - * PHY_DATA 0x8000 - * Reset - software reset - * LB (loop back) - normal - * SS (speed select) - 10 Mbit/s - * ANE (auto neg. enable) - enable - * PD (power down) - normal - * ISO (isolate) - normal - * RAN (restart auto neg.) - normal - * DM (duplex mode) - half duplex - * CT (collision test) - enable - */ - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0c09000); - -#endif - - /* Make sure the CPU port is disabled for now. We - * don't want packets to get stacked for us until - * we enable DMA and are prepared to receive them. - */ - SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf); - - SW_READ_REG(INCA_IP_Switch_ARL_CTL, regValue); - - /* CRC GEN is enabled. - */ - regValue |= 0x00000200; - SW_WRITE_REG(INCA_IP_Switch_ARL_CTL, regValue); - - /* ADD TAG is disabled. - */ - SW_READ_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue); - regValue &= ~0x00000002; - SW_WRITE_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue); -} - - -static void inca_dma_init(void) -{ - /* Switch off all DMA channels. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR1, INCA_IP_DMA_DMA_RXCCR1_OFF); - - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR1, INCA_IP_DMA_DMA_TXCCR1_OFF); - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR2, INCA_IP_DMA_DMA_TXCCR2_OFF); - - /* Setup TX channel polling time. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXPOLL, INCA_DMA_TX_POLLING_TIME); - - /* Setup RX channel polling time. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXPOLL, INCA_DMA_RX_POLLING_TIME); - - /* ERRATA: write reset value into the DMA RX IMR register. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXIMR, 0xFFFFFFFF); - - /* Just in case: disable all transmit interrupts also. - */ - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXIMR, 0xFFFFFFFF); - - DMA_WRITE_REG(INCA_IP_DMA_DMA_TXISR, 0xFFFFFFFF); - DMA_WRITE_REG(INCA_IP_DMA_DMA_RXISR, 0xFFFFFFFF); -} - -#if defined(CONFIG_INCA_IP_SWITCH_AMDIX) -static int inca_amdix(void) -{ - u32 phyReg1 = 0; - u32 phyReg4 = 0; - u32 phyReg5 = 0; - u32 phyReg6 = 0; - u32 phyReg31 = 0; - u32 regEphy = 0; - int mdi_flag; - int retries; - - /* Setup GPIO pins. - */ - *INCA_IP_AUTO_MDIX_LAN_PORTS_DIR |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); - *INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); - -#if 0 - /* Wait for signal. - */ - retries = WAIT_SIGNAL_RETRIES; - while (--retries) { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (17 << 16)); /* PHY_MCSR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); - } while (phyReg1 & (1 << 31)); - - if (phyReg1 & (1 << 1)) { - /* Signal detected */ - break; - } - } - - if (!retries) - goto Fail; -#endif - - /* Set MDI mode. - */ - *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); - mdi_flag = 1; - - /* Wait for link. - */ - retries = WAIT_LINK_RETRIES; - while (--retries) { - udelay(LINK_RETRY_DELAY * 1000); - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (1 << 16)); /* PHY_BSR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); - } while (phyReg1 & (1 << 31)); - - if (phyReg1 & (1 << 2)) { - /* Link is up */ - break; - } else if (mdi_flag) { - /* Set MDIX mode */ - *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); - mdi_flag = 0; - } else { - /* Set MDI mode */ - *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); - mdi_flag = 1; - } - } - - if (!retries) { - goto Fail; - } else { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (1 << 16)); /* PHY_BSR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); - } while (phyReg1 & (1 << 31)); - - /* Auto-negotiation / Parallel detection complete - */ - if (phyReg1 & (1 << 5)) { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (31 << 16)); /* PHY_SCSR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg31); - } while (phyReg31 & (1 << 31)); - - switch ((phyReg31 >> 2) & 0x7) { - case INCA_SWITCH_PHY_SPEED_10H: - /* 10Base-T Half-duplex */ - regEphy = 0; - break; - case INCA_SWITCH_PHY_SPEED_10F: - /* 10Base-T Full-duplex */ - regEphy = INCA_IP_Switch_EPHY_DL; - break; - case INCA_SWITCH_PHY_SPEED_100H: - /* 100Base-TX Half-duplex */ - regEphy = INCA_IP_Switch_EPHY_SL; - break; - case INCA_SWITCH_PHY_SPEED_100F: - /* 100Base-TX Full-duplex */ - regEphy = INCA_IP_Switch_EPHY_SL | INCA_IP_Switch_EPHY_DL; - break; - } - - /* In case of Auto-negotiation, - * update the negotiated PAUSE support status - */ - if (phyReg1 & (1 << 3)) { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (6 << 16)); /* PHY_ANER */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg6); - } while (phyReg6 & (1 << 31)); - - /* We are Autoneg-able. - * Is Link partner also able to autoneg? - */ - if (phyReg6 & (1 << 0)) { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (4 << 16)); /* PHY_ANAR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg4); - } while (phyReg4 & (1 << 31)); - - /* We advertise PAUSE capab. - * Does link partner also advertise it? - */ - if (phyReg4 & (1 << 10)) { - SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, - (0x1 << 31) | /* RA */ - (0x0 << 30) | /* Read */ - (0x6 << 21) | /* LAN */ - (5 << 16)); /* PHY_ANLPAR */ - do { - SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg5); - } while (phyReg5 & (1 << 31)); - - /* Link partner is PAUSE capab. - */ - if (phyReg5 & (1 << 10)) { - regEphy |= INCA_IP_Switch_EPHY_PL; - } - } - } - - } - - /* Link is up */ - regEphy |= INCA_IP_Switch_EPHY_LL; - - SW_WRITE_REG(INCA_IP_Switch_EPHY, regEphy); - } - } - - return 0; - -Fail: - printf("No Link on LAN port\n"); - return -1; -} -#endif /* CONFIG_INCA_IP_SWITCH_AMDIX */ - -#endif diff --git a/drivers/ks8695eth.c b/drivers/ks8695eth.c deleted file mode 100644 index b598dd7f23..0000000000 --- a/drivers/ks8695eth.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * ks8695eth.c -- KS8695 ethernet driver - * - * (C) Copyright 2004-2005, Greg Ungerer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/****************************************************************************/ - -#include - -#ifdef CONFIG_DRIVER_KS8695ETH -#include -#include -#include -#include - -/****************************************************************************/ - -/* - * Hardware register access to the KS8695 LAN ethernet port - * (well, it is the 4 port switch really). - */ -#define ks8695_read(a) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) -#define ks8695_write(a,v) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) = (v) - -/****************************************************************************/ - -/* - * Define the descriptor in-memory data structures. - */ -struct ks8695_txdesc { - uint32_t owner; - uint32_t ctrl; - uint32_t addr; - uint32_t next; -}; - -struct ks8695_rxdesc { - uint32_t status; - uint32_t ctrl; - uint32_t addr; - uint32_t next; -}; - -/****************************************************************************/ - -/* - * Allocate local data structures to use for receiving and sending - * packets. Just to keep it all nice and simple. - */ - -#define TXDESCS 4 -#define RXDESCS 4 -#define BUFSIZE 2048 - -volatile struct ks8695_txdesc ks8695_tx[TXDESCS] __attribute__((aligned(256))); -volatile struct ks8695_rxdesc ks8695_rx[RXDESCS] __attribute__((aligned(256))); -volatile uint8_t ks8695_bufs[BUFSIZE*(TXDESCS+RXDESCS)] __attribute__((aligned(2048)));; - -/****************************************************************************/ - -/* - * Ideally we want to use the MAC address stored in flash. - * But we do some sanity checks in case they are not present - * first. - */ -unsigned char eth_mac[] = { - 0x00, 0x13, 0xc6, 0x00, 0x00, 0x00 -}; - -void ks8695_getmac(void) -{ - unsigned char *fp; - int i; - - /* Check if flash MAC is valid */ - fp = (unsigned char *) 0x0201c000; - for (i = 0; (i < 6); i++) { - if ((fp[i] != 0) && (fp[i] != 0xff)) - break; - } - - /* If we found a valid looking MAC address then use it */ - if (i < 6) - memcpy(ð_mac[0], fp, 6); -} - -/****************************************************************************/ - -void eth_reset(bd_t *bd) -{ - int i; - - debug ("%s(%d): eth_reset()\n", __FILE__, __LINE__); - - /* Reset the ethernet engines first */ - ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); - ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); - - ks8695_getmac(); - - /* Set MAC address */ - ks8695_write(KS8695_LAN_MAC_LOW, (eth_mac[5] | (eth_mac[4] << 8) | - (eth_mac[3] << 16) | (eth_mac[2] << 24))); - ks8695_write(KS8695_LAN_MAC_HIGH, (eth_mac[1] | (eth_mac[0] << 8))); - - /* Turn the 4 port switch on */ - i = ks8695_read(KS8695_SWITCH_CTRL0); - ks8695_write(KS8695_SWITCH_CTRL0, (i | 0x1)); - /* ks8695_write(KS8695_WAN_CONTROL, 0x3f000066); */ - - /* Initialize descriptor rings */ - for (i = 0; (i < TXDESCS); i++) { - ks8695_tx[i].owner = 0; - ks8695_tx[i].ctrl = 0; - ks8695_tx[i].addr = (uint32_t) &ks8695_bufs[i*BUFSIZE]; - ks8695_tx[i].next = (uint32_t) &ks8695_tx[i+1]; - } - ks8695_tx[TXDESCS-1].ctrl = 0x02000000; - ks8695_tx[TXDESCS-1].next = (uint32_t) &ks8695_tx[0]; - - for (i = 0; (i < RXDESCS); i++) { - ks8695_rx[i].status = 0x80000000; - ks8695_rx[i].ctrl = BUFSIZE - 4; - ks8695_rx[i].addr = (uint32_t) &ks8695_bufs[(i+TXDESCS)*BUFSIZE]; - ks8695_rx[i].next = (uint32_t) &ks8695_rx[i+1]; - } - ks8695_rx[RXDESCS-1].ctrl |= 0x00080000; - ks8695_rx[RXDESCS-1].next = (uint32_t) &ks8695_rx[0]; - - /* The KS8695 is pretty slow reseting the ethernets... */ - udelay(2000000); - - /* Enable the ethernet engine */ - ks8695_write(KS8695_LAN_TX_LIST, (uint32_t) &ks8695_tx[0]); - ks8695_write(KS8695_LAN_RX_LIST, (uint32_t) &ks8695_rx[0]); - ks8695_write(KS8695_LAN_DMA_TX, 0x3); - ks8695_write(KS8695_LAN_DMA_RX, 0x71); - ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); - - printf("KS8695 ETHERNET: "); - for (i = 0; (i < 5); i++) { - bd->bi_enetaddr[i] = eth_mac[i]; - printf("%02x:", eth_mac[i]); - } - bd->bi_enetaddr[i] = eth_mac[i]; - printf("%02x\n", eth_mac[i]); -} - -/****************************************************************************/ - -int eth_init(bd_t *bd) -{ - debug ("%s(%d): eth_init()\n", __FILE__, __LINE__); - - eth_reset(bd); - return 0; -} - -/****************************************************************************/ - -void eth_halt(void) -{ - debug ("%s(%d): eth_halt()\n", __FILE__, __LINE__); - - /* Reset the ethernet engines */ - ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); - ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); -} - -/****************************************************************************/ - -int eth_rx(void) -{ - volatile struct ks8695_rxdesc *dp; - int i, len = 0; - - debug ("%s(%d): eth_rx()\n", __FILE__, __LINE__); - - for (i = 0; (i < RXDESCS); i++) { - dp= &ks8695_rx[i]; - if ((dp->status & 0x80000000) == 0) { - len = (dp->status & 0x7ff) - 4; - NetReceive((void *) dp->addr, len); - dp->status = 0x80000000; - ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); - break; - } - } - - return len; -} - -/****************************************************************************/ - -int eth_send(volatile void *packet, int len) -{ - volatile struct ks8695_txdesc *dp; - static int next = 0; - - debug ("%s(%d): eth_send(packet=%x,len=%d)\n", __FILE__, __LINE__, - packet, len); - - dp = &ks8695_tx[next]; - memcpy((void *) dp->addr, (void *) packet, len); - - if (len < 64) { - memset((void *) (dp->addr + len), 0, 64-len); - len = 64; - } - - dp->ctrl = len | 0xe0000000; - dp->owner = 0x80000000; - - ks8695_write(KS8695_LAN_DMA_TX, 0x3); - ks8695_write(KS8695_LAN_DMA_TX_START, 0x1); - - if (++next >= TXDESCS) - next = 0; - - return len; -} - -#endif /* CONFIG_DRIVER_KS8695ETH */ diff --git a/drivers/lan91c96.c b/drivers/lan91c96.c deleted file mode 100644 index ecdcbd9b32..0000000000 --- a/drivers/lan91c96.c +++ /dev/null @@ -1,967 +0,0 @@ -/*------------------------------------------------------------------------ - * lan91c96.c - * This is a driver for SMSC's LAN91C96 single-chip Ethernet device, based - * on the SMC91111 driver from U-boot. - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Rolf Offermanns - * - * Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - * Developed by Simple Network Magic Corporation (SNMC) - * Copyright (C) 1996 by Erik Stahlman (ES) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Information contained in this file was obtained from the LAN91C96 - * manual from SMC. To get a copy, if you really want one, you can find - * information under www.smsc.com. - * - * - * "Features" of the SMC chip: - * 6144 byte packet memory. ( for the 91C96 ) - * EEPROM for configuration - * AUI/TP selection ( mine has 10Base2/10BaseT select ) - * - * Arguments: - * io = for the base address - * irq = for the IRQ - * - * author: - * Erik Stahlman ( erik@vt.edu ) - * Daris A Nevil ( dnevil@snmc.com ) - * - * - * Hardware multicast code from Peter Cammaert ( pc@denkart.be ) - * - * Sources: - * o SMSC LAN91C96 databook (www.smsc.com) - * o smc91111.c (u-boot driver) - * o smc9194.c (linux kernel driver) - * o lan91c96.c (Intel Diagnostic Manager driver) - * - * History: - * 04/30/03 Mathijs Haarman Modified smc91111.c (u-boot version) - * for lan91c96 - *--------------------------------------------------------------------------- - */ - -#include -#include -#include "lan91c96.h" -#include - -#ifdef CONFIG_DRIVER_LAN91C96 - -#if defined(CONFIG_CMD_NET) - -/*------------------------------------------------------------------------ - * - * Configuration options, for the experienced user to change. - * - -------------------------------------------------------------------------*/ - -/* Use power-down feature of the chip */ -#define POWER_DOWN 0 - -/* - * Wait time for memory to be free. This probably shouldn't be - * tuned that much, as waiting for this means nothing else happens - * in the system -*/ -#define MEMORY_WAIT_TIME 16 - -#define SMC_DEBUG 0 - -#if (SMC_DEBUG > 2 ) -#define PRINTK3(args...) printf(args) -#else -#define PRINTK3(args...) -#endif - -#if SMC_DEBUG > 1 -#define PRINTK2(args...) printf(args) -#else -#define PRINTK2(args...) -#endif - -#ifdef SMC_DEBUG -#define PRINTK(args...) printf(args) -#else -#define PRINTK(args...) -#endif - - -/*------------------------------------------------------------------------ - * - * The internal workings of the driver. If you are changing anything - * here with the SMC stuff, you should have the datasheet and know - * what you are doing. - * - *------------------------------------------------------------------------ - */ -#define CARDNAME "LAN91C96" - -#define SMC_BASE_ADDRESS CONFIG_LAN91C96_BASE - -#define SMC_DEV_NAME "LAN91C96" -#define SMC_ALLOC_MAX_TRY 5 -#define SMC_TX_TIMEOUT 30 - -#define ETH_ZLEN 60 - -#ifdef CONFIG_LAN91C96_USE_32_BIT -#define USE_32_BIT 1 -#else -#undef USE_32_BIT -#endif - -/*----------------------------------------------------------------- - * - * The driver can be entered at any of the following entry points. - * - *----------------------------------------------------------------- - */ - -extern int eth_init (bd_t * bd); -extern void eth_halt (void); -extern int eth_rx (void); -extern int eth_send (volatile void *packet, int length); -#if 0 -static int smc_hw_init (void); -#endif - -/* - * This is called by register_netdev(). It is responsible for - * checking the portlist for the SMC9000 series chipset. If it finds - * one, then it will initialize the device, find the hardware information, - * and sets up the appropriate device parameters. - * NOTE: Interrupts are *OFF* when this procedure is called. - * - * NB:This shouldn't be static since it is referred to externally. - */ -int smc_init (void); - -/* - * This is called by unregister_netdev(). It is responsible for - * cleaning up before the driver is finally unregistered and discarded. - */ -void smc_destructor (void); - -/* - * The kernel calls this function when someone wants to use the device, - * typically 'ifconfig ethX up'. - */ -static int smc_open (bd_t *bd); - - -/* - * This is called by the kernel in response to 'ifconfig ethX down'. It - * is responsible for cleaning up everything that the open routine - * does, and maybe putting the card into a powerdown state. - */ -static int smc_close (void); - -/* - * This is a separate procedure to handle the receipt of a packet, to - * leave the interrupt code looking slightly cleaner - */ -static int smc_rcv (void); - -/* See if a MAC address is defined in the current environment. If so use it. If not - . print a warning and set the environment and other globals with the default. - . If an EEPROM is present it really should be consulted. -*/ -int smc_get_ethaddr(bd_t *bd); -int get_rom_mac(unsigned char *v_rom_mac); - -/* ------------------------------------------------------------ - * Internal routines - * ------------------------------------------------------------ - */ - -static unsigned char smc_mac_addr[] = { 0xc0, 0x00, 0x00, 0x1b, 0x62, 0x9c }; - -/* - * This function must be called before smc_open() if you want to override - * the default mac address. - */ - -void smc_set_mac_addr (const unsigned char *addr) -{ - int i; - - for (i = 0; i < sizeof (smc_mac_addr); i++) { - smc_mac_addr[i] = addr[i]; - } -} - -/* - * smc_get_macaddr is no longer used. If you want to override the default - * mac address, call smc_get_mac_addr as a part of the board initialisation. - */ - -#if 0 -void smc_get_macaddr (byte * addr) -{ - /* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */ - unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010); - int i; - - - for (i = 0; i < 6; i++) { - addr[0] = *(dnp1110_mac + 0); - addr[1] = *(dnp1110_mac + 1); - addr[2] = *(dnp1110_mac + 2); - addr[3] = *(dnp1110_mac + 3); - addr[4] = *(dnp1110_mac + 4); - addr[5] = *(dnp1110_mac + 5); - } -} -#endif /* 0 */ - -/*********************************************** - * Show available memory * - ***********************************************/ -void dump_memory_info (void) -{ - word mem_info; - word old_bank; - - old_bank = SMC_inw (LAN91C96_BANK_SELECT) & 0xF; - - SMC_SELECT_BANK (0); - mem_info = SMC_inw (LAN91C96_MIR); - PRINTK2 ("Memory: %4d available\n", (mem_info >> 8) * 2048); - - SMC_SELECT_BANK (old_bank); -} - -/* - * A rather simple routine to print out a packet for debugging purposes. - */ -#if SMC_DEBUG > 2 -static void print_packet (byte *, int); -#endif - -/* #define tx_done(dev) 1 */ - - -/* this does a soft reset on the device */ -static void smc_reset (void); - -/* Enable Interrupts, Receive, and Transmit */ -static void smc_enable (void); - -/* this puts the device in an inactive state */ -static void smc_shutdown (void); - - -static int poll4int (byte mask, int timeout) -{ - int tmo = get_timer (0) + timeout * CFG_HZ; - int is_timeout = 0; - word old_bank = SMC_inw (LAN91C96_BANK_SELECT); - - PRINTK2 ("Polling...\n"); - SMC_SELECT_BANK (2); - while ((SMC_inw (LAN91C96_INT_STATS) & mask) == 0) { - if (get_timer (0) >= tmo) { - is_timeout = 1; - break; - } - } - - /* restore old bank selection */ - SMC_SELECT_BANK (old_bank); - - if (is_timeout) - return 1; - else - return 0; -} - -/* - * Function: smc_reset( void ) - * Purpose: - * This sets the SMC91111 chip to its normal state, hopefully from whatever - * mess that any other DOS driver has put it in. - * - * Maybe I should reset more registers to defaults in here? SOFTRST should - * do that for me. - * - * Method: - * 1. send a SOFT RESET - * 2. wait for it to finish - * 3. enable autorelease mode - * 4. reset the memory management unit - * 5. clear all interrupts - * -*/ -static void smc_reset (void) -{ - PRINTK2 ("%s:smc_reset\n", SMC_DEV_NAME); - - /* This resets the registers mostly to defaults, but doesn't - affect EEPROM. That seems unnecessary */ - SMC_SELECT_BANK (0); - SMC_outw (LAN91C96_RCR_SOFT_RST, LAN91C96_RCR); - - udelay (10); - - /* Disable transmit and receive functionality */ - SMC_outw (0, LAN91C96_RCR); - SMC_outw (0, LAN91C96_TCR); - - /* set the control register */ - SMC_SELECT_BANK (1); - SMC_outw (SMC_inw (LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8, - LAN91C96_CONTROL); - - /* Disable all interrupts */ - SMC_outb (0, LAN91C96_INT_MASK); -} - -/* - * Function: smc_enable - * Purpose: let the chip talk to the outside work - * Method: - * 1. Initialize the Memory Configuration Register - * 2. Enable the transmitter - * 3. Enable the receiver -*/ -static void smc_enable () -{ - PRINTK2 ("%s:smc_enable\n", SMC_DEV_NAME); - SMC_SELECT_BANK (0); - - /* Initialize the Memory Configuration Register. See page - 49 of the LAN91C96 data sheet for details. */ - SMC_outw (LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR); - - /* Initialize the Transmit Control Register */ - SMC_outw (LAN91C96_TCR_TXENA, LAN91C96_TCR); - /* Initialize the Receive Control Register - * FIXME: - * The promiscuous bit set because I could not receive ARP reply - * packets from the server when I send a ARP request. It only works - * when I set the promiscuous bit - */ - SMC_outw (LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR); -} - -/* - * Function: smc_shutdown - * Purpose: closes down the SMC91xxx chip. - * Method: - * 1. zero the interrupt mask - * 2. clear the enable receive flag - * 3. clear the enable xmit flags - * - * TODO: - * (1) maybe utilize power down mode. - * Why not yet? Because while the chip will go into power down mode, - * the manual says that it will wake up in response to any I/O requests - * in the register space. Empirical results do not show this working. - */ -static void smc_shutdown () -{ - PRINTK2 (CARDNAME ":smc_shutdown\n"); - - /* no more interrupts for me */ - SMC_SELECT_BANK (2); - SMC_outb (0, LAN91C96_INT_MASK); - - /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK (0); - SMC_outb (0, LAN91C96_RCR); - SMC_outb (0, LAN91C96_TCR); -} - - -/* - * Function: smc_hardware_send_packet(struct net_device * ) - * Purpose: - * This sends the actual packet to the SMC9xxx chip. - * - * Algorithm: - * First, see if a saved_skb is available. - * ( this should NOT be called if there is no 'saved_skb' - * Now, find the packet number that the chip allocated - * Point the data pointers at it in memory - * Set the length word in the chip's memory - * Dump the packet to chip memory - * Check if a last byte is needed ( odd length packet ) - * if so, set the control flag right - * Tell the card to send it - * Enable the transmit interrupt, so I know if it failed - * Free the kernel data if I actually sent it. - */ -static int smc_send_packet (volatile void *packet, int packet_length) -{ - byte packet_no; - unsigned long ioaddr; - byte *buf; - int length; - int numPages; - int try = 0; - int time_out; - byte status; - - - PRINTK3 ("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); - - length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; - - /* allocate memory - ** The MMU wants the number of pages to be the number of 256 bytes - ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) - ** - ** The 91C111 ignores the size bits, but the code is left intact - ** for backwards and future compatibility. - ** - ** Pkt size for allocating is data length +6 (for additional status - ** words, length and ctl!) - ** - ** If odd size then last byte is included in this header. - */ - numPages = ((length & 0xfffe) + 6); - numPages >>= 8; /* Divide by 256 */ - - if (numPages > 7) { - printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); - return 0; - } - - /* now, try to allocate the memory */ - - SMC_SELECT_BANK (2); - SMC_outw (LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU); - - again: - try++; - time_out = MEMORY_WAIT_TIME; - do { - status = SMC_inb (LAN91C96_INT_STATS); - if (status & LAN91C96_IST_ALLOC_INT) { - - SMC_outb (LAN91C96_IST_ALLOC_INT, LAN91C96_INT_STATS); - break; - } - } while (--time_out); - - if (!time_out) { - PRINTK2 ("%s: memory allocation, try %d failed ...\n", - SMC_DEV_NAME, try); - if (try < SMC_ALLOC_MAX_TRY) - goto again; - else - return 0; - } - - PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", - SMC_DEV_NAME, try); - - /* I can send the packet now.. */ - - ioaddr = SMC_BASE_ADDRESS; - - buf = (byte *) packet; - - /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = SMC_inb (LAN91C96_ARR); - if (packet_no & LAN91C96_ARR_FAILED) { - /* or isn't there? BAD CHIP! */ - printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); - return 0; - } - - /* we have a packet address, so tell the card to use it */ - SMC_outb (packet_no, LAN91C96_PNR); - - /* point to the beginning of the packet */ - SMC_outw (LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); - - PRINTK3 ("%s: Trying to xmit packet of length %x\n", - SMC_DEV_NAME, length); - -#if SMC_DEBUG > 2 - printf ("Transmitting Packet\n"); - print_packet (buf, length); -#endif - - /* send the packet length ( +6 for status, length and ctl byte ) - and the status word ( set to zeros ) */ -#ifdef USE_32_BIT - SMC_outl ((length + 6) << 16, LAN91C96_DATA_HIGH); -#else - SMC_outw (0, LAN91C96_DATA_HIGH); - /* send the packet length ( +6 for status words, length, and ctl */ - SMC_outw ((length + 6), LAN91C96_DATA_HIGH); -#endif /* USE_32_BIT */ - - /* send the actual data - * I _think_ it's faster to send the longs first, and then - * mop up by sending the last word. It depends heavily - * on alignment, at least on the 486. Maybe it would be - * a good idea to check which is optimal? But that could take - * almost as much time as is saved? - */ -#ifdef USE_32_BIT - SMC_outsl (LAN91C96_DATA_HIGH, buf, length >> 2); - if (length & 0x2) - SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), - LAN91C96_DATA_HIGH); -#else - SMC_outsw (LAN91C96_DATA_HIGH, buf, (length) >> 1); -#endif /* USE_32_BIT */ - - /* Send the last byte, if there is one. */ - if ((length & 1) == 0) { - SMC_outw (0, LAN91C96_DATA_HIGH); - } else { - SMC_outw (buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH); - } - - /* and let the chipset deal with it */ - SMC_outw (LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU); - - /* poll for TX INT */ - if (poll4int (LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) { - /* sending failed */ - PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); - - /* release packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); - - /* wait for MMU getting ready (low) */ - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { - udelay (10); - } - - PRINTK2 ("MMU ready\n"); - - - return 0; - } else { - /* ack. int */ - SMC_outw (LAN91C96_IST_TX_INT, LAN91C96_INT_STATS); - - PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); - - /* release packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); - - /* wait for MMU getting ready (low) */ - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { - udelay (10); - } - - PRINTK2 ("MMU ready\n"); - } - - return length; -} - -/*------------------------------------------------------------------------- - * smc_destructor( struct net_device * dev ) - * Input parameters: - * dev, pointer to the device structure - * - * Output: - * None. - *-------------------------------------------------------------------------- - */ -void smc_destructor () -{ - PRINTK2 (CARDNAME ":smc_destructor\n"); -} - - -/* - * Open and Initialize the board - * - * Set up everything, reset the card, etc .. - * - */ -static int smc_open (bd_t *bd) -{ - int i, err; /* used to set hw ethernet address */ - - PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME); - - /* reset the hardware */ - - smc_reset (); - smc_enable (); - - SMC_SELECT_BANK (1); - - err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ - if (err < 0) { - memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ - return (-1); /* upper code ignores this, but NOT bi_enetaddr */ - } -#ifdef USE_32_BIT - for (i = 0; i < 6; i += 2) { - word address; - - address = smc_mac_addr[i + 1] << 8; - address |= smc_mac_addr[i]; - SMC_outw (address, LAN91C96_IA0 + i); - } -#else - for (i = 0; i < 6; i++) - SMC_outb (smc_mac_addr[i], LAN91C96_IA0 + i); -#endif - return 0; -} - -/*------------------------------------------------------------- - * - * smc_rcv - receive a packet from the card - * - * There is ( at least ) a packet waiting to be read from - * chip-memory. - * - * o Read the status - * o If an error, record it - * o otherwise, read in the packet - *------------------------------------------------------------- - */ -static int smc_rcv () -{ - int packet_number; - word status; - word packet_length; - int is_error = 0; - -#ifdef USE_32_BIT - dword stat_len; -#endif - - - SMC_SELECT_BANK (2); - packet_number = SMC_inw (LAN91C96_FIFO); - - if (packet_number & LAN91C96_FIFO_RXEMPTY) { - return 0; - } - - PRINTK3 ("%s:smc_rcv\n", SMC_DEV_NAME); - /* start reading from the start of the packet */ - SMC_outw (LAN91C96_PTR_READ | LAN91C96_PTR_RCV | - LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); - - /* First two words are status and packet_length */ -#ifdef USE_32_BIT - stat_len = SMC_inl (LAN91C96_DATA_HIGH); - status = stat_len & 0xffff; - packet_length = stat_len >> 16; -#else - status = SMC_inw (LAN91C96_DATA_HIGH); - packet_length = SMC_inw (LAN91C96_DATA_HIGH); -#endif - - packet_length &= 0x07ff; /* mask off top bits */ - - PRINTK2 ("RCV: STATUS %4x LENGTH %4x\n", status, packet_length); - - if (!(status & FRAME_FILTER)) { - /* Adjust for having already read the first two words */ - packet_length -= 4; /*4; */ - - - /* set odd length for bug in LAN91C111, */ - /* which never sets RS_ODDFRAME */ - /* TODO ? */ - - -#ifdef USE_32_BIT - PRINTK3 (" Reading %d dwords (and %d bytes) \n", - packet_length >> 2, packet_length & 3); - /* QUESTION: Like in the TX routine, do I want - to send the DWORDs or the bytes first, or some - mixture. A mixture might improve already slow PIO - performance */ - SMC_insl (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 2); - /* read the left over bytes */ - if (packet_length & 3) { - int i; - - byte *tail = (byte *) (NetRxPackets[0] + (packet_length & ~3)); - dword leftover = SMC_inl (LAN91C96_DATA_HIGH); - - for (i = 0; i < (packet_length & 3); i++) - *tail++ = (byte) (leftover >> (8 * i)) & 0xff; - } -#else - PRINTK3 (" Reading %d words and %d byte(s) \n", - (packet_length >> 1), packet_length & 1); - SMC_insw (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 1); - -#endif /* USE_32_BIT */ - -#if SMC_DEBUG > 2 - printf ("Receiving Packet\n"); - print_packet (NetRxPackets[0], packet_length); -#endif - } else { - /* error ... */ - /* TODO ? */ - is_error = 1; - } - - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) - udelay (1); /* Wait until not busy */ - - /* error or good, tell the card to get rid of this packet */ - SMC_outw (LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU); - - while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) - udelay (1); /* Wait until not busy */ - - if (!is_error) { - /* Pass the packet up to the protocol layers. */ - NetReceive (NetRxPackets[0], packet_length); - return packet_length; - } else { - return 0; - } - -} - -/*---------------------------------------------------- - * smc_close - * - * this makes the board clean up everything that it can - * and not talk to the outside world. Caused by - * an 'ifconfig ethX down' - * - -----------------------------------------------------*/ -static int smc_close () -{ - PRINTK2 ("%s:smc_close\n", SMC_DEV_NAME); - - /* clear everything */ - smc_shutdown (); - - return 0; -} - -#if SMC_DEBUG > 2 -static void print_packet (byte * buf, int length) -{ -#if 0 - int i; - int remainder; - int lines; - - printf ("Packet of length %d \n", length); - - lines = length / 16; - remainder = length % 16; - - for (i = 0; i < lines; i++) { - int cur; - - for (cur = 0; cur < 8; cur++) { - byte a, b; - - a = *(buf++); - b = *(buf++); - printf ("%02x%02x ", a, b); - } - printf ("\n"); - } - for (i = 0; i < remainder / 2; i++) { - byte a, b; - - a = *(buf++); - b = *(buf++); - printf ("%02x%02x ", a, b); - } - printf ("\n"); -#endif /* 0 */ -} -#endif /* SMC_DEBUG > 2 */ - -int eth_init (bd_t * bd) -{ - return (smc_open(bd)); -} - -void eth_halt () -{ - smc_close (); -} - -int eth_rx () -{ - return smc_rcv (); -} - -int eth_send (volatile void *packet, int length) -{ - return smc_send_packet (packet, length); -} - - -#if 0 -/*------------------------------------------------------------------------- - * smc_hw_init() - * - * Function: - * Reset and enable the device, check if the I/O space location - * is correct - * - * Input parameters: - * None - * - * Output: - * 0 --> success - * 1 --> error - *-------------------------------------------------------------------------- - */ -static int smc_hw_init () -{ - unsigned short status_test; - - /* The attribute register of the LAN91C96 is located at address - 0x0e000000 on the lubbock platform */ - volatile unsigned *attaddr = (unsigned *) (0x0e000000); - - /* first reset, then enable the device. Sequence is critical */ - attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_SRESET; - udelay (100); - attaddr[LAN91C96_ECOR] &= ~LAN91C96_ECOR_SRESET; - attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_ENABLE; - - /* force 16-bit mode */ - attaddr[LAN91C96_ECSR] &= ~LAN91C96_ECSR_IOIS8; - udelay (100); - - /* check if the I/O address is correct, the upper byte of the - bank select register should read 0x33 */ - - status_test = SMC_inw (LAN91C96_BANK_SELECT); - if ((status_test & 0xFF00) != 0x3300) { - printf ("Failed to initialize ethernetchip\n"); - return 1; - } - return 0; -} -#endif /* 0 */ - -#endif /* COMMANDS & CFG_NET */ - - -/* smc_get_ethaddr (bd_t * bd) - * - * This checks both the environment and the ROM for an ethernet address. If - * found, the environment takes precedence. - */ - -int smc_get_ethaddr (bd_t * bd) -{ - int env_size = 0; - int rom_valid = 0; - int env_present = 0; - int reg = 0; - char *s = NULL; - char *e = NULL; - char *v_mac, es[] = "11:22:33:44:55:66"; - char s_env_mac[64]; - uchar v_env_mac[6]; - uchar v_rom_mac[6]; - - env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); - if (env_size != sizeof(es)) { /* Ignore if env is bad or not set */ - printf ("\n*** Warning: ethaddr is not set properly, ignoring!!\n"); - } else { - env_present = 1; - s = s_env_mac; - - for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ - v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; - if (s) - s = (*e) ? e + 1 : e; - } - } - - rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ - - if (!env_present) { /* if NO env */ - if (rom_valid) { /* but ROM is valid */ - v_mac = (char *)v_rom_mac; - sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", - v_mac[0], v_mac[1], v_mac[2], v_mac[3], - v_mac[4], v_mac[5]); - setenv ("ethaddr", s_env_mac); - } else { /* no env, bad ROM */ - printf ("\n*** ERROR: ethaddr is NOT set !!\n"); - return (-1); - } - } else { /* good env, don't care ROM */ - v_mac = (char *)v_env_mac; /* always use a good env over a ROM */ - } - - if (env_present && rom_valid) { /* if both env and ROM are good */ - if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { - printf ("\nWarning: MAC addresses don't match:\n"); - printf ("\tHW MAC address: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - v_rom_mac[0], v_rom_mac[1], - v_rom_mac[2], v_rom_mac[3], - v_rom_mac[4], v_rom_mac[5] ); - printf ("\t\"ethaddr\" value: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - v_env_mac[0], v_env_mac[1], - v_env_mac[2], v_env_mac[3], - v_env_mac[4], v_env_mac[5]) ; - debug ("### Set MAC addr from environment\n"); - } - } - memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ - smc_set_mac_addr ((unsigned char *)v_mac); /* use old function to update smc default */ - PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], - v_mac[2], v_mac[3], v_mac[4], v_mac[5]); - return (0); -} - -/* - * get_rom_mac() - * Note, this has omly been tested for the OMAP730 P2. - */ - -int get_rom_mac (unsigned char *v_rom_mac) -{ -#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ - char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; - - memcpy (v_rom_mac, hw_mac_addr, 6); - return (1); -#else - int i; - SMC_SELECT_BANK (1); - for (i=0; i<6; i++) - { - v_rom_mac[i] = SMC_inb (LAN91C96_IA0 + i); - } - return (1); -#endif -} - -#endif /* CONFIG_DRIVER_LAN91C96 */ diff --git a/drivers/lan91c96.h b/drivers/lan91c96.h deleted file mode 100644 index 7d33a821f3..0000000000 --- a/drivers/lan91c96.h +++ /dev/null @@ -1,643 +0,0 @@ -/*------------------------------------------------------------------------ - * lan91c96.h - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Rolf Offermanns - * Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - * Developed by Simple Network Magic Corporation (SNMC) - * Copyright (C) 1996 by Erik Stahlman (ES) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This file contains register information and access macros for - * the LAN91C96 single chip ethernet controller. It is a modified - * version of the smc9111.h file. - * - * Information contained in this file was obtained from the LAN91C96 - * manual from SMC. To get a copy, if you really want one, you can find - * information under www.smsc.com. - * - * Authors - * Erik Stahlman ( erik@vt.edu ) - * Daris A Nevil ( dnevil@snmc.com ) - * - * History - * 04/30/03 Mathijs Haarman Modified smc91111.h (u-boot version) - * for lan91c96 - *------------------------------------------------------------------------- - */ -#ifndef _LAN91C96_H_ -#define _LAN91C96_H_ - -#include -#include -#include - -/* - * This function may be called by the board specific initialisation code - * in order to override the default mac address. - */ - -void smc_set_mac_addr(const unsigned char *addr); - - -/* I want some simple types */ - -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long int dword; - -/* - * DEBUGGING LEVELS - * - * 0 for normal operation - * 1 for slightly more details - * >2 for various levels of increasingly useless information - * 2 for interrupt tracking, status flags - * 3 for packet info - * 4 for complete packet dumps - */ -/*#define SMC_DEBUG 0 */ - -/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ - -#define SMC_IO_EXTENT 16 - -#ifdef CONFIG_PXA250 - -#ifdef CONFIG_LUBBOCK -#define SMC_IO_SHIFT 2 -#undef USE_32_BIT - -#else -#define SMC_IO_SHIFT 0 -#endif - -#define SMCREG(r) (SMC_BASE_ADDRESS+((r)<>= 8; \ - else __v &= 0xff; \ - __v; }) - -#define SMC_outl(d,r) (*((volatile dword *)SMCREG(r)) = d) -#define SMC_outw(d,r) (*((volatile word *)SMCREG(r)) = d) -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ - __w &= ((r)&1) ? 0x00FF : 0xFF00; \ - __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ - }) - -#define SMC_outsl(r,b,l) ({ int __i; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outl( *(__b2 + __i), r ); \ - } \ - }) - -#define SMC_outsw(r,b,l) ({ int __i; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r ); \ - } \ - }) - -#define SMC_insl(r,b,l) ({ int __i ; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inl(r); \ - SMC_inl(0); \ - }; \ - }) - -#define SMC_insw(r,b,l) ({ int __i ; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ - }; \ - }) - -#define SMC_insb(r,b,l) ({ int __i ; \ - byte *__b2; \ - __b2 = (byte *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inb(r); \ - SMC_inb(0); \ - }; \ - }) - -#else /* if not CONFIG_PXA250 */ - -/* - * We have only 16 Bit PCMCIA access on Socket 0 - */ - -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) -#define SMC_inb(r) (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF) - -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ - __w &= ((r)&1) ? 0x00FF : 0xFF00; \ - __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ - }) -#if 0 -#define SMC_outsw(r,b,l) outsw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_outsw(r,b,l) ({ int __i; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r); \ - } \ - }) -#endif - -#if 0 -#define SMC_insw(r,b,l) insw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_insw(r,b,l) ({ int __i ; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ - }; \ - }) -#endif - -#endif - -/* - **************************************************************************** - * Bank Select Field - **************************************************************************** - */ -#define LAN91C96_BANK_SELECT 14 /* Bank Select Register */ -#define LAN91C96_BANKSELECT (0x3UC << 0) -#define BANK0 0x00 -#define BANK1 0x01 -#define BANK2 0x02 -#define BANK3 0x03 -#define BANK4 0x04 - -/* - **************************************************************************** - * EEPROM Addresses. - **************************************************************************** - */ -#define EEPROM_MAC_OFFSET_1 0x6020 -#define EEPROM_MAC_OFFSET_2 0x6021 -#define EEPROM_MAC_OFFSET_3 0x6022 - -/* - **************************************************************************** - * Bank 0 Register Map in I/O Space - **************************************************************************** - */ -#define LAN91C96_TCR 0 /* Transmit Control Register */ -#define LAN91C96_EPH_STATUS 2 /* EPH Status Register */ -#define LAN91C96_RCR 4 /* Receive Control Register */ -#define LAN91C96_COUNTER 6 /* Counter Register */ -#define LAN91C96_MIR 8 /* Memory Information Register */ -#define LAN91C96_MCR 10 /* Memory Configuration Register */ - -/* - **************************************************************************** - * Transmit Control Register - Bank 0 - Offset 0 - **************************************************************************** - */ -#define LAN91C96_TCR_TXENA (0x1U << 0) -#define LAN91C96_TCR_LOOP (0x1U << 1) -#define LAN91C96_TCR_FORCOL (0x1U << 2) -#define LAN91C96_TCR_TXP_EN (0x1U << 3) -#define LAN91C96_TCR_PAD_EN (0x1U << 7) -#define LAN91C96_TCR_NOCRC (0x1U << 8) -#define LAN91C96_TCR_MON_CSN (0x1U << 10) -#define LAN91C96_TCR_FDUPLX (0x1U << 11) -#define LAN91C96_TCR_STP_SQET (0x1U << 12) -#define LAN91C96_TCR_EPH_LOOP (0x1U << 13) -#define LAN91C96_TCR_ETEN_TYPE (0x1U << 14) -#define LAN91C96_TCR_FDSE (0x1U << 15) - -/* - **************************************************************************** - * EPH Status Register - Bank 0 - Offset 2 - **************************************************************************** - */ -#define LAN91C96_EPHSR_TX_SUC (0x1U << 0) -#define LAN91C96_EPHSR_SNGL_COL (0x1U << 1) -#define LAN91C96_EPHSR_MUL_COL (0x1U << 2) -#define LAN91C96_EPHSR_LTX_MULT (0x1U << 3) -#define LAN91C96_EPHSR_16COL (0x1U << 4) -#define LAN91C96_EPHSR_SQET (0x1U << 5) -#define LAN91C96_EPHSR_LTX_BRD (0x1U << 6) -#define LAN91C96_EPHSR_TX_DEFR (0x1U << 7) -#define LAN91C96_EPHSR_WAKEUP (0x1U << 8) -#define LAN91C96_EPHSR_LATCOL (0x1U << 9) -#define LAN91C96_EPHSR_LOST_CARR (0x1U << 10) -#define LAN91C96_EPHSR_EXC_DEF (0x1U << 11) -#define LAN91C96_EPHSR_CTR_ROL (0x1U << 12) - -#define LAN91C96_EPHSR_LINK_OK (0x1U << 14) -#define LAN91C96_EPHSR_TX_UNRN (0x1U << 15) - -#define LAN91C96_EPHSR_ERRORS (LAN91C96_EPHSR_SNGL_COL | \ - LAN91C96_EPHSR_MUL_COL | \ - LAN91C96_EPHSR_16COL | \ - LAN91C96_EPHSR_SQET | \ - LAN91C96_EPHSR_TX_DEFR | \ - LAN91C96_EPHSR_LATCOL | \ - LAN91C96_EPHSR_LOST_CARR | \ - LAN91C96_EPHSR_EXC_DEF | \ - LAN91C96_EPHSR_LINK_OK | \ - LAN91C96_EPHSR_TX_UNRN) - -/* - **************************************************************************** - * Receive Control Register - Bank 0 - Offset 4 - **************************************************************************** - */ -#define LAN91C96_RCR_RX_ABORT (0x1U << 0) -#define LAN91C96_RCR_PRMS (0x1U << 1) -#define LAN91C96_RCR_ALMUL (0x1U << 2) -#define LAN91C96_RCR_RXEN (0x1U << 8) -#define LAN91C96_RCR_STRIP_CRC (0x1U << 9) -#define LAN91C96_RCR_FILT_CAR (0x1U << 14) -#define LAN91C96_RCR_SOFT_RST (0x1U << 15) - -/* - **************************************************************************** - * Counter Register - Bank 0 - Offset 6 - **************************************************************************** - */ -#define LAN91C96_ECR_SNGL_COL (0xFU << 0) -#define LAN91C96_ECR_MULT_COL (0xFU << 5) -#define LAN91C96_ECR_DEF_TX (0xFU << 8) -#define LAN91C96_ECR_EXC_DEF_TX (0xFU << 12) - -/* - **************************************************************************** - * Memory Information Register - Bank 0 - OFfset 8 - **************************************************************************** - */ -#define LAN91C96_MIR_SIZE (0x18 << 0) /* 6144 bytes */ - -/* - **************************************************************************** - * Memory Configuration Register - Bank 0 - Offset 10 - **************************************************************************** - */ -#define LAN91C96_MCR_MEM_RES (0xFFU << 0) -#define LAN91C96_MCR_MEM_MULT (0x3U << 9) -#define LAN91C96_MCR_HIGH_ID (0x3U << 12) - -#define LAN91C96_MCR_TRANSMIT_PAGES 0x6 - -/* - **************************************************************************** - * Bank 1 Register Map in I/O Space - **************************************************************************** - */ -#define LAN91C96_CONFIG 0 /* Configuration Register */ -#define LAN91C96_BASE 2 /* Base Address Register */ -#define LAN91C96_IA0 4 /* Individual Address Register - 0 */ -#define LAN91C96_IA1 5 /* Individual Address Register - 1 */ -#define LAN91C96_IA2 6 /* Individual Address Register - 2 */ -#define LAN91C96_IA3 7 /* Individual Address Register - 3 */ -#define LAN91C96_IA4 8 /* Individual Address Register - 4 */ -#define LAN91C96_IA5 9 /* Individual Address Register - 5 */ -#define LAN91C96_GEN_PURPOSE 10 /* General Address Registers */ -#define LAN91C96_CONTROL 12 /* Control Register */ - -/* - **************************************************************************** - * Configuration Register - Bank 1 - Offset 0 - **************************************************************************** - */ -#define LAN91C96_CR_INT_SEL0 (0x1U << 1) -#define LAN91C96_CR_INT_SEL1 (0x1U << 2) -#define LAN91C96_CR_RES (0x3U << 3) -#define LAN91C96_CR_DIS_LINK (0x1U << 6) -#define LAN91C96_CR_16BIT (0x1U << 7) -#define LAN91C96_CR_AUI_SELECT (0x1U << 8) -#define LAN91C96_CR_SET_SQLCH (0x1U << 9) -#define LAN91C96_CR_FULL_STEP (0x1U << 10) -#define LAN91C96_CR_NO_WAIT (0x1U << 12) - -/* - **************************************************************************** - * Base Address Register - Bank 1 - Offset 2 - **************************************************************************** - */ -#define LAN91C96_BAR_RA_BITS (0x27U << 0) -#define LAN91C96_BAR_ROM_SIZE (0x1U << 6) -#define LAN91C96_BAR_A_BITS (0xFFU << 8) - -/* - **************************************************************************** - * Control Register - Bank 1 - Offset 12 - **************************************************************************** - */ -#define LAN91C96_CTR_STORE (0x1U << 0) -#define LAN91C96_CTR_RELOAD (0x1U << 1) -#define LAN91C96_CTR_EEPROM (0x1U << 2) -#define LAN91C96_CTR_TE_ENABLE (0x1U << 5) -#define LAN91C96_CTR_CR_ENABLE (0x1U << 6) -#define LAN91C96_CTR_LE_ENABLE (0x1U << 7) -#define LAN91C96_CTR_BIT_8 (0x1U << 8) -#define LAN91C96_CTR_AUTO_RELEASE (0x1U << 11) -#define LAN91C96_CTR_WAKEUP_EN (0x1U << 12) -#define LAN91C96_CTR_PWRDN (0x1U << 13) -#define LAN91C96_CTR_RCV_BAD (0x1U << 14) - -/* - **************************************************************************** - * Bank 2 Register Map in I/O Space - **************************************************************************** - */ -#define LAN91C96_MMU 0 /* MMU Command Register */ -#define LAN91C96_AUTO_TX_START 1 /* Auto Tx Start Register */ -#define LAN91C96_PNR 2 /* Packet Number Register */ -#define LAN91C96_ARR 3 /* Allocation Result Register */ -#define LAN91C96_FIFO 4 /* FIFO Ports Register */ -#define LAN91C96_POINTER 6 /* Pointer Register */ -#define LAN91C96_DATA_HIGH 8 /* Data High Register */ -#define LAN91C96_DATA_LOW 10 /* Data Low Register */ -#define LAN91C96_INT_STATS 12 /* Interrupt Status Register - RO */ -#define LAN91C96_INT_ACK 12 /* Interrupt Acknowledge Register -WO */ -#define LAN91C96_INT_MASK 13 /* Interrupt Mask Register */ - -/* - **************************************************************************** - * MMU Command Register - Bank 2 - Offset 0 - **************************************************************************** - */ -#define LAN91C96_MMUCR_NO_BUSY (0x1U << 0) -#define LAN91C96_MMUCR_N1 (0x1U << 1) -#define LAN91C96_MMUCR_N2 (0x1U << 2) -#define LAN91C96_MMUCR_COMMAND (0xFU << 4) -#define LAN91C96_MMUCR_ALLOC_TX (0x2U << 4) /* WXYZ = 0010 */ -#define LAN91C96_MMUCR_RESET_MMU (0x4U << 4) /* WXYZ = 0100 */ -#define LAN91C96_MMUCR_REMOVE_RX (0x6U << 4) /* WXYZ = 0110 */ -#define LAN91C96_MMUCR_REMOVE_TX (0x7U << 4) /* WXYZ = 0111 */ -#define LAN91C96_MMUCR_RELEASE_RX (0x8U << 4) /* WXYZ = 1000 */ -#define LAN91C96_MMUCR_RELEASE_TX (0xAU << 4) /* WXYZ = 1010 */ -#define LAN91C96_MMUCR_ENQUEUE (0xCU << 4) /* WXYZ = 1100 */ -#define LAN91C96_MMUCR_RESET_TX (0xEU << 4) /* WXYZ = 1110 */ - -/* - **************************************************************************** - * Auto Tx Start Register - Bank 2 - Offset 1 - **************************************************************************** - */ -#define LAN91C96_AUTOTX (0xFFU << 0) - -/* - **************************************************************************** - * Packet Number Register - Bank 2 - Offset 2 - **************************************************************************** - */ -#define LAN91C96_PNR_TX (0x1FU << 0) - -/* - **************************************************************************** - * Allocation Result Register - Bank 2 - Offset 3 - **************************************************************************** - */ -#define LAN91C96_ARR_ALLOC_PN (0x7FU << 0) -#define LAN91C96_ARR_FAILED (0x1U << 7) - -/* - **************************************************************************** - * FIFO Ports Register - Bank 2 - Offset 4 - **************************************************************************** - */ -#define LAN91C96_FIFO_TX_DONE_PN (0x1FU << 0) -#define LAN91C96_FIFO_TEMPTY (0x1U << 7) -#define LAN91C96_FIFO_RX_DONE_PN (0x1FU << 8) -#define LAN91C96_FIFO_RXEMPTY (0x1U << 15) - -/* - **************************************************************************** - * Pointer Register - Bank 2 - Offset 6 - **************************************************************************** - */ -#define LAN91C96_PTR_LOW (0xFFU << 0) -#define LAN91C96_PTR_HIGH (0x7U << 8) -#define LAN91C96_PTR_AUTO_TX (0x1U << 11) -#define LAN91C96_PTR_ETEN (0x1U << 12) -#define LAN91C96_PTR_READ (0x1U << 13) -#define LAN91C96_PTR_AUTO_INCR (0x1U << 14) -#define LAN91C96_PTR_RCV (0x1U << 15) - -#define LAN91C96_PTR_RX_FRAME (LAN91C96_PTR_RCV | \ - LAN91C96_PTR_AUTO_INCR | \ - LAN91C96_PTR_READ) - -/* - **************************************************************************** - * Data Register - Bank 2 - Offset 8 - **************************************************************************** - */ -#define LAN91C96_CONTROL_CRC (0x1U << 4) /* CRC bit */ -#define LAN91C96_CONTROL_ODD (0x1U << 5) /* ODD bit */ - -/* - **************************************************************************** - * Interrupt Status Register - Bank 2 - Offset 12 - **************************************************************************** - */ -#define LAN91C96_IST_RCV_INT (0x1U << 0) -#define LAN91C96_IST_TX_INT (0x1U << 1) -#define LAN91C96_IST_TX_EMPTY_INT (0x1U << 2) -#define LAN91C96_IST_ALLOC_INT (0x1U << 3) -#define LAN91C96_IST_RX_OVRN_INT (0x1U << 4) -#define LAN91C96_IST_EPH_INT (0x1U << 5) -#define LAN91C96_IST_ERCV_INT (0x1U << 6) -#define LAN91C96_IST_RX_IDLE_INT (0x1U << 7) - -/* - **************************************************************************** - * Interrupt Acknowledge Register - Bank 2 - Offset 12 - **************************************************************************** - */ -#define LAN91C96_ACK_TX_INT (0x1U << 1) -#define LAN91C96_ACK_TX_EMPTY_INT (0x1U << 2) -#define LAN91C96_ACK_RX_OVRN_INT (0x1U << 4) -#define LAN91C96_ACK_ERCV_INT (0x1U << 6) - -/* - **************************************************************************** - * Interrupt Mask Register - Bank 2 - Offset 13 - **************************************************************************** - */ -#define LAN91C96_MSK_RCV_INT (0x1U << 0) -#define LAN91C96_MSK_TX_INT (0x1U << 1) -#define LAN91C96_MSK_TX_EMPTY_INT (0x1U << 2) -#define LAN91C96_MSK_ALLOC_INT (0x1U << 3) -#define LAN91C96_MSK_RX_OVRN_INT (0x1U << 4) -#define LAN91C96_MSK_EPH_INT (0x1U << 5) -#define LAN91C96_MSK_ERCV_INT (0x1U << 6) -#define LAN91C96_MSK_TX_IDLE_INT (0x1U << 7) - -/* - **************************************************************************** - * Bank 3 Register Map in I/O Space - ************************************************************************** - */ -#define LAN91C96_MGMT_MDO (0x1U << 0) -#define LAN91C96_MGMT_MDI (0x1U << 1) -#define LAN91C96_MGMT_MCLK (0x1U << 2) -#define LAN91C96_MGMT_MDOE (0x1U << 3) -#define LAN91C96_MGMT_LOW_ID (0x3U << 4) -#define LAN91C96_MGMT_IOS0 (0x1U << 8) -#define LAN91C96_MGMT_IOS1 (0x1U << 9) -#define LAN91C96_MGMT_IOS2 (0x1U << 10) -#define LAN91C96_MGMT_nXNDEC (0x1U << 11) -#define LAN91C96_MGMT_HIGH_ID (0x3U << 12) - -/* - **************************************************************************** - * Revision Register - Bank 3 - Offset 10 - **************************************************************************** - */ -#define LAN91C96_REV_REVID (0xFU << 0) -#define LAN91C96_REV_CHIPID (0xFU << 4) - -/* - **************************************************************************** - * Early RCV Register - Bank 3 - Offset 12 - **************************************************************************** - */ -#define LAN91C96_ERCV_THRESHOLD (0x1FU << 0) -#define LAN91C96_ERCV_RCV_DISCRD (0x1U << 7) - -/* - **************************************************************************** - * PCMCIA Configuration Registers - **************************************************************************** - */ -#define LAN91C96_ECOR 0x8000 /* Ethernet Configuration Register */ -#define LAN91C96_ECSR 0x8002 /* Ethernet Configuration and Status */ - -/* - **************************************************************************** - * PCMCIA Ethernet Configuration Option Register (ECOR) - **************************************************************************** - */ -#define LAN91C96_ECOR_ENABLE (0x1U << 0) -#define LAN91C96_ECOR_WR_ATTRIB (0x1U << 2) -#define LAN91C96_ECOR_LEVEL_REQ (0x1U << 6) -#define LAN91C96_ECOR_SRESET (0x1U << 7) - -/* - **************************************************************************** - * PCMCIA Ethernet Configuration and Status Register (ECSR) - **************************************************************************** - */ -#define LAN91C96_ECSR_INTR (0x1U << 1) -#define LAN91C96_ECSR_PWRDWN (0x1U << 2) -#define LAN91C96_ECSR_IOIS8 (0x1U << 5) - -/* - **************************************************************************** - * Receive Frame Status Word - See page 38 of the LAN91C96 specification. - **************************************************************************** - */ -#define LAN91C96_TOO_SHORT (0x1U << 10) -#define LAN91C96_TOO_LONG (0x1U << 11) -#define LAN91C96_ODD_FRM (0x1U << 12) -#define LAN91C96_BAD_CRC (0x1U << 13) -#define LAN91C96_BROD_CAST (0x1U << 14) -#define LAN91C96_ALGN_ERR (0x1U << 15) - -#define FRAME_FILTER (LAN91C96_TOO_SHORT | LAN91C96_TOO_LONG | LAN91C96_BAD_CRC | LAN91C96_ALGN_ERR) - -/* - **************************************************************************** - * Default MAC Address - **************************************************************************** - */ -#define MAC_DEF_HI 0x0800 -#define MAC_DEF_MED 0x3333 -#define MAC_DEF_LO 0x0100 - -/* - **************************************************************************** - * Default I/O Signature - 0x33 - **************************************************************************** - */ -#define LAN91C96_LOW_SIGNATURE (0x33U << 0) -#define LAN91C96_HIGH_SIGNATURE (0x33U << 8) -#define LAN91C96_SIGNATURE (LAN91C96_HIGH_SIGNATURE | LAN91C96_LOW_SIGNATURE) - -#define LAN91C96_MAX_PAGES 6 /* Maximum number of 256 pages. */ -#define ETHERNET_MAX_LENGTH 1514 - - -/*------------------------------------------------------------------------- - * I define some macros to make it easier to do somewhat common - * or slightly complicated, repeated tasks. - *------------------------------------------------------------------------- - */ - -/* select a register bank, 0 to 3 */ - -#define SMC_SELECT_BANK(x) { SMC_outw( x, LAN91C96_BANK_SELECT ); } - -/* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( LAN91C96_INT_MASK );\ - mask |= (x);\ - SMC_outb( mask, LAN91C96_INT_MASK ); \ -} - -/* this disables an interrupt from the interrupt mask register */ - -#define SMC_DISABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( LAN91C96_INT_MASK );\ - mask &= ~(x);\ - SMC_outb( mask, LAN91C96_INT_MASK ); \ -} - -/*---------------------------------------------------------------------- - * Define the interrupts that I want to receive from the card - * - * I want: - * LAN91C96_IST_EPH_INT, for nasty errors - * LAN91C96_IST_RCV_INT, for happy received packets - * LAN91C96_IST_RX_OVRN_INT, because I have to kick the receiver - *------------------------------------------------------------------------- - */ -#define SMC_INTERRUPT_MASK (LAN91C96_IST_EPH_INT | LAN91C96_IST_RX_OVRN_INT | LAN91C96_IST_RCV_INT) - -#endif /* _LAN91C96_H_ */ diff --git a/drivers/macb.c b/drivers/macb.c deleted file mode 100644 index 95cdc496cb..0000000000 --- a/drivers/macb.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include - -#if defined(CONFIG_MACB) \ - && (defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_MII)) - -/* - * The u-boot networking stack is a little weird. It seems like the - * networking core allocates receive buffers up front without any - * regard to the hardware that's supposed to actually receive those - * packets. - * - * The MACB receives packets into 128-byte receive buffers, so the - * buffers allocated by the core isn't very practical to use. We'll - * allocate our own, but we need one such buffer in case a packet - * wraps around the DMA ring so that we have to copy it. - * - * Therefore, define CFG_RX_ETH_BUFFER to 1 in the board-specific - * configuration header. This way, the core allocates one RX buffer - * and one TX buffer, each of which can hold a ethernet packet of - * maximum size. - * - * For some reason, the networking core unconditionally specifies a - * 32-byte packet "alignment" (which really should be called - * "padding"). MACB shouldn't need that, but we'll refrain from any - * core modifications here... - */ - -#include -#include - -#include -#include -#include -#include - -#include "macb.h" - -#define barrier() asm volatile("" ::: "memory") - -#define CFG_MACB_RX_BUFFER_SIZE 4096 -#define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128) -#define CFG_MACB_TX_RING_SIZE 16 -#define CFG_MACB_TX_TIMEOUT 1000 -#define CFG_MACB_AUTONEG_TIMEOUT 5000000 - -struct macb_dma_desc { - u32 addr; - u32 ctrl; -}; - -#define RXADDR_USED 0x00000001 -#define RXADDR_WRAP 0x00000002 - -#define RXBUF_FRMLEN_MASK 0x00000fff -#define RXBUF_FRAME_START 0x00004000 -#define RXBUF_FRAME_END 0x00008000 -#define RXBUF_TYPEID_MATCH 0x00400000 -#define RXBUF_ADDR4_MATCH 0x00800000 -#define RXBUF_ADDR3_MATCH 0x01000000 -#define RXBUF_ADDR2_MATCH 0x02000000 -#define RXBUF_ADDR1_MATCH 0x04000000 -#define RXBUF_BROADCAST 0x80000000 - -#define TXBUF_FRMLEN_MASK 0x000007ff -#define TXBUF_FRAME_END 0x00008000 -#define TXBUF_NOCRC 0x00010000 -#define TXBUF_EXHAUSTED 0x08000000 -#define TXBUF_UNDERRUN 0x10000000 -#define TXBUF_MAXRETRY 0x20000000 -#define TXBUF_WRAP 0x40000000 -#define TXBUF_USED 0x80000000 - -struct macb_device { - void *regs; - - unsigned int rx_tail; - unsigned int tx_head; - unsigned int tx_tail; - - void *rx_buffer; - void *tx_buffer; - struct macb_dma_desc *rx_ring; - struct macb_dma_desc *tx_ring; - - unsigned long rx_buffer_dma; - unsigned long rx_ring_dma; - unsigned long tx_ring_dma; - - const struct device *dev; - struct eth_device netdev; - unsigned short phy_addr; -}; -#define to_macb(_nd) container_of(_nd, struct macb_device, netdev) - -static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) -{ - unsigned long netctl; - unsigned long netstat; - unsigned long frame; - - netctl = macb_readl(macb, NCR); - netctl |= MACB_BIT(MPE); - macb_writel(macb, NCR, netctl); - - frame = (MACB_BF(SOF, 1) - | MACB_BF(RW, 1) - | MACB_BF(PHYA, macb->phy_addr) - | MACB_BF(REGA, reg) - | MACB_BF(CODE, 2) - | MACB_BF(DATA, value)); - macb_writel(macb, MAN, frame); - - do { - netstat = macb_readl(macb, NSR); - } while (!(netstat & MACB_BIT(IDLE))); - - netctl = macb_readl(macb, NCR); - netctl &= ~MACB_BIT(MPE); - macb_writel(macb, NCR, netctl); -} - -static u16 macb_mdio_read(struct macb_device *macb, u8 reg) -{ - unsigned long netctl; - unsigned long netstat; - unsigned long frame; - - netctl = macb_readl(macb, NCR); - netctl |= MACB_BIT(MPE); - macb_writel(macb, NCR, netctl); - - frame = (MACB_BF(SOF, 1) - | MACB_BF(RW, 2) - | MACB_BF(PHYA, macb->phy_addr) - | MACB_BF(REGA, reg) - | MACB_BF(CODE, 2)); - macb_writel(macb, MAN, frame); - - do { - netstat = macb_readl(macb, NSR); - } while (!(netstat & MACB_BIT(IDLE))); - - frame = macb_readl(macb, MAN); - - netctl = macb_readl(macb, NCR); - netctl &= ~MACB_BIT(MPE); - macb_writel(macb, NCR, netctl); - - return MACB_BFEXT(DATA, frame); -} - -#if defined(CONFIG_CMD_NET) - -static int macb_send(struct eth_device *netdev, volatile void *packet, - int length) -{ - struct macb_device *macb = to_macb(netdev); - unsigned long paddr, ctrl; - unsigned int tx_head = macb->tx_head; - int i; - - paddr = dma_map_single(packet, length, DMA_TO_DEVICE); - - ctrl = length & TXBUF_FRMLEN_MASK; - ctrl |= TXBUF_FRAME_END; - if (tx_head == (CFG_MACB_TX_RING_SIZE - 1)) { - ctrl |= TXBUF_WRAP; - macb->tx_head = 0; - } else - macb->tx_head++; - - macb->tx_ring[tx_head].ctrl = ctrl; - macb->tx_ring[tx_head].addr = paddr; - barrier(); - macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); - - /* - * I guess this is necessary because the networking core may - * re-use the transmit buffer as soon as we return... - */ - for (i = 0; i <= CFG_MACB_TX_TIMEOUT; i++) { - barrier(); - ctrl = macb->tx_ring[tx_head].ctrl; - if (ctrl & TXBUF_USED) - break; - udelay(1); - } - - dma_unmap_single(packet, length, paddr); - - if (i <= CFG_MACB_TX_TIMEOUT) { - if (ctrl & TXBUF_UNDERRUN) - printf("%s: TX underrun\n", netdev->name); - if (ctrl & TXBUF_EXHAUSTED) - printf("%s: TX buffers exhausted in mid frame\n", - netdev->name); - } else { - printf("%s: TX timeout\n", netdev->name); - } - - /* No one cares anyway */ - return 0; -} - -static void reclaim_rx_buffers(struct macb_device *macb, - unsigned int new_tail) -{ - unsigned int i; - - i = macb->rx_tail; - while (i > new_tail) { - macb->rx_ring[i].addr &= ~RXADDR_USED; - i++; - if (i > CFG_MACB_RX_RING_SIZE) - i = 0; - } - - while (i < new_tail) { - macb->rx_ring[i].addr &= ~RXADDR_USED; - i++; - } - - barrier(); - macb->rx_tail = new_tail; -} - -static int macb_recv(struct eth_device *netdev) -{ - struct macb_device *macb = to_macb(netdev); - unsigned int rx_tail = macb->rx_tail; - void *buffer; - int length; - int wrapped = 0; - u32 status; - - for (;;) { - if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) - return -1; - - status = macb->rx_ring[rx_tail].ctrl; - if (status & RXBUF_FRAME_START) { - if (rx_tail != macb->rx_tail) - reclaim_rx_buffers(macb, rx_tail); - wrapped = 0; - } - - if (status & RXBUF_FRAME_END) { - buffer = macb->rx_buffer + 128 * macb->rx_tail; - length = status & RXBUF_FRMLEN_MASK; - if (wrapped) { - unsigned int headlen, taillen; - - headlen = 128 * (CFG_MACB_RX_RING_SIZE - - macb->rx_tail); - taillen = length - headlen; - memcpy((void *)NetRxPackets[0], - buffer, headlen); - memcpy((void *)NetRxPackets[0] + headlen, - macb->rx_buffer, taillen); - buffer = (void *)NetRxPackets[0]; - } - - NetReceive(buffer, length); - if (++rx_tail >= CFG_MACB_RX_RING_SIZE) - rx_tail = 0; - reclaim_rx_buffers(macb, rx_tail); - } else { - if (++rx_tail >= CFG_MACB_RX_RING_SIZE) { - wrapped = 1; - rx_tail = 0; - } - } - barrier(); - } - - return 0; -} - -static void macb_phy_reset(struct macb_device *macb) -{ - struct eth_device *netdev = &macb->netdev; - int i; - u16 status, adv; - - adv = ADVERTISE_CSMA | ADVERTISE_ALL; - macb_mdio_write(macb, MII_ADVERTISE, adv); - printf("%s: Starting autonegotiation...\n", netdev->name); - macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE - | BMCR_ANRESTART)); - - for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { - status = macb_mdio_read(macb, MII_BMSR); - if (status & BMSR_ANEGCOMPLETE) - break; - udelay(100); - } - - if (status & BMSR_ANEGCOMPLETE) - printf("%s: Autonegotiation complete\n", netdev->name); - else - printf("%s: Autonegotiation timed out (status=0x%04x)\n", - netdev->name, status); -} - -static int macb_phy_init(struct macb_device *macb) -{ - struct eth_device *netdev = &macb->netdev; - u32 ncfgr; - u16 phy_id, status, adv, lpa; - int media, speed, duplex; - int i; - - /* Check if the PHY is up to snuff... */ - phy_id = macb_mdio_read(macb, MII_PHYSID1); - if (phy_id == 0xffff) { - printf("%s: No PHY present\n", netdev->name); - return 0; - } - - status = macb_mdio_read(macb, MII_BMSR); - if (!(status & BMSR_LSTATUS)) { - /* Try to re-negotiate if we don't have link already. */ - macb_phy_reset(macb); - - for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { - status = macb_mdio_read(macb, MII_BMSR); - if (status & BMSR_LSTATUS) - break; - udelay(100); - } - } - - if (!(status & BMSR_LSTATUS)) { - printf("%s: link down (status: 0x%04x)\n", - netdev->name, status); - return 0; - } else { - adv = macb_mdio_read(macb, MII_ADVERTISE); - lpa = macb_mdio_read(macb, MII_LPA); - media = mii_nway_result(lpa & adv); - speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) - ? 1 : 0); - duplex = (media & ADVERTISE_FULL) ? 1 : 0; - printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", - netdev->name, - speed ? "100" : "10", - duplex ? "full" : "half", - lpa); - - ncfgr = macb_readl(macb, NCFGR); - ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); - if (speed) - ncfgr |= MACB_BIT(SPD); - if (duplex) - ncfgr |= MACB_BIT(FD); - macb_writel(macb, NCFGR, ncfgr); - return 1; - } -} - -static int macb_init(struct eth_device *netdev, bd_t *bd) -{ - struct macb_device *macb = to_macb(netdev); - unsigned long paddr; - u32 hwaddr_bottom; - u16 hwaddr_top; - int i; - - /* - * macb_halt should have been called at some point before now, - * so we'll assume the controller is idle. - */ - - /* initialize DMA descriptors */ - paddr = macb->rx_buffer_dma; - for (i = 0; i < CFG_MACB_RX_RING_SIZE; i++) { - if (i == (CFG_MACB_RX_RING_SIZE - 1)) - paddr |= RXADDR_WRAP; - macb->rx_ring[i].addr = paddr; - macb->rx_ring[i].ctrl = 0; - paddr += 128; - } - for (i = 0; i < CFG_MACB_TX_RING_SIZE; i++) { - macb->tx_ring[i].addr = 0; - if (i == (CFG_MACB_TX_RING_SIZE - 1)) - macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; - else - macb->tx_ring[i].ctrl = TXBUF_USED; - } - macb->rx_tail = macb->tx_head = macb->tx_tail = 0; - - macb_writel(macb, RBQP, macb->rx_ring_dma); - macb_writel(macb, TBQP, macb->tx_ring_dma); - - /* set hardware address */ - hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr)); - macb_writel(macb, SA1B, hwaddr_bottom); - hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))); - macb_writel(macb, SA1T, hwaddr_top); - - /* choose RMII or MII mode. This depends on the board */ -#ifdef CONFIG_RMII - macb_writel(macb, USRIO, 0); -#else - macb_writel(macb, USRIO, MACB_BIT(MII)); -#endif - - if (!macb_phy_init(macb)) - return 0; - - /* Enable TX and RX */ - macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); - - return 1; -} - -static void macb_halt(struct eth_device *netdev) -{ - struct macb_device *macb = to_macb(netdev); - u32 ncr, tsr; - - /* Halt the controller and wait for any ongoing transmission to end. */ - ncr = macb_readl(macb, NCR); - ncr |= MACB_BIT(THALT); - macb_writel(macb, NCR, ncr); - - do { - tsr = macb_readl(macb, TSR); - } while (tsr & MACB_BIT(TGO)); - - /* Disable TX and RX, and clear statistics */ - macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); -} - -int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) -{ - struct macb_device *macb; - struct eth_device *netdev; - unsigned long macb_hz; - u32 ncfgr; - - macb = malloc(sizeof(struct macb_device)); - if (!macb) { - printf("Error: Failed to allocate memory for MACB%d\n", id); - return -1; - } - memset(macb, 0, sizeof(struct macb_device)); - - netdev = &macb->netdev; - - macb->rx_buffer = dma_alloc_coherent(CFG_MACB_RX_BUFFER_SIZE, - &macb->rx_buffer_dma); - macb->rx_ring = dma_alloc_coherent(CFG_MACB_RX_RING_SIZE - * sizeof(struct macb_dma_desc), - &macb->rx_ring_dma); - macb->tx_ring = dma_alloc_coherent(CFG_MACB_TX_RING_SIZE - * sizeof(struct macb_dma_desc), - &macb->tx_ring_dma); - - macb->regs = regs; - macb->phy_addr = phy_addr; - - sprintf(netdev->name, "macb%d", id); - netdev->init = macb_init; - netdev->halt = macb_halt; - netdev->send = macb_send; - netdev->recv = macb_recv; - - /* - * Do some basic initialization so that we at least can talk - * to the PHY - */ - macb_hz = get_macb_pclk_rate(id); - if (macb_hz < 20000000) - ncfgr = MACB_BF(CLK, MACB_CLK_DIV8); - else if (macb_hz < 40000000) - ncfgr = MACB_BF(CLK, MACB_CLK_DIV16); - else if (macb_hz < 80000000) - ncfgr = MACB_BF(CLK, MACB_CLK_DIV32); - else - ncfgr = MACB_BF(CLK, MACB_CLK_DIV64); - - macb_writel(macb, NCFGR, ncfgr); - - eth_register(netdev); - - return 0; -} - -#endif - -#if defined(CONFIG_CMD_MII) - -int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) -{ - unsigned long netctl; - unsigned long netstat; - unsigned long frame; - int iflag; - - iflag = disable_interrupts(); - netctl = macb_readl(&macb, EMACB_NCR); - netctl |= MACB_BIT(MPE); - macb_writel(&macb, EMACB_NCR, netctl); - if (iflag) - enable_interrupts(); - - frame = (MACB_BF(SOF, 1) - | MACB_BF(RW, 2) - | MACB_BF(PHYA, addr) - | MACB_BF(REGA, reg) - | MACB_BF(CODE, 2)); - macb_writel(&macb, EMACB_MAN, frame); - - do { - netstat = macb_readl(&macb, EMACB_NSR); - } while (!(netstat & MACB_BIT(IDLE))); - - frame = macb_readl(&macb, EMACB_MAN); - *value = MACB_BFEXT(DATA, frame); - - iflag = disable_interrupts(); - netctl = macb_readl(&macb, EMACB_NCR); - netctl &= ~MACB_BIT(MPE); - macb_writel(&macb, EMACB_NCR, netctl); - if (iflag) - enable_interrupts(); - - return 0; -} - -int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) -{ - unsigned long netctl; - unsigned long netstat; - unsigned long frame; - int iflag; - - iflag = disable_interrupts(); - netctl = macb_readl(&macb, EMACB_NCR); - netctl |= MACB_BIT(MPE); - macb_writel(&macb, EMACB_NCR, netctl); - if (iflag) - enable_interrupts(); - - frame = (MACB_BF(SOF, 1) - | MACB_BF(RW, 1) - | MACB_BF(PHYA, addr) - | MACB_BF(REGA, reg) - | MACB_BF(CODE, 2) - | MACB_BF(DATA, value)); - macb_writel(&macb, EMACB_MAN, frame); - - do { - netstat = macb_readl(&macb, EMACB_NSR); - } while (!(netstat & MACB_BIT(IDLE))); - - iflag = disable_interrupts(); - netctl = macb_readl(&macb, EMACB_NCR); - netctl &= ~MACB_BIT(MPE); - macb_writel(&macb, EMACB_NCR, netctl); - if (iflag) - enable_interrupts(); - - return 0; -} - -#endif - -#endif /* CONFIG_MACB */ diff --git a/drivers/macb.h b/drivers/macb.h deleted file mode 100644 index c778e4ee49..0000000000 --- a/drivers/macb.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2005-2006 Atmel Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#ifndef __DRIVERS_MACB_H__ -#define __DRIVERS_MACB_H__ - -/* MACB register offsets */ -#define MACB_NCR 0x0000 -#define MACB_NCFGR 0x0004 -#define MACB_NSR 0x0008 -#define MACB_TSR 0x0014 -#define MACB_RBQP 0x0018 -#define MACB_TBQP 0x001c -#define MACB_RSR 0x0020 -#define MACB_ISR 0x0024 -#define MACB_IER 0x0028 -#define MACB_IDR 0x002c -#define MACB_IMR 0x0030 -#define MACB_MAN 0x0034 -#define MACB_PTR 0x0038 -#define MACB_PFR 0x003c -#define MACB_FTO 0x0040 -#define MACB_SCF 0x0044 -#define MACB_MCF 0x0048 -#define MACB_FRO 0x004c -#define MACB_FCSE 0x0050 -#define MACB_ALE 0x0054 -#define MACB_DTF 0x0058 -#define MACB_LCOL 0x005c -#define MACB_EXCOL 0x0060 -#define MACB_TUND 0x0064 -#define MACB_CSE 0x0068 -#define MACB_RRE 0x006c -#define MACB_ROVR 0x0070 -#define MACB_RSE 0x0074 -#define MACB_ELE 0x0078 -#define MACB_RJA 0x007c -#define MACB_USF 0x0080 -#define MACB_STE 0x0084 -#define MACB_RLE 0x0088 -#define MACB_TPF 0x008c -#define MACB_HRB 0x0090 -#define MACB_HRT 0x0094 -#define MACB_SA1B 0x0098 -#define MACB_SA1T 0x009c -#define MACB_SA2B 0x00a0 -#define MACB_SA2T 0x00a4 -#define MACB_SA3B 0x00a8 -#define MACB_SA3T 0x00ac -#define MACB_SA4B 0x00b0 -#define MACB_SA4T 0x00b4 -#define MACB_TID 0x00b8 -#define MACB_TPQ 0x00bc -#define MACB_USRIO 0x00c0 -#define MACB_WOL 0x00c4 - -/* Bitfields in NCR */ -#define MACB_LB_OFFSET 0 -#define MACB_LB_SIZE 1 -#define MACB_LLB_OFFSET 1 -#define MACB_LLB_SIZE 1 -#define MACB_RE_OFFSET 2 -#define MACB_RE_SIZE 1 -#define MACB_TE_OFFSET 3 -#define MACB_TE_SIZE 1 -#define MACB_MPE_OFFSET 4 -#define MACB_MPE_SIZE 1 -#define MACB_CLRSTAT_OFFSET 5 -#define MACB_CLRSTAT_SIZE 1 -#define MACB_INCSTAT_OFFSET 6 -#define MACB_INCSTAT_SIZE 1 -#define MACB_WESTAT_OFFSET 7 -#define MACB_WESTAT_SIZE 1 -#define MACB_BP_OFFSET 8 -#define MACB_BP_SIZE 1 -#define MACB_TSTART_OFFSET 9 -#define MACB_TSTART_SIZE 1 -#define MACB_THALT_OFFSET 10 -#define MACB_THALT_SIZE 1 -#define MACB_NCR_TPF_OFFSET 11 -#define MACB_NCR_TPF_SIZE 1 -#define MACB_TZQ_OFFSET 12 -#define MACB_TZQ_SIZE 1 - -/* Bitfields in NCFGR */ -#define MACB_SPD_OFFSET 0 -#define MACB_SPD_SIZE 1 -#define MACB_FD_OFFSET 1 -#define MACB_FD_SIZE 1 -#define MACB_BIT_RATE_OFFSET 2 -#define MACB_BIT_RATE_SIZE 1 -#define MACB_JFRAME_OFFSET 3 -#define MACB_JFRAME_SIZE 1 -#define MACB_CAF_OFFSET 4 -#define MACB_CAF_SIZE 1 -#define MACB_NBC_OFFSET 5 -#define MACB_NBC_SIZE 1 -#define MACB_NCFGR_MTI_OFFSET 6 -#define MACB_NCFGR_MTI_SIZE 1 -#define MACB_UNI_OFFSET 7 -#define MACB_UNI_SIZE 1 -#define MACB_BIG_OFFSET 8 -#define MACB_BIG_SIZE 1 -#define MACB_EAE_OFFSET 9 -#define MACB_EAE_SIZE 1 -#define MACB_CLK_OFFSET 10 -#define MACB_CLK_SIZE 2 -#define MACB_RTY_OFFSET 12 -#define MACB_RTY_SIZE 1 -#define MACB_PAE_OFFSET 13 -#define MACB_PAE_SIZE 1 -#define MACB_RBOF_OFFSET 14 -#define MACB_RBOF_SIZE 2 -#define MACB_RLCE_OFFSET 16 -#define MACB_RLCE_SIZE 1 -#define MACB_DRFCS_OFFSET 17 -#define MACB_DRFCS_SIZE 1 -#define MACB_EFRHD_OFFSET 18 -#define MACB_EFRHD_SIZE 1 -#define MACB_IRXFCS_OFFSET 19 -#define MACB_IRXFCS_SIZE 1 - -/* Bitfields in NSR */ -#define MACB_NSR_LINK_OFFSET 0 -#define MACB_NSR_LINK_SIZE 1 -#define MACB_MDIO_OFFSET 1 -#define MACB_MDIO_SIZE 1 -#define MACB_IDLE_OFFSET 2 -#define MACB_IDLE_SIZE 1 - -/* Bitfields in TSR */ -#define MACB_UBR_OFFSET 0 -#define MACB_UBR_SIZE 1 -#define MACB_COL_OFFSET 1 -#define MACB_COL_SIZE 1 -#define MACB_TSR_RLE_OFFSET 2 -#define MACB_TSR_RLE_SIZE 1 -#define MACB_TGO_OFFSET 3 -#define MACB_TGO_SIZE 1 -#define MACB_BEX_OFFSET 4 -#define MACB_BEX_SIZE 1 -#define MACB_COMP_OFFSET 5 -#define MACB_COMP_SIZE 1 -#define MACB_UND_OFFSET 6 -#define MACB_UND_SIZE 1 - -/* Bitfields in RSR */ -#define MACB_BNA_OFFSET 0 -#define MACB_BNA_SIZE 1 -#define MACB_REC_OFFSET 1 -#define MACB_REC_SIZE 1 -#define MACB_OVR_OFFSET 2 -#define MACB_OVR_SIZE 1 - -/* Bitfields in ISR/IER/IDR/IMR */ -#define MACB_MFD_OFFSET 0 -#define MACB_MFD_SIZE 1 -#define MACB_RCOMP_OFFSET 1 -#define MACB_RCOMP_SIZE 1 -#define MACB_RXUBR_OFFSET 2 -#define MACB_RXUBR_SIZE 1 -#define MACB_TXUBR_OFFSET 3 -#define MACB_TXUBR_SIZE 1 -#define MACB_ISR_TUND_OFFSET 4 -#define MACB_ISR_TUND_SIZE 1 -#define MACB_ISR_RLE_OFFSET 5 -#define MACB_ISR_RLE_SIZE 1 -#define MACB_TXERR_OFFSET 6 -#define MACB_TXERR_SIZE 1 -#define MACB_TCOMP_OFFSET 7 -#define MACB_TCOMP_SIZE 1 -#define MACB_ISR_LINK_OFFSET 9 -#define MACB_ISR_LINK_SIZE 1 -#define MACB_ISR_ROVR_OFFSET 10 -#define MACB_ISR_ROVR_SIZE 1 -#define MACB_HRESP_OFFSET 11 -#define MACB_HRESP_SIZE 1 -#define MACB_PFR_OFFSET 12 -#define MACB_PFR_SIZE 1 -#define MACB_PTZ_OFFSET 13 -#define MACB_PTZ_SIZE 1 - -/* Bitfields in MAN */ -#define MACB_DATA_OFFSET 0 -#define MACB_DATA_SIZE 16 -#define MACB_CODE_OFFSET 16 -#define MACB_CODE_SIZE 2 -#define MACB_REGA_OFFSET 18 -#define MACB_REGA_SIZE 5 -#define MACB_PHYA_OFFSET 23 -#define MACB_PHYA_SIZE 5 -#define MACB_RW_OFFSET 28 -#define MACB_RW_SIZE 2 -#define MACB_SOF_OFFSET 30 -#define MACB_SOF_SIZE 2 - -/* Bitfields in USRIO */ -#define MACB_MII_OFFSET 0 -#define MACB_MII_SIZE 1 -#define MACB_EAM_OFFSET 1 -#define MACB_EAM_SIZE 1 -#define MACB_TX_PAUSE_OFFSET 2 -#define MACB_TX_PAUSE_SIZE 1 -#define MACB_TX_PAUSE_ZERO_OFFSET 3 -#define MACB_TX_PAUSE_ZERO_SIZE 1 - -/* Bitfields in WOL */ -#define MACB_IP_OFFSET 0 -#define MACB_IP_SIZE 16 -#define MACB_MAG_OFFSET 16 -#define MACB_MAG_SIZE 1 -#define MACB_ARP_OFFSET 17 -#define MACB_ARP_SIZE 1 -#define MACB_SA1_OFFSET 18 -#define MACB_SA1_SIZE 1 -#define MACB_WOL_MTI_OFFSET 19 -#define MACB_WOL_MTI_SIZE 1 - -/* Constants for CLK */ -#define MACB_CLK_DIV8 0 -#define MACB_CLK_DIV16 1 -#define MACB_CLK_DIV32 2 -#define MACB_CLK_DIV64 3 - -/* Constants for MAN register */ -#define MACB_MAN_SOF 1 -#define MACB_MAN_WRITE 1 -#define MACB_MAN_READ 2 -#define MACB_MAN_CODE 2 - -/* Bit manipulation macros */ -#define MACB_BIT(name) \ - (1 << MACB_##name##_OFFSET) -#define MACB_BF(name,value) \ - (((value) & ((1 << MACB_##name##_SIZE) - 1)) \ - << MACB_##name##_OFFSET) -#define MACB_BFEXT(name,value)\ - (((value) >> MACB_##name##_OFFSET) \ - & ((1 << MACB_##name##_SIZE) - 1)) -#define MACB_BFINS(name,value,old) \ - (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \ - << MACB_##name##_OFFSET)) \ - | MACB_BF(name,value)) - -/* Register access macros */ -#define macb_readl(port,reg) \ - readl((port)->regs + MACB_##reg) -#define macb_writel(port,reg,value) \ - writel((value), (port)->regs + MACB_##reg) - -#endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/natsemi.c b/drivers/natsemi.c deleted file mode 100644 index 075d6c52c4..0000000000 --- a/drivers/natsemi.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - natsemi.c: A U-Boot driver for the NatSemi DP8381x series. - Author: Mark A. Rakes (mark_rakes@vivato.net) - - Adapted from an Etherboot driver written by: - - Copyright (C) 2001 Entity Cyber, Inc. - - This development of this Etherboot driver was funded by - - Sicom Systems: http://www.sicompos.com/ - - Author: Marty Connor (mdc@thinguin.org) - Adapted from a Linux driver which was written by Donald Becker - - This software may be used and distributed according to the terms - of the GNU Public License (GPL), incorporated herein by reference. - - Original Copyright Notice: - - Written/copyright 1999-2001 by Donald Becker. - - This software may be used and distributed according to the terms of - the GNU General Public License (GPL), incorporated herein by reference. - Drivers based on or derived from this code fall under the GPL and must - retain the authorship, copyright and license notice. This file is not - a complete program and may only be used when the entire operating - system is licensed under the GPL. License for under other terms may be - available. Contact the original author for details. - - The original author may be reached as becker@scyld.com, or at - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Support information and updates available at - http://www.scyld.com/network/netsemi.html - - References: - http://www.scyld.com/expert/100mbps.html - http://www.scyld.com/expert/NWay.html - Datasheet is available from: - http://www.national.com/pf/DP/DP83815.html -*/ - -/* Revision History - * October 2002 mar 1.0 - * Initial U-Boot Release. Tested with Netgear FA311 board - * and dp83815 chipset on custom board -*/ - -/* Includes */ -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_NATSEMI) - -/* defines */ -#define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ - -#define DSIZE 0x00000FFF -#define ETH_ALEN 6 -#define CRC_SIZE 4 -#define TOUT_LOOP 500000 -#define TX_BUF_SIZE 1536 -#define RX_BUF_SIZE 1536 -#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ - -/* Offsets to the device registers. - Unlike software-only systems, device drivers interact with complex hardware. - It's not useful to define symbolic names for every register bit in the - device. */ -enum register_offsets { - ChipCmd = 0x00, - ChipConfig = 0x04, - EECtrl = 0x08, - IntrMask = 0x14, - IntrEnable = 0x18, - TxRingPtr = 0x20, - TxConfig = 0x24, - RxRingPtr = 0x30, - RxConfig = 0x34, - ClkRun = 0x3C, - RxFilterAddr = 0x48, - RxFilterData = 0x4C, - SiliconRev = 0x58, - PCIPM = 0x44, - BasicControl = 0x80, - BasicStatus = 0x84, - /* These are from the spec, around page 78... on a separate table. */ - PGSEL = 0xCC, - PMDCSR = 0xE4, - TSTDAT = 0xFC, - DSPCFG = 0xF4, - SDCFG = 0x8C -}; - -/* Bit in ChipCmd. */ -enum ChipCmdBits { - ChipReset = 0x100, - RxReset = 0x20, - TxReset = 0x10, - RxOff = 0x08, - RxOn = 0x04, - TxOff = 0x02, - TxOn = 0x01 -}; - -enum ChipConfigBits { - LinkSts = 0x80000000, - HundSpeed = 0x40000000, - FullDuplex = 0x20000000, - TenPolarity = 0x10000000, - AnegDone = 0x08000000, - AnegEnBothBoth = 0x0000E000, - AnegDis100Full = 0x0000C000, - AnegEn100Both = 0x0000A000, - AnegDis100Half = 0x00008000, - AnegEnBothHalf = 0x00006000, - AnegDis10Full = 0x00004000, - AnegEn10Both = 0x00002000, - DuplexMask = 0x00008000, - SpeedMask = 0x00004000, - AnegMask = 0x00002000, - AnegDis10Half = 0x00000000, - ExtPhy = 0x00001000, - PhyRst = 0x00000400, - PhyDis = 0x00000200, - BootRomDisable = 0x00000004, - BEMode = 0x00000001, -}; - -enum TxConfig_bits { - TxDrthMask = 0x3f, - TxFlthMask = 0x3f00, - TxMxdmaMask = 0x700000, - TxMxdma_512 = 0x0, - TxMxdma_4 = 0x100000, - TxMxdma_8 = 0x200000, - TxMxdma_16 = 0x300000, - TxMxdma_32 = 0x400000, - TxMxdma_64 = 0x500000, - TxMxdma_128 = 0x600000, - TxMxdma_256 = 0x700000, - TxCollRetry = 0x800000, - TxAutoPad = 0x10000000, - TxMacLoop = 0x20000000, - TxHeartIgn = 0x40000000, - TxCarrierIgn = 0x80000000 -}; - -enum RxConfig_bits { - RxDrthMask = 0x3e, - RxMxdmaMask = 0x700000, - RxMxdma_512 = 0x0, - RxMxdma_4 = 0x100000, - RxMxdma_8 = 0x200000, - RxMxdma_16 = 0x300000, - RxMxdma_32 = 0x400000, - RxMxdma_64 = 0x500000, - RxMxdma_128 = 0x600000, - RxMxdma_256 = 0x700000, - RxAcceptLong = 0x8000000, - RxAcceptTx = 0x10000000, - RxAcceptRunt = 0x40000000, - RxAcceptErr = 0x80000000 -}; - -/* Bits in the RxMode register. */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0xC0000000, - AcceptMulticast = 0x00200000, - AcceptAllMulticast = 0x20000000, - AcceptAllPhys = 0x10000000, - AcceptMyPhys = 0x08000000 -}; - -typedef struct _BufferDesc { - u32 link; - vu_long cmdsts; - u32 bufptr; - u32 software_use; -} BufferDesc; - -/* Bits in network_desc.status */ -enum desc_status_bits { - DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, - DescNoCRC = 0x10000000, DescPktOK = 0x08000000, - DescSizeMask = 0xfff, - - DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000, - DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000, - DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000, - DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000, - - DescRxAbort = 0x04000000, DescRxOver = 0x02000000, - DescRxDest = 0x01800000, DescRxLong = 0x00400000, - DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000, - DescRxCRC = 0x00080000, DescRxAlign = 0x00040000, - DescRxLoop = 0x00020000, DesRxColl = 0x00010000, -}; - -/* Globals */ -#ifdef NATSEMI_DEBUG -static int natsemi_debug = 0; /* 1 verbose debugging, 0 normal */ -#endif -static u32 SavedClkRun; -static unsigned int cur_rx; -static unsigned int advertising; -static unsigned int rx_config; -static unsigned int tx_config; - -/* Note: transmit and receive buffers and descriptors must be - longword aligned */ -static BufferDesc txd __attribute__ ((aligned(4))); -static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4))); - -static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4))); -static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] - __attribute__ ((aligned(4))); - -/* Function Prototypes */ -#if 0 -static void write_eeprom(struct eth_device *dev, long addr, int location, - short value); -#endif -static int read_eeprom(struct eth_device *dev, long addr, int location); -static int mdio_read(struct eth_device *dev, int phy_id, int location); -static int natsemi_init(struct eth_device *dev, bd_t * bis); -static void natsemi_reset(struct eth_device *dev); -static void natsemi_init_rxfilter(struct eth_device *dev); -static void natsemi_init_txd(struct eth_device *dev); -static void natsemi_init_rxd(struct eth_device *dev); -static void natsemi_set_rx_mode(struct eth_device *dev); -static void natsemi_check_duplex(struct eth_device *dev); -static int natsemi_send(struct eth_device *dev, volatile void *packet, - int length); -static int natsemi_poll(struct eth_device *dev); -static void natsemi_disable(struct eth_device *dev); - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815}, - {} -}; - -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) - -static inline int -INW(struct eth_device *dev, u_long addr) -{ - return le16_to_cpu(*(vu_short *) (addr + dev->iobase)); -} - -static int -INL(struct eth_device *dev, u_long addr) -{ - return le32_to_cpu(*(vu_long *) (addr + dev->iobase)); -} - -static inline void -OUTW(struct eth_device *dev, int command, u_long addr) -{ - *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command); -} - -static inline void -OUTL(struct eth_device *dev, int command, u_long addr) -{ - *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command); -} - -/* - * Function: natsemi_initialize - * - * Description: Retrieves the MAC address of the card, and sets up some - * globals required by other routines, and initializes the NIC, making it - * ready to send and receive packets. - * - * Side effects: - * leaves the natsemi initialized, and ready to recieve packets. - * - * Returns: struct eth_device *: pointer to NIC data structure - */ - -int -natsemi_initialize(bd_t * bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase, status, chip_config; - int i, idx = 0; - int prev_eedata; - u32 tmp; - - while (1) { - /* Find PCI device(s) */ - if ((devno = pci_find_devices(supported, idx++)) < 0) { - break; - } - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); - iobase &= ~0x3; /* bit 1: unused and bit 0: I/O Space Indicator */ - - pci_write_config_dword(devno, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword(devno, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEM access.\n"); - continue; - } else if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } - - dev = (struct eth_device *) malloc(sizeof *dev); - - sprintf(dev->name, "dp83815#%d", card_number); - dev->iobase = bus_to_phys(iobase); -#ifdef NATSEMI_DEBUG - printf("natsemi: NatSemi ns8381[56] @ %#x\n", dev->iobase); -#endif - dev->priv = (void *) devno; - dev->init = natsemi_init; - dev->halt = natsemi_disable; - dev->send = natsemi_send; - dev->recv = natsemi_poll; - - eth_register(dev); - - card_number++; - - /* Set the latency timer for value. */ - pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); - - udelay(10 * 1000); - - /* natsemi has a non-standard PM control register - * in PCI config space. Some boards apparently need - * to be brought to D0 in this manner. */ - pci_read_config_dword(devno, PCIPM, &tmp); - if (tmp & (0x03 | 0x100)) { - /* D0 state, disable PME assertion */ - u32 newtmp = tmp & ~(0x03 | 0x100); - pci_write_config_dword(devno, PCIPM, newtmp); - } - - printf("natsemi: EEPROM contents:\n"); - for (i = 0; i <= EEPROM_SIZE; i++) { - short eedata = read_eeprom(dev, EECtrl, i); - printf(" %04hx", eedata); - } - printf("\n"); - - /* get MAC address */ - prev_eedata = read_eeprom(dev, EECtrl, 6); - for (i = 0; i < 3; i++) { - int eedata = read_eeprom(dev, EECtrl, i + 7); - dev->enetaddr[i*2] = (eedata << 1) + (prev_eedata >> 15); - dev->enetaddr[i*2+1] = eedata >> 7; - prev_eedata = eedata; - } - - /* Reset the chip to erase any previous misconfiguration. */ - OUTL(dev, ChipReset, ChipCmd); - - advertising = mdio_read(dev, 1, 4); - chip_config = INL(dev, ChipConfig); -#ifdef NATSEMI_DEBUG - printf("%s: Transceiver status %#08X advertising %#08X\n", - dev->name, (int) INL(dev, BasicStatus), advertising); - printf("%s: Transceiver default autoneg. %s 10%s %s duplex.\n", - dev->name, chip_config & AnegMask ? "enabled, advertise" : - "disabled, force", chip_config & SpeedMask ? "0" : "", - chip_config & DuplexMask ? "full" : "half"); -#endif - chip_config |= AnegEnBothBoth; -#ifdef NATSEMI_DEBUG - printf("%s: changed to autoneg. %s 10%s %s duplex.\n", - dev->name, chip_config & AnegMask ? "enabled, advertise" : - "disabled, force", chip_config & SpeedMask ? "0" : "", - chip_config & DuplexMask ? "full" : "half"); -#endif - /*write new autoneg bits, reset phy*/ - OUTL(dev, (chip_config | PhyRst), ChipConfig); - /*un-reset phy*/ - OUTL(dev, chip_config, ChipConfig); - - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. */ - SavedClkRun = INL(dev, ClkRun); - OUTL(dev, SavedClkRun & ~0x100, ClkRun); - } - return card_number; -} - -/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. - The EEPROM code is for common 93c06/46 EEPROMs w/ 6bit addresses. */ - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but future 66Mhz - access may need a delay. */ -#define eeprom_delay(ee_addr) INL(dev, ee_addr) - -enum EEPROM_Ctrl_Bits { - EE_ShiftClk = 0x04, - EE_DataIn = 0x01, - EE_ChipSelect = 0x08, - EE_DataOut = 0x02 -}; - -#define EE_Write0 (EE_ChipSelect) -#define EE_Write1 (EE_ChipSelect | EE_DataIn) -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WrEnCmd = (4 << 6), EE_WriteCmd = (5 << 6), - EE_ReadCmd = (6 << 6), EE_EraseCmd = (7 << 6), -}; - -#if 0 -static void -write_eeprom(struct eth_device *dev, long addr, int location, short value) -{ - int i; - int ee_addr = (typeof(ee_addr))addr; - short wren_cmd = EE_WrEnCmd | 0x30; /*wren is 100 + 11XXXX*/ - short write_cmd = location | EE_WriteCmd; - -#ifdef NATSEMI_DEBUG - printf("write_eeprom: %08x, %04hx, %04hx\n", - dev->iobase + ee_addr, write_cmd, value); -#endif - /* Shift the write enable command bits out. */ - for (i = 9; i >= 0; i--) { - short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0; - OUTL(dev, cmdval, ee_addr); - eeprom_delay(ee_addr); - OUTL(dev, cmdval | EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - } - - OUTL(dev, 0, ee_addr); /*bring chip select low*/ - OUTL(dev, EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - - /* Shift the write command bits out. */ - for (i = 9; i >= 0; i--) { - short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0; - OUTL(dev, cmdval, ee_addr); - eeprom_delay(ee_addr); - OUTL(dev, cmdval | EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - } - - for (i = 0; i < 16; i++) { - short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0; - OUTL(dev, cmdval, ee_addr); - eeprom_delay(ee_addr); - OUTL(dev, cmdval | EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - } - - OUTL(dev, 0, ee_addr); /*bring chip select low*/ - OUTL(dev, EE_ShiftClk, ee_addr); - for (i = 0; i < 200000; i++) { - OUTL(dev, EE_Write0, ee_addr); /*poll for done*/ - if (INL(dev, ee_addr) & EE_DataOut) { - break; /*finished*/ - } - } - eeprom_delay(ee_addr); - - /* Terminate the EEPROM access. */ - OUTL(dev, EE_Write0, ee_addr); - OUTL(dev, 0, ee_addr); - return; -} -#endif - -static int -read_eeprom(struct eth_device *dev, long addr, int location) -{ - int i; - int retval = 0; - int ee_addr = (typeof(ee_addr))addr; - int read_cmd = location | EE_ReadCmd; - - OUTL(dev, EE_Write0, ee_addr); - - /* Shift the read command bits out. */ - for (i = 10; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; - OUTL(dev, dataval, ee_addr); - eeprom_delay(ee_addr); - OUTL(dev, dataval | EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - } - OUTL(dev, EE_ChipSelect, ee_addr); - eeprom_delay(ee_addr); - - for (i = 0; i < 16; i++) { - OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr); - eeprom_delay(ee_addr); - retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0; - OUTL(dev, EE_ChipSelect, ee_addr); - eeprom_delay(ee_addr); - } - - /* Terminate the EEPROM access. */ - OUTL(dev, EE_Write0, ee_addr); - OUTL(dev, 0, ee_addr); -#ifdef NATSEMI_DEBUG - if (natsemi_debug) - printf("read_eeprom: %08x, %08x, retval %08x\n", - dev->iobase + ee_addr, read_cmd, retval); -#endif - return retval; -} - -/* MII transceiver control section. - The 83815 series has an internal transceiver, and we present the - management registers as if they were MII connected. */ - -static int -mdio_read(struct eth_device *dev, int phy_id, int location) -{ - if (phy_id == 1 && location < 32) - return INL(dev, BasicControl+(location<<2))&0xffff; - else - return 0xffff; -} - -/* Function: natsemi_init - * - * Description: resets the ethernet controller chip and configures - * registers and data structures required for sending and receiving packets. - * - * Arguments: struct eth_device *dev: NIC data structure - * - * returns: int. - */ - -static int -natsemi_init(struct eth_device *dev, bd_t * bis) -{ - - natsemi_reset(dev); - - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. */ - OUTL(dev, SavedClkRun & ~0x100, ClkRun); - - natsemi_init_rxfilter(dev); - natsemi_init_txd(dev); - natsemi_init_rxd(dev); - - /* Configure the PCI bus bursts and FIFO thresholds. */ - tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002); - rx_config = RxMxdma_256 | 0x20; - -#ifdef NATSEMI_DEBUG - printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); - printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config); -#endif - OUTL(dev, tx_config, TxConfig); - OUTL(dev, rx_config, RxConfig); - - natsemi_check_duplex(dev); - natsemi_set_rx_mode(dev); - - OUTL(dev, (RxOn | TxOn), ChipCmd); - return 1; -} - -/* - * Function: natsemi_reset - * - * Description: soft resets the controller chip - * - * Arguments: struct eth_device *dev: NIC data structure - * - * Returns: void. - */ -static void -natsemi_reset(struct eth_device *dev) -{ - OUTL(dev, ChipReset, ChipCmd); - - /* On page 78 of the spec, they recommend some settings for "optimum - performance" to be done in sequence. These settings optimize some - of the 100Mbit autodetection circuitry. Also, we only want to do - this for rev C of the chip. */ - if (INL(dev, SiliconRev) == 0x302) { - OUTW(dev, 0x0001, PGSEL); - OUTW(dev, 0x189C, PMDCSR); - OUTW(dev, 0x0000, TSTDAT); - OUTW(dev, 0x5040, DSPCFG); - OUTW(dev, 0x008C, SDCFG); - } - /* Disable interrupts using the mask. */ - OUTL(dev, 0, IntrMask); - OUTL(dev, 0, IntrEnable); -} - -/* Function: natsemi_init_rxfilter - * - * Description: sets receive filter address to our MAC address - * - * Arguments: struct eth_device *dev: NIC data structure - * - * returns: void. - */ - -static void -natsemi_init_rxfilter(struct eth_device *dev) -{ - int i; - - for (i = 0; i < ETH_ALEN; i += 2) { - OUTL(dev, i, RxFilterAddr); - OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), - RxFilterData); - } -} - -/* - * Function: natsemi_init_txd - * - * Description: initializes the Tx descriptor - * - * Arguments: struct eth_device *dev: NIC data structure - * - * returns: void. - */ - -static void -natsemi_init_txd(struct eth_device *dev) -{ - txd.link = (u32) 0; - txd.cmdsts = (u32) 0; - txd.bufptr = (u32) & txb[0]; - - /* load Transmit Descriptor Register */ - OUTL(dev, (u32) & txd, TxRingPtr); -#ifdef NATSEMI_DEBUG - printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n", - INL(dev, TxRingPtr)); -#endif -} - -/* Function: natsemi_init_rxd - * - * Description: initializes the Rx descriptor ring - * - * Arguments: struct eth_device *dev: NIC data structure - * - * Returns: void. - */ - -static void -natsemi_init_rxd(struct eth_device *dev) -{ - int i; - - cur_rx = 0; - - /* init RX descriptor */ - for (i = 0; i < NUM_RX_DESC; i++) { - rxd[i].link = - cpu_to_le32((i + 1 < - NUM_RX_DESC) ? (u32) & rxd[i + - 1] : (u32) & - rxd[0]); - rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); - rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]); -#ifdef NATSEMI_DEBUG - printf - ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n", - i, &rxd[i], le32_to_cpu(rxd[i].link), - rxd[i].cmdsts, rxd[i].bufptr); -#endif - } - - /* load Receive Descriptor Register */ - OUTL(dev, (u32) & rxd[0], RxRingPtr); - -#ifdef NATSEMI_DEBUG - printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", - INL(dev, RxRingPtr)); -#endif -} - -/* Function: natsemi_set_rx_mode - * - * Description: - * sets the receive mode to accept all broadcast packets and packets - * with our MAC address, and reject all multicast packets. - * - * Arguments: struct eth_device *dev: NIC data structure - * - * Returns: void. - */ - -static void -natsemi_set_rx_mode(struct eth_device *dev) -{ - u32 rx_mode = AcceptBroadcast | AcceptMyPhys; - - OUTL(dev, rx_mode, RxFilterAddr); -} - -static void -natsemi_check_duplex(struct eth_device *dev) -{ - int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0; - -#ifdef NATSEMI_DEBUG - printf("%s: Setting %s-duplex based on negotiated link" - " capability.\n", dev->name, duplex ? "full" : "half"); -#endif - if (duplex) { - rx_config |= RxAcceptTx; - tx_config |= (TxCarrierIgn | TxHeartIgn); - } else { - rx_config &= ~RxAcceptTx; - tx_config &= ~(TxCarrierIgn | TxHeartIgn); - } - OUTL(dev, tx_config, TxConfig); - OUTL(dev, rx_config, RxConfig); -} - -/* Function: natsemi_send - * - * Description: transmits a packet and waits for completion or timeout. - * - * Returns: void. */ -static int -natsemi_send(struct eth_device *dev, volatile void *packet, int length) -{ - u32 i, status = 0; - u32 tx_status = 0; - vu_long *res = (vu_long *)&tx_status; - - /* Stop the transmitter */ - OUTL(dev, TxOff, ChipCmd); - -#ifdef NATSEMI_DEBUG - if (natsemi_debug) - printf("natsemi_send: sending %d bytes\n", (int) length); -#endif - - /* set the transmit buffer descriptor and enable Transmit State Machine */ - txd.link = cpu_to_le32(0); - txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet)); - txd.cmdsts = cpu_to_le32(DescOwn | length); - - /* load Transmit Descriptor Register */ - OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr); -#ifdef NATSEMI_DEBUG - if (natsemi_debug) - printf("natsemi_send: TX descriptor register loaded with: %#08X\n", - INL(dev, TxRingPtr)); -#endif - /* restart the transmitter */ - OUTL(dev, TxOn, ChipCmd); - - for (i = 0; - (*res = le32_to_cpu(txd.cmdsts)) & DescOwn; - i++) { - if (i >= TOUT_LOOP) { - printf - ("%s: tx error buffer not ready: txd.cmdsts == %#X\n", - dev->name, tx_status); - goto Done; - } - } - - if (!(tx_status & DescPktOK)) { - printf("natsemi_send: Transmit error, Tx status %X.\n", - tx_status); - goto Done; - } - - status = 1; - Done: - return status; -} - -/* Function: natsemi_poll - * - * Description: checks for a received packet and returns it if found. - * - * Arguments: struct eth_device *dev: NIC data structure - * - * Returns: 1 if packet was received. - * 0 if no packet was received. - * - * Side effects: - * Returns (copies) the packet to the array dev->packet. - * Returns the length of the packet. - */ - -static int -natsemi_poll(struct eth_device *dev) -{ - int retstat = 0; - int length = 0; - u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); - - if (!(rx_status & (u32) DescOwn)) - return retstat; -#ifdef NATSEMI_DEBUG - if (natsemi_debug) - printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", - cur_rx, rx_status); -#endif - length = (rx_status & DSIZE) - CRC_SIZE; - - if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { - printf - ("natsemi_poll: Corrupted packet received, buffer status = %X\n", - rx_status); - retstat = 0; - } else { /* give packet to higher level routine */ - NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); - retstat = 1; - } - - /* return the descriptor and buffer to receive ring */ - rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); - rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]); - - if (++cur_rx == NUM_RX_DESC) - cur_rx = 0; - - /* re-enable the potentially idle receive state machine */ - OUTL(dev, RxOn, ChipCmd); - - return retstat; -} - -/* Function: natsemi_disable - * - * Description: Turns off interrupts and stops Tx and Rx engines - * - * Arguments: struct eth_device *dev: NIC data structure - * - * Returns: void. - */ - -static void -natsemi_disable(struct eth_device *dev) -{ - /* Disable interrupts using the mask. */ - OUTL(dev, 0, IntrMask); - OUTL(dev, 0, IntrEnable); - - /* Stop the chip's Tx and Rx processes. */ - OUTL(dev, RxOff | TxOff, ChipCmd); - - /* Restore PME enable bit */ - OUTL(dev, SavedClkRun, ClkRun); -} - -#endif diff --git a/drivers/ne2000.c b/drivers/ne2000.c deleted file mode 100644 index c978d62ef3..0000000000 --- a/drivers/ne2000.c +++ /dev/null @@ -1,940 +0,0 @@ -/* -Ported to U-Boot by Christian Pellegrin - -Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and -eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world -are GPL, so this is, of course, GPL. - - -========================================================================== - -dev/if_dp83902a.c - -Ethernet device driver for NS DP83902a ethernet controller - -========================================================================== -####ECOSGPLCOPYRIGHTBEGIN#### -------------------------------------------- -This file is part of eCos, the Embedded Configurable Operating System. -Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. - -eCos is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 or (at your option) any later version. - -eCos is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with eCos; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - -As a special exception, if other files instantiate templates or use macros -or inline functions from this file, or you compile this file and link it -with other works to produce a work based on this file, this file does not -by itself cause the resulting work to be covered by the GNU General Public -License. However the source code for this file must still be made available -in accordance with section (3) of the GNU General Public License. - -This exception does not invalidate any other reasons why a work based on -this file might be covered by the GNU General Public License. - -Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. -at http://sources.redhat.com/ecos/ecos-license/ -------------------------------------------- -####ECOSGPLCOPYRIGHTEND#### -####BSDCOPYRIGHTBEGIN#### - -------------------------------------------- - -Portions of this software may have been derived from OpenBSD or other sources, -and are covered by the appropriate copyright disclaimers included herein. - -------------------------------------------- - -####BSDCOPYRIGHTEND#### -========================================================================== -#####DESCRIPTIONBEGIN#### - -Author(s): gthomas -Contributors: gthomas, jskov, rsandifo -Date: 2001-06-13 -Purpose: -Description: - -FIXME: Will fail if pinged with large packets (1520 bytes) -Add promisc config -Add SNMP - -####DESCRIPTIONEND#### - - -========================================================================== - -*/ - -#include -#include -#include -#include - -#ifdef CONFIG_DRIVER_NE2000 - -/* wor around udelay resetting OCR */ -static void my_udelay(long us) { - long tmo; - - tmo = get_timer (0) + us * CFG_HZ / 1000000; /* will this be much greater than 0 ? */ - while (get_timer (0) < tmo); -} - -#define mdelay(n) my_udelay((n)*1000) - -/* forward definition of function used for the uboot interface */ -void uboot_push_packet_len(int len); -void uboot_push_tx_done(int key, int val); - -/* timeout for tx/rx in s */ -#define TOUT 5 - -#define ETHER_ADDR_LEN 6 - -/* - ------------------------------------------------------------------------ - Debugging details - - Set to perms of: - 0 disables all debug output - 1 for process debug output - 2 for added data IO output: get_reg, put_reg - 4 for packet allocation/free output - 8 for only startup status, so we can tell we're installed OK -*/ -/*#define DEBUG 0xf*/ -#define DEBUG 0 - -#if DEBUG & 1 -#define DEBUG_FUNCTION() do { printf("%s\n", __FUNCTION__); } while (0) -#define DEBUG_LINE() do { printf("%d\n", __LINE__); } while (0) -#else -#define DEBUG_FUNCTION() do {} while(0) -#define DEBUG_LINE() do {} while(0) -#endif - -#include "ne2000.h" - -#if DEBUG & 1 -#define PRINTK(args...) printf(args) -#else -#define PRINTK(args...) -#endif - -static dp83902a_priv_data_t nic; /* just one instance of the card supported */ - -static bool -dp83902a_init(void) -{ - dp83902a_priv_data_t *dp = &nic; - cyg_uint8* base; - int i; - - DEBUG_FUNCTION(); - - base = dp->base; - if (!base) return false; /* No device found */ - - DEBUG_LINE(); - - /* Prepare ESA */ - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); /* Select page 1 */ - /* Use the address from the serial EEPROM */ - for (i = 0; i < 6; i++) - DP_IN(base, DP_P1_PAR0+i, dp->esa[i]); - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); /* Select page 0 */ - - printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", - "eeprom", - dp->esa[0], - dp->esa[1], - dp->esa[2], - dp->esa[3], - dp->esa[4], - dp->esa[5] ); - - return true; -} - -static void -dp83902a_stop(void) -{ - dp83902a_priv_data_t *dp = &nic; - cyg_uint8 *base = dp->base; - - DEBUG_FUNCTION(); - - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ - DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ - DP_OUT(base, DP_IMR, 0x00); /* Disable all interrupts */ - - dp->running = false; -} - -/* - This function is called to "start up" the interface. It may be called - multiple times, even when the hardware is already running. It will be - called whenever something "hardware oriented" changes and should leave - the hardware ready to send/receive packets. -*/ -static void -dp83902a_start(unsigned char * enaddr) -{ - dp83902a_priv_data_t *dp = &nic; - cyg_uint8 *base = dp->base; - int i; - - DEBUG_FUNCTION(); - - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ - DP_OUT(base, DP_DCR, DP_DCR_INIT); - DP_OUT(base, DP_RBCH, 0); /* Remote byte count */ - DP_OUT(base, DP_RBCL, 0); - DP_OUT(base, DP_RCR, DP_RCR_MON); /* Accept no packets */ - DP_OUT(base, DP_TCR, DP_TCR_LOCAL); /* Transmitter [virtually] off */ - DP_OUT(base, DP_TPSR, dp->tx_buf1); /* Transmitter start page */ - dp->tx1 = dp->tx2 = 0; - dp->tx_next = dp->tx_buf1; - dp->tx_started = false; - DP_OUT(base, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */ - DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); /* Receive ring boundary */ - DP_OUT(base, DP_PSTOP, dp->rx_buf_end); /* Receive ring end page */ - dp->rx_next = dp->rx_buf_start-1; - DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ - DP_OUT(base, DP_IMR, DP_IMR_All); /* Enable all interrupts */ - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); /* Select page 1 */ - DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); /* Current page - next free page for Rx */ - for (i = 0; i < ETHER_ADDR_LEN; i++) { - DP_OUT(base, DP_P1_PAR0+i, enaddr[i]); - } - /* Enable and start device */ - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); - DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */ - DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */ - dp->running = true; -} - -/* - This routine is called to start the transmitter. It is split out from the - data handling routine so it may be called either when data becomes first - available or when an Tx interrupt occurs -*/ - -static void -dp83902a_start_xmit(int start_page, int len) -{ - dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic; - cyg_uint8 *base = dp->base; - - DEBUG_FUNCTION(); - -#if DEBUG & 1 - printf("Tx pkt %d len %d\n", start_page, len); - if (dp->tx_started) - printf("TX already started?!?\n"); -#endif - - DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE)); - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); - DP_OUT(base, DP_TBCL, len & 0xFF); - DP_OUT(base, DP_TBCH, len >> 8); - DP_OUT(base, DP_TPSR, start_page); - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); - - dp->tx_started = true; -} - -/* - This routine is called to send data to the hardware. It is known a-priori - that there is free buffer space (dp->tx_next). -*/ -static void -dp83902a_send(unsigned char *data, int total_len, unsigned long key) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - int len, start_page, pkt_len, i, isr; -#if DEBUG & 4 - int dx; -#endif - - DEBUG_FUNCTION(); - - len = pkt_len = total_len; - if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; - - start_page = dp->tx_next; - if (dp->tx_next == dp->tx_buf1) { - dp->tx1 = start_page; - dp->tx1_len = pkt_len; - dp->tx1_key = key; - dp->tx_next = dp->tx_buf2; - } else { - dp->tx2 = start_page; - dp->tx2_len = pkt_len; - dp->tx2_key = key; - dp->tx_next = dp->tx_buf1; - } - -#if DEBUG & 5 - printf("TX prep page %d len %d\n", start_page, pkt_len); -#endif - - DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ - { - /* Dummy read. The manual sez something slightly different, */ - /* but the code is extended a bit to do what Hitachi's monitor */ - /* does (i.e., also read data). */ - - cyg_uint16 tmp; - int len = 1; - - DP_OUT(base, DP_RSAL, 0x100-len); - DP_OUT(base, DP_RSAH, (start_page-1) & 0xff); - DP_OUT(base, DP_RBCL, len); - DP_OUT(base, DP_RBCH, 0); - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); - DP_IN_DATA(dp->data, tmp); - } - -#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA - /* Stall for a bit before continuing to work around random data */ - /* corruption problems on some platforms. */ - CYGACC_CALL_IF_DELAY_US(1); -#endif - - /* Send data to device buffer(s) */ - DP_OUT(base, DP_RSAL, 0); - DP_OUT(base, DP_RSAH, start_page); - DP_OUT(base, DP_RBCL, pkt_len & 0xFF); - DP_OUT(base, DP_RBCH, pkt_len >> 8); - DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START); - - /* Put data into buffer */ -#if DEBUG & 4 - printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len); - dx = 0; -#endif - while (len > 0) { -#if DEBUG & 4 - printf(" %02x", *data); - if (0 == (++dx % 16)) printf("\n "); -#endif - DP_OUT_DATA(dp->data, *data++); - len--; - } -#if DEBUG & 4 - printf("\n"); -#endif - if (total_len < pkt_len) { -#if DEBUG & 4 - printf(" + %d bytes of padding\n", pkt_len - total_len); -#endif - /* Padding to 802.3 length was required */ - for (i = total_len; i < pkt_len;) { - i++; - DP_OUT_DATA(dp->data, 0); - } - } - -#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA - /* After last data write, delay for a bit before accessing the */ - /* device again, or we may get random data corruption in the last */ - /* datum (on some platforms). */ - CYGACC_CALL_IF_DELAY_US(1); -#endif - - /* Wait for DMA to complete */ - do { - DP_IN(base, DP_ISR, isr); - } while ((isr & DP_ISR_RDC) == 0); - /* Then disable DMA */ - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); - - /* Start transmit if not already going */ - if (!dp->tx_started) { - if (start_page == dp->tx1) { - dp->tx_int = 1; /* Expecting interrupt from BUF1 */ - } else { - dp->tx_int = 2; /* Expecting interrupt from BUF2 */ - } - dp83902a_start_xmit(start_page, pkt_len); - } -} - -/* - This function is called when a packet has been received. It's job is - to prepare to unload the packet from the hardware. Once the length of - the packet is known, the upper layer of the driver can be told. When - the upper layer is ready to unload the packet, the internal function - 'dp83902a_recv' will be called to actually fetch it from the hardware. -*/ -static void -dp83902a_RxEvent(void) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - unsigned char rsr; - unsigned char rcv_hdr[4]; - int i, len, pkt, cur; - - DEBUG_FUNCTION(); - - DP_IN(base, DP_RSR, rsr); - while (true) { - /* Read incoming packet header */ - DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START); - DP_IN(base, DP_P1_CURP, cur); - DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); - DP_IN(base, DP_BNDRY, pkt); - - pkt += 1; - if (pkt == dp->rx_buf_end) - pkt = dp->rx_buf_start; - - if (pkt == cur) { - break; - } - DP_OUT(base, DP_RBCL, sizeof(rcv_hdr)); - DP_OUT(base, DP_RBCH, 0); - DP_OUT(base, DP_RSAL, 0); - DP_OUT(base, DP_RSAH, pkt); - if (dp->rx_next == pkt) { - if (cur == dp->rx_buf_start) - DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); - else - DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */ - return; - } - dp->rx_next = pkt; - DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ - DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); -#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA - CYGACC_CALL_IF_DELAY_US(10); -#endif - - for (i = 0; i < sizeof(rcv_hdr);) { - DP_IN_DATA(dp->data, rcv_hdr[i++]); - } - -#if DEBUG & 5 - printf("rx hdr %02x %02x %02x %02x\n", - rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]); -#endif - len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr); - uboot_push_packet_len(len); - if (rcv_hdr[1] == dp->rx_buf_start) - DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); - else - DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); /* Update pointer */ - } -} - -/* - This function is called as a result of the "eth_drv_recv()" call above. - It's job is to actually fetch data for a packet from the hardware once - memory buffers have been allocated for the packet. Note that the buffers - may come in pieces, using a scatter-gather list. This allows for more - efficient processing in the upper layers of the stack. -*/ -static void -dp83902a_recv(unsigned char *data, int len) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - int i, mlen; - cyg_uint8 saved_char = 0; - bool saved; -#if DEBUG & 4 - int dx; -#endif - - DEBUG_FUNCTION(); - -#if DEBUG & 5 - printf("Rx packet %d length %d\n", dp->rx_next, len); -#endif - - /* Read incoming packet data */ - DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); - DP_OUT(base, DP_RBCL, len & 0xFF); - DP_OUT(base, DP_RBCH, len >> 8); - DP_OUT(base, DP_RSAL, 4); /* Past header */ - DP_OUT(base, DP_RSAH, dp->rx_next); - DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ - DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); -#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA - CYGACC_CALL_IF_DELAY_US(10); -#endif - - saved = false; - for (i = 0; i < 1; i++) { - if (data) { - mlen = len; -#if DEBUG & 4 - printf(" sg buf %08lx len %08x \n", (unsigned long) data, mlen); - dx = 0; -#endif - while (0 < mlen) { - /* Saved byte from previous loop? */ - if (saved) { - *data++ = saved_char; - mlen--; - saved = false; - continue; - } - - { - cyg_uint8 tmp; - DP_IN_DATA(dp->data, tmp); -#if DEBUG & 4 - printf(" %02x", tmp); - if (0 == (++dx % 16)) printf("\n "); -#endif - *data++ = tmp;; - mlen--; - } - } -#if DEBUG & 4 - printf("\n"); -#endif - } - } -} - -static void -dp83902a_TxEvent(void) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - unsigned char tsr; - unsigned long key; - - DEBUG_FUNCTION(); - - DP_IN(base, DP_TSR, tsr); - if (dp->tx_int == 1) { - key = dp->tx1_key; - dp->tx1 = 0; - } else { - key = dp->tx2_key; - dp->tx2 = 0; - } - /* Start next packet if one is ready */ - dp->tx_started = false; - if (dp->tx1) { - dp83902a_start_xmit(dp->tx1, dp->tx1_len); - dp->tx_int = 1; - } else if (dp->tx2) { - dp83902a_start_xmit(dp->tx2, dp->tx2_len); - dp->tx_int = 2; - } else { - dp->tx_int = 0; - } - /* Tell higher level we sent this packet */ - uboot_push_tx_done(key, 0); -} - -/* Read the tally counters to clear them. Called in response to a CNT */ -/* interrupt. */ -static void -dp83902a_ClearCounters(void) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - cyg_uint8 cnt1, cnt2, cnt3; - - DP_IN(base, DP_FER, cnt1); - DP_IN(base, DP_CER, cnt2); - DP_IN(base, DP_MISSED, cnt3); - DP_OUT(base, DP_ISR, DP_ISR_CNT); -} - -/* Deal with an overflow condition. This code follows the procedure set */ -/* out in section 7.0 of the datasheet. */ -static void -dp83902a_Overflow(void) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic; - cyg_uint8 *base = dp->base; - cyg_uint8 isr; - - /* Issue a stop command and wait 1.6ms for it to complete. */ - DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA); - CYGACC_CALL_IF_DELAY_US(1600); - - /* Clear the remote byte counter registers. */ - DP_OUT(base, DP_RBCL, 0); - DP_OUT(base, DP_RBCH, 0); - - /* Enter loopback mode while we clear the buffer. */ - DP_OUT(base, DP_TCR, DP_TCR_LOCAL); - DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA); - - /* Read in as many packets as we can and acknowledge any and receive */ - /* interrupts. Since the buffer has overflowed, a receive event of */ - /* some kind will have occured. */ - dp83902a_RxEvent(); - DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE); - - /* Clear the overflow condition and leave loopback mode. */ - DP_OUT(base, DP_ISR, DP_ISR_OFLW); - DP_OUT(base, DP_TCR, DP_TCR_NORMAL); - - /* If a transmit command was issued, but no transmit event has occured, */ - /* restart it here. */ - DP_IN(base, DP_ISR, isr); - if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) { - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); - } -} - -static void -dp83902a_poll(void) -{ - struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; - cyg_uint8 *base = dp->base; - unsigned char isr; - - DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START); - DP_IN(base, DP_ISR, isr); - while (0 != isr) { - /* The CNT interrupt triggers when the MSB of one of the error */ - /* counters is set. We don't much care about these counters, but */ - /* we should read their values to reset them. */ - if (isr & DP_ISR_CNT) { - dp83902a_ClearCounters(); - } - /* Check for overflow. It's a special case, since there's a */ - /* particular procedure that must be followed to get back into */ - /* a running state.a */ - if (isr & DP_ISR_OFLW) { - dp83902a_Overflow(); - } else { - /* Other kinds of interrupts can be acknowledged simply by */ - /* clearing the relevant bits of the ISR. Do that now, then */ - /* handle the interrupts we care about. */ - DP_OUT(base, DP_ISR, isr); /* Clear set bits */ - if (!dp->running) break; /* Is this necessary? */ - /* Check for tx_started on TX event since these may happen */ - /* spuriously it seems. */ - if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) { - dp83902a_TxEvent(); - } - if (isr & (DP_ISR_RxP|DP_ISR_RxE)) { - dp83902a_RxEvent(); - } - } - DP_IN(base, DP_ISR, isr); - } -} - -/* find prom (taken from pc_net_cs.c from Linux) */ - -#include "8390.h" - -typedef struct hw_info_t { - u_int offset; - u_char a0, a1, a2; - u_int flags; -} hw_info_t; - -#define DELAY_OUTPUT 0x01 -#define HAS_MISC_REG 0x02 -#define USE_BIG_BUF 0x04 -#define HAS_IBM_MISC 0x08 -#define IS_DL10019 0x10 -#define IS_DL10022 0x20 -#define HAS_MII 0x40 -#define USE_SHMEM 0x80 /* autodetected */ - -#define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */ -#define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */ -#define MII_PHYID_REV_MASK 0xfffffff0 -#define MII_PHYID_REG1 0x02 -#define MII_PHYID_REG2 0x03 - -static hw_info_t hw_info[] = { - { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, - { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, - { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, - { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, - DELAY_OUTPUT | HAS_IBM_MISC }, - { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, - { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, - { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, - { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, - { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, - { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, - { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, - { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, - { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, - { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, - { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, - { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, - { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, - { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, - { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, - HAS_MISC_REG | HAS_IBM_MISC }, - { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, - { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, - { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, - { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, - DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, - { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, - { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, - { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, - { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, - { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }, - { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 } -}; - -#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) - -static hw_info_t default_info = { 0, 0, 0, 0, 0 }; - -unsigned char dev_addr[6]; - -#define PCNET_CMD 0x00 -#define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ -#define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ -#define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */ - -unsigned long nic_base; - -static void pcnet_reset_8390(void) -{ - int i, r; - - PRINTK("nic base is %lx\n", nic_base); - - n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); - PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); - n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD); - PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); - n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); - PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); - n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); - - n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET); - - for (i = 0; i < 100; i++) { - if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0) - break; - PRINTK("got %x in reset\n", r); - my_udelay(100); - } - n2k_outb(ENISR_RESET, EN0_ISR); /* Ack intr. */ - - if (i == 100) - printf("pcnet_reset_8390() did not complete.\n"); -} /* pcnet_reset_8390 */ - -static hw_info_t * get_prom(void ) { - unsigned char prom[32]; - int i, j; - struct { - u_char value, offset; - } program_seq[] = { - {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ - {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ - {0x00, EN0_RCNTLO}, /* Clear the count regs. */ - {0x00, EN0_RCNTHI}, - {0x00, EN0_IMR}, /* Mask completion irq. */ - {0xFF, EN0_ISR}, - {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ - {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ - {32, EN0_RCNTLO}, - {0x00, EN0_RCNTHI}, - {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ - {0x00, EN0_RSARHI}, - {E8390_RREAD+E8390_START, E8390_CMD}, - }; - - PRINTK("trying to get MAC via prom reading\n"); - - pcnet_reset_8390(); - - mdelay(10); - - for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) - n2k_outb(program_seq[i].value, program_seq[i].offset); - - PRINTK("PROM:"); - for (i = 0; i < 32; i++) { - prom[i] = n2k_inb(PCNET_DATAPORT); - PRINTK(" %02x", prom[i]); - } - PRINTK("\n"); - for (i = 0; i < NR_INFO; i++) { - if ((prom[0] == hw_info[i].a0) && - (prom[2] == hw_info[i].a1) && - (prom[4] == hw_info[i].a2)) { - PRINTK("matched board %d\n", i); - break; - } - } - if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) { - for (j = 0; j < 6; j++) - dev_addr[j] = prom[j<<1]; - PRINTK("on exit i is %d/%ld\n", i, NR_INFO); - PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n", - dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]); - return (i < NR_INFO) ? hw_info+i : &default_info; - } - return NULL; -} - -/* U-boot specific routines */ - - -static unsigned char *pbuf = NULL; - -static int pkey = -1; -static int initialized=0; - -void uboot_push_packet_len(int len) { - PRINTK("pushed len = %d\n", len); - if (len>=2000) { - printf("NE2000: packet too big\n"); - return; - } - dp83902a_recv(&pbuf[0], len); - - /*Just pass it to the upper layer*/ - NetReceive(&pbuf[0], len); -} - -void uboot_push_tx_done(int key, int val) { - PRINTK("pushed key = %d\n", key); - pkey = key; -} - -int eth_init(bd_t *bd) { - static hw_info_t * r; - char ethaddr[20]; - - PRINTK("### eth_init\n"); - - if (!pbuf) { - pbuf = malloc(2000); - if (!pbuf) { - printf("Cannot allocate rx buffer\n"); - return -1; - } - } - -#ifdef CONFIG_DRIVER_NE2000_CCR - { - volatile unsigned char *p = (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR; - - PRINTK("CCR before is %x\n", *p); - *p = CONFIG_DRIVER_NE2000_VAL; - PRINTK("CCR after is %x\n", *p); - } -#endif - - nic_base = CONFIG_DRIVER_NE2000_BASE; - nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE; - - r = get_prom(); - if (!r) - return -1; - - sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", - dev_addr[0], dev_addr[1], - dev_addr[2], dev_addr[3], - dev_addr[4], dev_addr[5]) ; - PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr); - setenv ("ethaddr", ethaddr); - - -#define DP_DATA 0x10 - nic.data = nic.base + DP_DATA; - nic.tx_buf1 = 0x40; - nic.tx_buf2 = 0x48; - nic.rx_buf_start = 0x50; - nic.rx_buf_end = 0x80; - - if (dp83902a_init() == false) - return -1; - dp83902a_start(dev_addr); - initialized=1; - return 0; -} - -void eth_halt() { - - PRINTK("### eth_halt\n"); - if(initialized) - dp83902a_stop(); - initialized=0; -} - -int eth_rx() { -dp83902a_poll(); -return 1; -} - -int eth_send(volatile void *packet, int length) { - int tmo; - - PRINTK("### eth_send\n"); - - pkey = -1; - - dp83902a_send((unsigned char *) packet, length, 666); - tmo = get_timer (0) + TOUT * CFG_HZ; - while(1) { - dp83902a_poll(); - if (pkey != -1) { - PRINTK("Packet sucesfully sent\n"); - return 0; - } - if (get_timer (0) >= tmo) { - printf("transmission error (timoeut)\n"); - return 0; - } - - } - return 0; -} -#endif diff --git a/drivers/ne2000.h b/drivers/ne2000.h deleted file mode 100644 index c13d9f0bbb..0000000000 --- a/drivers/ne2000.h +++ /dev/null @@ -1,279 +0,0 @@ -/* -Ported to U-Boot by Christian Pellegrin - -Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and -eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world -are GPL, so this is, of course, GPL. - - -========================================================================== - - dev/dp83902a.h - - National Semiconductor DP83902a ethernet chip - -========================================================================== -####ECOSGPLCOPYRIGHTBEGIN#### - ------------------------------------------- - This file is part of eCos, the Embedded Configurable Operating System. - Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. - - eCos is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 or (at your option) any later version. - - eCos is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with eCos; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - As a special exception, if other files instantiate templates or use macros - or inline functions from this file, or you compile this file and link it - with other works to produce a work based on this file, this file does not - by itself cause the resulting work to be covered by the GNU General Public - License. However the source code for this file must still be made available - in accordance with section (3) of the GNU General Public License. - - This exception does not invalidate any other reasons why a work based on - this file might be covered by the GNU General Public License. - - Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. - at http://sources.redhat.com/ecos/ecos-license/ - ------------------------------------------- -####ECOSGPLCOPYRIGHTEND#### -####BSDCOPYRIGHTBEGIN#### - - ------------------------------------------- - - Portions of this software may have been derived from OpenBSD or other sources, - and are covered by the appropriate copyright disclaimers included herein. - - ------------------------------------------- - -####BSDCOPYRIGHTEND#### -========================================================================== -#####DESCRIPTIONBEGIN#### - - Author(s): gthomas - Contributors: gthomas, jskov - Date: 2001-06-13 - Purpose: - Description: - -####DESCRIPTIONEND#### - -========================================================================== - -*/ - -/* - ------------------------------------------------------------------------ - Macros for accessing DP registers - These can be overridden by the platform header -*/ - -#define DP_IN(_b_, _o_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_))) -#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = (_d_) - -#define DP_IN_DATA(_b_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_))) -#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned char *) ((_b_))) = (_d_) - - -/* here is all the data */ - -#define cyg_uint8 unsigned char -#define cyg_uint16 unsigned short -#define bool int - -#define false 0 -#define true 1 - -#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1 -#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X) - -typedef struct dp83902a_priv_data { - cyg_uint8* base; - cyg_uint8* data; - cyg_uint8* reset; - int tx_next; /* First free Tx page */ - int tx_int; /* Expecting interrupt from this buffer */ - int rx_next; /* First free Rx page */ - int tx1, tx2; /* Page numbers for Tx buffers */ - unsigned long tx1_key, tx2_key; /* Used to ack when packet sent */ - int tx1_len, tx2_len; - bool tx_started, running, hardwired_esa; - cyg_uint8 esa[6]; - void* plf_priv; - - /* Buffer allocation */ - int tx_buf1, tx_buf2; - int rx_buf_start, rx_buf_end; -} dp83902a_priv_data_t; - -/* - ------------------------------------------------------------------------ - Some forward declarations -*/ -static void dp83902a_poll(void); - -/* ------------------------------------------------------------------------ */ -/* Register offsets */ - -#define DP_CR 0x00 -#define DP_CLDA0 0x01 -#define DP_PSTART 0x01 /* write */ -#define DP_CLDA1 0x02 -#define DP_PSTOP 0x02 /* write */ -#define DP_BNDRY 0x03 -#define DP_TSR 0x04 -#define DP_TPSR 0x04 /* write */ -#define DP_NCR 0x05 -#define DP_TBCL 0x05 /* write */ -#define DP_FIFO 0x06 -#define DP_TBCH 0x06 /* write */ -#define DP_ISR 0x07 -#define DP_CRDA0 0x08 -#define DP_RSAL 0x08 /* write */ -#define DP_CRDA1 0x09 -#define DP_RSAH 0x09 /* write */ -#define DP_RBCL 0x0a /* write */ -#define DP_RBCH 0x0b /* write */ -#define DP_RSR 0x0c -#define DP_RCR 0x0c /* write */ -#define DP_FER 0x0d -#define DP_TCR 0x0d /* write */ -#define DP_CER 0x0e -#define DP_DCR 0x0e /* write */ -#define DP_MISSED 0x0f -#define DP_IMR 0x0f /* write */ -#define DP_DATAPORT 0x10 /* "eprom" data port */ - -#define DP_P1_CR 0x00 -#define DP_P1_PAR0 0x01 -#define DP_P1_PAR1 0x02 -#define DP_P1_PAR2 0x03 -#define DP_P1_PAR3 0x04 -#define DP_P1_PAR4 0x05 -#define DP_P1_PAR5 0x06 -#define DP_P1_CURP 0x07 -#define DP_P1_MAR0 0x08 -#define DP_P1_MAR1 0x09 -#define DP_P1_MAR2 0x0a -#define DP_P1_MAR3 0x0b -#define DP_P1_MAR4 0x0c -#define DP_P1_MAR5 0x0d -#define DP_P1_MAR6 0x0e -#define DP_P1_MAR7 0x0f - -#define DP_P2_CR 0x00 -#define DP_P2_PSTART 0x01 -#define DP_P2_CLDA0 0x01 /* write */ -#define DP_P2_PSTOP 0x02 -#define DP_P2_CLDA1 0x02 /* write */ -#define DP_P2_RNPP 0x03 -#define DP_P2_TPSR 0x04 -#define DP_P2_LNPP 0x05 -#define DP_P2_ACH 0x06 -#define DP_P2_ACL 0x07 -#define DP_P2_RCR 0x0c -#define DP_P2_TCR 0x0d -#define DP_P2_DCR 0x0e -#define DP_P2_IMR 0x0f - -/* Command register - common to all pages */ - -#define DP_CR_STOP 0x01 /* Stop: software reset */ -#define DP_CR_START 0x02 /* Start: initialize device */ -#define DP_CR_TXPKT 0x04 /* Transmit packet */ -#define DP_CR_RDMA 0x08 /* Read DMA (recv data from device) */ -#define DP_CR_WDMA 0x10 /* Write DMA (send data to device) */ -#define DP_CR_SEND 0x18 /* Send packet */ -#define DP_CR_NODMA 0x20 /* Remote (or no) DMA */ -#define DP_CR_PAGE0 0x00 /* Page select */ -#define DP_CR_PAGE1 0x40 -#define DP_CR_PAGE2 0x80 -#define DP_CR_PAGEMSK 0x3F /* Used to mask out page bits */ - -/* Data configuration register */ - -#define DP_DCR_WTS 0x01 /* 1=16 bit word transfers */ -#define DP_DCR_BOS 0x02 /* 1=Little Endian */ -#define DP_DCR_LAS 0x04 /* 1=Single 32 bit DMA mode */ -#define DP_DCR_LS 0x08 /* 1=normal mode, 0=loopback */ -#define DP_DCR_ARM 0x10 /* 0=no send command (program I/O) */ -#define DP_DCR_FIFO_1 0x00 /* FIFO threshold */ -#define DP_DCR_FIFO_2 0x20 -#define DP_DCR_FIFO_4 0x40 -#define DP_DCR_FIFO_6 0x60 - -#define DP_DCR_INIT (DP_DCR_LS|DP_DCR_FIFO_4) - -/* Interrupt status register */ - -#define DP_ISR_RxP 0x01 /* Packet received */ -#define DP_ISR_TxP 0x02 /* Packet transmitted */ -#define DP_ISR_RxE 0x04 /* Receive error */ -#define DP_ISR_TxE 0x08 /* Transmit error */ -#define DP_ISR_OFLW 0x10 /* Receive overflow */ -#define DP_ISR_CNT 0x20 /* Tally counters need emptying */ -#define DP_ISR_RDC 0x40 /* Remote DMA complete */ -#define DP_ISR_RESET 0x80 /* Device has reset (shutdown, error) */ - -/* Interrupt mask register */ - -#define DP_IMR_RxP 0x01 /* Packet received */ -#define DP_IMR_TxP 0x02 /* Packet transmitted */ -#define DP_IMR_RxE 0x04 /* Receive error */ -#define DP_IMR_TxE 0x08 /* Transmit error */ -#define DP_IMR_OFLW 0x10 /* Receive overflow */ -#define DP_IMR_CNT 0x20 /* Tall counters need emptying */ -#define DP_IMR_RDC 0x40 /* Remote DMA complete */ - -#define DP_IMR_All 0x3F /* Everything but remote DMA */ - -/* Receiver control register */ - -#define DP_RCR_SEP 0x01 /* Save bad(error) packets */ -#define DP_RCR_AR 0x02 /* Accept runt packets */ -#define DP_RCR_AB 0x04 /* Accept broadcast packets */ -#define DP_RCR_AM 0x08 /* Accept multicast packets */ -#define DP_RCR_PROM 0x10 /* Promiscuous mode */ -#define DP_RCR_MON 0x20 /* Monitor mode - 1=accept no packets */ - -/* Receiver status register */ - -#define DP_RSR_RxP 0x01 /* Packet received */ -#define DP_RSR_CRC 0x02 /* CRC error */ -#define DP_RSR_FRAME 0x04 /* Framing error */ -#define DP_RSR_FO 0x08 /* FIFO overrun */ -#define DP_RSR_MISS 0x10 /* Missed packet */ -#define DP_RSR_PHY 0x20 /* 0=pad match, 1=mad match */ -#define DP_RSR_DIS 0x40 /* Receiver disabled */ -#define DP_RSR_DFR 0x80 /* Receiver processing deferred */ - -/* Transmitter control register */ - -#define DP_TCR_NOCRC 0x01 /* 1=inhibit CRC */ -#define DP_TCR_NORMAL 0x00 /* Normal transmitter operation */ -#define DP_TCR_LOCAL 0x02 /* Internal NIC loopback */ -#define DP_TCR_INLOOP 0x04 /* Full internal loopback */ -#define DP_TCR_OUTLOOP 0x08 /* External loopback */ -#define DP_TCR_ATD 0x10 /* Auto transmit disable */ -#define DP_TCR_OFFSET 0x20 /* Collision offset adjust */ - -/* Transmit status register */ - -#define DP_TSR_TxP 0x01 /* Packet transmitted */ -#define DP_TSR_COL 0x04 /* Collision (at least one) */ -#define DP_TSR_ABT 0x08 /* Aborted because of too many collisions */ -#define DP_TSR_CRS 0x10 /* Lost carrier */ -#define DP_TSR_FU 0x20 /* FIFO underrun */ -#define DP_TSR_CDH 0x40 /* Collision Detect Heartbeat */ -#define DP_TSR_OWC 0x80 /* Collision outside normal window */ - -#define IEEE_8023_MAX_FRAME 1518 /* Largest possible ethernet frame */ -#define IEEE_8023_MIN_FRAME 64 /* Smallest possible ethernet frame */ diff --git a/drivers/net/3c589.c b/drivers/net/3c589.c new file mode 100644 index 0000000000..080b686e21 --- /dev/null +++ b/drivers/net/3c589.c @@ -0,0 +1,519 @@ +/*------------------------------------------------------------------------ + . 3c589.c + . This is a driver for 3Com's 3C589 (Etherlink III) PCMCIA Ethernet device. + . + . (C) Copyright 2002 + . Sysgo Real-Time Solutions, GmbH + . Rolf Offermanns + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + ----------------------------------------------------------------------------*/ + +#include +#include +#include + +#ifdef CONFIG_DRIVER_3C589 + +#include "3c589.h" + + +/* Use power-down feature of the chip */ +#define POWER_DOWN 0 + +#define NO_AUTOPROBE + +static const char version[] = + "Your ad here! :P\n"; + + +#undef EL_DEBUG + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long int dword; +/*------------------------------------------------------------------------ + . + . Configuration options, for the experienced user to change. + . + -------------------------------------------------------------------------*/ + +/* + . Wait time for memory to be free. This probably shouldn't be + . tuned that much, as waiting for this means nothing else happens + . in the system +*/ +#define MEMORY_WAIT_TIME 16 + + +#if (EL_DEBUG > 2 ) +#define PRINTK3(args...) printf(args) +#else +#define PRINTK3(args...) +#endif + +#if EL_DEBUG > 1 +#define PRINTK2(args...) printf(args) +#else +#define PRINTK2(args...) +#endif + +#ifdef EL_DEBUG +#define PRINTK(args...) printf(args) +#else +#define PRINTK(args...) +#endif + +#define outb(args...) mmio_outb(args) +#define mmio_outb(value, addr) (*((volatile byte *)(addr)) = value) + +#define inb(args...) mmio_inb(args) +#define mmio_inb(addr) (*((volatile byte *)(addr))) + +#define outw(args...) mmio_outw(args) +#define mmio_outw(value, addr) (*((volatile word *)(addr)) = value) + +#define inw(args...) mmio_inw(args) +#define mmio_inw(addr) (*((volatile word *)(addr))) + +#define outsw(args...) mmio_outsw(args) +#define mmio_outsw(r,b,l) ({ int __i; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + mmio_outw( *(__b2 + __i), r); \ + } \ + }) + +#define insw(args...) mmio_insw(args) +#define mmio_insw(r,b,l) ({ int __i ; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = mmio_inw(r); \ + mmio_inw(0); \ + }; \ + }) + +/*------------------------------------------------------------------------ + . + . The internal workings of the driver. If you are changing anything + . here with the 3Com stuff, you should have the datasheet and know + . what you are doing. + . + -------------------------------------------------------------------------*/ +#define EL_BASE_ADDR 0x20000000 + + +/* Offsets from base I/O address. */ +#define EL3_DATA 0x00 +#define EL3_TIMER 0x0a +#define EL3_CMD 0x0e +#define EL3_STATUS 0x0e + +#define EEPROM_READ 0x0080 + +#define EL3WINDOW(win_num) mmio_outw(SelectWindow + (win_num), EL_BASE_ADDR + EL3_CMD) + +/* The top five bits written to EL3_CMD are a command, the lower + 11 bits are the parameter, if applicable. */ +enum c509cmd { + TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, + RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, + TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, + FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, + SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, + SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, + StatsDisable = 22<<11, StopCoax = 23<<11, +}; + +enum c509status { + IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, + TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, + IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 +}; + +/* The SetRxFilter command accepts the following classes: */ +enum RxFilter { + RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 +}; + +/* Register window 1 offsets, the window used in normal operation. */ +#define TX_FIFO 0x00 +#define RX_FIFO 0x00 +#define RX_STATUS 0x08 +#define TX_STATUS 0x0B +#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */ + + +/* + Read a word from the EEPROM using the regular EEPROM access register. + Assume that we are in register window zero. +*/ +static word read_eeprom(dword ioaddr, int index) +{ + int i; + outw(EEPROM_READ + index, ioaddr + 0xa); + /* Reading the eeprom takes 162 us */ + for (i = 1620; i >= 0; i--) + if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) + break; + return inw(ioaddr + 0xc); +} + +static void el_get_mac_addr( unsigned char *mac_addr ) +{ + int i; + union + { + word w; + unsigned char b[2]; + } wrd; + unsigned char old_window = inw( EL_BASE_ADDR + EL3_STATUS ) >> 13; + GO_WINDOW(0); + VX_BUSY_WAIT; + for (i = 0; i < 3; i++) + { + wrd.w = read_eeprom(EL_BASE_ADDR, 0xa+i); +#ifdef __BIG_ENDIAN + mac_addr[2*i] = wrd.b[0]; + mac_addr[2*i+1] = wrd.b[1]; +#else + mac_addr[2*i] = wrd.b[1]; + mac_addr[2*i+1] = wrd.b[0]; +#endif + } + GO_WINDOW(old_window); + VX_BUSY_WAIT; +} + + +#if EL_DEBUG > 1 +static void print_packet( byte * buf, int length ) +{ + int i; + int remainder; + int lines; + + PRINTK2("Packet of length %d \n", length ); + + lines = length / 16; + remainder = length % 16; + + for ( i = 0; i < lines ; i ++ ) { + int cur; + + for ( cur = 0; cur < 8; cur ++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + PRINTK2("%02x%02x ", a, b ); + } + PRINTK2("\n"); + } + for ( i = 0; i < remainder/2 ; i++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + PRINTK2("%02x%02x ", a, b ); + } + PRINTK2("\n"); +} +#endif /* EL_DEBUG > 1 */ + + +/************************************************************************** +ETH_RESET - Reset adapter +***************************************************************************/ +static void el_reset(bd_t *bd) +{ + /*********************************************************** + Reset 3Com 595 card + *************************************************************/ + /* QUICK HACK + * - adjust timing for 3c589 + * - enable io for PCMCIA */ + outw(0x0004, 0xa0000018); + udelay(100); + outw(0x0041, 0x28010000); + udelay(100); + + /* issue global reset */ + outw(GLOBAL_RESET, BASE + VX_COMMAND); + + /* must wait for at least 1ms */ + udelay(100000000); + + /* set mac addr */ + { + unsigned char *mac_addr = bd->bi_enetaddr; + int i; + + el_get_mac_addr( mac_addr ); + + GO_WINDOW(2); + VX_BUSY_WAIT; + + printf("3C589 MAC Addr.: "); + for (i = 0; i < 6; i++) + { + printf("%02x", mac_addr[i]); + outb(mac_addr[i], BASE + VX_W2_ADDR_0 + i); + VX_BUSY_WAIT; + } + printf("\n\n"); + } + + /* set RX filter */ + outw(SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST, BASE + VX_COMMAND); + VX_BUSY_WAIT; + + + /* set irq mask and read_zero */ + outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | + S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); + VX_BUSY_WAIT; + + outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | + S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); + VX_BUSY_WAIT; + + /* enable TP Linkbeat */ + GO_WINDOW(4); + VX_BUSY_WAIT; + + outw( ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE); + VX_BUSY_WAIT; + + +/* + * Attempt to get rid of any stray interrupts that occured during + * configuration. On the i386 this isn't possible because one may + * already be queued. However, a single stray interrupt is + * unimportant. + */ + + outw(ACK_INTR | 0xff, BASE + VX_COMMAND); + VX_BUSY_WAIT; + + /* enable TX and RX */ + outw( RX_ENABLE, BASE + VX_COMMAND ); + VX_BUSY_WAIT; + + outw( TX_ENABLE, BASE + VX_COMMAND ); + VX_BUSY_WAIT; + + + /* print the diag. regs. */ + PRINTK2("Diag. Regs\n"); + PRINTK2("--> MEDIA_TYPE: %04x\n", inw(BASE + VX_W4_MEDIA_TYPE)); + PRINTK2("--> NET_DIAG: %04x\n", inw(BASE + VX_W4_NET_DIAG)); + PRINTK2("--> FIFO_DIAG: %04x\n", inw(BASE + VX_W4_FIFO_DIAG)); + PRINTK2("--> CTRLR_STATUS: %04x\n", inw(BASE + VX_W4_CTRLR_STATUS)); + PRINTK2("\n\n"); + + /* enter working mode */ + GO_WINDOW(1); + VX_BUSY_WAIT; + + /* wait for another 1ms */ + udelay(100000000); +} + + +/*----------------------------------------------------------------- + . + . The driver can be entered at any of the following entry points. + . + .------------------------------------------------------------------ */ + +extern int eth_init(bd_t *bd); +extern void eth_halt(void); +extern int eth_rx(void); +extern int eth_send(volatile void *packet, int length); + + +/* + ------------------------------------------------------------ + . + . Internal routines + . + ------------------------------------------------------------ +*/ + +int eth_init(bd_t *bd) +{ + el_reset(bd); + return 0; +} + +void eth_halt() { + return; +} + +#define EDEBUG 1 + + +/************************************************************************** +ETH_POLL - Wait for a frame +***************************************************************************/ + +int eth_rx() +{ + word status, rx_status, packet_size; + + VX_BUSY_WAIT; + + status = inw( BASE + VX_STATUS ); + + if ( (status & S_RX_COMPLETE) == 0 ) return 0; /* nothing to do */ + + /* Packet waiting -> check RX_STATUS */ + rx_status = inw( BASE + VX_W1_RX_STATUS ); + + if ( rx_status & ERR_RX ) + { + /* error in packet -> discard */ + PRINTK("[ERROR] Invalid packet -> discarding\n"); + PRINTK("-- error code 0x%02x\n", rx_status & ERR_MASK); + PRINTK("-- rx bytes 0x%04d\n", rx_status & ((1<<11) - 1)); + PRINTK("[ERROR] Invalid packet -> discarding\n"); + outw( RX_DISCARD_TOP_PACK, BASE + VX_COMMAND ); + return 0; + } + + /* correct pack. waiting in fifo */ + packet_size = rx_status & RX_BYTES_MASK; + + PRINTK("Correct packet waiting in fifo, size: %d\n", packet_size); + + { + volatile word *packet_start = (word *)(BASE + VX_W1_RX_PIO_RD_1); + word *RcvBuffer = (word *)(NetRxPackets[0]); + int wcount = 0; + + for (wcount = 0; wcount < (packet_size >> 1); wcount++) + { + *RcvBuffer++ = *(packet_start); + } + + /* handle odd packets */ + if ( packet_size & 1 ) + { + *RcvBuffer++ = *(packet_start); + } + } + + /* fifo should now be empty (besides the padding bytes) */ + if ( ((*((word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK) > 3 ) + { + PRINTK("[ERROR] Fifo not empty after packet read (remaining pkts: %d)\n", + (((*(word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK)); + } + + /* discard packet */ + *((word *)(BASE + VX_COMMAND)) = RX_DISCARD_TOP_PACK; + + /* Pass Packets to upper Layer */ + NetReceive(NetRxPackets[0], packet_size); + return packet_size; +} + + +/************************************************************************** +ETH_TRANSMIT - Transmit a frame +***************************************************************************/ +static char padmap[] = { + 0, 3, 2, 1}; + + +int eth_send(volatile void *packet, int length) { + int pad; + int status; + volatile word *buf = (word *)packet; + int dummy = 0; + + /* padding stuff */ + pad = padmap[length & 3]; + + PRINTK("eth_send(), length: %d\n", length); + /* drop acknowledgements */ + while(( status=inb(EL_BASE_ADDR + VX_W1_TX_STATUS) )& TXS_COMPLETE ) { + if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { + outw(TX_RESET, EL_BASE_ADDR + VX_COMMAND); + outw(TX_ENABLE, EL_BASE_ADDR + VX_COMMAND); + PRINTK("Bad status, resetting and reenabling transmitter\n"); + } + + outb(0x0, EL_BASE_ADDR + VX_W1_TX_STATUS); + } + + + while (inw(EL_BASE_ADDR + VX_W1_FREE_TX) < length + pad + 4) { + /* no room in FIFO */ + if (dummy == 0) + { + PRINTK("No room in FIFO, waiting...\n"); + dummy++; + } + + } + + PRINTK(" ---> FIFO ready\n"); + + + outw(length, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); + + /* Second dword meaningless */ + outw(0x0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); + +#if EL_DEBUG > 1 + print_packet((byte *)buf, length); +#endif + + /* write packet */ + { + unsigned int i, totw; + + totw = ((length + 1) >> 1); + PRINTK("Buffer: (totw = %d)\n", totw); + for (i = 0; i < totw; i++) { + outw( *(buf+i), EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); + udelay(10); + } + if(totw & 1) + { /* pad to double word length */ + outw( 0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1); + udelay(10); + } + PRINTK("\n\n"); + } + + /* wait for Tx complete */ + PRINTK("Waiting for Tx to complete...\n"); + while(((status = inw(EL_BASE_ADDR + VX_STATUS)) & S_COMMAND_IN_PROGRESS) != 0) + { + udelay(10); + } + PRINTK(" ---> Tx completed, status = 0x%04x\n", status); + + return length; +} + + +#endif /* CONFIG_DRIVER_3C589 */ diff --git a/drivers/net/3c589.h b/drivers/net/3c589.h new file mode 100644 index 0000000000..6735bf9f63 --- /dev/null +++ b/drivers/net/3c589.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. The name + * of the author may not be used to endorse or promote products derived from + * this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + October 2, 1994 + + Modified by: Andres Vega Garcia + + INRIA - Sophia Antipolis, France + e-mail: avega@sophia.inria.fr + finger: avega@pax.inria.fr + + */ + +/* + * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the + * 3c590 family. + */ + +/* + * Modified by Shusuke Nisiyama + * for etherboot + * Mar. 14, 2000 +*/ + +/* + * Ethernet software status per interface. + */ + +/* + * Some global constants + */ + +#define TX_INIT_RATE 16 +#define TX_INIT_MAX_RATE 64 +#define RX_INIT_LATENCY 64 +#define RX_INIT_EARLY_THRESH 64 +#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */ +#define MIN_RX_EARLY_THRESHL 4 + +#define EEPROMSIZE 0x40 +#define MAX_EEPROMBUSY 1000 +#define VX_LAST_TAG 0xd7 +#define VX_MAX_BOARDS 16 +#define VX_ID_PORT 0x100 + +/* + * some macros to acces long named fields + */ +#define BASE (EL_BASE_ADDR) + +/* + * Commands to read/write EEPROM trough EEPROM command register (Window 0, + * Offset 0xa) + */ +#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ +#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ +#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ +#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ + +#define EEPROM_BUSY (1<<15) + +/* + * Some short functions, worth to let them be a macro + */ + +/************************************************************************** + * * + * These define the EEPROM data structure. They are used in the probe + * function to verify the existence of the adapter after having sent + * the ID_Sequence. + * + * There are others but only the ones we use are defined here. + * + **************************************************************************/ + +#define EEPROM_NODE_ADDR_0 0x0 /* Word */ +#define EEPROM_NODE_ADDR_1 0x1 /* Word */ +#define EEPROM_NODE_ADDR_2 0x2 /* Word */ +#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ +#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ +#define EEPROM_ADDR_CFG 0x8 /* Base addr */ +#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ +#define EEPROM_OEM_ADDR_0 0xa /* Word */ +#define EEPROM_OEM_ADDR_1 0xb /* Word */ +#define EEPROM_OEM_ADDR_2 0xc /* Word */ +#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */ + +#define NO_RX_OVN_ANOMALY (1<<5) + +/************************************************************************** + * * + * These are the registers for the 3Com 3c509 and their bit patterns when * + * applicable. They have been taken out the the "EtherLink III Parallel * + * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * + * from 3com. * + * * + **************************************************************************/ + +#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a + * command reg. */ +#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status + * reg. */ +#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window + * reg. */ +/* + * Window 0 registers. Setup. + */ +/* Write */ +#define VX_W0_EEPROM_DATA 0x0c +#define VX_W0_EEPROM_COMMAND 0x0a +#define VX_W0_RESOURCE_CFG 0x08 +#define VX_W0_ADDRESS_CFG 0x06 +#define VX_W0_CONFIG_CTRL 0x04 + /* Read */ +#define VX_W0_PRODUCT_ID 0x02 +#define VX_W0_MFG_ID 0x00 + + +/* + * Window 1 registers. Operating Set. + */ +/* Write */ +#define VX_W1_TX_PIO_WR_2 0x02 +#define VX_W1_TX_PIO_WR_1 0x00 +/* Read */ +#define VX_W1_FREE_TX 0x0c +#define VX_W1_TX_STATUS 0x0b /* byte */ +#define VX_W1_TIMER 0x0a /* byte */ +#define VX_W1_RX_STATUS 0x08 +#define VX_W1_RX_PIO_RD_2 0x02 +#define VX_W1_RX_PIO_RD_1 0x00 + +/* + * Window 2 registers. Station Address Setup/Read + */ +/* Read/Write */ +#define VX_W2_ADDR_5 0x05 +#define VX_W2_ADDR_4 0x04 +#define VX_W2_ADDR_3 0x03 +#define VX_W2_ADDR_2 0x02 +#define VX_W2_ADDR_1 0x01 +#define VX_W2_ADDR_0 0x00 + +/* + * Window 3 registers. FIFO Management. + */ +/* Read */ +#define VX_W3_INTERNAL_CFG 0x00 +#define VX_W3_RESET_OPT 0x08 +#define VX_W3_FREE_TX 0x0c +#define VX_W3_FREE_RX 0x0a + +/* + * Window 4 registers. Diagnostics. + */ +/* Read/Write */ +#define VX_W4_MEDIA_TYPE 0x0a +#define VX_W4_CTRLR_STATUS 0x08 +#define VX_W4_NET_DIAG 0x06 +#define VX_W4_FIFO_DIAG 0x04 +#define VX_W4_HOST_DIAG 0x02 +#define VX_W4_TX_DIAG 0x00 + +/* + * Window 5 Registers. Results and Internal status. + */ +/* Read */ +#define VX_W5_READ_0_MASK 0x0c +#define VX_W5_INTR_MASK 0x0a +#define VX_W5_RX_FILTER 0x08 +#define VX_W5_RX_EARLY_THRESH 0x06 +#define VX_W5_TX_AVAIL_THRESH 0x02 +#define VX_W5_TX_START_THRESH 0x00 + +/* + * Window 6 registers. Statistics. + */ +/* Read/Write */ +#define TX_TOTAL_OK 0x0c +#define RX_TOTAL_OK 0x0a +#define TX_DEFERRALS 0x08 +#define RX_FRAMES_OK 0x07 +#define TX_FRAMES_OK 0x06 +#define RX_OVERRUNS 0x05 +#define TX_COLLISIONS 0x04 +#define TX_AFTER_1_COLLISION 0x03 +#define TX_AFTER_X_COLLISIONS 0x02 +#define TX_NO_SQE 0x01 +#define TX_CD_LOST 0x00 + +/**************************************** + * + * Register definitions. + * + ****************************************/ + +/* + * Command register. All windows. + * + * 16 bit register. + * 15-11: 5-bit code for command to be executed. + * 10-0: 11-bit arg if any. For commands with no args; + * this can be set to anything. + */ +#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms + * after issuing */ +#define WINDOW_SELECT (unsigned short) (0x1<<11) +#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to + * determine whether + * this is needed. If + * so; wait 800 uSec + * before using trans- + * ceiver. */ +#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on + * power-up */ +#define RX_ENABLE (unsigned short) (0x4<<11) +#define RX_RESET (unsigned short) (0x5<<11) +#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11) +#define TX_ENABLE (unsigned short) (0x9<<11) +#define TX_DISABLE (unsigned short) (0xa<<11) +#define TX_RESET (unsigned short) (0xb<<11) +#define REQ_INTR (unsigned short) (0xc<<11) +/* + * The following C_* acknowledge the various interrupts. Some of them don't + * do anything. See the manual. + */ +#define ACK_INTR (unsigned short) (0x6800) +# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1) +# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2) +# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4) +# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8) +# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10) +# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20) +# define C_INT_RQD (unsigned short) (ACK_INTR|0x40) +# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80) +#define SET_INTR_MASK (unsigned short) (0xe<<11) +#define SET_RD_0_MASK (unsigned short) (0xf<<11) +#define SET_RX_FILTER (unsigned short) (0x10<<11) +# define FIL_INDIVIDUAL (unsigned short) (0x1) +# define FIL_MULTICAST (unsigned short) (0x02) +# define FIL_BRDCST (unsigned short) (0x04) +# define FIL_PROMISC (unsigned short) (0x08) +#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11) +#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11) +#define SET_TX_START_THRESH (unsigned short) (0x13<<11) +#define STATS_ENABLE (unsigned short) (0x15<<11) +#define STATS_DISABLE (unsigned short) (0x16<<11) +#define STOP_TRANSCEIVER (unsigned short) (0x17<<11) + +/* + * Status register. All windows. + * + * 15-13: Window number(0-7). + * 12: Command_in_progress. + * 11: reserved. + * 10: reserved. + * 9: reserved. + * 8: reserved. + * 7: Update Statistics. + * 6: Interrupt Requested. + * 5: RX Early. + * 4: RX Complete. + * 3: TX Available. + * 2: TX Complete. + * 1: Adapter Failure. + * 0: Interrupt Latch. + */ +#define S_INTR_LATCH (unsigned short) (0x1) +#define S_CARD_FAILURE (unsigned short) (0x2) +#define S_TX_COMPLETE (unsigned short) (0x4) +#define S_TX_AVAIL (unsigned short) (0x8) +#define S_RX_COMPLETE (unsigned short) (0x10) +#define S_RX_EARLY (unsigned short) (0x20) +#define S_INT_RQD (unsigned short) (0x40) +#define S_UPD_STATS (unsigned short) (0x80) +#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000) + +#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) + +/* Address Config. Register. + * Window 0/Port 06 + */ + +#define ACF_CONNECTOR_BITS 14 +#define ACF_CONNECTOR_UTP 0 +#define ACF_CONNECTOR_AUI 1 +#define ACF_CONNECTOR_BNC 3 + +#define INTERNAL_CONNECTOR_BITS 20 +#define INTERNAL_CONNECTOR_MASK 0x01700000 + +/* + * FIFO Registers. RX Status. + * + * 15: Incomplete or FIFO empty. + * 14: 1: Error in RX Packet 0: Incomplete or no error. + * 13-11: Type of error. + * 1000 = Overrun. + * 1011 = Run Packet Error. + * 1100 = Alignment Error. + * 1101 = CRC Error. + * 1001 = Oversize Packet Error (>1514 bytes) + * 0010 = Dribble Bits. + * (all other error codes, no errors.) + * + * 10-0: RX Bytes (0-1514) + */ +#define ERR_INCOMPLETE (unsigned short) (0x8000) +#define ERR_RX (unsigned short) (0x4000) +#define ERR_MASK (unsigned short) (0x7800) +#define ERR_OVERRUN (unsigned short) (0x4000) +#define ERR_RUNT (unsigned short) (0x5800) +#define ERR_ALIGNMENT (unsigned short) (0x6000) +#define ERR_CRC (unsigned short) (0x6800) +#define ERR_OVERSIZE (unsigned short) (0x4800) +#define ERR_DRIBBLE (unsigned short) (0x1000) + +/* + * TX Status. + * + * Reports the transmit status of a completed transmission. Writing this + * register pops the transmit completion stack. + * + * Window 1/Port 0x0b. + * + * 7: Complete + * 6: Interrupt on successful transmission requested. + * 5: Jabber Error (TP Only, TX Reset required. ) + * 4: Underrun (TX Reset required. ) + * 3: Maximum Collisions. + * 2: TX Status Overflow. + * 1-0: Undefined. + * + */ +#define TXS_COMPLETE 0x80 +#define TXS_INTR_REQ 0x40 +#define TXS_JABBER 0x20 +#define TXS_UNDERRUN 0x10 +#define TXS_MAX_COLLISION 0x8 +#define TXS_STATUS_OVERFLOW 0x4 + +#define RS_AUI (1<<5) +#define RS_BNC (1<<4) +#define RS_UTP (1<<3) +#define RS_T4 (1<<0) +#define RS_TX (1<<1) +#define RS_FX (1<<2) +#define RS_MII (1<<6) + + +/* + * FIFO Status (Window 4) + * + * Supports FIFO diagnostics + * + * Window 4/Port 0x04.1 + * + * 15: 1=RX receiving (RO). Set when a packet is being received + * into the RX FIFO. + * 14: Reserved + * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt. + * Requires RX Reset or Global Reset command to recover. + * It is generated when you read past the end of a packet - + * reading past what has been received so far will give bad + * data. + * 12: 1=RX status overrun (RO). Set when there are already 8 + * packets in the RX FIFO. While this bit is set, no additional + * packets are received. Requires no action on the part of + * the host. The condition is cleared once a packet has been + * read out of the RX FIFO. + * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there + * may not be an overrun packet yet). While this bit is set, + * no additional packets will be received (some additional + * bytes can still be pending between the wire and the RX + * FIFO). Requires no action on the part of the host. The + * condition is cleared once a few bytes have been read out + * from the RX FIFO. + * 10: 1=TX overrun (RO). Generates adapter failure interrupt. + * Requires TX Reset or Global Reset command to recover. + * Disables Transmitter. + * 9-8: Unassigned. + * 7-0: Built in self test bits for the RX and TX FIFO's. + */ +#define FIFOS_RX_RECEIVING (unsigned short) 0x8000 +#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000 +#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000 +#define FIFOS_RX_OVERRUN (unsigned short) 0x0800 +#define FIFOS_TX_OVERRUN (unsigned short) 0x0400 + +/* + * Misc defines for various things. + */ +#define TAG_ADAPTER 0xd0 +#define ACTIVATE_ADAPTER_TO_CONFIG 0xff +#define ENABLE_DRQ_IRQ 0x0001 +#define MFG_ID 0x506d /* `TCM' */ +#define PROD_ID 0x5090 +#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND) +#define JABBER_GUARD_ENABLE 0x40 +#define LINKBEAT_ENABLE 0x80 +#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE) +#define DISABLE_UTP 0x0 +#define RX_BYTES_MASK (unsigned short) (0x07ff) +#define RX_ERROR 0x4000 +#define RX_INCOMPLETE 0x8000 +#define TX_INDICATE 1<<15 +#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY) + +#define VX_IOSIZE 0x20 + +#define VX_CONNECTORS 8 + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/net/5701rls.c b/drivers/net/5701rls.c new file mode 100644 index 0000000000..86950d0f82 --- /dev/null +++ b/drivers/net/5701rls.c @@ -0,0 +1,46 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* */ +/******************************************************************************/ + +#if INCLUDE_5701_AX_FIX + +#include "bcm570x_mm.h" +#include "5701rls.h" + +LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice) +{ + T3_FWIMG_INFO FwImgInfo; + + FwImgInfo.StartAddress = t3FwStartAddr; + FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText; + FwImgInfo.Text.Offset = t3FwTextAddr; + FwImgInfo.Text.Length = t3FwTextLen; + FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata; + FwImgInfo.ROnlyData.Offset = t3FwRodataAddr; + FwImgInfo.ROnlyData.Length = t3FwRodataLen; + FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData; + FwImgInfo.Data.Offset = t3FwDataAddr; + FwImgInfo.Data.Length = t3FwDataLen; + + if (LM_LoadFirmware(pDevice, + &FwImgInfo, + T3_RX_CPU_ID | T3_TX_CPU_ID, + T3_RX_CPU_ID) != LM_STATUS_SUCCESS) + { + return LM_STATUS_FAILURE; + } + + return LM_STATUS_SUCCESS; +} + +#endif /* INCLUDE_5701_AX_FIX */ diff --git a/drivers/net/5701rls.h b/drivers/net/5701rls.h new file mode 100644 index 0000000000..30b127a429 --- /dev/null +++ b/drivers/net/5701rls.h @@ -0,0 +1,198 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ + +typedef unsigned long U32; +int t3FwReleaseMajor = 0x0; +int t3FwReleaseMinor = 0x0; +int t3FwReleaseFix = 0x0; +U32 t3FwStartAddr = 0x08000000; +U32 t3FwTextAddr = 0x08000000; +int t3FwTextLen = 0x9c0; +U32 t3FwRodataAddr = 0x080009c0; +int t3FwRodataLen = 0x60; +U32 t3FwDataAddr = 0x08000a40; +int t3FwDataLen = 0x20; +U32 t3FwSbssAddr = 0x08000a60; +int t3FwSbssLen = 0xc; +U32 t3FwBssAddr = 0x08000a70; +int t3FwBssLen = 0x10; +U32 t3FwText[(0x9c0/4) + 1] = { +0x0, +0x10000003, 0x0, 0xd, 0xd, +0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, +0x26100000, 0xe000018, 0x0, 0xd, +0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, +0x26100034, 0xe00021c, 0x0, 0xd, +0x0, 0x0, 0x0, 0x27bdffe0, +0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c, +0x241b2105, 0x97850000, 0x97870002, 0x9782002c, +0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014, +0x21400, 0x621825, 0x52c00, 0xafa30010, +0x8f860010, 0xe52825, 0xe000060, 0x24070102, +0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100, +0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, +0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f, +0xaf825d00, 0xe000140, 0x0, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, +0x8f835400, 0x34630400, 0xaf835400, 0xaf825404, +0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008, +0xaf805400, 0x0, 0x0, 0x3c020800, +0x34423000, 0x3c030800, 0x34633000, 0x3c040800, +0x348437ff, 0x3c010800, 0xac220a64, 0x24020040, +0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, +0xac600000, 0x24630004, 0x83102b, 0x5040fffd, +0xac600000, 0x3e00008, 0x0, 0x804821, +0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, +0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b, +0x3c010800, 0xac230a60, 0x14400003, 0x4021, +0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, +0x3c030800, 0x8c630a64, 0x91240000, 0x21140, +0x431021, 0x481021, 0x25080001, 0xa0440000, +0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, +0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c, +0x21140, 0x431021, 0xac440008, 0xac45000c, +0xac460010, 0xac470014, 0xac4a0018, 0x3e00008, +0xac4b001c, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x2000008, +0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3, +0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3, +0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3, +0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3, +0x3c0a0014, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x27bdffe0, +0x1821, 0x1021, 0xafbf0018, 0xafb10014, +0xafb00010, 0x3c010800, 0x220821, 0xac200a70, +0x3c010800, 0x220821, 0xac200a74, 0x3c010800, +0x220821, 0xac200a78, 0x24630001, 0x1860fff5, +0x2442000c, 0x24110001, 0x8f906810, 0x32020004, +0x14400005, 0x24040001, 0x3c020800, 0x8c420a78, +0x18400003, 0x2021, 0xe000182, 0x0, +0x32020001, 0x10400003, 0x0, 0xe000169, +0x0, 0xa000153, 0xaf915028, 0x8fbf0018, +0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, +0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80, +0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800, +0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060, +0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810, +0x821004, 0x21027, 0x621824, 0x3e00008, +0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e, +0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec, +0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, +0xaf825cec, 0x8e020000, 0x18400016, 0x0, +0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0, +0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201, +0xac220a74, 0x10400005, 0x0, 0x8e020000, +0x24420001, 0xa0001df, 0xae020000, 0x3c020800, +0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5, +0xafa2001c, 0xe000201, 0x0, 0x1040001f, +0x0, 0x8e020000, 0x8fa3001c, 0x24420001, +0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, +0xa0001df, 0xae020000, 0x3c100800, 0x26100a78, +0x8e020000, 0x18400028, 0x0, 0xe000201, +0x0, 0x14400024, 0x0, 0x8e020000, +0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c, +0x18400006, 0xae020000, 0x31402, 0x221c0, +0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, +0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000, +0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014, +0x8fa6001c, 0x24050008, 0xe000060, 0x3821, +0xa0001df, 0x0, 0xaf825cf8, 0x3c020800, +0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8, +0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, +0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800, +0x248409e8, 0x2821, 0x3021, 0x3821, +0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014, +0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c, +0x8f85680c, 0x21827, 0x3182b, 0x31823, +0x431024, 0x441021, 0xa2282b, 0x10a00006, +0x0, 0x401821, 0x8f82680c, 0x43102b, +0x1440fffd, 0x0, 0x3e00008, 0x0, +0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, +0x64102b, 0x54400002, 0x831023, 0x641023, +0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0, +0x802821, 0x3c040800, 0x24840a00, 0x3021, +0x3821, 0xafbf0018, 0xafa00010, 0xe000060, +0xafa00014, 0xa000216, 0x0, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0, +0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c, +0x3c040800, 0x24840a10, 0x3802821, 0x3021, +0x3821, 0xafa00010, 0xe000060, 0xafa00014, +0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234, +0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0x0, 0x0, 0x0, 0x27bdffe8, +0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003, +0xac200000, 0x8f826810, 0x30422000, 0x10400003, +0x0, 0xe000246, 0x0, 0xa00023a, +0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008, +0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff, +0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024, +0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003, +0x3c074000, 0x851824, 0x8c620010, 0x3c010800, +0xac230a50, 0x30420008, 0x10400005, 0x871025, +0x8cc20000, 0x24420001, 0xacc20000, 0x871025, +0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000, +0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, +0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50, +0x851024, 0x1443ffe8, 0x851824, 0x27bd0008, +0x3e00008, 0x0, 0x0, 0x0 }; +U32 t3FwRodata[(0x60/4) + 1] = { +0x35373031, 0x726c7341, 0x0, +0x0, 0x53774576, 0x656e7430, 0x0, +0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, +0x45766e74, 0x0, 0x0, 0x0, +0x0, 0x66617461, 0x6c457272, 0x0, +0x0, 0x4d61696e, 0x43707542, 0x0, +0x0, 0x0 }; +U32 t3FwData[(0x20/4) + 1] = { +0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0 }; diff --git a/drivers/net/8390.h b/drivers/net/8390.h new file mode 100644 index 0000000000..f087217ed0 --- /dev/null +++ b/drivers/net/8390.h @@ -0,0 +1,124 @@ +/* + +Ported to U-Boot by Christian Pellegrin + +Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and +eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world +are GPL, so this is, of course, GPL. + +*/ + +/* Generic NS8390 register definitions. */ +/* This file is part of Donald Becker's 8390 drivers, and is distributed + under the same license. Auto-loading of 8390.o only in v2.2 - Paul G. + Some of these names and comments originated from the Crynwr + packet drivers, which are distributed under the GPL. */ + +#ifndef _8390_h +#define _8390_h + +/* Some generic ethernet register configurations. */ +#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ +#define E8390_RX_IRQ_MASK 0x5 +#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ +#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ +#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* + * Only generate indirect loads given a machine that needs them. + * - removed AMIGA_PCMCIA from this list, handled as ISA io now + */ + +#define n2k_inb(port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE))) +#define n2k_outb(val,port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = val) + +#define EI_SHIFT(x) (x) + +#define E8390_CMD EI_SHIFT(0x00) /* The command register (for all pages) */ +/* Page 0 register offsets. */ +#define EN0_CLDALO EI_SHIFT(0x01) /* Low byte of current local dma addr RD */ +#define EN0_STARTPG EI_SHIFT(0x01) /* Starting page of ring bfr WR */ +#define EN0_CLDAHI EI_SHIFT(0x02) /* High byte of current local dma addr RD */ +#define EN0_STOPPG EI_SHIFT(0x02) /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY EI_SHIFT(0x03) /* Boundary page of ring bfr RD WR */ +#define EN0_TSR EI_SHIFT(0x04) /* Transmit status reg RD */ +#define EN0_TPSR EI_SHIFT(0x04) /* Transmit starting page WR */ +#define EN0_NCR EI_SHIFT(0x05) /* Number of collision reg RD */ +#define EN0_TCNTLO EI_SHIFT(0x05) /* Low byte of tx byte count WR */ +#define EN0_FIFO EI_SHIFT(0x06) /* FIFO RD */ +#define EN0_TCNTHI EI_SHIFT(0x06) /* High byte of tx byte count WR */ +#define EN0_ISR EI_SHIFT(0x07) /* Interrupt status reg RD WR */ +#define EN0_CRDALO EI_SHIFT(0x08) /* low byte of current remote dma address RD */ +#define EN0_RSARLO EI_SHIFT(0x08) /* Remote start address reg 0 */ +#define EN0_CRDAHI EI_SHIFT(0x09) /* high byte, current remote dma address RD */ +#define EN0_RSARHI EI_SHIFT(0x09) /* Remote start address reg 1 */ +#define EN0_RCNTLO EI_SHIFT(0x0a) /* Remote byte count reg WR */ +#define EN0_RCNTHI EI_SHIFT(0x0b) /* Remote byte count reg WR */ +#define EN0_RSR EI_SHIFT(0x0c) /* rx status reg RD */ +#define EN0_RXCR EI_SHIFT(0x0c) /* RX configuration reg WR */ +#define EN0_TXCR EI_SHIFT(0x0d) /* TX configuration reg WR */ +#define EN0_COUNTER0 EI_SHIFT(0x0d) /* Rcv alignment error counter RD */ +#define EN0_DCFG EI_SHIFT(0x0e) /* Data configuration reg WR */ +#define EN0_COUNTER1 EI_SHIFT(0x0e) /* Rcv CRC error counter RD */ +#define EN0_IMR EI_SHIFT(0x0f) /* Interrupt mask reg WR */ +#define EN0_COUNTER2 EI_SHIFT(0x0f) /* Rcv missed frame error counter RD */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in EN0_DCFG - Data config register */ +#define ENDCFG_WTS 0x01 /* word transfer mode selection */ +#define ENDCFG_BOS 0x02 /* byte order selection */ +#define ENDCFG_AUTO_INIT 0x10 /* Auto-init to remove packets from ring */ +#define ENDCFG_FIFO 0x40 /* 8 bytes */ + +/* Page 1 register offsets. */ +#define EN1_PHYS EI_SHIFT(0x01) /* This board's physical enet addr RD WR */ +#define EN1_PHYS_SHIFT(i) EI_SHIFT(i+1) /* Get and set mac address */ +#define EN1_CURPAG EI_SHIFT(0x07) /* Current memory page RD WR */ +#define EN1_MULT EI_SHIFT(0x08) /* Multicast filter mask array (8 bytes) RD WR */ +#define EN1_MULT_SHIFT(i) EI_SHIFT(8+i) /* Get and set multicast filter */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicast address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ +#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ +#define ENTSR_COL 0x04 /* The transmit collided at least once. */ +#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ +#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ +#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ +#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ +#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ + +#define NIC_RECEIVE_MONITOR_MODE 0x20 + +#endif /* _8390_h */ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 37d69b9949..41e1bdeb3b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -25,8 +25,39 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnet.a -COBJS := mcffec.o +COBJS-y += 3c589.o +COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o +COBJS-y += cs8900.o +COBJS-y += dc2114x.o +COBJS-y += dm9000x.o +COBJS-y += e1000.o +COBJS-y += eepro100.o +COBJS-y += enc28j60.o +COBJS-y += inca-ip_sw.o +COBJS-y += ks8695eth.o +COBJS-y += lan91c96.o +COBJS-y += macb.o +COBJS-y += mcffec.o +COBJS-y += natsemi.o +COBJS-y += ne2000.o +COBJS-y += netarm_eth.o +COBJS-y += netconsole.o +COBJS-y += ns7520_eth.o +COBJS-y += ns8382x.o +COBJS-y += ns9750_eth.o +COBJS-y += pcnet.o +COBJS-y += plb2800_eth.o +COBJS-y += rtl8019.o +COBJS-y += rtl8139.o +COBJS-y += rtl8169.o +COBJS-y += s3c4510b_eth.o +COBJS-y += smc91111.o +COBJS-y += tigon3.o +COBJS-y += tsec.o +COBJS-y += tsi108_eth.o +COBJS-y += uli526x.o +COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/drivers/net/bcm570x.c b/drivers/net/bcm570x.c new file mode 100644 index 0000000000..c8f4064224 --- /dev/null +++ b/drivers/net/bcm570x.c @@ -0,0 +1,1603 @@ +/* + * Broadcom BCM570x Ethernet Driver for U-Boot. + * Support 5701, 5702, 5703, and 5704. Single instance driver. + * Copyright (C) 2002 James F. Dougherty (jfd@broadcom.com) + */ + +#include + +#if defined(CONFIG_CMD_NET) \ + && (!defined(CONFIG_NET_MULTI)) && defined(CONFIG_BCM570x) + +#ifdef CONFIG_BMW +#include +#endif +#include +#include "bcm570x_mm.h" +#include "bcm570x_autoneg.h" +#include +#include + +/* + * PCI Registers and definitions. + */ +#define PCI_CMD_MASK 0xffff0000 /* mask to save status bits */ +#define PCI_ANY_ID (~0) + +/* + * PCI memory base for Ethernet device as well as device Interrupt. + */ +#define BCM570X_MBAR 0x80100000 +#define BCM570X_ILINE 1 + +#define SECOND_USEC 1000000 +#define MAX_PACKET_SIZE 1600 +#define MAX_UNITS 4 + +/* Globals to this module */ +int initialized = 0; +unsigned int ioBase = 0; +volatile PLM_DEVICE_BLOCK pDevice = NULL; /* 570x softc */ +volatile PUM_DEVICE_BLOCK pUmDevice = NULL; + +/* Used to pass the full-duplex flag, etc. */ +int line_speed[MAX_UNITS] = { 0, 0, 0, 0 }; +static int full_duplex[MAX_UNITS] = { 1, 1, 1, 1 }; +static int rx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; +static int tx_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; +static int auto_flow_control[MAX_UNITS] = { 0, 0, 0, 0 }; +static int tx_checksum[MAX_UNITS] = { 1, 1, 1, 1 }; +static int rx_checksum[MAX_UNITS] = { 1, 1, 1, 1 }; +static int auto_speed[MAX_UNITS] = { 1, 1, 1, 1 }; + +#if JUMBO_FRAMES +/* Jumbo MTU for interfaces. */ +static int mtu[MAX_UNITS] = { 0, 0, 0, 0 }; +#endif + +/* Turn on Wake-on lan for a device unit */ +static int enable_wol[MAX_UNITS] = { 0, 0, 0, 0 }; + +#define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT +static unsigned int tx_pkt_desc_cnt[MAX_UNITS] = + { TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT, TX_DESC_CNT }; + +#define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT +static unsigned int rx_std_desc_cnt[MAX_UNITS] = + { RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT, RX_DESC_CNT }; + +static unsigned int rx_adaptive_coalesce[MAX_UNITS] = { 1, 1, 1, 1 }; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT +#define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT +static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] = + { JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT, JBO_DESC_CNT }; +#endif +#define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS +static unsigned int rx_coalesce_ticks[MAX_UNITS] = + { RX_COAL_TK, RX_COAL_TK, RX_COAL_TK, RX_COAL_TK }; + +#define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES +static unsigned int rx_max_coalesce_frames[MAX_UNITS] = + { RX_COAL_FM, RX_COAL_FM, RX_COAL_FM, RX_COAL_FM }; + +#define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS +static unsigned int tx_coalesce_ticks[MAX_UNITS] = + { TX_COAL_TK, TX_COAL_TK, TX_COAL_TK, TX_COAL_TK }; + +#define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES +static unsigned int tx_max_coalesce_frames[MAX_UNITS] = + { TX_COAL_FM, TX_COAL_FM, TX_COAL_FM, TX_COAL_FM }; + +#define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS +static unsigned int stats_coalesce_ticks[MAX_UNITS] = + { ST_COAL_TK, ST_COAL_TK, ST_COAL_TK, ST_COAL_TK }; + +/* + * Legitimate values for BCM570x device types + */ +typedef enum { + BCM5700VIGIL = 0, + BCM5700A6, + BCM5700T6, + BCM5700A9, + BCM5700T9, + BCM5700, + BCM5701A5, + BCM5701T1, + BCM5701T8, + BCM5701A7, + BCM5701A10, + BCM5701A12, + BCM5701, + BCM5702, + BCM5703, + BCM5703A31, + TC996T, + TC996ST, + TC996SSX, + TC996SX, + TC996BT, + TC997T, + TC997SX, + TC1000T, + TC940BR01, + TC942BR01, + NC6770, + NC7760, + NC7770, + NC7780 +} board_t; + +/* Chip-Rev names for each device-type */ +static struct { + char *name; +} chip_rev[] = { + { + "BCM5700VIGIL"}, { + "BCM5700A6"}, { + "BCM5700T6"}, { + "BCM5700A9"}, { + "BCM5700T9"}, { + "BCM5700"}, { + "BCM5701A5"}, { + "BCM5701T1"}, { + "BCM5701T8"}, { + "BCM5701A7"}, { + "BCM5701A10"}, { + "BCM5701A12"}, { + "BCM5701"}, { + "BCM5702"}, { + "BCM5703"}, { + "BCM5703A31"}, { + "TC996T"}, { + "TC996ST"}, { + "TC996SSX"}, { + "TC996SX"}, { + "TC996BT"}, { + "TC997T"}, { + "TC997SX"}, { + "TC1000T"}, { + "TC940BR01"}, { + "TC942BR01"}, { + "NC6770"}, { + "NC7760"}, { + "NC7770"}, { + "NC7780"}, { + 0} +}; + +/* indexed by board_t, above */ +static struct { + char *name; +} board_info[] = { + { + "Broadcom Vigil B5700 1000Base-T"}, { + "Broadcom BCM5700 1000Base-T"}, { + "Broadcom BCM5700 1000Base-SX"}, { + "Broadcom BCM5700 1000Base-SX"}, { + "Broadcom BCM5700 1000Base-T"}, { + "Broadcom BCM5700"}, { + "Broadcom BCM5701 1000Base-T"}, { + "Broadcom BCM5701 1000Base-T"}, { + "Broadcom BCM5701 1000Base-T"}, { + "Broadcom BCM5701 1000Base-SX"}, { + "Broadcom BCM5701 1000Base-T"}, { + "Broadcom BCM5701 1000Base-T"}, { + "Broadcom BCM5701"}, { + "Broadcom BCM5702 1000Base-T"}, { + "Broadcom BCM5703 1000Base-T"}, { + "Broadcom BCM5703 1000Base-SX"}, { + "3Com 3C996 10/100/1000 Server NIC"}, { + "3Com 3C996 10/100/1000 Server NIC"}, { + "3Com 3C996 Gigabit Fiber-SX Server NIC"}, { + "3Com 3C996 Gigabit Fiber-SX Server NIC"}, { + "3Com 3C996B Gigabit Server NIC"}, { + "3Com 3C997 Gigabit Server NIC"}, { + "3Com 3C997 Gigabit Fiber-SX Server NIC"}, { + "3Com 3C1000 Gigabit NIC"}, { + "3Com 3C940 Gigabit LOM (21X21)"}, { + "3Com 3C942 Gigabit LOM (31X31)"}, { + "Compaq NC6770 Gigabit Server Adapter"}, { + "Compaq NC7760 Gigabit Server Adapter"}, { + "Compaq NC7770 Gigabit Server Adapter"}, { + "Compaq NC7780 Gigabit Server Adapter"}, { +0},}; + +/* PCI Devices which use the 570x chipset */ +struct pci_device_table { + unsigned short vendor_id, device_id; /* Vendor/DeviceID */ + unsigned short subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ + unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ + unsigned long board_id; /* Data private to the driver */ + int io_size, min_latency; +} bcm570xDevices[] = { + { + 0x14e4, 0x1644, 0x1014, 0x0277, 0, 0, BCM5700VIGIL, 128, 32}, { + 0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6, 128, 32}, { + 0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6, 128, 32}, { + 0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9, 128, 32}, { + 0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9, 128, 32}, { + 0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700, 128, 32}, { + 0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700, 128, 32}, { + 0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700, 128, 32}, { + 0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX, 128, 32}, { + 0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01, 128, 32}, { + 0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10, 128, 32}, { + 0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12, 128, 32}, { + 0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770, 128, 32}, { + 0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770, 128, 32}, { + 0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780, 128, 32}, { + 0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701, 128, 32}, { + 0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX, 128, 32}, { + 0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT, 128, 32}, { + 0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T, 128, 32}, { + 0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01, 128, 32}, { + 0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701, 128, 32}, { + 0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, { + 0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, { + 0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, { + 0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702, 128, 32}, { + 0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760, 128, 32}, { + 0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702, 128, 32}, { + 0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, { + 0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x1647, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, { + 0x14e4, 0x1647, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, { + 0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31, 128, 32}, { + 0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703, 128, 32}, { + 0x14e4, 0x16a7, 0x0e11, 0x9a, 0, 0, NC7770, 128, 32}, { + 0x14e4, 0x16a7, 0x0e11, 0x99, 0, 0, NC7780, 128, 32}, { + 0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703, 128, 32} +}; + +#define n570xDevices (sizeof(bcm570xDevices)/sizeof(bcm570xDevices[0])) + +/* + * Allocate a packet buffer from the bcm570x packet pool. + */ +void *bcm570xPktAlloc (int u, int pksize) +{ + return malloc (pksize); +} + +/* + * Free a packet previously allocated from the bcm570x packet + * buffer pool. + */ +void bcm570xPktFree (int u, void *p) +{ + free (p); +} + +int bcm570xReplenishRxBuffers (PUM_DEVICE_BLOCK pUmDevice) +{ + PLM_PACKET pPacket; + PUM_PACKET pUmPacket; + void *skb; + int queue_rx = 0; + int ret = 0; + + while ((pUmPacket = (PUM_PACKET) + QQ_PopHead (&pUmDevice->rx_out_of_buf_q.Container)) != 0) { + + pPacket = (PLM_PACKET) pUmPacket; + + /* reuse an old skb */ + if (pUmPacket->skbuff) { + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, + pPacket); + queue_rx = 1; + continue; + } + if ((skb = bcm570xPktAlloc (pUmDevice->index, + pPacket->u.Rx.RxBufferSize + 2)) == + 0) { + QQ_PushHead (&pUmDevice->rx_out_of_buf_q.Container, + pPacket); + printf ("NOTICE: Out of RX memory.\n"); + ret = 1; + break; + } + + pUmPacket->skbuff = skb; + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + queue_rx = 1; + } + + if (queue_rx) { + LM_QueueRxPackets (pDevice); + } + + return ret; +} + +/* + * Probe, Map, and Init 570x device. + */ +int eth_init (bd_t * bis) +{ + int i, rv, devFound = FALSE; + pci_dev_t devbusfn; + unsigned short status; + + /* Find PCI device, if it exists, configure ... */ + for (i = 0; i < n570xDevices; i++) { + devbusfn = pci_find_device (bcm570xDevices[i].vendor_id, + bcm570xDevices[i].device_id, 0); + if (devbusfn == -1) { + continue; /* No device of that vendor/device ID */ + } else { + + /* Set ILINE */ + pci_write_config_byte (devbusfn, + PCI_INTERRUPT_LINE, + BCM570X_ILINE); + + /* + * 0x10 - 0x14 define one 64-bit MBAR. + * 0x14 is the higher-order address bits of the BAR. + */ + pci_write_config_dword (devbusfn, + PCI_BASE_ADDRESS_1, 0); + + ioBase = BCM570X_MBAR; + + pci_write_config_dword (devbusfn, + PCI_BASE_ADDRESS_0, ioBase); + + /* + * Enable PCI memory, IO, and Master -- don't + * reset any status bits in doing so. + */ + pci_read_config_word (devbusfn, PCI_COMMAND, &status); + + status |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + + pci_write_config_word (devbusfn, PCI_COMMAND, status); + + printf + ("\n%s: bus %d, device %d, function %d: MBAR=0x%x\n", + board_info[bcm570xDevices[i].board_id].name, + PCI_BUS (devbusfn), PCI_DEV (devbusfn), + PCI_FUNC (devbusfn), ioBase); + + /* Allocate once, but always clear on init */ + if (!pDevice) { + pDevice = malloc (sizeof (UM_DEVICE_BLOCK)); + pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + memset (pDevice, 0x0, sizeof (UM_DEVICE_BLOCK)); + } + + /* Configure pci dev structure */ + pUmDevice->pdev = devbusfn; + pUmDevice->index = 0; + pUmDevice->tx_pkt = 0; + pUmDevice->rx_pkt = 0; + devFound = TRUE; + break; + } + } + + if (!devFound) { + printf + ("eth_init: FAILURE: no BCM570x Ethernet devices found.\n"); + return -1; + } + + /* Setup defaults for chip */ + pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; + + if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) { + pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; + } else { + + if (rx_checksum[i]) { + pDevice->TaskToOffload |= + LM_TASK_OFFLOAD_RX_TCP_CHECKSUM | + LM_TASK_OFFLOAD_RX_UDP_CHECKSUM; + } + + if (tx_checksum[i]) { + pDevice->TaskToOffload |= + LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | + LM_TASK_OFFLOAD_TX_UDP_CHECKSUM; + pDevice->NoTxPseudoHdrChksum = TRUE; + } + } + + /* Set Device PCI Memory base address */ + pDevice->pMappedMemBase = (PLM_UINT8) ioBase; + + /* Pull down adapter info */ + if ((rv = LM_GetAdapterInfo (pDevice)) != LM_STATUS_SUCCESS) { + printf ("bcm570xEnd: LM_GetAdapterInfo failed: rv=%d!\n", rv); + return -2; + } + + /* Lock not needed */ + pUmDevice->do_global_lock = 0; + + if (T3_ASIC_REV (pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) { + /* The 5700 chip works best without interleaved register */ + /* accesses on certain machines. */ + pUmDevice->do_global_lock = 1; + } + + /* Setup timer delays */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + pDevice->UseTaggedStatus = TRUE; + pUmDevice->timer_interval = CFG_HZ; + } else { + pUmDevice->timer_interval = CFG_HZ / 50; + } + + /* Grab name .... */ + pUmDevice->name = + (char *)malloc (strlen (board_info[bcm570xDevices[i].board_id].name) + + 1); + strcpy (pUmDevice->name, board_info[bcm570xDevices[i].board_id].name); + + memcpy (pDevice->NodeAddress, bis->bi_enetaddr, 6); + LM_SetMacAddress (pDevice, bis->bi_enetaddr); + /* Init queues .. */ + QQ_InitQueue (&pUmDevice->rx_out_of_buf_q.Container, + MAX_RX_PACKET_DESC_COUNT); + pUmDevice->rx_last_cnt = pUmDevice->tx_last_cnt = 0; + + /* delay for 4 seconds */ + pUmDevice->delayed_link_ind = (4 * CFG_HZ) / pUmDevice->timer_interval; + + pUmDevice->adaptive_expiry = CFG_HZ / pUmDevice->timer_interval; + + /* Sometimes we get spurious ints. after reset when link is down. */ + /* This field tells the isr to service the int. even if there is */ + /* no status block update. */ + pUmDevice->adapter_just_inited = + (3 * CFG_HZ) / pUmDevice->timer_interval; + + /* Initialize 570x */ + if (LM_InitializeAdapter (pDevice) != LM_STATUS_SUCCESS) { + printf ("ERROR: Adapter initialization failed.\n"); + return ERROR; + } + + /* Enable chip ISR */ + LM_EnableInterrupt (pDevice); + + /* Clear MC table */ + LM_MulticastClear (pDevice); + + /* Enable Multicast */ + LM_SetReceiveMask (pDevice, + pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST); + + pUmDevice->opened = 1; + pUmDevice->tx_full = 0; + pUmDevice->tx_pkt = 0; + pUmDevice->rx_pkt = 0; + printf ("eth%d: %s @0x%lx,", + pDevice->index, pUmDevice->name, (unsigned long)ioBase); + printf ("node addr "); + for (i = 0; i < 6; i++) { + printf ("%2.2x", pDevice->NodeAddress[i]); + } + printf ("\n"); + + printf ("eth%d: ", pDevice->index); + printf ("%s with ", chip_rev[bcm570xDevices[i].board_id].name); + + if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID) + printf ("Broadcom BCM5400 Copper "); + else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) + printf ("Broadcom BCM5401 Copper "); + else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID) + printf ("Broadcom BCM5411 Copper "); + else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) + printf ("Broadcom BCM5701 Integrated Copper "); + else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) + printf ("Broadcom BCM5703 Integrated Copper "); + else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID) + printf ("Broadcom BCM8002 SerDes "); + else if (pDevice->EnableTbi) + printf ("Agilent HDMP-1636 SerDes "); + else + printf ("Unknown "); + printf ("transceiver found\n"); + + printf ("eth%d: %s, MTU: %d,", + pDevice->index, pDevice->BusSpeedStr, 1500); + + if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) && rx_checksum[i]) + printf ("Rx Checksum ON\n"); + else + printf ("Rx Checksum OFF\n"); + initialized++; + + return 0; +} + +/* Ethernet Interrupt service routine */ +void eth_isr (void) +{ + LM_UINT32 oldtag, newtag; + int i; + + pUmDevice->interrupt = 1; + + if (pDevice->UseTaggedStatus) { + if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) || + pUmDevice->adapter_just_inited) { + MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1); + oldtag = pDevice->pStatusBlkVirt->StatusTag; + + for (i = 0;; i++) { + pDevice->pStatusBlkVirt->Status &= + ~STATUS_BLOCK_UPDATED; + LM_ServiceInterrupts (pDevice); + newtag = pDevice->pStatusBlkVirt->StatusTag; + if ((newtag == oldtag) || (i > 50)) { + MB_REG_WR (pDevice, + Mailbox.Interrupt[0].Low, + newtag << 24); + if (pDevice->UndiFix) { + REG_WR (pDevice, Grc.LocalCtrl, + pDevice-> + GrcLocalCtrl | 0x2); + } + break; + } + oldtag = newtag; + } + } + } else { + while (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { + unsigned int dummy; + + pDevice->pMemView->Mailbox.Interrupt[0].Low = 1; + pDevice->pStatusBlkVirt->Status &= + ~STATUS_BLOCK_UPDATED; + LM_ServiceInterrupts (pDevice); + pDevice->pMemView->Mailbox.Interrupt[0].Low = 0; + dummy = pDevice->pMemView->Mailbox.Interrupt[0].Low; + } + } + + /* Allocate new RX buffers */ + if (QQ_GetEntryCnt (&pUmDevice->rx_out_of_buf_q.Container)) { + bcm570xReplenishRxBuffers (pUmDevice); + } + + /* Queue packets */ + if (QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container)) { + LM_QueueRxPackets (pDevice); + } + + if (pUmDevice->tx_queued) { + pUmDevice->tx_queued = 0; + } + + if (pUmDevice->tx_full) { + if (pDevice->LinkStatus != LM_STATUS_LINK_DOWN) { + printf + ("NOTICE: tx was previously blocked, restarting MUX\n"); + pUmDevice->tx_full = 0; + } + } + + pUmDevice->interrupt = 0; + +} + +int eth_send (volatile void *packet, int length) +{ + int status = 0; +#if ET_DEBUG + unsigned char *ptr = (unsigned char *)packet; +#endif + PLM_PACKET pPacket; + PUM_PACKET pUmPacket; + + /* Link down, return */ + while (pDevice->LinkStatus == LM_STATUS_LINK_DOWN) { +#if 0 + printf ("eth%d: link down - check cable or link partner.\n", + pUmDevice->index); +#endif + eth_isr (); + + /* Wait to see link for one-half a second before sending ... */ + udelay (1500000); + + } + + /* Clear sent flag */ + pUmDevice->tx_pkt = 0; + + /* Previously blocked */ + if (pUmDevice->tx_full) { + printf ("eth%d: tx blocked.\n", pUmDevice->index); + return 0; + } + + pPacket = (PLM_PACKET) + QQ_PopHead (&pDevice->TxPacketFreeQ.Container); + + if (pPacket == 0) { + pUmDevice->tx_full = 1; + printf ("bcm570xEndSend: TX full!\n"); + return 0; + } + + if (pDevice->SendBdLeft.counter == 0) { + pUmDevice->tx_full = 1; + printf ("bcm570xEndSend: no more TX descriptors!\n"); + QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); + return 0; + } + + if (length <= 0) { + printf ("eth: bad packet size: %d\n", length); + goto out; + } + + /* Get packet buffers and fragment list */ + pUmPacket = (PUM_PACKET) pPacket; + /* Single DMA Descriptor transmit. + * Fragments may be provided, but one DMA descriptor max is + * used to send the packet. + */ + if (MM_CoalesceTxBuffer (pDevice, pPacket) != LM_STATUS_SUCCESS) { + if (pUmPacket->skbuff == NULL) { + /* Packet was discarded */ + printf ("TX: failed (1)\n"); + status = 1; + } else { + printf ("TX: failed (2)\n"); + status = 2; + } + QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); + return status; + } + + /* Copy packet to DMA buffer */ + memset (pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE); + memcpy ((void *)pUmPacket->skbuff, (void *)packet, length); + pPacket->PacketSize = length; + pPacket->Flags |= SND_BD_FLAG_END | SND_BD_FLAG_COAL_NOW; + pPacket->u.Tx.FragCount = 1; + /* We've already provided a frame ready for transmission */ + pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM; + + if (LM_SendPacket (pDevice, pPacket) == LM_STATUS_FAILURE) { + /* + * A lower level send failure will push the packet descriptor back + * in the free queue, so just deal with the VxWorks clusters. + */ + if (pUmPacket->skbuff == NULL) { + printf ("TX failed (1)!\n"); + /* Packet was discarded */ + status = 3; + } else { + /* A resource problem ... */ + printf ("TX failed (2)!\n"); + status = 4; + } + + if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) == 0) { + printf ("TX: emptyQ!\n"); + pUmDevice->tx_full = 1; + } + } + + while (pUmDevice->tx_pkt == 0) { + /* Service TX */ + eth_isr (); + } +#if ET_DEBUG + printf ("eth_send: 0x%x, %d bytes\n" + "[%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x] ...\n", + (int)pPacket, length, + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], + ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], + ptr[13], ptr[14], ptr[15]); +#endif + pUmDevice->tx_pkt = 0; + QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket); + + /* Done with send */ + out: + return status; +} + +/* Ethernet receive */ +int eth_rx (void) +{ + PLM_PACKET pPacket = NULL; + PUM_PACKET pUmPacket = NULL; + void *skb; + int size = 0; + + while (TRUE) { + + bcm570x_service_isr: + /* Pull down packet if it is there */ + eth_isr (); + + /* Indicate RX packets called */ + if (pUmDevice->rx_pkt) { + /* printf("eth_rx: got a packet...\n"); */ + pUmDevice->rx_pkt = 0; + } else { + /* printf("eth_rx: waiting for packet...\n"); */ + goto bcm570x_service_isr; + } + + pPacket = (PLM_PACKET) + QQ_PopHead (&pDevice->RxPacketReceivedQ.Container); + + if (pPacket == 0) { + printf ("eth_rx: empty packet!\n"); + goto bcm570x_service_isr; + } + + pUmPacket = (PUM_PACKET) pPacket; +#if ET_DEBUG + printf ("eth_rx: packet @0x%x\n", (int)pPacket); +#endif + /* If the packet generated an error, reuse buffer */ + if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) || + ((size = pPacket->PacketSize) > pDevice->RxMtu)) { + + /* reuse skb */ + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, + pPacket); + printf ("eth_rx: error in packet dma!\n"); + goto bcm570x_service_isr; + } + + /* Set size and address */ + skb = pUmPacket->skbuff; + size = pPacket->PacketSize; + + /* Pass the packet up to the protocol + * layers. + */ + NetReceive (skb, size); + + /* Free packet buffer */ + bcm570xPktFree (pUmDevice->index, skb); + pUmPacket->skbuff = NULL; + + /* Reuse SKB */ + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + + return 0; /* Got a packet, bail ... */ + } + return size; +} + +/* Shut down device */ +void eth_halt (void) +{ + int i; + if (initialized) + if (pDevice && pUmDevice && pUmDevice->opened) { + printf ("\neth%d:%s,", pUmDevice->index, + pUmDevice->name); + printf ("HALT,"); + /* stop device */ + LM_Halt (pDevice); + printf ("POWER DOWN,"); + LM_SetPowerState (pDevice, LM_POWER_STATE_D3); + + /* Free the memory allocated by the device in tigon3 */ + for (i = 0; i < pUmDevice->mem_list_num; i++) { + if (pUmDevice->mem_list[i]) { + /* sanity check */ + if (pUmDevice->dma_list[i]) { /* cache-safe memory */ + free (pUmDevice->mem_list[i]); + } else { + free (pUmDevice->mem_list[i]); /* normal memory */ + } + } + } + pUmDevice->opened = 0; + free (pDevice); + pDevice = NULL; + pUmDevice = NULL; + initialized = 0; + printf ("done - offline.\n"); + } +} + +/* + * + * Middle Module: Interface between the HW driver (tigon3 modules) and + * the native (SENS) driver. These routines implement the system + * interface for tigon3 on VxWorks. + */ + +/* Middle module dependency - size of a packet descriptor */ +int MM_Packet_Desc_Size = sizeof (UM_PACKET); + +LM_STATUS +MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice, + LM_UINT32 Offset, LM_UINT32 * pValue32) +{ + UM_DEVICE_BLOCK *pUmDevice; + pUmDevice = (UM_DEVICE_BLOCK *) pDevice; + pci_read_config_dword (pUmDevice->pdev, Offset, (u32 *) pValue32); + return LM_STATUS_SUCCESS; +} + +LM_STATUS +MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 Value32) +{ + UM_DEVICE_BLOCK *pUmDevice; + pUmDevice = (UM_DEVICE_BLOCK *) pDevice; + pci_write_config_dword (pUmDevice->pdev, Offset, Value32); + return LM_STATUS_SUCCESS; +} + +LM_STATUS +MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice, + LM_UINT32 Offset, LM_UINT16 * pValue16) +{ + UM_DEVICE_BLOCK *pUmDevice; + pUmDevice = (UM_DEVICE_BLOCK *) pDevice; + pci_read_config_word (pUmDevice->pdev, Offset, (u16 *) pValue16); + return LM_STATUS_SUCCESS; +} + +LM_STATUS +MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT16 Value16) +{ + UM_DEVICE_BLOCK *pUmDevice; + pUmDevice = (UM_DEVICE_BLOCK *) pDevice; + pci_write_config_word (pUmDevice->pdev, Offset, Value16); + return LM_STATUS_SUCCESS; +} + +LM_STATUS +MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, + PLM_VOID * pMemoryBlockVirt, + PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, LM_BOOL Cached) +{ + PLM_VOID pvirt; + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + dma_addr_t mapping; + + pvirt = malloc (BlockSize); + mapping = (dma_addr_t) (pvirt); + if (!pvirt) + return LM_STATUS_FAILURE; + + pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; + pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping; + pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; + memset (pvirt, 0, BlockSize); + + *pMemoryBlockVirt = (PLM_VOID) pvirt; + MM_SetAddr (pMemoryBlockPhy, (dma_addr_t) mapping); + + return LM_STATUS_SUCCESS; +} + +LM_STATUS +MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, + PLM_VOID * pMemoryBlockVirt) +{ + PLM_VOID pvirt; + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + + pvirt = malloc (BlockSize); + + if (!pvirt) + return LM_STATUS_FAILURE; + + pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt; + pUmDevice->dma_list[pUmDevice->mem_list_num] = 0; + pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize; + memset (pvirt, 0, BlockSize); + *pMemoryBlockVirt = pvirt; + + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice) +{ + printf ("BCM570x PCI Memory base address @0x%x\n", + (unsigned int)pDevice->pMappedMemBase); + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice) +{ + int i; + void *skb; + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + PUM_PACKET pUmPacket = NULL; + PLM_PACKET pPacket = NULL; + + for (i = 0; i < pDevice->RxPacketDescCnt; i++) { + pPacket = QQ_PopHead (&pDevice->RxPacketFreeQ.Container); + pUmPacket = (PUM_PACKET) pPacket; + + if (pPacket == 0) { + printf ("MM_InitializeUmPackets: Bad RxPacketFreeQ\n"); + } + + skb = bcm570xPktAlloc (pUmDevice->index, + pPacket->u.Rx.RxBufferSize + 2); + + if (skb == 0) { + pUmPacket->skbuff = 0; + QQ_PushTail (&pUmDevice->rx_out_of_buf_q.Container, + pPacket); + printf ("MM_InitializeUmPackets: out of buffer.\n"); + continue; + } + + pUmPacket->skbuff = skb; + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + } + + pUmDevice->rx_low_buf_thresh = pDevice->RxPacketDescCnt / 8; + + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice) +{ + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + int index = pDevice->index; + + if (auto_speed[index] == 0) + pDevice->DisableAutoNeg = TRUE; + else + pDevice->DisableAutoNeg = FALSE; + + if (line_speed[index] == 0) { + pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; + pDevice->DisableAutoNeg = FALSE; + } else { + if (line_speed[index] == 1000) { + if (pDevice->EnableTbi) { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX; + } else if (full_duplex[index]) { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX; + } else { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS; + } + if (!pDevice->EnableTbi) + pDevice->DisableAutoNeg = FALSE; + } else if (line_speed[index] == 100) { + if (full_duplex[index]) { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX; + } else { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS; + } + } else if (line_speed[index] == 10) { + if (full_duplex[index]) { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX; + } else { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; + } + } else { + pDevice->RequestedMediaType = + LM_REQUESTED_MEDIA_TYPE_AUTO; + pDevice->DisableAutoNeg = FALSE; + } + + } + pDevice->FlowControlCap = 0; + if (rx_flow_control[index] != 0) { + pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + if (tx_flow_control[index] != 0) { + pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; + } + if ((auto_flow_control[index] != 0) && + (pDevice->DisableAutoNeg == FALSE)) { + + pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE; + if ((tx_flow_control[index] == 0) && + (rx_flow_control[index] == 0)) { + pDevice->FlowControlCap |= + LM_FLOW_CONTROL_TRANSMIT_PAUSE | + LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + } + + /* Default MTU for now */ + pUmDevice->mtu = 1500; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + if (pUmDevice->mtu > 1500) { + pDevice->RxMtu = pUmDevice->mtu; + pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; + } else { + pDevice->RxJumboDescCnt = 0; + } + pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index]; +#else + pDevice->RxMtu = pUmDevice->mtu; +#endif + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + pDevice->UseTaggedStatus = TRUE; + pUmDevice->timer_interval = CFG_HZ; + } else { + pUmDevice->timer_interval = CFG_HZ / 50; + } + + pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index]; + pDevice->RxStdDescCnt = rx_std_desc_cnt[index]; + /* Note: adaptive coalescence really isn't adaptive in this driver */ + pUmDevice->rx_adaptive_coalesce = rx_adaptive_coalesce[index]; + if (!pUmDevice->rx_adaptive_coalesce) { + pDevice->RxCoalescingTicks = rx_coalesce_ticks[index]; + if (pDevice->RxCoalescingTicks > MAX_RX_COALESCING_TICKS) + pDevice->RxCoalescingTicks = MAX_RX_COALESCING_TICKS; + pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks; + + pDevice->RxMaxCoalescedFrames = rx_max_coalesce_frames[index]; + if (pDevice->RxMaxCoalescedFrames > MAX_RX_MAX_COALESCED_FRAMES) + pDevice->RxMaxCoalescedFrames = + MAX_RX_MAX_COALESCED_FRAMES; + pUmDevice->rx_curr_coalesce_frames = + pDevice->RxMaxCoalescedFrames; + pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index]; + if (pDevice->StatsCoalescingTicks > MAX_STATS_COALESCING_TICKS) + pDevice->StatsCoalescingTicks = + MAX_STATS_COALESCING_TICKS; + } else { + pUmDevice->rx_curr_coalesce_frames = + DEFAULT_RX_MAX_COALESCED_FRAMES; + pUmDevice->rx_curr_coalesce_ticks = DEFAULT_RX_COALESCING_TICKS; + } + pDevice->TxCoalescingTicks = tx_coalesce_ticks[index]; + if (pDevice->TxCoalescingTicks > MAX_TX_COALESCING_TICKS) + pDevice->TxCoalescingTicks = MAX_TX_COALESCING_TICKS; + pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index]; + if (pDevice->TxMaxCoalescedFrames > MAX_TX_MAX_COALESCED_FRAMES) + pDevice->TxMaxCoalescedFrames = MAX_TX_MAX_COALESCED_FRAMES; + + if (enable_wol[index]) { + pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET; + pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET; + } + pDevice->NicSendBd = TRUE; + + /* Don't update status blocks during interrupt */ + pDevice->RxCoalescingTicksDuringInt = 0; + pDevice->TxCoalescingTicksDuringInt = 0; + + return LM_STATUS_SUCCESS; + +} + +LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + printf ("Start TX DMA: dev=%d packet @0x%x\n", + (int)pUmDevice->index, (unsigned int)pPacket); + + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + printf ("Complete TX DMA: dev=%d packet @0x%x\n", + (int)pUmDevice->index, (unsigned int)pPacket); + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status) +{ + char buf[128]; + char lcd[4]; + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + LM_FLOW_CONTROL flow_control; + + pUmDevice->delayed_link_ind = 0; + memset (lcd, 0x0, 4); + + if (Status == LM_STATUS_LINK_DOWN) { + sprintf (buf, "eth%d: %s: NIC Link is down\n", + pUmDevice->index, pUmDevice->name); + lcd[0] = 'L'; + lcd[1] = 'N'; + lcd[2] = 'K'; + lcd[3] = '?'; + } else if (Status == LM_STATUS_LINK_ACTIVE) { + sprintf (buf, "eth%d:%s: ", pUmDevice->index, pUmDevice->name); + + if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) { + strcat (buf, "1000 Mbps "); + lcd[0] = '1'; + lcd[1] = 'G'; + lcd[2] = 'B'; + } else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS) { + strcat (buf, "100 Mbps "); + lcd[0] = '1'; + lcd[1] = '0'; + lcd[2] = '0'; + } else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { + strcat (buf, "10 Mbps "); + lcd[0] = '1'; + lcd[1] = '0'; + lcd[2] = ' '; + } + if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) { + strcat (buf, "full duplex"); + lcd[3] = 'F'; + } else { + strcat (buf, "half duplex"); + lcd[3] = 'H'; + } + strcat (buf, " link up"); + + flow_control = pDevice->FlowControl & + (LM_FLOW_CONTROL_RECEIVE_PAUSE | + LM_FLOW_CONTROL_TRANSMIT_PAUSE); + + if (flow_control) { + if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) { + strcat (buf, ", receive "); + if (flow_control & + LM_FLOW_CONTROL_TRANSMIT_PAUSE) + strcat (buf, " & transmit "); + } else { + strcat (buf, ", transmit "); + } + strcat (buf, "flow control ON"); + } else { + strcat (buf, ", flow control OFF"); + } + strcat (buf, "\n"); + printf ("%s", buf); + } +#if 0 + sysLedDsply (lcd[0], lcd[1], lcd[2], lcd[3]); +#endif + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + PUM_PACKET pUmPacket; + void *skb; + + pUmPacket = (PUM_PACKET) pPacket; + + if ((skb = pUmPacket->skbuff)) + bcm570xPktFree (pUmDevice->index, skb); + + pUmPacket->skbuff = 0; + + return LM_STATUS_SUCCESS; +} + +unsigned long MM_AnGetCurrentTime_us (PAN_STATE_INFO pAnInfo) +{ + return get_timer (0); +} + +/* + * Transform an MBUF chain into a single MBUF. + * This routine will fail if the amount of data in the + * chain overflows a transmit buffer. In that case, + * the incoming MBUF chain will be freed. This routine can + * also fail by not being able to allocate a new MBUF (including + * cluster and mbuf headers). In that case the failure is + * non-fatal. The incoming cluster chain is not freed, giving + * the caller the choice of whether to try a retransmit later. + */ +LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + void *skbnew; + int len = 0; + + if (len == 0) + return (LM_STATUS_SUCCESS); + + if (len > MAX_PACKET_SIZE) { + printf ("eth%d: xmit frame discarded, too big!, size = %d\n", + pUmDevice->index, len); + return (LM_STATUS_FAILURE); + } + + skbnew = bcm570xPktAlloc (pUmDevice->index, MAX_PACKET_SIZE); + + if (skbnew == NULL) { + pUmDevice->tx_full = 1; + printf ("eth%d: out of transmit buffers", pUmDevice->index); + return (LM_STATUS_FAILURE); + } + + /* New packet values */ + pUmPacket->skbuff = skbnew; + pUmPacket->lm_packet.u.Tx.FragCount = 1; + + return (LM_STATUS_SUCCESS); +} + +LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice) +{ + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + pUmDevice->rx_pkt = 1; + return LM_STATUS_SUCCESS; +} + +LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice) +{ + PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice; + PLM_PACKET pPacket; + PUM_PACKET pUmPacket; + void *skb; + while (TRUE) { + + pPacket = (PLM_PACKET) + QQ_PopHead (&pDevice->TxPacketXmittedQ.Container); + + if (pPacket == 0) + break; + + pUmPacket = (PUM_PACKET) pPacket; + skb = (void *)pUmPacket->skbuff; + + /* + * Free MBLK if we transmitted a fragmented packet or a + * non-fragmented packet straight from the VxWorks + * buffer pool. If packet was copied to a local transmit + * buffer, then there's no MBUF to free, just free + * the transmit buffer back to the cluster pool. + */ + + if (skb) + bcm570xPktFree (pUmDevice->index, skb); + + pUmPacket->skbuff = 0; + QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket); + pUmDevice->tx_pkt = 1; + } + if (pUmDevice->tx_full) { + if (QQ_GetEntryCnt (&pDevice->TxPacketFreeQ.Container) >= + (QQ_GetSize (&pDevice->TxPacketFreeQ.Container) >> 1)) + pUmDevice->tx_full = 0; + } + return LM_STATUS_SUCCESS; +} + +/* + * Scan an MBUF chain until we reach fragment number "frag" + * Return its length and physical address. + */ +void MM_MapTxDma + (PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, + T3_64BIT_HOST_ADDR * paddr, LM_UINT32 * len, int frag) { + PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; + *len = pPacket->PacketSize; + MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff); +} + +/* + * Convert an mbuf address, a CPU local virtual address, + * to a physical address as seen from a PCI device. Store the + * result at paddr. + */ +void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr) +{ + PUM_PACKET pUmPacket = (PUM_PACKET) pPacket; + MM_SetT3Addr (paddr, (dma_addr_t) pUmPacket->skbuff); +} + +void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr) +{ +#if (BITS_PER_LONG == 64) + paddr->High = ((unsigned long)addr) >> 32; + paddr->Low = ((unsigned long)addr) & 0xffffffff; +#else + paddr->High = 0; + paddr->Low = (unsigned long)addr; +#endif +} + +void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr) +{ + unsigned long baddr = (unsigned long)addr; +#if (BITS_PER_LONG == 64) + set_64bit_addr (paddr, baddr & 0xffffffff, baddr >> 32); +#else + set_64bit_addr (paddr, baddr, 0); +#endif +} + +/* + * This combination of `inline' and `extern' has almost the effect of a + * macro. The way to use it is to put a function definition in a header + * file with these keywords, and put another copy of the definition + * (lacking `inline' and `extern') in a library file. The definition in + * the header file will cause most calls to the function to be inlined. + * If any uses of the function remain, they will refer to the single copy + * in the library. + */ +void atomic_set (atomic_t * entry, int val) +{ + entry->counter = val; +} + +int atomic_read (atomic_t * entry) +{ + return entry->counter; +} + +void atomic_inc (atomic_t * entry) +{ + if (entry) + entry->counter++; +} + +void atomic_dec (atomic_t * entry) +{ + if (entry) + entry->counter--; +} + +void atomic_sub (int a, atomic_t * entry) +{ + if (entry) + entry->counter -= a; +} + +void atomic_add (int a, atomic_t * entry) +{ + if (entry) + entry->counter += a; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +void QQ_InitQueue (PQQ_CONTAINER pQueue, unsigned int QueueSize) +{ + pQueue->Head = 0; + pQueue->Tail = 0; + pQueue->Size = QueueSize + 1; + atomic_set (&pQueue->EntryCnt, 0); +} /* QQ_InitQueue */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +char QQ_Full (PQQ_CONTAINER pQueue) +{ + unsigned int NewHead; + + NewHead = (pQueue->Head + 1) % pQueue->Size; + + return (NewHead == pQueue->Tail); +} /* QQ_Full */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +char QQ_Empty (PQQ_CONTAINER pQueue) +{ + return (pQueue->Head == pQueue->Tail); +} /* QQ_Empty */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +unsigned int QQ_GetSize (PQQ_CONTAINER pQueue) +{ + return pQueue->Size; +} /* QQ_GetSize */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +unsigned int QQ_GetEntryCnt (PQQ_CONTAINER pQueue) +{ + return atomic_read (&pQueue->EntryCnt); +} /* QQ_GetEntryCnt */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +char QQ_PushHead (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) +{ + unsigned int Head; + + Head = (pQueue->Head + 1) % pQueue->Size; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if (Head == pQueue->Tail) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[pQueue->Head] = pEntry; + wmb (); + pQueue->Head = Head; + atomic_inc (&pQueue->EntryCnt); + + return -1; +} /* QQ_PushHead */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +char QQ_PushTail (PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) +{ + unsigned int Tail; + + Tail = pQueue->Tail; + if (Tail == 0) { + Tail = pQueue->Size; + } /* if */ + Tail--; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if (Tail == pQueue->Head) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[Tail] = pEntry; + wmb (); + pQueue->Tail = Tail; + atomic_inc (&pQueue->EntryCnt); + + return -1; +} /* QQ_PushTail */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +PQQ_ENTRY QQ_PopHead (PQQ_CONTAINER pQueue) +{ + unsigned int Head; + PQQ_ENTRY Entry; + + Head = pQueue->Head; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if (Head == pQueue->Tail) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + if (Head == 0) { + Head = pQueue->Size; + } /* if */ + Head--; + + Entry = pQueue->Array[Head]; + membar (); + + pQueue->Head = Head; + atomic_dec (&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopHead */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +PQQ_ENTRY QQ_PopTail (PQQ_CONTAINER pQueue) +{ + unsigned int Tail; + PQQ_ENTRY Entry; + + Tail = pQueue->Tail; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if (Tail == pQueue->Head) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + Entry = pQueue->Array[Tail]; + membar (); + pQueue->Tail = (Tail + 1) % pQueue->Size; + atomic_dec (&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopTail */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +PQQ_ENTRY QQ_GetHead (PQQ_CONTAINER pQueue, unsigned int Idx) +{ + if (Idx >= atomic_read (&pQueue->EntryCnt)) { + return (PQQ_ENTRY) 0; + } + + if (pQueue->Head > Idx) { + Idx = pQueue->Head - Idx; + } else { + Idx = pQueue->Size - (Idx - pQueue->Head); + } + Idx--; + + return pQueue->Array[Idx]; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +PQQ_ENTRY QQ_GetTail (PQQ_CONTAINER pQueue, unsigned int Idx) +{ + if (Idx >= atomic_read (&pQueue->EntryCnt)) { + return (PQQ_ENTRY) 0; + } + + Idx += pQueue->Tail; + if (Idx >= pQueue->Size) { + Idx = Idx - pQueue->Size; + } + + return pQueue->Array[Idx]; +} + +#endif diff --git a/drivers/net/bcm570x_autoneg.c b/drivers/net/bcm570x_autoneg.c new file mode 100644 index 0000000000..9023796aa0 --- /dev/null +++ b/drivers/net/bcm570x_autoneg.c @@ -0,0 +1,439 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ +#if !defined(CONFIG_NET_MULTI) +#if INCLUDE_TBI_SUPPORT +#include "bcm570x_autoneg.h" +#include "bcm570x_mm.h" + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +void +MM_AnTxConfig( + PAN_STATE_INFO pAnInfo) +{ + PLM_DEVICE_BLOCK pDevice; + + pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; + + REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT); + + pDevice->MacMode |= MAC_MODE_SEND_CONFIGS; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); +} + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +void +MM_AnTxIdle( + PAN_STATE_INFO pAnInfo) +{ + PLM_DEVICE_BLOCK pDevice; + + pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; + + pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); +} + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +char +MM_AnRxConfig( + PAN_STATE_INFO pAnInfo, + unsigned short *pRxConfig) +{ + PLM_DEVICE_BLOCK pDevice; + LM_UINT32 Value32; + char Retcode; + + Retcode = AN_FALSE; + + pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; + + Value32 = REG_RD(pDevice, MacCtrl.Status); + if(Value32 & MAC_STATUS_RECEIVING_CFG) + { + Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg); + *pRxConfig = (unsigned short) Value32; + + Retcode = AN_TRUE; + } + + return Retcode; +} + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +void +AutonegInit( + PAN_STATE_INFO pAnInfo) +{ + unsigned long j; + + for(j = 0; j < sizeof(AN_STATE_INFO); j++) + { + ((unsigned char *) pAnInfo)[j] = 0; + } + + /* Initialize the default advertisement register. */ + pAnInfo->mr_adv_full_duplex = 1; + pAnInfo->mr_adv_sym_pause = 1; + pAnInfo->mr_adv_asym_pause = 1; + pAnInfo->mr_an_enable = 1; +} + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +AUTONEG_STATUS +Autoneg8023z( + PAN_STATE_INFO pAnInfo) +{ + unsigned short RxConfig; + unsigned long Delta_us; + AUTONEG_STATUS AnRet; + + /* Get the current time. */ + if(pAnInfo->State == AN_STATE_UNKNOWN) + { + pAnInfo->RxConfig.AsUSHORT = 0; + pAnInfo->CurrentTime_us = 0; + pAnInfo->LinkTime_us = 0; + pAnInfo->AbilityMatchCfg = 0; + pAnInfo->AbilityMatchCnt = 0; + pAnInfo->AbilityMatch = AN_FALSE; + pAnInfo->IdleMatch = AN_FALSE; + pAnInfo->AckMatch = AN_FALSE; + } + + /* Increment the timer tick. This function is called every microsecon. */ +/* pAnInfo->CurrentTime_us++; */ + + /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */ + /* corresponding conditions are satisfied. */ + if(MM_AnRxConfig(pAnInfo, &RxConfig)) + { + if(RxConfig != pAnInfo->AbilityMatchCfg) + { + pAnInfo->AbilityMatchCfg = RxConfig; + pAnInfo->AbilityMatch = AN_FALSE; + pAnInfo->AbilityMatchCnt = 0; + } + else + { + pAnInfo->AbilityMatchCnt++; + if(pAnInfo->AbilityMatchCnt > 1) + { + pAnInfo->AbilityMatch = AN_TRUE; + pAnInfo->AbilityMatchCfg = RxConfig; + } + } + + if(RxConfig & AN_CONFIG_ACK) + { + pAnInfo->AckMatch = AN_TRUE; + } + else + { + pAnInfo->AckMatch = AN_FALSE; + } + + pAnInfo->IdleMatch = AN_FALSE; + } + else + { + pAnInfo->IdleMatch = AN_TRUE; + + pAnInfo->AbilityMatchCfg = 0; + pAnInfo->AbilityMatchCnt = 0; + pAnInfo->AbilityMatch = AN_FALSE; + pAnInfo->AckMatch = AN_FALSE; + + RxConfig = 0; + } + + /* Save the last Config. */ + pAnInfo->RxConfig.AsUSHORT = RxConfig; + + /* Default return code. */ + AnRet = AUTONEG_STATUS_OK; + + /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */ + switch(pAnInfo->State) + { + case AN_STATE_UNKNOWN: + if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an) + { + pAnInfo->CurrentTime_us = 0; + pAnInfo->State = AN_STATE_AN_ENABLE; + } + + /* Fall through.*/ + + case AN_STATE_AN_ENABLE: + pAnInfo->mr_an_complete = AN_FALSE; + pAnInfo->mr_page_rx = AN_FALSE; + + if(pAnInfo->mr_an_enable) + { + pAnInfo->LinkTime_us = 0; + pAnInfo->AbilityMatchCfg = 0; + pAnInfo->AbilityMatchCnt = 0; + pAnInfo->AbilityMatch = AN_FALSE; + pAnInfo->IdleMatch = AN_FALSE; + pAnInfo->AckMatch = AN_FALSE; + + pAnInfo->State = AN_STATE_AN_RESTART_INIT; + } + else + { + pAnInfo->State = AN_STATE_DISABLE_LINK_OK; + } + break; + + case AN_STATE_AN_RESTART_INIT: + pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; + pAnInfo->mr_np_loaded = AN_FALSE; + + pAnInfo->TxConfig.AsUSHORT = 0; + MM_AnTxConfig(pAnInfo); + + AnRet = AUTONEG_STATUS_TIMER_ENABLED; + + pAnInfo->State = AN_STATE_AN_RESTART; + + /* Fall through.*/ + + case AN_STATE_AN_RESTART: + /* Get the current time and compute the delta with the saved */ + /* link timer. */ + Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; + if(Delta_us > AN_LINK_TIMER_INTERVAL_US) + { + pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT; + } + else + { + AnRet = AUTONEG_STATUS_TIMER_ENABLED; + } + break; + + case AN_STATE_DISABLE_LINK_OK: + AnRet = AUTONEG_STATUS_DONE; + break; + + case AN_STATE_ABILITY_DETECT_INIT: + /* Note: in the state diagram, this variable is set to */ + /* mr_adv_ability<12>. Is this right?. */ + pAnInfo->mr_toggle_tx = AN_FALSE; + + /* Send the config as advertised in the advertisement register. */ + pAnInfo->TxConfig.AsUSHORT = 0; + pAnInfo->TxConfig.D5_FD = pAnInfo->mr_adv_full_duplex; + pAnInfo->TxConfig.D6_HD = pAnInfo->mr_adv_half_duplex; + pAnInfo->TxConfig.D7_PS1 = pAnInfo->mr_adv_sym_pause; + pAnInfo->TxConfig.D8_PS2 = pAnInfo->mr_adv_asym_pause; + pAnInfo->TxConfig.D12_RF1 = pAnInfo->mr_adv_remote_fault1; + pAnInfo->TxConfig.D13_RF2 = pAnInfo->mr_adv_remote_fault2; + pAnInfo->TxConfig.D15_NP = pAnInfo->mr_adv_next_page; + + MM_AnTxConfig(pAnInfo); + + pAnInfo->State = AN_STATE_ABILITY_DETECT; + + break; + + case AN_STATE_ABILITY_DETECT: + if(pAnInfo->AbilityMatch == AN_TRUE && + pAnInfo->RxConfig.AsUSHORT != 0) + { + pAnInfo->State = AN_STATE_ACK_DETECT_INIT; + } + + break; + + case AN_STATE_ACK_DETECT_INIT: + pAnInfo->TxConfig.D14_ACK = 1; + MM_AnTxConfig(pAnInfo); + + pAnInfo->State = AN_STATE_ACK_DETECT; + + /* Fall through. */ + + case AN_STATE_ACK_DETECT: + if(pAnInfo->AckMatch == AN_TRUE) + { + if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) == + (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK)) + { + pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT; + } + else + { + pAnInfo->State = AN_STATE_AN_ENABLE; + } + } + else if(pAnInfo->AbilityMatch == AN_TRUE && + pAnInfo->RxConfig.AsUSHORT == 0) + { + pAnInfo->State = AN_STATE_AN_ENABLE; + } + + break; + + case AN_STATE_COMPLETE_ACK_INIT: + /* Make sure invalid bits are not set. */ + if(pAnInfo->RxConfig.bits.D0 || pAnInfo->RxConfig.bits.D1 || + pAnInfo->RxConfig.bits.D2 || pAnInfo->RxConfig.bits.D3 || + pAnInfo->RxConfig.bits.D4 || pAnInfo->RxConfig.bits.D9 || + pAnInfo->RxConfig.bits.D10 || pAnInfo->RxConfig.bits.D11) + { + AnRet = AUTONEG_STATUS_FAILED; + break; + } + + /* Set up the link partner advertisement register. */ + pAnInfo->mr_lp_adv_full_duplex = pAnInfo->RxConfig.D5_FD; + pAnInfo->mr_lp_adv_half_duplex = pAnInfo->RxConfig.D6_HD; + pAnInfo->mr_lp_adv_sym_pause = pAnInfo->RxConfig.D7_PS1; + pAnInfo->mr_lp_adv_asym_pause = pAnInfo->RxConfig.D8_PS2; + pAnInfo->mr_lp_adv_remote_fault1 = pAnInfo->RxConfig.D12_RF1; + pAnInfo->mr_lp_adv_remote_fault2 = pAnInfo->RxConfig.D13_RF2; + pAnInfo->mr_lp_adv_next_page = pAnInfo->RxConfig.D15_NP; + + pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; + + pAnInfo->mr_toggle_tx = !pAnInfo->mr_toggle_tx; + pAnInfo->mr_toggle_rx = pAnInfo->RxConfig.bits.D11; + pAnInfo->mr_np_rx = pAnInfo->RxConfig.D15_NP; + pAnInfo->mr_page_rx = AN_TRUE; + + pAnInfo->State = AN_STATE_COMPLETE_ACK; + AnRet = AUTONEG_STATUS_TIMER_ENABLED; + + break; + + case AN_STATE_COMPLETE_ACK: + if(pAnInfo->AbilityMatch == AN_TRUE && + pAnInfo->RxConfig.AsUSHORT == 0) + { + pAnInfo->State = AN_STATE_AN_ENABLE; + break; + } + + Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; + + if(Delta_us > AN_LINK_TIMER_INTERVAL_US) + { + if(pAnInfo->mr_adv_next_page == 0 || + pAnInfo->mr_lp_adv_next_page == 0) + { + pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; + } + else + { + if(pAnInfo->TxConfig.bits.D15 == 0 && + pAnInfo->mr_np_rx == 0) + { + pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; + } + else + { + AnRet = AUTONEG_STATUS_FAILED; + } + } + } + + break; + + case AN_STATE_IDLE_DETECT_INIT: + pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; + + MM_AnTxIdle(pAnInfo); + + pAnInfo->State = AN_STATE_IDLE_DETECT; + + AnRet = AUTONEG_STATUS_TIMER_ENABLED; + + break; + + case AN_STATE_IDLE_DETECT: + if(pAnInfo->AbilityMatch == AN_TRUE && + pAnInfo->RxConfig.AsUSHORT == 0) + { + pAnInfo->State = AN_STATE_AN_ENABLE; + break; + } + + Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; + if(Delta_us > AN_LINK_TIMER_INTERVAL_US) + { +#if 0 +/* if(pAnInfo->IdleMatch == AN_TRUE) */ +/* { */ +#endif + pAnInfo->State = AN_STATE_LINK_OK; +#if 0 +/* } */ +/* else */ +/* { */ +/* AnRet = AUTONEG_STATUS_FAILED; */ +/* break; */ +/* } */ +#endif + } + + break; + + case AN_STATE_LINK_OK: + pAnInfo->mr_an_complete = AN_TRUE; + pAnInfo->mr_link_ok = AN_TRUE; + AnRet = AUTONEG_STATUS_DONE; + + break; + + case AN_STATE_NEXT_PAGE_WAIT_INIT: + break; + + case AN_STATE_NEXT_PAGE_WAIT: + break; + + default: + AnRet = AUTONEG_STATUS_FAILED; + break; + } + + return AnRet; +} +#endif /* INCLUDE_TBI_SUPPORT */ + +#endif /* !defined(CONFIG_NET_MULTI) */ diff --git a/drivers/net/bcm570x_autoneg.h b/drivers/net/bcm570x_autoneg.h new file mode 100644 index 0000000000..7830944b8a --- /dev/null +++ b/drivers/net/bcm570x_autoneg.h @@ -0,0 +1,408 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ + + +#ifndef AUTONEG_H +#define AUTONEG_H + + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +#define AN_LINK_TIMER_INTERVAL_US 9000 /* 10ms */ + +/* TRUE, FALSE */ +#define AN_TRUE 1 +#define AN_FALSE 0 + + +/******************************************************************************/ +/* Main data structure for keeping track of 802.3z auto-negotation state */ +/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */ +/******************************************************************************/ + +typedef struct +{ + /* Current auto-negotiation state. */ + unsigned long State; + #define AN_STATE_UNKNOWN 0 + #define AN_STATE_AN_ENABLE 1 + #define AN_STATE_AN_RESTART_INIT 2 + #define AN_STATE_AN_RESTART 3 + #define AN_STATE_DISABLE_LINK_OK 4 + #define AN_STATE_ABILITY_DETECT_INIT 5 + #define AN_STATE_ABILITY_DETECT 6 + #define AN_STATE_ACK_DETECT_INIT 7 + #define AN_STATE_ACK_DETECT 8 + #define AN_STATE_COMPLETE_ACK_INIT 9 + #define AN_STATE_COMPLETE_ACK 10 + #define AN_STATE_IDLE_DETECT_INIT 11 + #define AN_STATE_IDLE_DETECT 12 + #define AN_STATE_LINK_OK 13 + #define AN_STATE_NEXT_PAGE_WAIT_INIT 14 + #define AN_STATE_NEXT_PAGE_WAIT 16 + + /* Link timer. */ + unsigned long LinkTime_us; + + /* Current time. */ + unsigned long CurrentTime_us; + + /* Need these values for consistency check. */ + unsigned short AbilityMatchCfg; + + /* Ability, idle, and ack match functions. */ + unsigned long AbilityMatchCnt; + char AbilityMatch; + char IdleMatch; + char AckMatch; + + /* Tx config data */ + union + { + /* The TxConfig register is arranged as follows: */ + /* */ + /* MSB LSB */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + struct + { +#ifdef BIG_ENDIAN_HOST + unsigned int D7:1; /* PS1 */ + unsigned int D6:1; /* HD */ + unsigned int D5:1; /* FD */ + unsigned int D4:1; + unsigned int D3:1; + unsigned int D2:1; + unsigned int D1:1; + unsigned int D0:1; + unsigned int D15:1; /* NP */ + unsigned int D14:1; /* ACK */ + unsigned int D13:1; /* RF2 */ + unsigned int D12:1; /* RF1 */ + unsigned int D11:1; + unsigned int D10:1; + unsigned int D9:1; + unsigned int D8:1; /* PS2 */ +#else /* BIG_ENDIAN_HOST */ + unsigned int D8:1; /* PS2 */ + unsigned int D9:1; + unsigned int D10:1; + unsigned int D11:1; + unsigned int D12:1; /* RF1 */ + unsigned int D13:1; /* RF2 */ + unsigned int D14:1; /* ACK */ + unsigned int D15:1; /* NP */ + unsigned int D0:1; + unsigned int D1:1; + unsigned int D2:1; + unsigned int D3:1; + unsigned int D4:1; + unsigned int D5:1; /* FD */ + unsigned int D6:1; /* HD */ + unsigned int D7:1; /* PS1 */ +#endif + } bits; + + unsigned short AsUSHORT; + + #define D8_PS2 bits.D8 + #define D12_RF1 bits.D12 + #define D13_RF2 bits.D13 + #define D14_ACK bits.D14 + #define D15_NP bits.D15 + #define D5_FD bits.D5 + #define D6_HD bits.D6 + #define D7_PS1 bits.D7 + } TxConfig; + + /* Rx config data */ + union + { + /* The RxConfig register is arranged as follows: */ + /* */ + /* MSB LSB */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + struct + { +#ifdef BIG_ENDIAN_HOST + unsigned int D7:1; /* PS1 */ + unsigned int D6:1; /* HD */ + unsigned int D5:1; /* FD */ + unsigned int D4:1; + unsigned int D3:1; + unsigned int D2:1; + unsigned int D1:1; + unsigned int D0:1; + unsigned int D15:1; /* NP */ + unsigned int D14:1; /* ACK */ + unsigned int D13:1; /* RF2 */ + unsigned int D12:1; /* RF1 */ + unsigned int D11:1; + unsigned int D10:1; + unsigned int D9:1; + unsigned int D8:1; /* PS2 */ +#else /* BIG_ENDIAN_HOST */ + unsigned int D8:1; /* PS2 */ + unsigned int D9:1; + unsigned int D10:1; + unsigned int D11:1; + unsigned int D12:1; /* RF1 */ + unsigned int D13:1; /* RF2 */ + unsigned int D14:1; /* ACK */ + unsigned int D15:1; /* NP */ + unsigned int D0:1; + unsigned int D1:1; + unsigned int D2:1; + unsigned int D3:1; + unsigned int D4:1; + unsigned int D5:1; /* FD */ + unsigned int D6:1; /* HD */ + unsigned int D7:1; /* PS1 */ +#endif + } bits; + + unsigned short AsUSHORT; + } RxConfig; + + #define AN_CONFIG_NP 0x0080 + #define AN_CONFIG_ACK 0x0040 + #define AN_CONFIG_RF2 0x0020 + #define AN_CONFIG_RF1 0x0010 + #define AN_CONFIG_PS2 0x0001 + #define AN_CONFIG_PS1 0x8000 + #define AN_CONFIG_HD 0x4000 + #define AN_CONFIG_FD 0x2000 + + + /* Management registers. */ + + /* Control register. */ + union + { + struct + { + unsigned int an_enable:1; + unsigned int loopback:1; + unsigned int reset:1; + unsigned int restart_an:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_an_enable Mr0.bits.an_enable + #define mr_loopback Mr0.bits.loopback + #define mr_main_reset Mr0.bits.reset + #define mr_restart_an Mr0.bits.restart_an + } Mr0; + + /* Status register. */ + union + { + struct + { + unsigned int an_complete:1; + unsigned int link_ok:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_an_complete Mr1.bits.an_complete + #define mr_link_ok Mr1.bits.link_ok + } Mr1; + + /* Advertisement register. */ + union + { + struct + { + unsigned int reserved_4:5; + unsigned int full_duplex:1; + unsigned int half_duplex:1; + unsigned int sym_pause:1; + unsigned int asym_pause:1; + unsigned int reserved_11:3; + unsigned int remote_fault1:1; + unsigned int remote_fault2:1; + unsigned int reserved_14:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_adv_full_duplex Mr4.bits.full_duplex + #define mr_adv_half_duplex Mr4.bits.half_duplex + #define mr_adv_sym_pause Mr4.bits.sym_pause + #define mr_adv_asym_pause Mr4.bits.asym_pause + #define mr_adv_remote_fault1 Mr4.bits.remote_fault1 + #define mr_adv_remote_fault2 Mr4.bits.remote_fault2 + #define mr_adv_next_page Mr4.bits.next_page + } Mr4; + + /* Link partner advertisement register. */ + union + { + struct + { + unsigned int reserved_4:5; + unsigned int lp_full_duplex:1; + unsigned int lp_half_duplex:1; + unsigned int lp_sym_pause:1; + unsigned int lp_asym_pause:1; + unsigned int reserved_11:3; + unsigned int lp_remote_fault1:1; + unsigned int lp_remote_fault2:1; + unsigned int lp_ack:1; + unsigned int lp_next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_lp_adv_full_duplex Mr5.bits.lp_full_duplex + #define mr_lp_adv_half_duplex Mr5.bits.lp_half_duplex + #define mr_lp_adv_sym_pause Mr5.bits.lp_sym_pause + #define mr_lp_adv_asym_pause Mr5.bits.lp_asym_pause + #define mr_lp_adv_remote_fault1 Mr5.bits.lp_remote_fault1 + #define mr_lp_adv_remote_fault2 Mr5.bits.lp_remote_fault2 + #define mr_lp_adv_next_page Mr5.bits.lp_next_page + } Mr5; + + /* Auto-negotiation expansion register. */ + union + { + struct + { + unsigned int reserved_0:1; + unsigned int page_received:1; + unsigned int next_pageable:1; + unsigned int reserved_15:13; + } bits; + + unsigned short AsUSHORT; + } Mr6; + + /* Auto-negotiation next page transmit register. */ + union + { + struct + { + unsigned int code_field:11; + unsigned int toggle:1; + unsigned int ack2:1; + unsigned int message_page:1; + unsigned int reserved_14:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_np_tx Mr7.AsUSHORT + } Mr7; + + /* Auto-negotiation link partner ability register. */ + union + { + struct + { + unsigned int code_field:11; + unsigned int toggle:1; + unsigned int ack2:1; + unsigned int message_page:1; + unsigned int ack:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_lp_np_rx Mr8.AsUSHORT + } Mr8; + + /* Extended status register. */ + union + { + struct + { + unsigned int reserved_11:12; + unsigned int base1000_t_hd:1; + unsigned int base1000_t_fd:1; + unsigned int base1000_x_hd:1; + unsigned int base1000_x_fd:1; + } bits; + + unsigned short AsUSHORT; + } Mr15; + + /* Miscellaneous state variables. */ + union + { + struct + { + unsigned int toggle_tx:1; + unsigned int toggle_rx:1; + unsigned int np_rx:1; + unsigned int page_rx:1; + unsigned int np_loaded:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_toggle_tx MrMisc.bits.toggle_tx + #define mr_toggle_rx MrMisc.bits.toggle_rx + #define mr_np_rx MrMisc.bits.np_rx + #define mr_page_rx MrMisc.bits.page_rx + #define mr_np_loaded MrMisc.bits.np_loaded + } MrMisc; + + + /* Implement specifics */ + + /* Pointer to the operating system specific data structure. */ + void *pContext; +} AN_STATE_INFO, *PAN_STATE_INFO; + + +/******************************************************************************/ +/* Return code of Autoneg8023z. */ +/******************************************************************************/ + +typedef enum +{ + AUTONEG_STATUS_OK = 0, + AUTONEG_STATUS_DONE = 1, + AUTONEG_STATUS_TIMER_ENABLED = 2, + AUTONEG_STATUS_FAILED = 0xfffffff +} AUTONEG_STATUS, *PAUTONEG_STATUS; + + +/******************************************************************************/ +/* Function prototypes. */ +/******************************************************************************/ + +AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo); +void AutonegInit(PAN_STATE_INFO pAnInfo); + + +/******************************************************************************/ +/* The following functions are defined in the os-dependent module. */ +/******************************************************************************/ + +void MM_AnTxConfig(PAN_STATE_INFO pAnInfo); +void MM_AnTxIdle(PAN_STATE_INFO pAnInfo); +char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig); + + +#endif /* AUTONEG_H */ diff --git a/drivers/net/bcm570x_bits.h b/drivers/net/bcm570x_bits.h new file mode 100644 index 0000000000..615d61e98b --- /dev/null +++ b/drivers/net/bcm570x_bits.h @@ -0,0 +1,57 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef BITS_H +#define BITS_H + + +/******************************************************************************/ +/* Bit Mask definitions */ +/******************************************************************************/ +#define BIT_NONE 0x00 +#define BIT_0 0x01 +#define BIT_1 0x02 +#define BIT_2 0x04 +#define BIT_3 0x08 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x0100 +#define BIT_9 0x0200 +#define BIT_10 0x0400 +#define BIT_11 0x0800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x010000 +#define BIT_17 0x020000 +#define BIT_18 0x040000 +#define BIT_19 0x080000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x01000000 +#define BIT_25 0x02000000 +#define BIT_26 0x04000000 +#define BIT_27 0x08000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + +#endif /* BITS_H */ diff --git a/drivers/net/bcm570x_debug.h b/drivers/net/bcm570x_debug.h new file mode 100644 index 0000000000..88e209b0fb --- /dev/null +++ b/drivers/net/bcm570x_debug.h @@ -0,0 +1,109 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef VXWORKS +#include +#endif + +/******************************************************************************/ +/* Debug macros */ +/******************************************************************************/ + +/* Code path for controlling output debug messages. */ +/* Define your code path here. */ +#define CP_INIT 0x010000 +#define CP_SEND 0x020000 +#define CP_RCV 0x040000 +#define CP_INT 0x080000 +#define CP_UINIT 0x100000 +#define CP_RESET 0x200000 + +#define CP_ALL (CP_INIT | CP_SEND | CP_RCV | CP_INT | \ + CP_RESET | CP_UINIT) + +#define CP_MASK 0xffff0000 + + +/* Debug message levels. */ +#define LV_VERBOSE 0x03 +#define LV_INFORM 0x02 +#define LV_WARN 0x01 +#define LV_FATAL 0x00 + +#define LV_MASK 0xffff + + +/* Code path and messsage level combined. These are the first argument of */ +/* the DbgMessage macro. */ +#define INIT_V (CP_INIT | LV_VERBOSE) +#define INIT_I (CP_INIT | LV_INFORM) +#define INIT_W (CP_INIT | LV_WARN) +#define SEND_V (CP_SEND | LV_VERBOSE) +#define SEND_I (CP_SEND | LV_INFORM) +#define SEND_W (CP_SEND | LV_WARN) +#define RCV_V (CP_RCV | LV_VERBOSE) +#define RCV_I (CP_RCV | LV_INFORM) +#define RCV_W (CP_RCV | LV_WARN) +#define INT_V (CP_INT | LV_VERBOSE) +#define INT_I (CP_INT | LV_INFORM) +#define INT_W (CP_INT | LV_WARN) +#define UINIT_V (CP_UINIT | LV_VERBOSE) +#define UINIT_I (CP_UINIT | LV_INFORM) +#define UINIT_W (CP_UINIT | LV_WARN) +#define RESET_V (CP_RESET | LV_VERBOSE) +#define RESET_I (CP_RESET | LV_INFORM) +#define RESET_W (CP_RESET | LV_WARN) +#define CPALL_V (CP_ALL | LV_VERBOSE) +#define CPALL_I (CP_ALL | LV_INFORM) +#define CPALL_W (CP_ALL | LV_WARN) + + +/* All code path message levels. */ +#define FATAL (CP_ALL | LV_FATAL) +#define WARN (CP_ALL | LV_WARN) +#define INFORM (CP_ALL | LV_INFORM) +#define VERBOSE (CP_ALL | LV_VERBOSE) + + +/* These constants control the message output. */ +/* Set your debug message output level and code path here. */ +#ifndef DBG_MSG_CP +#define DBG_MSG_CP CP_ALL /* Where to output messages. */ +#endif + +#ifndef DBG_MSG_LV +#define DBG_MSG_LV LV_VERBOSE /* Level of message output. */ +#endif + +/* DbgMessage macro. */ +#if DBG +#define DbgMessage(CNTRL, MESSAGE) \ + if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \ + printf MESSAGE +#define DbgBreak() DbgBreakPoint() +#undef STATIC +#define STATIC +#else +#define DbgMessage(CNTRL, MESSAGE) +#define DbgBreak() +#undef STATIC +#define STATIC static +#endif /* DBG */ + + +#endif /* DEBUG_H */ diff --git a/drivers/net/bcm570x_lm.h b/drivers/net/bcm570x_lm.h new file mode 100644 index 0000000000..2ea6ca8fa9 --- /dev/null +++ b/drivers/net/bcm570x_lm.h @@ -0,0 +1,434 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef LM_H +#define LM_H + +#include "bcm570x_queue.h" +#include "bcm570x_bits.h" + +/******************************************************************************/ +/* Basic types. */ +/******************************************************************************/ + +typedef char LM_CHAR, *PLM_CHAR; +typedef unsigned int LM_UINT, *PLM_UINT; +typedef unsigned char LM_UINT8, *PLM_UINT8; +typedef unsigned short LM_UINT16, *PLM_UINT16; +typedef unsigned int LM_UINT32, *PLM_UINT32; +typedef unsigned int LM_COUNTER, *PLM_COUNTER; +typedef void LM_VOID, *PLM_VOID; +typedef char LM_BOOL, *PLM_BOOL; + +/* 64bit value. */ +typedef struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT32 High; + LM_UINT32 Low; +#else /* BIG_ENDIAN_HOST */ + LM_UINT32 Low; + LM_UINT32 High; +#endif /* !BIG_ENDIAN_HOST */ +} LM_UINT64, *PLM_UINT64; + +typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS; + +/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */ +#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize) \ + { \ + LM_UINT32 OrgLow; \ + \ + OrgLow = (pAddr)->Low; \ + (pAddr)->Low += IncSize; \ + if((pAddr)->Low < OrgLow) { \ + (pAddr)->High++; /* Wrap around. */ \ + } \ + } + +#ifndef NULL +#define NULL ((void *) 0) +#endif /* NULL */ + +#ifndef OFFSETOF +#define OFFSETOF(_s, _m) (MM_UINT_PTR(&(((_s *) 0)->_m))) +#endif /* OFFSETOF */ + +/******************************************************************************/ +/* Simple macros. */ +/******************************************************************************/ + +#define IS_ETH_BROADCAST(_pEthAddr) \ + (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff)) + +#define IS_ETH_MULTICAST(_pEthAddr) \ + (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01)) + +#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2) \ + ((((unsigned char *) (_pEtherAddr1))[0] == \ + ((unsigned char *) (_pEtherAddr2))[0]) && \ + (((unsigned char *) (_pEtherAddr1))[1] == \ + ((unsigned char *) (_pEtherAddr2))[1]) && \ + (((unsigned char *) (_pEtherAddr1))[2] == \ + ((unsigned char *) (_pEtherAddr2))[2]) && \ + (((unsigned char *) (_pEtherAddr1))[3] == \ + ((unsigned char *) (_pEtherAddr2))[3]) && \ + (((unsigned char *) (_pEtherAddr1))[4] == \ + ((unsigned char *) (_pEtherAddr2))[4]) && \ + (((unsigned char *) (_pEtherAddr1))[5] == \ + ((unsigned char *) (_pEtherAddr2))[5])) + +#define COPY_ETH_ADDRESS(_Src, _Dst) \ + ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0]; \ + ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1]; \ + ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2]; \ + ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3]; \ + ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4]; \ + ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5]; + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +#define ETHERNET_ADDRESS_SIZE 6 +#define ETHERNET_PACKET_HEADER_SIZE 14 +#define MIN_ETHERNET_PACKET_SIZE 64 /* with 4 byte crc. */ +#define MAX_ETHERNET_PACKET_SIZE 1518 /* with 4 byte crc. */ +#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60 +#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514 +#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536 /* A nice even number. */ + +#ifndef LM_MAX_MC_TABLE_SIZE +#define LM_MAX_MC_TABLE_SIZE 32 +#endif /* LM_MAX_MC_TABLE_SIZE */ +#define LM_MC_ENTRY_SIZE (ETHERNET_ADDRESS_SIZE+1) +#define LM_MC_INSTANCE_COUNT_INDEX (LM_MC_ENTRY_SIZE-1) + +/* Receive filter masks. */ +#define LM_ACCEPT_UNICAST 0x0001 +#define LM_ACCEPT_MULTICAST 0x0002 +#define LM_ACCEPT_ALL_MULTICAST 0x0004 +#define LM_ACCEPT_BROADCAST 0x0008 +#define LM_ACCEPT_ERROR_PACKET 0x0010 + +#define LM_PROMISCUOUS_MODE 0x10000 + +/******************************************************************************/ +/* PCI registers. */ +/******************************************************************************/ + +#define PCI_VENDOR_ID_REG 0x00 +#define PCI_DEVICE_ID_REG 0x02 + +#define PCI_COMMAND_REG 0x04 +#define PCI_IO_SPACE_ENABLE 0x0001 +#define PCI_MEM_SPACE_ENABLE 0x0002 +#define PCI_BUSMASTER_ENABLE 0x0004 +#define PCI_MEMORY_WRITE_INVALIDATE 0x0010 +#define PCI_PARITY_ERROR_ENABLE 0x0040 +#define PCI_SYSTEM_ERROR_ENABLE 0x0100 +#define PCI_FAST_BACK_TO_BACK_ENABLE 0x0200 + +#define PCI_STATUS_REG 0x06 +#define PCI_REV_ID_REG 0x08 + +#define PCI_CACHE_LINE_SIZE_REG 0x0c + +#define PCI_IO_BASE_ADDR_REG 0x10 +#define PCI_IO_BASE_ADDR_MASK 0xfffffff0 + +#define PCI_MEM_BASE_ADDR_LOW 0x10 +#define PCI_MEM_BASE_ADDR_HIGH 0x14 + +#define PCI_SUBSYSTEM_VENDOR_ID_REG 0x2c +#define PCI_SUBSYSTEM_ID_REG 0x2e +#define PCI_INT_LINE_REG 0x3c + +#define PCIX_CAP_REG 0x40 +#define PCIX_ENABLE_RELAXED_ORDERING BIT_17 + +/******************************************************************************/ +/* Fragment structure. */ +/******************************************************************************/ + +typedef struct { + LM_UINT32 FragSize; + LM_PHYSICAL_ADDRESS FragBuf; +} LM_FRAG, *PLM_FRAG; + +typedef struct { + /* FragCount is initialized for the caller to the maximum array size, on */ + /* return FragCount is the number of the actual fragments in the array. */ + LM_UINT32 FragCount; + + /* Total buffer size. */ + LM_UINT32 TotalSize; + + /* Fragment array buffer. */ + LM_FRAG Fragments[1]; +} LM_FRAG_LIST, *PLM_FRAG_LIST; + +#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \ + typedef struct { \ + LM_FRAG_LIST FragList; \ + LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1]; \ + } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME + +/******************************************************************************/ +/* Status codes. */ +/******************************************************************************/ + +#define LM_STATUS_SUCCESS 0 +#define LM_STATUS_FAILURE 1 + +#define LM_STATUS_INTERRUPT_ACTIVE 2 +#define LM_STATUS_INTERRUPT_NOT_ACTIVE 3 + +#define LM_STATUS_LINK_ACTIVE 4 +#define LM_STATUS_LINK_DOWN 5 +#define LM_STATUS_LINK_SETTING_MISMATCH 6 + +#define LM_STATUS_TOO_MANY_FRAGMENTS 7 +#define LM_STATUS_TRANSMIT_ABORTED 8 +#define LM_STATUS_TRANSMIT_ERROR 9 +#define LM_STATUS_RECEIVE_ABORTED 10 +#define LM_STATUS_RECEIVE_ERROR 11 +#define LM_STATUS_INVALID_PACKET_SIZE 12 +#define LM_STATUS_OUT_OF_MAP_REGISTERS 13 +#define LM_STATUS_UNKNOWN_ADAPTER 14 + +typedef LM_UINT LM_STATUS, *PLM_STATUS; + +/******************************************************************************/ +/* Requested media type. */ +/******************************************************************************/ + +#define LM_REQUESTED_MEDIA_TYPE_AUTO 0 +#define LM_REQUESTED_MEDIA_TYPE_BNC 1 +#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO 2 +#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS 3 +#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX 4 +#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS 5 +#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX 6 +#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS 7 +#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX 8 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS 9 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX 10 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS 11 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX 12 +#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK 0xfffe +#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK 0xffff + +typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE; + +/******************************************************************************/ +/* Media type. */ +/******************************************************************************/ + +#define LM_MEDIA_TYPE_UNKNOWN -1 +#define LM_MEDIA_TYPE_AUTO 0 +#define LM_MEDIA_TYPE_UTP 1 +#define LM_MEDIA_TYPE_BNC 2 +#define LM_MEDIA_TYPE_AUI 3 +#define LM_MEDIA_TYPE_FIBER 4 + +typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE; + +/******************************************************************************/ +/* Line speed. */ +/******************************************************************************/ + +#define LM_LINE_SPEED_UNKNOWN 0 +#define LM_LINE_SPEED_10MBPS 1 +#define LM_LINE_SPEED_100MBPS 2 +#define LM_LINE_SPEED_1000MBPS 3 + +typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED; + +/******************************************************************************/ +/* Duplex mode. */ +/******************************************************************************/ + +#define LM_DUPLEX_MODE_UNKNOWN 0 +#define LM_DUPLEX_MODE_HALF 1 +#define LM_DUPLEX_MODE_FULL 2 + +typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE; + +/******************************************************************************/ +/* Power state. */ +/******************************************************************************/ + +#define LM_POWER_STATE_D0 0 +#define LM_POWER_STATE_D1 1 +#define LM_POWER_STATE_D2 2 +#define LM_POWER_STATE_D3 3 + +typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE; + +/******************************************************************************/ +/* Task offloading. */ +/******************************************************************************/ + +#define LM_TASK_OFFLOAD_NONE 0x0000 +#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM 0x0001 +#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM 0x0002 +#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM 0x0004 +#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM 0x0008 +#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM 0x0010 +#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM 0x0020 +#define LM_TASK_OFFLOAD_TCP_SEGMENTATION 0x0040 + +typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD; + +/******************************************************************************/ +/* Flow control. */ +/******************************************************************************/ + +#define LM_FLOW_CONTROL_NONE 0x00 +#define LM_FLOW_CONTROL_RECEIVE_PAUSE 0x01 +#define LM_FLOW_CONTROL_TRANSMIT_PAUSE 0x02 +#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \ + LM_FLOW_CONTROL_TRANSMIT_PAUSE) + +/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE. If the */ +/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */ +/* bits are set, then flow control is enabled regardless of link partner's */ +/* flow control capability. */ +#define LM_FLOW_CONTROL_AUTO_PAUSE 0x80000000 + +typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL; + +/******************************************************************************/ +/* Wake up mode. */ +/******************************************************************************/ + +#define LM_WAKE_UP_MODE_NONE 0 +#define LM_WAKE_UP_MODE_MAGIC_PACKET 1 +#define LM_WAKE_UP_MODE_NWUF 2 +#define LM_WAKE_UP_MODE_LINK_CHANGE 4 + +typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE; + +/******************************************************************************/ +/* Counters. */ +/******************************************************************************/ + +#define LM_COUNTER_FRAMES_XMITTED_OK 0 +#define LM_COUNTER_FRAMES_RECEIVED_OK 1 +#define LM_COUNTER_ERRORED_TRANSMIT_COUNT 2 +#define LM_COUNTER_ERRORED_RECEIVE_COUNT 3 +#define LM_COUNTER_RCV_CRC_ERROR 4 +#define LM_COUNTER_ALIGNMENT_ERROR 5 +#define LM_COUNTER_SINGLE_COLLISION_FRAMES 6 +#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES 7 +#define LM_COUNTER_FRAMES_DEFERRED 8 +#define LM_COUNTER_MAX_COLLISIONS 9 +#define LM_COUNTER_RCV_OVERRUN 10 +#define LM_COUNTER_XMIT_UNDERRUN 11 +#define LM_COUNTER_UNICAST_FRAMES_XMIT 12 +#define LM_COUNTER_MULTICAST_FRAMES_XMIT 13 +#define LM_COUNTER_BROADCAST_FRAMES_XMIT 14 +#define LM_COUNTER_UNICAST_FRAMES_RCV 15 +#define LM_COUNTER_MULTICAST_FRAMES_RCV 16 +#define LM_COUNTER_BROADCAST_FRAMES_RCV 17 + +typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE; + +/******************************************************************************/ +/* Forward definition. */ +/******************************************************************************/ + +typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK; +typedef struct _LM_PACKET *PLM_PACKET; + +/******************************************************************************/ +/* Function prototypes. */ +/******************************************************************************/ + +LM_STATUS LM_GetAdapterInfo (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_InitializeAdapter (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_DisableInterrupt (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_EnableInterrupt (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS LM_ServiceInterrupts (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask); +LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); +LM_STATUS LM_MulticastDel (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); +LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetMacAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress); +LM_STATUS LM_LoopbackAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress); + +LM_UINT32 LM_GetCrcCounter (PLM_DEVICE_BLOCK pDevice); + +LM_WAKE_UP_MODE LM_PMCapabilities (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_NwufAdd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, + LM_UINT8 * pByteMask, LM_UINT8 * pPattern); +LM_STATUS LM_NwufRemove (PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, + LM_UINT8 * pByteMask, LM_UINT8 * pPattern); +LM_STATUS LM_SetPowerState (PLM_DEVICE_BLOCK pDevice, + LM_POWER_STATE PowerLevel); + +LM_VOID LM_ReadPhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, + PLM_UINT32 pData32); +LM_VOID LM_WritePhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, + LM_UINT32 Data32); + +LM_STATUS LM_ControlLoopBack (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control); +LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice); +int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration); + +/******************************************************************************/ +/* These are the OS specific functions called by LMAC. */ +/******************************************************************************/ + +LM_STATUS MM_ReadConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT16 * pValue16); +LM_STATUS MM_WriteConfig16 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT16 Value16); +LM_STATUS MM_ReadConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT32 * pValue32); +LM_STATUS MM_WriteConfig32 (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT32 Value32); +LM_STATUS MM_MapMemBase (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_MapIoBase (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateRxPackets (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateTxPackets (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_StartTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_CompleteTxDma (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_AllocateMemory (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, + PLM_VOID * pMemoryBlockVirt); +LM_STATUS MM_AllocateSharedMemory (PLM_DEVICE_BLOCK pDevice, + LM_UINT32 BlockSize, + PLM_VOID * pMemoryBlockVirt, + PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, + LM_BOOL Cached); +LM_STATUS MM_GetConfig (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateStatus (PLM_DEVICE_BLOCK pDevice, LM_STATUS Status); +LM_STATUS MM_InitializeUmPackets (PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_FreeRxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_CoalesceTxBuffer (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS LM_MbufWorkAround (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetLinkSpeed (PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType); + +#if INCLUDE_5703_A0_FIX +LM_STATUS LM_Load5703DmaWFirmware (PLM_DEVICE_BLOCK pDevice); +#endif + +#endif /* LM_H */ diff --git a/drivers/net/bcm570x_mm.h b/drivers/net/bcm570x_mm.h new file mode 100644 index 0000000000..ff5302f47c --- /dev/null +++ b/drivers/net/bcm570x_mm.h @@ -0,0 +1,158 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/******************************************************************************/ + +#ifndef MM_H +#define MM_H + +#define __raw_readl readl +#define __raw_writel writel + +#define BIG_ENDIAN_HOST 1 +#define readl(addr) (*(volatile unsigned int*)(addr)) +#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) + +/* Define memory barrier function here if needed */ +#define wmb() +#define membar() +#include +#include +#include "bcm570x_lm.h" +#include "bcm570x_queue.h" +#include "tigon3.h" +#include + +#define FALSE 0 +#define TRUE 1 +#define ERROR -1 + +#if DBG +#define STATIC +#else +#define STATIC static +#endif + +extern int MM_Packet_Desc_Size; + +#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size + +DECLARE_QUEUE_TYPE (UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT + 1); + +#define MAX_MEM 16 + +/* Synch */ +typedef int mutex_t; +typedef int spinlock_t; + +/* Embedded device control */ +typedef struct _UM_DEVICE_BLOCK { + LM_DEVICE_BLOCK lm_dev; + pci_dev_t pdev; + char *name; + void *mem_list[MAX_MEM]; + dma_addr_t dma_list[MAX_MEM]; + int mem_size_list[MAX_MEM]; + int mem_list_num; + int mtu; + int index; + int opened; + int delayed_link_ind; /* Delay link status during initial load */ + int adapter_just_inited; /* the first few seconds after init. */ + int spurious_int; /* new -- unsupported */ + int timer_interval; + int adaptive_expiry; + int crc_counter_expiry; /* new -- unsupported */ + int poll_tib_expiry; /* new -- unsupported */ + int tx_full; + int tx_queued; + int line_speed; /* in Mbps, 0 if link is down */ + UM_RX_PACKET_Q rx_out_of_buf_q; + int rx_out_of_buf; + int rx_low_buf_thresh; /* changed to rx_buf_repl_thresh */ + int rx_buf_repl_panic_thresh; + int rx_buf_align; /* new -- unsupported */ + int do_global_lock; + mutex_t global_lock; + mutex_t undi_lock; + long undi_flags; + volatile int interrupt; + int tasklet_pending; + int tasklet_busy; /* new -- unsupported */ + int rx_pkt; + int tx_pkt; +#ifdef NICE_SUPPORT /* unsupported, this is a linux ioctl */ + void (*nice_rx) (void *, void *); + void *nice_ctx; +#endif /* NICE_SUPPORT */ + int rx_adaptive_coalesce; + unsigned int rx_last_cnt; + unsigned int tx_last_cnt; + unsigned int rx_curr_coalesce_frames; + unsigned int rx_curr_coalesce_ticks; + unsigned int tx_curr_coalesce_frames; /* new -- unsupported */ +#if TIGON3_DEBUG /* new -- unsupported */ + uint tx_zc_count; + uint tx_chksum_count; + uint tx_himem_count; + uint rx_good_chksum_count; +#endif + unsigned int rx_bad_chksum_count; /* new -- unsupported */ + unsigned int rx_misc_errors; /* new -- unsupported */ +} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK; + +/* Physical/PCI DMA address */ +typedef union { + dma_addr_t dma_map; +} dma_map_t; + +/* Packet */ +typedef struct + _UM_PACKET { + LM_PACKET lm_packet; + void *skbuff; /* Address of packet buffer */ +} UM_PACKET, *PUM_PACKET; + +#define MM_ACQUIRE_UNDI_LOCK(_pDevice) +#define MM_RELEASE_UNDI_LOCK(_pDevice) +#define MM_ACQUIRE_INT_LOCK(_pDevice) +#define MM_RELEASE_INT_LOCK(_pDevice) +#define MM_UINT_PTR(_ptr) ((unsigned long) (_ptr)) + +/* Macro for setting 64bit address struct */ +#define set_64bit_addr(paddr, low, high) \ + (paddr)->Low = low; \ + (paddr)->High = high; + +/* Assume that PCI controller's view of host memory is same as host */ + +#define MEM_TO_PCI_PHYS(addr) (addr) + +extern void MM_SetAddr (LM_PHYSICAL_ADDRESS * paddr, dma_addr_t addr); +extern void MM_SetT3Addr (T3_64BIT_HOST_ADDR * paddr, dma_addr_t addr); +extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR * paddr, + LM_UINT32 * len, int frag); +extern void MM_MapRxDma (PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, + T3_64BIT_HOST_ADDR * paddr); + +/* BSP needs to provide sysUsecDelay and sysSerialPrintString */ +extern void sysSerialPrintString (char *s); +#define MM_Wait(usec) udelay(usec) + +/* Define memory barrier function here if needed */ +#define wmb() + +#if 0 +#define cpu_to_le32(val) LONGSWAP(val) +#endif +#endif /* MM_H */ diff --git a/drivers/net/bcm570x_queue.h b/drivers/net/bcm570x_queue.h new file mode 100644 index 0000000000..336b3caa4a --- /dev/null +++ b/drivers/net/bcm570x_queue.h @@ -0,0 +1,387 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* Queue functions. */ +/* void QQ_InitQueue(PQQ_CONTAINER pQueue) */ +/* char QQ_Full(PQQ_CONTAINER pQueue) */ +/* char QQ_Empty(PQQ_CONTAINER pQueue) */ +/* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) */ +/* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) */ +/* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ +/* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ +/* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) */ +/* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) */ +/* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) */ +/* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) */ +/* */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef BCM_QUEUE_H +#define BCM_QUEUE_H +#ifndef EMBEDDED +#define EMBEDDED 1 +#endif + +/******************************************************************************/ +/* Queue definitions. */ +/******************************************************************************/ + +/* Entry for queueing. */ +typedef void *PQQ_ENTRY; + +/* Linux Atomic Ops support */ +typedef struct { int counter; } atomic_t; + + +/* + * This combination of `inline' and `extern' has almost the effect of a + * macro. The way to use it is to put a function definition in a header + * file with these keywords, and put another copy of the definition + * (lacking `inline' and `extern') in a library file. The definition in + * the header file will cause most calls to the function to be inlined. + * If any uses of the function remain, they will refer to the single copy + * in the library. + */ +extern __inline void +atomic_set(atomic_t* entry, int val) +{ + entry->counter = val; +} +extern __inline int +atomic_read(atomic_t* entry) +{ + return entry->counter; +} +extern __inline void +atomic_inc(atomic_t* entry) +{ + if(entry) + entry->counter++; +} + +extern __inline void +atomic_dec(atomic_t* entry) +{ + if(entry) + entry->counter--; +} + +extern __inline void +atomic_sub(int a, atomic_t* entry) +{ + if(entry) + entry->counter -= a; +} +extern __inline void +atomic_add(int a, atomic_t* entry) +{ + if(entry) + entry->counter += a; +} + + +/* Queue header -- base type. */ +typedef struct { + unsigned int Head; + unsigned int Tail; + unsigned int Size; + atomic_t EntryCnt; + PQQ_ENTRY Array[1]; +} QQ_CONTAINER, *PQQ_CONTAINER; + + +/* Declare queue type macro. */ +#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \ + \ + typedef struct { \ + QQ_CONTAINER Container; \ + PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \ + } _QUEUE_TYPE, *P##_QUEUE_TYPE + + +/******************************************************************************/ +/* Compilation switches. */ +/******************************************************************************/ + +#if DBG +#undef QQ_NO_OVERFLOW_CHECK +#undef QQ_NO_UNDERFLOW_CHECK +#endif /* DBG */ + +#ifdef QQ_USE_MACROS +/* notdone */ +#else + +#ifdef QQ_NO_INLINE +#define __inline +#endif /* QQ_NO_INLINE */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline void +QQ_InitQueue( +PQQ_CONTAINER pQueue, +unsigned int QueueSize) { + pQueue->Head = 0; + pQueue->Tail = 0; + pQueue->Size = QueueSize+1; + atomic_set(&pQueue->EntryCnt, 0); +} /* QQ_InitQueue */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline char +QQ_Full( +PQQ_CONTAINER pQueue) { + unsigned int NewHead; + + NewHead = (pQueue->Head + 1) % pQueue->Size; + + return(NewHead == pQueue->Tail); +} /* QQ_Full */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline char +QQ_Empty( +PQQ_CONTAINER pQueue) { + return(pQueue->Head == pQueue->Tail); +} /* QQ_Empty */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline unsigned int +QQ_GetSize( +PQQ_CONTAINER pQueue) { + return pQueue->Size; +} /* QQ_GetSize */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline unsigned int +QQ_GetEntryCnt( +PQQ_CONTAINER pQueue) { + return atomic_read(&pQueue->EntryCnt); +} /* QQ_GetEntryCnt */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +extern __inline char +QQ_PushHead( +PQQ_CONTAINER pQueue, +PQQ_ENTRY pEntry) { + unsigned int Head; + + Head = (pQueue->Head + 1) % pQueue->Size; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if(Head == pQueue->Tail) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[pQueue->Head] = pEntry; + wmb(); + pQueue->Head = Head; + atomic_inc(&pQueue->EntryCnt); + + return -1; +} /* QQ_PushHead */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +extern __inline char +QQ_PushTail( +PQQ_CONTAINER pQueue, +PQQ_ENTRY pEntry) { + unsigned int Tail; + + Tail = pQueue->Tail; + if(Tail == 0) { + Tail = pQueue->Size; + } /* if */ + Tail--; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if(Tail == pQueue->Head) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[Tail] = pEntry; + wmb(); + pQueue->Tail = Tail; + atomic_inc(&pQueue->EntryCnt); + + return -1; +} /* QQ_PushTail */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_PopHead( +PQQ_CONTAINER pQueue) { + unsigned int Head; + PQQ_ENTRY Entry; + + Head = pQueue->Head; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if(Head == pQueue->Tail) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + if(Head == 0) { + Head = pQueue->Size; + } /* if */ + Head--; + + Entry = pQueue->Array[Head]; +#ifdef EMBEDDED + membar(); +#else + mb(); +#endif + pQueue->Head = Head; + atomic_dec(&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopHead */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_PopTail( +PQQ_CONTAINER pQueue) { + unsigned int Tail; + PQQ_ENTRY Entry; + + Tail = pQueue->Tail; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if(Tail == pQueue->Head) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + Entry = pQueue->Array[Tail]; +#ifdef EMBEDDED + membar(); +#else + mb(); +#endif + pQueue->Tail = (Tail + 1) % pQueue->Size; + atomic_dec(&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopTail */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_GetHead( + PQQ_CONTAINER pQueue, + unsigned int Idx) +{ + if(Idx >= atomic_read(&pQueue->EntryCnt)) + { + return (PQQ_ENTRY) 0; + } + + if(pQueue->Head > Idx) + { + Idx = pQueue->Head - Idx; + } + else + { + Idx = pQueue->Size - (Idx - pQueue->Head); + } + Idx--; + + return pQueue->Array[Idx]; +} + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_GetTail( + PQQ_CONTAINER pQueue, + unsigned int Idx) +{ + if(Idx >= atomic_read(&pQueue->EntryCnt)) + { + return (PQQ_ENTRY) 0; + } + + Idx += pQueue->Tail; + if(Idx >= pQueue->Size) + { + Idx = Idx - pQueue->Size; + } + + return pQueue->Array[Idx]; +} + +#endif /* QQ_USE_MACROS */ + + +#endif /* QUEUE_H */ diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c new file mode 100644 index 0000000000..80c4ba21a6 --- /dev/null +++ b/drivers/net/cs8900.c @@ -0,0 +1,322 @@ +/* + * Cirrus Logic CS8900A Ethernet + * + * (C) 2003 Wolfgang Denk, wd@denx.de + * Extension to synchronize ethaddr environment variable + * against value in EEPROM + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * Copyright (C) 1999 Ben Williamson + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is loaded into SRAM in bootstrap mode, where it waits + * for commands on UART1 to read and write memory, jump to code etc. + * A design goal for this program is to be entirely independent of the + * target board. Anything with a CL-PS7111 or EP7211 should be able to run + * this code in bootstrap mode. All the board specifics can be handled on + * the host. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "cs8900.h" +#include + +#ifdef CONFIG_DRIVER_CS8900 + +#if defined(CONFIG_CMD_NET) + +#undef DEBUG + +/* packet page register access functions */ + +#ifdef CS8900_BUS32 +/* we don't need 16 bit initialisation on 32 bit bus */ +#define get_reg_init_bus(x) get_reg((x)) +#else +static unsigned short get_reg_init_bus (int regno) +{ + /* force 16 bit busmode */ + volatile unsigned char c; + + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; +} +#endif + +static unsigned short get_reg (int regno) +{ + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; +} + + +static void put_reg (int regno, unsigned short val) +{ + CS8900_PPTR = regno; + CS8900_PDATA = val; +} + +static void eth_reset (void) +{ + int tmo; + unsigned short us; + + /* reset NIC */ + put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset); + + /* wait for 200ms */ + udelay (200000); + /* Wait until the chip is reset */ + + tmo = get_timer (0) + 1 * CFG_HZ; + while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) + && tmo < get_timer (0)) + /*NOP*/; +} + +static void eth_reginit (void) +{ + /* receive only error free packets addressed to this card */ + put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); + /* do not generate any interrupts on receive operations */ + put_reg (PP_RxCFG, 0); + /* do not generate any interrupts on transmit operations */ + put_reg (PP_TxCFG, 0); + /* do not generate any interrupts on buffer operations */ + put_reg (PP_BufCFG, 0); + /* enable transmitter/receiver mode */ + put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); +} + +void cs8900_get_enetaddr (uchar * addr) +{ + int i; + unsigned char env_enetaddr[6]; + char *tmp = getenv ("ethaddr"); + char *end; + + for (i=0; i<6; i++) { + env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + + /* verify chip id */ + if (get_reg_init_bus (PP_ChipID) != 0x630e) + return; + eth_reset (); + if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == + (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) { + + /* Load the MAC from EEPROM */ + for (i = 0; i < 6 / 2; i++) { + unsigned int Addr; + + Addr = get_reg (PP_IA + i * 2); + addr[i * 2] = Addr & 0xFF; + addr[i * 2 + 1] = Addr >> 8; + } + + if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 && + memcmp(env_enetaddr, addr, 6) != 0) { + printf ("\nWarning: MAC addresses don't match:\n"); + printf ("\tHW MAC address: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + addr[0], addr[1], + addr[2], addr[3], + addr[4], addr[5] ); + printf ("\t\"ethaddr\" value: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + env_enetaddr[0], env_enetaddr[1], + env_enetaddr[2], env_enetaddr[3], + env_enetaddr[4], env_enetaddr[5]) ; + debug ("### Set MAC addr from environment\n"); + memcpy (addr, env_enetaddr, 6); + } + if (!tmp) { + char ethaddr[20]; + sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + addr[0], addr[1], + addr[2], addr[3], + addr[4], addr[5]) ; + debug ("### Set environment from HW MAC addr = \"%s\"\n", ethaddr); + setenv ("ethaddr", ethaddr); + } + + } +} + +void eth_halt (void) +{ + /* disable transmitter/receiver mode */ + put_reg (PP_LineCTL, 0); + + /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ + get_reg_init_bus (PP_ChipID); +} + +int eth_init (bd_t * bd) +{ + + /* verify chip id */ + if (get_reg_init_bus (PP_ChipID) != 0x630e) { + printf ("CS8900 Ethernet chip not found?!\n"); + return 0; + } + + eth_reset (); + /* set the ethernet address */ + put_reg (PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); + put_reg (PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); + put_reg (PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); + + eth_reginit (); + return 0; +} + +/* Get a data block via Ethernet */ +extern int eth_rx (void) +{ + int i; + unsigned short rxlen; + unsigned short *addr; + unsigned short status; + + status = get_reg (PP_RER); + + if ((status & PP_RER_RxOK) == 0) + return 0; + + status = CS8900_RTDATA; /* stat */ + rxlen = CS8900_RTDATA; /* len */ + +#ifdef DEBUG + if (rxlen > PKTSIZE_ALIGN + PKTALIGN) + printf ("packet too big!\n"); +#endif + for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0; + i--) + *addr++ = CS8900_RTDATA; + if (rxlen & 1) + *addr++ = CS8900_RTDATA; + + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], rxlen); + + return rxlen; +} + +/* Send a data block via Ethernet. */ +extern int eth_send (volatile void *packet, int length) +{ + volatile unsigned short *addr; + int tmo; + unsigned short s; + +retry: + /* initiate a transmit sequence */ + CS8900_TxCMD = PP_TxCmd_TxStart_Full; + CS8900_TxLEN = length; + + /* Test to see if the chip has allocated memory for the packet */ + if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { + /* Oops... this should not happen! */ +#ifdef DEBUG + printf ("cs: unable to send packet; retrying...\n"); +#endif + for (tmo = get_timer (0) + 5 * CFG_HZ; get_timer (0) < tmo;) + /*NOP*/; + eth_reset (); + eth_reginit (); + goto retry; + } + + /* Write the contents of the packet */ + /* assume even number of bytes */ + for (addr = packet; length > 0; length -= 2) + CS8900_RTDATA = *addr++; + + /* wait for transfer to succeed */ + tmo = get_timer (0) + 5 * CFG_HZ; + while ((s = get_reg (PP_TER) & ~0x1F) == 0) { + if (get_timer (0) >= tmo) + break; + } + + /* nothing */ ; + if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { +#ifdef DEBUG + printf ("\ntransmission error %#x\n", s); +#endif + } + + return 0; +} + +static void cs8900_e2prom_ready(void) +{ + while(get_reg(PP_SelfST) & SI_BUSY); +} + +/***********************************************************/ +/* read a 16-bit word out of the EEPROM */ +/***********************************************************/ + +int cs8900_e2prom_read(unsigned char addr, unsigned short *value) +{ + cs8900_e2prom_ready(); + put_reg(PP_EECMD, EEPROM_READ_CMD | addr); + cs8900_e2prom_ready(); + *value = get_reg(PP_EEData); + + return 0; +} + + +/***********************************************************/ +/* write a 16-bit word into the EEPROM */ +/***********************************************************/ + +int cs8900_e2prom_write(unsigned char addr, unsigned short value) +{ + cs8900_e2prom_ready(); + put_reg(PP_EECMD, EEPROM_WRITE_EN); + cs8900_e2prom_ready(); + put_reg(PP_EEData, value); + put_reg(PP_EECMD, EEPROM_WRITE_CMD | addr); + cs8900_e2prom_ready(); + put_reg(PP_EECMD, EEPROM_WRITE_DIS); + cs8900_e2prom_ready(); + + return 0; +} + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/net/cs8900.h b/drivers/net/cs8900.h new file mode 100644 index 0000000000..f886d103c1 --- /dev/null +++ b/drivers/net/cs8900.h @@ -0,0 +1,258 @@ +/* + * Cirrus Logic CS8900A Ethernet + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * Copyright (C) 1999 Ben Williamson + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is loaded into SRAM in bootstrap mode, where it waits + * for commands on UART1 to read and write memory, jump to code etc. + * A design goal for this program is to be entirely independent of the + * target board. Anything with a CL-PS7111 or EP7211 should be able to run + * this code in bootstrap mode. All the board specifics can be handled on + * the host. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#ifdef CONFIG_DRIVER_CS8900 + +/* although the registers are 16 bit, they are 32-bit aligned on the + EDB7111. so we have to read them as 32-bit registers and ignore the + upper 16-bits. i'm not sure if this holds for the EDB7211. */ + +#ifdef CS8900_BUS16 + /* 16 bit aligned registers, 16 bit wide */ + #define CS8900_REG u16 + #define CS8900_OFF 0x02 + #define CS8900_BUS16_0 *(volatile u8 *)(CS8900_BASE+0x00) + #define CS8900_BUS16_1 *(volatile u8 *)(CS8900_BASE+0x01) +#elif defined(CS8900_BUS32) + /* 32 bit aligned registers, 16 bit wide (we ignore upper 16 bits) */ + #define CS8900_REG u32 + #define CS8900_OFF 0x04 +#else + #error unknown bussize ... +#endif + +#define CS8900_RTDATA *(volatile CS8900_REG *)(CS8900_BASE+0x00*CS8900_OFF) +#define CS8900_TxCMD *(volatile CS8900_REG *)(CS8900_BASE+0x02*CS8900_OFF) +#define CS8900_TxLEN *(volatile CS8900_REG *)(CS8900_BASE+0x03*CS8900_OFF) +#define CS8900_ISQ *(volatile CS8900_REG *)(CS8900_BASE+0x04*CS8900_OFF) +#define CS8900_PPTR *(volatile CS8900_REG *)(CS8900_BASE+0x05*CS8900_OFF) +#define CS8900_PDATA *(volatile CS8900_REG *)(CS8900_BASE+0x06*CS8900_OFF) + + +#define ISQ_RxEvent 0x04 +#define ISQ_TxEvent 0x08 +#define ISQ_BufEvent 0x0C +#define ISQ_RxMissEvent 0x10 +#define ISQ_TxColEvent 0x12 +#define ISQ_EventMask 0x3F + +/* packet page register offsets */ + +/* bus interface registers */ +#define PP_ChipID 0x0000 /* Chip identifier - must be 0x630E */ +#define PP_ChipRev 0x0002 /* Chip revision, model codes */ + +#define PP_IntReg 0x0022 /* Interrupt configuration */ +#define PP_IntReg_IRQ0 0x0000 /* Use INTR0 pin */ +#define PP_IntReg_IRQ1 0x0001 /* Use INTR1 pin */ +#define PP_IntReg_IRQ2 0x0002 /* Use INTR2 pin */ +#define PP_IntReg_IRQ3 0x0003 /* Use INTR3 pin */ + +/* status and control registers */ + +#define PP_RxCFG 0x0102 /* Receiver configuration */ +#define PP_RxCFG_Skip1 0x0040 /* Skip (i.e. discard) current frame */ +#define PP_RxCFG_Stream 0x0080 /* Enable streaming mode */ +#define PP_RxCFG_RxOK 0x0100 /* RxOK interrupt enable */ +#define PP_RxCFG_RxDMAonly 0x0200 /* Use RxDMA for all frames */ +#define PP_RxCFG_AutoRxDMA 0x0400 /* Select RxDMA automatically */ +#define PP_RxCFG_BufferCRC 0x0800 /* Include CRC characters in frame */ +#define PP_RxCFG_CRC 0x1000 /* Enable interrupt on CRC error */ +#define PP_RxCFG_RUNT 0x2000 /* Enable interrupt on RUNT frames */ +#define PP_RxCFG_EXTRA 0x4000 /* Enable interrupt on frames with extra data */ + +#define PP_RxCTL 0x0104 /* Receiver control */ +#define PP_RxCTL_IAHash 0x0040 /* Accept frames that match hash */ +#define PP_RxCTL_Promiscuous 0x0080 /* Accept any frame */ +#define PP_RxCTL_RxOK 0x0100 /* Accept well formed frames */ +#define PP_RxCTL_Multicast 0x0200 /* Accept multicast frames */ +#define PP_RxCTL_IA 0x0400 /* Accept frame that matches IA */ +#define PP_RxCTL_Broadcast 0x0800 /* Accept broadcast frames */ +#define PP_RxCTL_CRC 0x1000 /* Accept frames with bad CRC */ +#define PP_RxCTL_RUNT 0x2000 /* Accept runt frames */ +#define PP_RxCTL_EXTRA 0x4000 /* Accept frames that are too long */ + +#define PP_TxCFG 0x0106 /* Transmit configuration */ +#define PP_TxCFG_CRS 0x0040 /* Enable interrupt on loss of carrier */ +#define PP_TxCFG_SQE 0x0080 /* Enable interrupt on Signal Quality Error */ +#define PP_TxCFG_TxOK 0x0100 /* Enable interrupt on successful xmits */ +#define PP_TxCFG_Late 0x0200 /* Enable interrupt on "out of window" */ +#define PP_TxCFG_Jabber 0x0400 /* Enable interrupt on jabber detect */ +#define PP_TxCFG_Collision 0x0800 /* Enable interrupt if collision */ +#define PP_TxCFG_16Collisions 0x8000 /* Enable interrupt if > 16 collisions */ + +#define PP_TxCmd 0x0108 /* Transmit command status */ +#define PP_TxCmd_TxStart_5 0x0000 /* Start after 5 bytes in buffer */ +#define PP_TxCmd_TxStart_381 0x0040 /* Start after 381 bytes in buffer */ +#define PP_TxCmd_TxStart_1021 0x0080 /* Start after 1021 bytes in buffer */ +#define PP_TxCmd_TxStart_Full 0x00C0 /* Start after all bytes loaded */ +#define PP_TxCmd_Force 0x0100 /* Discard any pending packets */ +#define PP_TxCmd_OneCollision 0x0200 /* Abort after a single collision */ +#define PP_TxCmd_NoCRC 0x1000 /* Do not add CRC */ +#define PP_TxCmd_NoPad 0x2000 /* Do not pad short packets */ + +#define PP_BufCFG 0x010A /* Buffer configuration */ +#define PP_BufCFG_SWI 0x0040 /* Force interrupt via software */ +#define PP_BufCFG_RxDMA 0x0080 /* Enable interrupt on Rx DMA */ +#define PP_BufCFG_TxRDY 0x0100 /* Enable interrupt when ready for Tx */ +#define PP_BufCFG_TxUE 0x0200 /* Enable interrupt in Tx underrun */ +#define PP_BufCFG_RxMiss 0x0400 /* Enable interrupt on missed Rx packets */ +#define PP_BufCFG_Rx128 0x0800 /* Enable Rx interrupt after 128 bytes */ +#define PP_BufCFG_TxCol 0x1000 /* Enable int on Tx collision ctr overflow */ +#define PP_BufCFG_Miss 0x2000 /* Enable int on Rx miss ctr overflow */ +#define PP_BufCFG_RxDest 0x8000 /* Enable int on Rx dest addr match */ + +#define PP_LineCTL 0x0112 /* Line control */ +#define PP_LineCTL_Rx 0x0040 /* Enable receiver */ +#define PP_LineCTL_Tx 0x0080 /* Enable transmitter */ +#define PP_LineCTL_AUIonly 0x0100 /* AUI interface only */ +#define PP_LineCTL_AutoAUI10BT 0x0200 /* Autodetect AUI or 10BaseT interface */ +#define PP_LineCTL_ModBackoffE 0x0800 /* Enable modified backoff algorithm */ +#define PP_LineCTL_PolarityDis 0x1000 /* Disable Rx polarity autodetect */ +#define PP_LineCTL_2partDefDis 0x2000 /* Disable two-part defferal */ +#define PP_LineCTL_LoRxSquelch 0x4000 /* Reduce receiver squelch threshold */ + +#define PP_SelfCTL 0x0114 /* Chip self control */ +#define PP_SelfCTL_Reset 0x0040 /* Self-clearing reset */ +#define PP_SelfCTL_SWSuspend 0x0100 /* Initiate suspend mode */ +#define PP_SelfCTL_HWSleepE 0x0200 /* Enable SLEEP input */ +#define PP_SelfCTL_HWStandbyE 0x0400 /* Enable standby mode */ +#define PP_SelfCTL_HC0E 0x1000 /* use HCB0 for LINK LED */ +#define PP_SelfCTL_HC1E 0x2000 /* use HCB1 for BSTATUS LED */ +#define PP_SelfCTL_HCB0 0x4000 /* control LINK LED if HC0E set */ +#define PP_SelfCTL_HCB1 0x8000 /* control BSTATUS LED if HC1E set */ + +#define PP_BusCTL 0x0116 /* Bus control */ +#define PP_BusCTL_ResetRxDMA 0x0040 /* Reset RxDMA pointer */ +#define PP_BusCTL_DMAextend 0x0100 /* Extend DMA cycle */ +#define PP_BusCTL_UseSA 0x0200 /* Assert MEMCS16 on address decode */ +#define PP_BusCTL_MemoryE 0x0400 /* Enable memory mode */ +#define PP_BusCTL_DMAburst 0x0800 /* Limit DMA access burst */ +#define PP_BusCTL_IOCHRDYE 0x1000 /* Set IOCHRDY high impedence */ +#define PP_BusCTL_RxDMAsize 0x2000 /* Set DMA buffer size 64KB */ +#define PP_BusCTL_EnableIRQ 0x8000 /* Generate interrupt on interrupt event */ + +#define PP_TestCTL 0x0118 /* Test control */ +#define PP_TestCTL_DisableLT 0x0080 /* Disable link status */ +#define PP_TestCTL_ENDECloop 0x0200 /* Internal loopback */ +#define PP_TestCTL_AUIloop 0x0400 /* AUI loopback */ +#define PP_TestCTL_DisBackoff 0x0800 /* Disable backoff algorithm */ +#define PP_TestCTL_FDX 0x4000 /* Enable full duplex mode */ + +#define PP_ISQ 0x0120 /* Interrupt Status Queue */ + +#define PP_RER 0x0124 /* Receive event */ +#define PP_RER_IAHash 0x0040 /* Frame hash match */ +#define PP_RER_Dribble 0x0080 /* Frame had 1-7 extra bits after last byte */ +#define PP_RER_RxOK 0x0100 /* Frame received with no errors */ +#define PP_RER_Hashed 0x0200 /* Frame address hashed OK */ +#define PP_RER_IA 0x0400 /* Frame address matched IA */ +#define PP_RER_Broadcast 0x0800 /* Broadcast frame */ +#define PP_RER_CRC 0x1000 /* Frame had CRC error */ +#define PP_RER_RUNT 0x2000 /* Runt frame */ +#define PP_RER_EXTRA 0x4000 /* Frame was too long */ + +#define PP_TER 0x0128 /* Transmit event */ +#define PP_TER_CRS 0x0040 /* Carrier lost */ +#define PP_TER_SQE 0x0080 /* Signal Quality Error */ +#define PP_TER_TxOK 0x0100 /* Packet sent without error */ +#define PP_TER_Late 0x0200 /* Out of window */ +#define PP_TER_Jabber 0x0400 /* Stuck transmit? */ +#define PP_TER_NumCollisions 0x7800 /* Number of collisions */ +#define PP_TER_16Collisions 0x8000 /* > 16 collisions */ + +#define PP_BER 0x012C /* Buffer event */ +#define PP_BER_SWint 0x0040 /* Software interrupt */ +#define PP_BER_RxDMAFrame 0x0080 /* Received framed DMAed */ +#define PP_BER_Rdy4Tx 0x0100 /* Ready for transmission */ +#define PP_BER_TxUnderrun 0x0200 /* Transmit underrun */ +#define PP_BER_RxMiss 0x0400 /* Received frame missed */ +#define PP_BER_Rx128 0x0800 /* 128 bytes received */ +#define PP_BER_RxDest 0x8000 /* Received framed passed address filter */ + +#define PP_RxMiss 0x0130 /* Receiver miss counter */ + +#define PP_TxCol 0x0132 /* Transmit collision counter */ + +#define PP_LineSTAT 0x0134 /* Line status */ +#define PP_LineSTAT_LinkOK 0x0080 /* Line is connected and working */ +#define PP_LineSTAT_AUI 0x0100 /* Connected via AUI */ +#define PP_LineSTAT_10BT 0x0200 /* Connected via twisted pair */ +#define PP_LineSTAT_Polarity 0x1000 /* Line polarity OK (10BT only) */ +#define PP_LineSTAT_CRS 0x4000 /* Frame being received */ + +#define PP_SelfSTAT 0x0136 /* Chip self status */ +#define PP_SelfSTAT_33VActive 0x0040 /* supply voltage is 3.3V */ +#define PP_SelfSTAT_InitD 0x0080 /* Chip initialization complete */ +#define PP_SelfSTAT_SIBSY 0x0100 /* EEPROM is busy */ +#define PP_SelfSTAT_EEPROM 0x0200 /* EEPROM present */ +#define PP_SelfSTAT_EEPROM_OK 0x0400 /* EEPROM checks out */ +#define PP_SelfSTAT_ELPresent 0x0800 /* External address latch logic available */ +#define PP_SelfSTAT_EEsize 0x1000 /* Size of EEPROM */ + +#define PP_BusSTAT 0x0138 /* Bus status */ +#define PP_BusSTAT_TxBid 0x0080 /* Tx error */ +#define PP_BusSTAT_TxRDY 0x0100 /* Ready for Tx data */ + +#define PP_TDR 0x013C /* AUI Time Domain Reflectometer */ + +/* initiate transmit registers */ + +#define PP_TxCommand 0x0144 /* Tx Command */ +#define PP_TxLength 0x0146 /* Tx Length */ + + +/* address filter registers */ + +#define PP_LAF 0x0150 /* Logical address filter (6 bytes) */ +#define PP_IA 0x0158 /* Individual address (MAC) */ + +/* EEPROM Kram */ +#define SI_BUSY 0x0100 +#define PP_SelfST 0x0136 /* Self State register */ +#define PP_EECMD 0x0040 /* NVR Interface Command register */ +#define PP_EEData 0x0042 /* NVR Interface Data Register */ +#define EEPROM_WRITE_EN 0x00F0 +#define EEPROM_WRITE_DIS 0x0000 +#define EEPROM_WRITE_CMD 0x0100 +#define EEPROM_READ_CMD 0x0200 +#define EEPROM_ERASE_CMD 0x0300 + +extern int cs8900_e2prom_read(uchar, ushort *); +extern int cs8900_e2prom_write(uchar, ushort); + +#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c new file mode 100644 index 0000000000..d5275dceb0 --- /dev/null +++ b/drivers/net/dc2114x.c @@ -0,0 +1,771 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_TULIP) + +#include +#include +#include + +#undef DEBUG_SROM +#undef DEBUG_SROM2 + +#undef UPDATE_SROM + +/* PCI Registers. + */ +#define PCI_CFDA_PSM 0x43 + +#define CFRV_RN 0x000000f0 /* Revision Number */ + +#define WAKEUP 0x00 /* Power Saving Wakeup */ +#define SLEEP 0x80 /* Power Saving Sleep Mode */ + +#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */ + +/* Ethernet chip registers. + */ +#define DE4X5_BMR 0x000 /* Bus Mode Register */ +#define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */ +#define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */ +#define DE4X5_TRBA 0x020 /* TX Ring Base Address Reg */ +#define DE4X5_STS 0x028 /* Status Register */ +#define DE4X5_OMR 0x030 /* Operation Mode Register */ +#define DE4X5_SICR 0x068 /* SIA Connectivity Register */ +#define DE4X5_APROM 0x048 /* Ethernet Address PROM */ + +/* Register bits. + */ +#define BMR_SWR 0x00000001 /* Software Reset */ +#define STS_TS 0x00700000 /* Transmit Process State */ +#define STS_RS 0x000e0000 /* Receive Process State */ +#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ +#define OMR_SR 0x00000002 /* Start/Stop Receive */ +#define OMR_PS 0x00040000 /* Port Select */ +#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ +#define OMR_PM 0x00000080 /* Pass All Multicast */ + +/* Descriptor bits. + */ +#define R_OWN 0x80000000 /* Own Bit */ +#define RD_RER 0x02000000 /* Receive End Of Ring */ +#define RD_LS 0x00000100 /* Last Descriptor */ +#define RD_ES 0x00008000 /* Error Summary */ +#define TD_TER 0x02000000 /* Transmit End Of Ring */ +#define T_OWN 0x80000000 /* Own Bit */ +#define TD_LS 0x40000000 /* Last Segment */ +#define TD_FS 0x20000000 /* First Segment */ +#define TD_ES 0x00008000 /* Error Summary */ +#define TD_SET 0x08000000 /* Setup Packet */ + +/* The EEPROM commands include the alway-set leading bit. */ +#define SROM_WRITE_CMD 5 +#define SROM_READ_CMD 6 +#define SROM_ERASE_CMD 7 + +#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */ +#define SROM_RD 0x00004000 /* Read from Boot ROM */ +#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x4801 +#define EE_WRITE_1 0x4805 +#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ +#define SROM_SR 0x00000800 /* Select Serial ROM when set */ + +#define DT_IN 0x00000004 /* Serial Data In */ +#define DT_CLK 0x00000002 /* Serial ROM Clock */ +#define DT_CS 0x00000001 /* Serial ROM Chip Select */ + +#define POLL_DEMAND 1 + +#ifdef CONFIG_TULIP_FIX_DAVICOM +#define RESET_DM9102(dev) {\ + unsigned long i;\ + i=INL(dev, 0x0);\ + udelay(1000);\ + OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ + udelay(1000);\ +} +#else +#define RESET_DE4X5(dev) {\ + int i;\ + i=INL(dev, DE4X5_BMR);\ + udelay(1000);\ + OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ + udelay(1000);\ + OUTL(dev, i, DE4X5_BMR);\ + udelay(1000);\ + for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\ + udelay(1000);\ +} +#endif + +#define START_DE4X5(dev) {\ + s32 omr; \ + omr = INL(dev, DE4X5_OMR);\ + omr |= OMR_ST | OMR_SR;\ + OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\ +} + +#define STOP_DE4X5(dev) {\ + s32 omr; \ + omr = INL(dev, DE4X5_OMR);\ + omr &= ~(OMR_ST|OMR_SR);\ + OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ +} + +#define NUM_RX_DESC PKTBUFSRX +#ifndef CONFIG_TULIP_FIX_DAVICOM + #define NUM_TX_DESC 1 /* Number of TX descriptors */ +#else + #define NUM_TX_DESC 4 +#endif +#define RX_BUFF_SZ PKTSIZE_ALIGN + +#define TOUT_LOOP 1000000 + +#define SETUP_FRAME_LEN 192 +#define ETH_ALEN 6 + +struct de4x5_desc { + volatile s32 status; + u32 des1; + u32 buf; + u32 next; +}; + +static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring */ +static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring */ +static int rx_new; /* RX descriptor ring pointer */ +static int tx_new; /* TX descriptor ring pointer */ + +static char rxRingSize; +static char txRingSize; + +#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) +static void sendto_srom(struct eth_device* dev, u_int command, u_long addr); +static int getfrom_srom(struct eth_device* dev, u_long addr); +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr,int cmd,int cmd_len); +static int do_read_eeprom(struct eth_device *dev,u_long ioaddr,int location,int addr_len); +#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value); +static void update_srom(struct eth_device *dev, bd_t *bis); +#endif +#ifndef CONFIG_TULIP_FIX_DAVICOM +static int read_srom(struct eth_device *dev, u_long ioaddr, int index); +static void read_hw_addr(struct eth_device* dev, bd_t * bis); +#endif /* CONFIG_TULIP_FIX_DAVICOM */ +static void send_setup_frame(struct eth_device* dev, bd_t * bis); + +static int dc21x4x_init(struct eth_device* dev, bd_t* bis); +static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length); +static int dc21x4x_recv(struct eth_device* dev); +static void dc21x4x_halt(struct eth_device* dev); +#ifdef CONFIG_TULIP_SELECT_MEDIA +extern void dc21x4x_select_media(struct eth_device* dev); +#endif + +#if defined(CONFIG_E500) +#define phys_to_bus(a) (a) +#else +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#endif + +static int INL(struct eth_device* dev, u_long addr) +{ + return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); +} + +static void OUTL(struct eth_device* dev, int command, u_long addr) +{ + *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); +} + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, +#ifdef CONFIG_TULIP_FIX_DAVICOM + { PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DAVICOM_DM9102A }, +#endif + { } +}; + +int dc21x4x_initialize(bd_t *bis) +{ + int idx=0; + int card_number = 0; + unsigned int cfrv; + unsigned char timer; + pci_dev_t devbusfn; + unsigned int iobase; + unsigned short status; + struct eth_device* dev; + + while(1) { + devbusfn = pci_find_devices(supported, idx++); + if (devbusfn == -1) { + break; + } + + /* Get the chip configuration revision register. */ + pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); + +#ifndef CONFIG_TULIP_FIX_DAVICOM + if ((cfrv & CFRV_RN) < DC2114x_BRK ) { + printf("Error: The chip is not DC21143.\n"); + continue; + } +#endif + + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + status |= +#ifdef CONFIG_TULIP_USE_IO + PCI_COMMAND_IO | +#else + PCI_COMMAND_MEMORY | +#endif + PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, status); + + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_IO)) { + printf("Error: Can not enable I/O access.\n"); + continue; + } + + if (!(status & PCI_COMMAND_IO)) { + printf("Error: Can not enable I/O access.\n"); + continue; + } + + if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } + + /* Check the latency timer for values >= 0x60. */ + pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); + + if (timer < 0x60) { + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60); + } + +#ifdef CONFIG_TULIP_USE_IO + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); + iobase &= PCI_BASE_ADDRESS_IO_MASK; +#else + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); + iobase &= PCI_BASE_ADDRESS_MEM_MASK; +#endif + debug ("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); + + dev = (struct eth_device*) malloc(sizeof *dev); + +#ifdef CONFIG_TULIP_FIX_DAVICOM + sprintf(dev->name, "Davicom#%d", card_number); +#else + sprintf(dev->name, "dc21x4x#%d", card_number); +#endif + +#ifdef CONFIG_TULIP_USE_IO + dev->iobase = pci_io_to_phys(devbusfn, iobase); +#else + dev->iobase = pci_mem_to_phys(devbusfn, iobase); +#endif + dev->priv = (void*) devbusfn; + dev->init = dc21x4x_init; + dev->halt = dc21x4x_halt; + dev->send = dc21x4x_send; + dev->recv = dc21x4x_recv; + + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + + udelay(10 * 1000); + +#ifndef CONFIG_TULIP_FIX_DAVICOM + read_hw_addr(dev, bis); +#endif + eth_register(dev); + + card_number++; + } + + return card_number; +} + +static int dc21x4x_init(struct eth_device* dev, bd_t* bis) +{ + int i; + int devbusfn = (int) dev->priv; + + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + +#ifdef CONFIG_TULIP_FIX_DAVICOM + RESET_DM9102(dev); +#else + RESET_DE4X5(dev); +#endif + + if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { + printf("Error: Cannot reset ethernet controller.\n"); + return 0; + } + +#ifdef CONFIG_TULIP_SELECT_MEDIA + dc21x4x_select_media(dev); +#else + OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); +#endif + + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = cpu_to_le32(R_OWN); + rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); + rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i])); +#ifdef CONFIG_TULIP_FIX_DAVICOM + rx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &rx_ring[(i+1) % NUM_RX_DESC])); +#else + rx_ring[i].next = 0; +#endif + } + + for (i=0; i < NUM_TX_DESC; i++) { + tx_ring[i].status = 0; + tx_ring[i].des1 = 0; + tx_ring[i].buf = 0; + +#ifdef CONFIG_TULIP_FIX_DAVICOM + tx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &tx_ring[(i+1) % NUM_TX_DESC])); +#else + tx_ring[i].next = 0; +#endif + } + + rxRingSize = NUM_RX_DESC; + txRingSize = NUM_TX_DESC; + + /* Write the end of list marker to the descriptor lists. */ + rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); + tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER); + + /* Tell the adapter where the TX/RX rings are located. */ + OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA); + OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA); + + START_DE4X5(dev); + + tx_new = 0; + rx_new = 0; + + send_setup_frame(dev, bis); + + return 1; +} + +static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length) +{ + int status = -1; + int i; + + if (length <= 0) { + printf("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx error buffer not ready\n", dev->name); + goto Done; + } + } + + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet)); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); + tx_ring[tx_new].status = cpu_to_le32(T_OWN); + + OUTL(dev, POLL_DEMAND, DE4X5_TPD); + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf(".%s: tx buffer not ready\n", dev->name); + goto Done; + } + } + + if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) { +#if 0 /* test-only */ + printf("TX error status = 0x%08X\n", + le32_to_cpu(tx_ring[tx_new].status)); +#endif + tx_ring[tx_new].status = 0x0; + goto Done; + } + + status = length; + + Done: + tx_new = (tx_new+1) % NUM_TX_DESC; + return status; +} + +static int dc21x4x_recv(struct eth_device* dev) +{ + s32 status; + int length = 0; + + for ( ; ; ) { + status = (s32)le32_to_cpu(rx_ring[rx_new].status); + + if (status & R_OWN) { + break; + } + + if (status & RD_LS) { + /* Valid frame status. + */ + if (status & RD_ES) { + + /* There was an error. + */ + printf("RX error status = 0x%08X\n", status); + } else { + /* A valid frame received. + */ + length = (le32_to_cpu(rx_ring[rx_new].status) >> 16); + + /* Pass the packet up to the protocol + * layers. + */ + NetReceive(NetRxPackets[rx_new], length - 4); + } + + /* Change buffer ownership for this frame, back + * to the adapter. + */ + rx_ring[rx_new].status = cpu_to_le32(R_OWN); + } + + /* Update entry information. + */ + rx_new = (rx_new + 1) % rxRingSize; + } + + return length; +} + +static void dc21x4x_halt(struct eth_device* dev) +{ + int devbusfn = (int) dev->priv; + + STOP_DE4X5(dev); + OUTL(dev, 0, DE4X5_SICR); + + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); +} + +static void send_setup_frame(struct eth_device* dev, bd_t *bis) +{ + int i; + char setup_frame[SETUP_FRAME_LEN]; + char *pa = &setup_frame[0]; + + memset(pa, 0xff, SETUP_FRAME_LEN); + + for (i = 0; i < ETH_ALEN; i++) { + *(pa + (i & 1)) = dev->enetaddr[i]; + if (i & 0x01) { + pa += 4; + } + } + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx error buffer not ready\n", dev->name); + goto Done; + } + } + + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0])); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN); + tx_ring[tx_new].status = cpu_to_le32(T_OWN); + + OUTL(dev, POLL_DEMAND, DE4X5_TPD); + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx buffer not ready\n", dev->name); + goto Done; + } + } + + if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { + printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status)); + } + tx_new = (tx_new+1) % NUM_TX_DESC; + +Done: + return; +} + +#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) +/* SROM Read and write routines. + */ +static void +sendto_srom(struct eth_device* dev, u_int command, u_long addr) +{ + OUTL(dev, command, addr); + udelay(1); +} + +static int +getfrom_srom(struct eth_device* dev, u_long addr) +{ + s32 tmp; + + tmp = INL(dev, addr); + udelay(1); + + return tmp; +} + +/* Note: this routine returns extra data bits for size detection. */ +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len) +{ + int i; + unsigned retval = 0; + int read_cmd = location | (SROM_READ_CMD << addr_len); + + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + +#ifdef DEBUG_SROM + printf(" EEPROM read at %d ", location); +#endif + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr); + udelay(10); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + } + + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + +#ifdef DEBUG_SROM2 + printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); +#endif + + for (i = 16; i > 0; i--) { + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + udelay(10); + } + + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + +#ifdef DEBUG_SROM2 + printf(" EEPROM value at %d is %5.5x.\n", location, retval); +#endif + + return retval; +} +#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ + +/* This executes a generic EEPROM command, typically a write or write + * enable. It returns the data output from the EEPROM, and thus may + * also be used for reads. + */ +#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM) +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len) +{ + unsigned retval = 0; + +#ifdef DEBUG_SROM + printf(" EEPROM op 0x%x: ", cmd); +#endif + + sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + + /* Shift the command bits out. */ + do { + short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + sendto_srom(dev,dataval, ioaddr); + udelay(10); + +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev,ioaddr) & 15); +#endif + + sendto_srom(dev,dataval | DT_CLK, ioaddr); + udelay(10); + retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0); + } while (--cmd_len >= 0); + sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr); + + /* Terminate the EEPROM access. */ + sendto_srom(dev,SROM_RD | SROM_SR, ioaddr); + +#ifdef DEBUG_SROM + printf(" EEPROM result is 0x%5.5x.\n", retval); +#endif + + return retval; +} +#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */ + +#ifndef CONFIG_TULIP_FIX_DAVICOM +static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +{ + int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; + + return do_eeprom_cmd(dev, ioaddr, + (((SROM_READ_CMD << ee_addr_size) | index) << 16) + | 0xffff, 3 + ee_addr_size + 16); +} +#endif /* CONFIG_TULIP_FIX_DAVICOM */ + +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value) +{ + int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; + int i; + unsigned short newval; + + udelay(10*1000); /* test-only */ + +#ifdef DEBUG_SROM + printf("ee_addr_size=%d.\n", ee_addr_size); + printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); +#endif + + /* Enable programming modes. */ + do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size); + + /* Do the actual write. */ + do_eeprom_cmd(dev, ioaddr, + (((SROM_WRITE_CMD<enetaddr[0]); + int i, j = 0; + + for (i = 0; i < (ETH_ALEN >> 1); i++) { + tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i)); + *p = le16_to_cpu(tmp); + j += *p++; + } + + if ((j == 0) || (j == 0x2fffd)) { + memset (dev->enetaddr, 0, ETH_ALEN); + debug ("Warning: can't read HW address from SROM.\n"); + goto Done; + } + + return; + +Done: +#ifdef UPDATE_SROM + update_srom(dev, bis); +#endif + return; +} +#endif /* CONFIG_TULIP_FIX_DAVICOM */ + +#ifdef UPDATE_SROM +static void update_srom(struct eth_device *dev, bd_t *bis) +{ + int i; + static unsigned short eeprom[0x40] = { + 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ + 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ + 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ + 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ + 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ + 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ + }; + + /* Ethernet Addr... */ + eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff); + eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff); + eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff); + + for (i=0; i<0x40; i++) + { + write_srom(dev, DE4X5_APROM, i, eeprom[i]); + } +} +#endif /* UPDATE_SROM */ + +#endif diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c new file mode 100644 index 0000000000..6131b5c357 --- /dev/null +++ b/drivers/net/dm9000x.c @@ -0,0 +1,620 @@ +/* + dm9000.c: Version 1.2 12/15/2003 + + A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. + Copyright (C) 1997 Sten Wang + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. + +V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match + 06/22/2001 Support DM9801 progrmming + E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 + E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 + R17 = (R17 & 0xfff0) | NF + 3 + E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 + R17 = (R17 & 0xfff0) | NF + +v1.00 modify by simon 2001.9.5 + change for kernel 2.4.x + +v1.1 11/09/2001 fix force mode bug + +v1.2 03/18/2003 Weilun Huang : + Fixed phy reset. + Added tx/rx 32 bit mode. + Cleaned up for kernel merge. + +-------------------------------------- + + 12/15/2003 Initial port to u-boot by Sascha Hauer + +TODO: Homerun NIC and longrun NIC are not functional, only internal at the + moment. +*/ + +#include +#include +#include +#include + +#ifdef CONFIG_DRIVER_DM9000 + +#include "dm9000x.h" + +/* Board/System/Debug information/definition ---------------- */ + +#define DM9801_NOISE_FLOOR 0x08 +#define DM9802_NOISE_FLOOR 0x05 + +/* #define CONFIG_DM9000_DEBUG */ + +#ifdef CONFIG_DM9000_DEBUG +#define DM9000_DBG(fmt,args...) printf(fmt ,##args) +#else /* */ +#define DM9000_DBG(fmt,args...) +#endif /* */ +enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD = + 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO = + 8, DM9000_1M_HPNA = 0x10 +}; +enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2 +}; + +/* Structure/enum declaration ------------------------------- */ +typedef struct board_info { + u32 runt_length_counter; /* counter: RX length < 64byte */ + u32 long_length_counter; /* counter: RX length > 1514byte */ + u32 reset_counter; /* counter: RESET */ + u32 reset_tx_timeout; /* RESET caused by TX Timeout */ + u32 reset_rx_status; /* RESET caused by RX Statsus wrong */ + u16 tx_pkt_cnt; + u16 queue_start_addr; + u16 dbug_cnt; + u8 phy_addr; + u8 device_wait_reset; /* device state */ + u8 nic_type; /* NIC type */ + unsigned char srom[128]; +} board_info_t; +board_info_t dmfe_info; + +/* For module input parameter */ +static int media_mode = DM9000_AUTO; +static u8 nfloor = 0; + +/* function declaration ------------------------------------- */ +int eth_init(bd_t * bd); +int eth_send(volatile void *, int); +int eth_rx(void); +void eth_halt(void); +static int dm9000_probe(void); +static u16 phy_read(int); +static void phy_write(int, u16); +u16 read_srom_word(int); +static u8 DM9000_ior(int); +static void DM9000_iow(int reg, u8 value); + +/* DM9000 network board routine ---------------------------- */ + +#define DM9000_outb(d,r) ( *(volatile u8 *)r = d ) +#define DM9000_outw(d,r) ( *(volatile u16 *)r = d ) +#define DM9000_outl(d,r) ( *(volatile u32 *)r = d ) +#define DM9000_inb(r) (*(volatile u8 *)r) +#define DM9000_inw(r) (*(volatile u16 *)r) +#define DM9000_inl(r) (*(volatile u32 *)r) + +#ifdef CONFIG_DM9000_DEBUG +static void +dump_regs(void) +{ + DM9000_DBG("\n"); + DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0)); + DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1)); + DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2)); + DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3)); + DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4)); + DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5)); + DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6)); + DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(ISR)); + DM9000_DBG("\n"); +} +#endif /* */ + +/* + Search DM9000 board, allocate space and register it +*/ +int +dm9000_probe(void) +{ + u32 id_val; + id_val = DM9000_ior(DM9000_VIDL); + id_val |= DM9000_ior(DM9000_VIDH) << 8; + id_val |= DM9000_ior(DM9000_PIDL) << 16; + id_val |= DM9000_ior(DM9000_PIDH) << 24; + if (id_val == DM9000_ID) { + printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE, + id_val); + return 0; + } else { + printf("dm9000 not found at 0x%08x id: 0x%08x\n", + CONFIG_DM9000_BASE, id_val); + return -1; + } +} + +/* Set PHY operationg mode +*/ +static void +set_PHY_mode(void) +{ + u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000; + if (!(media_mode & DM9000_AUTO)) { + switch (media_mode) { + case DM9000_10MHD: + phy_reg4 = 0x21; + phy_reg0 = 0x0000; + break; + case DM9000_10MFD: + phy_reg4 = 0x41; + phy_reg0 = 0x1100; + break; + case DM9000_100MHD: + phy_reg4 = 0x81; + phy_reg0 = 0x2000; + break; + case DM9000_100MFD: + phy_reg4 = 0x101; + phy_reg0 = 0x3100; + break; + } + phy_write(4, phy_reg4); /* Set PHY media mode */ + phy_write(0, phy_reg0); /* Tmp */ + } + DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */ + DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */ +} + +/* + Init HomeRun DM9801 +*/ +static void +program_dm9801(u16 HPNA_rev) +{ + __u16 reg16, reg17, reg24, reg25; + if (!nfloor) + nfloor = DM9801_NOISE_FLOOR; + reg16 = phy_read(16); + reg17 = phy_read(17); + reg24 = phy_read(24); + reg25 = phy_read(25); + switch (HPNA_rev) { + case 0xb900: /* DM9801 E3 */ + reg16 |= 0x1000; + reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000; + break; + case 0xb901: /* DM9801 E4 */ + reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200; + reg17 = (reg17 & 0xfff0) + nfloor + 3; + break; + case 0xb902: /* DM9801 E5 */ + case 0xb903: /* DM9801 E6 */ + default: + reg16 |= 0x1000; + reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200; + reg17 = (reg17 & 0xfff0) + nfloor; + } + phy_write(16, reg16); + phy_write(17, reg17); + phy_write(25, reg25); +} + +/* + Init LongRun DM9802 +*/ +static void +program_dm9802(void) +{ + __u16 reg25; + if (!nfloor) + nfloor = DM9802_NOISE_FLOOR; + reg25 = phy_read(25); + reg25 = (reg25 & 0xff00) + nfloor; + phy_write(25, reg25); +} + +/* Identify NIC type +*/ +static void +identify_nic(void) +{ + struct board_info *db = &dmfe_info; /* Point a board information structure */ + u16 phy_reg3; + DM9000_iow(DM9000_NCR, NCR_EXT_PHY); + phy_reg3 = phy_read(3); + switch (phy_reg3 & 0xfff0) { + case 0xb900: + if (phy_read(31) == 0x4404) { + db->nic_type = HOMERUN_NIC; + program_dm9801(phy_reg3); + DM9000_DBG("found homerun NIC\n"); + } else { + db->nic_type = LONGRUN_NIC; + DM9000_DBG("found longrun NIC\n"); + program_dm9802(); + } + break; + default: + db->nic_type = FASTETHER_NIC; + break; + } + DM9000_iow(DM9000_NCR, 0); +} + +/* General Purpose dm9000 reset routine */ +static void +dm9000_reset(void) +{ + DM9000_DBG("resetting\n"); + DM9000_iow(DM9000_NCR, NCR_RST); + udelay(1000); /* delay 1ms */ +} + +/* Initilize dm9000 board +*/ +int +eth_init(bd_t * bd) +{ + int i, oft, lnk; + DM9000_DBG("eth_init()\n"); + + /* RESET device */ + dm9000_reset(); + dm9000_probe(); + + /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ + identify_nic(); + + /* GPIO0 on pre-activate PHY */ + DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */ + + /* Set PHY */ + set_PHY_mode(); + + /* Program operating register */ + DM9000_iow(DM9000_NCR, 0x0); /* only intern phy supported by now */ + DM9000_iow(DM9000_TCR, 0); /* TX Polling clear */ + DM9000_iow(DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ + DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); /* Flow Control : High/Low Water */ + DM9000_iow(DM9000_FCR, 0x0); /* SH FIXME: This looks strange! Flow Control */ + DM9000_iow(DM9000_SMCR, 0); /* Special Mode */ + DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */ + DM9000_iow(DM9000_ISR, 0x0f); /* Clear interrupt status */ + + /* Set Node address */ + for (i = 0; i < 6; i++) + ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i); + + if (is_zero_ether_addr(bd->bi_enetaddr) || + is_multicast_ether_addr(bd->bi_enetaddr)) { + /* try reading from environment */ + u8 i; + char *s, *e; + s = getenv ("ethaddr"); + for (i = 0; i < 6; ++i) { + bd->bi_enetaddr[i] = s ? + simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + } + + printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0], + bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3], + bd->bi_enetaddr[4], bd->bi_enetaddr[5]); + for (i = 0, oft = 0x10; i < 6; i++, oft++) + DM9000_iow(oft, bd->bi_enetaddr[i]); + for (i = 0, oft = 0x16; i < 8; i++, oft++) + DM9000_iow(oft, 0xff); + + /* read back mac, just to be sure */ + for (i = 0, oft = 0x10; i < 6; i++, oft++) + DM9000_DBG("%02x:", DM9000_ior(oft)); + DM9000_DBG("\n"); + + /* Activate DM9000 */ + DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */ + DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */ + i = 0; + while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */ + udelay(1000); + i++; + if (i == 10000) { + printf("could not establish link\n"); + return 0; + } + } + + /* see what we've got */ + lnk = phy_read(17) >> 12; + printf("operating at "); + switch (lnk) { + case 1: + printf("10M half duplex "); + break; + case 2: + printf("10M full duplex "); + break; + case 4: + printf("100M half duplex "); + break; + case 8: + printf("100M full duplex "); + break; + default: + printf("unknown: %d ", lnk); + break; + } + printf("mode\n"); + return 0; +} + +/* + Hardware start transmission. + Send a packet to media from the upper layer. +*/ +int +eth_send(volatile void *packet, int length) +{ + char *data_ptr; + u32 tmplen, i; + int tmo; + DM9000_DBG("eth_send: length: %d\n", length); + for (i = 0; i < length; i++) { + if (i % 8 == 0) + DM9000_DBG("\nSend: 02x: ", i); + DM9000_DBG("%02x ", ((unsigned char *) packet)[i]); + } DM9000_DBG("\n"); + + /* Move data to DM9000 TX RAM */ + data_ptr = (char *) packet; + DM9000_outb(DM9000_MWCMD, DM9000_IO); + +#ifdef CONFIG_DM9000_USE_8BIT + /* Byte mode */ + for (i = 0; i < length; i++) + DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_16BIT + tmplen = (length + 1) / 2; + for (i = 0; i < tmplen; i++) + DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_32BIT + tmplen = (length + 3) / 4; + for (i = 0; i < tmplen; i++) + DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); + +#endif /* */ + + /* Set TX length to DM9000 */ + DM9000_iow(DM9000_TXPLL, length & 0xff); + DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff); + + /* Issue TX polling command */ + DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ + + /* wait for end of transmission */ + tmo = get_timer(0) + 5 * CFG_HZ; + while (DM9000_ior(DM9000_TCR) & TCR_TXREQ) { + if (get_timer(0) >= tmo) { + printf("transmission timeout\n"); + break; + } + } + DM9000_DBG("transmit done\n\n"); + return 0; +} + +/* + Stop the interface. + The interface is stopped when it is brought. +*/ +void +eth_halt(void) +{ + DM9000_DBG("eth_halt\n"); + + /* RESET devie */ + phy_write(0, 0x8000); /* PHY RESET */ + DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */ + DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */ + DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */ +} + +/* + Received a packet and pass to upper layer +*/ +int +eth_rx(void) +{ + u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; + u16 RxStatus, RxLen = 0; + u32 tmplen, i; +#ifdef CONFIG_DM9000_USE_32BIT + u32 tmpdata; +#endif + + /* Check packet ready or not */ + DM9000_ior(DM9000_MRCMDX); /* Dummy read */ + rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */ + if (rxbyte == 0) + return 0; + + /* Status check: this byte must be 0 or 1 */ + if (rxbyte > 1) { + DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */ + DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ + DM9000_DBG("rx status check: %d\n", rxbyte); + } + DM9000_DBG("receiving packet\n"); + + /* A packet ready now & Get status/length */ + DM9000_outb(DM9000_MRCMD, DM9000_IO); + +#ifdef CONFIG_DM9000_USE_8BIT + RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); + RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_16BIT + RxStatus = DM9000_inw(DM9000_DATA); + RxLen = DM9000_inw(DM9000_DATA); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_32BIT + tmpdata = DM9000_inl(DM9000_DATA); + RxStatus = tmpdata; + RxLen = tmpdata >> 16; + +#endif /* */ + DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); + + /* Move data from DM9000 */ + /* Read received packet from RX SRAM */ +#ifdef CONFIG_DM9000_USE_8BIT + for (i = 0; i < RxLen; i++) + rdptr[i] = DM9000_inb(DM9000_DATA); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_16BIT + tmplen = (RxLen + 1) / 2; + for (i = 0; i < tmplen; i++) + ((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA); + +#endif /* */ +#ifdef CONFIG_DM9000_USE_32BIT + tmplen = (RxLen + 3) / 4; + for (i = 0; i < tmplen; i++) + ((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA); + +#endif /* */ + if ((RxStatus & 0xbf00) || (RxLen < 0x40) + || (RxLen > DM9000_PKT_MAX)) { + if (RxStatus & 0x100) { + printf("rx fifo error\n"); + } + if (RxStatus & 0x200) { + printf("rx crc error\n"); + } + if (RxStatus & 0x8000) { + printf("rx length error\n"); + } + if (RxLen > DM9000_PKT_MAX) { + printf("rx length too big\n"); + dm9000_reset(); + } + } else { + + /* Pass to upper layer */ + DM9000_DBG("passing packet to upper layer\n"); + NetReceive(NetRxPackets[0], RxLen); + return RxLen; + } + return 0; +} + +/* + Read a word data from SROM +*/ +u16 +read_srom_word(int offset) +{ + DM9000_iow(DM9000_EPAR, offset); + DM9000_iow(DM9000_EPCR, 0x4); + udelay(8000); + DM9000_iow(DM9000_EPCR, 0x0); + return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8)); +} + +void +write_srom_word(int offset, u16 val) +{ + DM9000_iow(DM9000_EPAR, offset); + DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff)); + DM9000_iow(DM9000_EPDRL, (val & 0xff)); + DM9000_iow(DM9000_EPCR, 0x12); + udelay(8000); + DM9000_iow(DM9000_EPCR, 0); +} + + +/* + Read a byte from I/O port +*/ +static u8 +DM9000_ior(int reg) +{ + DM9000_outb(reg, DM9000_IO); + return DM9000_inb(DM9000_DATA); +} + +/* + Write a byte to I/O port +*/ +static void +DM9000_iow(int reg, u8 value) +{ + DM9000_outb(reg, DM9000_IO); + DM9000_outb(value, DM9000_DATA); +} + +/* + Read a word from phyxcer +*/ +static u16 +phy_read(int reg) +{ + u16 val; + + /* Fill the phyxcer register into REG_0C */ + DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); + DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */ + udelay(100); /* Wait read complete */ + DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */ + val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL); + + /* The read data keeps on REG_0D & REG_0E */ + DM9000_DBG("phy_read(%d): %d\n", reg, val); + return val; +} + +/* + Write a word to phyxcer +*/ +static void +phy_write(int reg, u16 value) +{ + + /* Fill the phyxcer register into REG_0C */ + DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); + + /* Fill the written data into REG_0D & REG_0E */ + DM9000_iow(DM9000_EPDRL, (value & 0xff)); + DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff)); + DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */ + udelay(500); /* Wait write complete */ + DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value); +} +#endif /* CONFIG_DRIVER_DM9000 */ diff --git a/drivers/net/dm9000x.h b/drivers/net/dm9000x.h new file mode 100644 index 0000000000..f47ff8cb34 --- /dev/null +++ b/drivers/net/dm9000x.h @@ -0,0 +1,119 @@ +/* + * dm9000 Ethernet + */ + +#ifdef CONFIG_DRIVER_DM9000 + +#define DM9000_ID 0x90000A46 +#define DM9000_PKT_MAX 1536 /* Received packet max size */ +#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */ + +/* although the registers are 16 bit, they are 32-bit aligned. + */ + +#define DM9000_NCR 0x00 +#define DM9000_NSR 0x01 +#define DM9000_TCR 0x02 +#define DM9000_TSR1 0x03 +#define DM9000_TSR2 0x04 +#define DM9000_RCR 0x05 +#define DM9000_RSR 0x06 +#define DM9000_ROCR 0x07 +#define DM9000_BPTR 0x08 +#define DM9000_FCTR 0x09 +#define DM9000_FCR 0x0A +#define DM9000_EPCR 0x0B +#define DM9000_EPAR 0x0C +#define DM9000_EPDRL 0x0D +#define DM9000_EPDRH 0x0E +#define DM9000_WCR 0x0F + +#define DM9000_PAR 0x10 +#define DM9000_MAR 0x16 + +#define DM9000_GPCR 0x1e +#define DM9000_GPR 0x1f +#define DM9000_TRPAL 0x22 +#define DM9000_TRPAH 0x23 +#define DM9000_RWPAL 0x24 +#define DM9000_RWPAH 0x25 + +#define DM9000_VIDL 0x28 +#define DM9000_VIDH 0x29 +#define DM9000_PIDL 0x2A +#define DM9000_PIDH 0x2B + +#define DM9000_CHIPR 0x2C +#define DM9000_SMCR 0x2F + +#define DM9000_PHY 0x40 /* PHY address 0x01 */ + +#define DM9000_MRCMDX 0xF0 +#define DM9000_MRCMD 0xF2 +#define DM9000_MRRL 0xF4 +#define DM9000_MRRH 0xF5 +#define DM9000_MWCMDX 0xF6 +#define DM9000_MWCMD 0xF8 +#define DM9000_MWRL 0xFA +#define DM9000_MWRH 0xFB +#define DM9000_TXPLL 0xFC +#define DM9000_TXPLH 0xFD +#define DM9000_ISR 0xFE +#define DM9000_IMR 0xFF + +#define NCR_EXT_PHY (1<<7) +#define NCR_WAKEEN (1<<6) +#define NCR_FCOL (1<<4) +#define NCR_FDX (1<<3) +#define NCR_LBK (3<<1) +#define NCR_RST (1<<0) + +#define NSR_SPEED (1<<7) +#define NSR_LINKST (1<<6) +#define NSR_WAKEST (1<<5) +#define NSR_TX2END (1<<3) +#define NSR_TX1END (1<<2) +#define NSR_RXOV (1<<1) + +#define TCR_TJDIS (1<<6) +#define TCR_EXCECM (1<<5) +#define TCR_PAD_DIS2 (1<<4) +#define TCR_CRC_DIS2 (1<<3) +#define TCR_PAD_DIS1 (1<<2) +#define TCR_CRC_DIS1 (1<<1) +#define TCR_TXREQ (1<<0) + +#define TSR_TJTO (1<<7) +#define TSR_LC (1<<6) +#define TSR_NC (1<<5) +#define TSR_LCOL (1<<4) +#define TSR_COL (1<<3) +#define TSR_EC (1<<2) + +#define RCR_WTDIS (1<<6) +#define RCR_DIS_LONG (1<<5) +#define RCR_DIS_CRC (1<<4) +#define RCR_ALL (1<<3) +#define RCR_RUNT (1<<2) +#define RCR_PRMSC (1<<1) +#define RCR_RXEN (1<<0) + +#define RSR_RF (1<<7) +#define RSR_MF (1<<6) +#define RSR_LCS (1<<5) +#define RSR_RWTO (1<<4) +#define RSR_PLE (1<<3) +#define RSR_AE (1<<2) +#define RSR_CE (1<<1) +#define RSR_FOE (1<<0) + +#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 ) +#define FCTR_LWOT(ot) ( ot & 0xf ) + +#define IMR_PAR (1<<7) +#define IMR_ROOM (1<<3) +#define IMR_ROM (1<<2) +#define IMR_PTM (1<<1) +#define IMR_PRM (1<<0) + +#endif diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c new file mode 100644 index 0000000000..f0741da82b --- /dev/null +++ b/drivers/net/e1000.c @@ -0,0 +1,3016 @@ +/************************************************************************** +Inter Pro 1000 for ppcboot/das-u-boot +Drivers are port from Intel's Linux driver e1000-4.3.15 +and from Etherboot pro 1000 driver by mrakes at vivato dot net +tested on both gig copper and gig fiber boards +***************************************************************************/ +/******************************************************************************* + + + Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Linux NICS + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ +/* + * Copyright (C) Archway Digital Solutions. + * + * written by Chrsitopher Li or + * 2/9/2002 + * + * Copyright (C) Linux Networx. + * Massive upgrade to work with the new intel gigabit NICs. + * + */ + +#include "e1000.h" + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_E1000) + +#define TOUT_LOOP 100000 + +#undef virt_to_bus +#define virt_to_bus(x) ((unsigned long)x) +#define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) +#define mdelay(n) udelay((n)*1000) + +#define E1000_DEFAULT_PBA 0x00000030 + +/* NIC specific static variables go here */ + +static char tx_pool[128 + 16]; +static char rx_pool[128 + 16]; +static char packet[2096]; + +static struct e1000_tx_desc *tx_base; +static struct e1000_rx_desc *rx_base; + +static int tx_tail; +static int rx_tail, rx_last; + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_COPPER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_FIBER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_COPPER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_LOM}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_COPPER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM}, +}; + +/* Function forward declarations */ +static int e1000_setup_link(struct eth_device *nic); +static int e1000_setup_fiber_link(struct eth_device *nic); +static int e1000_setup_copper_link(struct eth_device *nic); +static int e1000_phy_setup_autoneg(struct e1000_hw *hw); +static void e1000_config_collision_dist(struct e1000_hw *hw); +static int e1000_config_mac_to_phy(struct e1000_hw *hw); +static int e1000_config_fc_after_link_up(struct e1000_hw *hw); +static int e1000_check_for_link(struct eth_device *nic); +static int e1000_wait_autoneg(struct e1000_hw *hw); +static void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, + uint16_t * duplex); +static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, + uint16_t * phy_data); +static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, + uint16_t phy_data); +static void e1000_phy_hw_reset(struct e1000_hw *hw); +static int e1000_phy_reset(struct e1000_hw *hw); +static int e1000_detect_gig_phy(struct e1000_hw *hw); + +#define E1000_WRITE_REG(a, reg, value) (writel((value), ((a)->hw_addr + E1000_##reg))) +#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_##reg)) +#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) (\ + writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2)))) +#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ + readl((a)->hw_addr + E1000_##reg + ((offset) << 2))) +#define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);} + +#ifndef CONFIG_AP1000 /* remove for warnings */ +/****************************************************************************** + * Raises the EEPROM's clock input. + * + * hw - Struct containing variables accessed by shared code + * eecd - EECD's current value + *****************************************************************************/ +static void +e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t * eecd) +{ + /* Raise the clock input to the EEPROM (by setting the SK bit), and then + * wait 50 microseconds. + */ + *eecd = *eecd | E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, *eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); +} + +/****************************************************************************** + * Lowers the EEPROM's clock input. + * + * hw - Struct containing variables accessed by shared code + * eecd - EECD's current value + *****************************************************************************/ +static void +e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t * eecd) +{ + /* Lower the clock input to the EEPROM (by clearing the SK bit), and then + * wait 50 microseconds. + */ + *eecd = *eecd & ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, *eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); +} + +/****************************************************************************** + * Shift data bits out to the EEPROM. + * + * hw - Struct containing variables accessed by shared code + * data - data to send to the EEPROM + * count - number of bits to shift out + *****************************************************************************/ +static void +e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count) +{ + uint32_t eecd; + uint32_t mask; + + /* We need to shift "count" bits out to the EEPROM. So, value in the + * "data" parameter will be shifted out to the EEPROM one bit at a time. + * In order to do this, "data" must be broken down into bits. + */ + mask = 0x01 << (count - 1); + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + do { + /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", + * and then raising and then lowering the clock (the SK bit controls + * the clock input to the EEPROM). A "0" is shifted out to the EEPROM + * by setting "DI" to "0" and then raising and then lowering the clock. + */ + eecd &= ~E1000_EECD_DI; + + if (data & mask) + eecd |= E1000_EECD_DI; + + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + + udelay(50); + + e1000_raise_ee_clk(hw, &eecd); + e1000_lower_ee_clk(hw, &eecd); + + mask = mask >> 1; + + } while (mask); + + /* We leave the "DI" bit set to "0" when we leave this routine. */ + eecd &= ~E1000_EECD_DI; + E1000_WRITE_REG(hw, EECD, eecd); +} + +/****************************************************************************** + * Shift data bits in from the EEPROM + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static uint16_t +e1000_shift_in_ee_bits(struct e1000_hw *hw) +{ + uint32_t eecd; + uint32_t i; + uint16_t data; + + /* In order to read a register from the EEPROM, we need to shift 16 bits + * in from the EEPROM. Bits are "shifted in" by raising the clock input to + * the EEPROM (setting the SK bit), and then reading the value of the "DO" + * bit. During this "shifting in" process the "DI" bit should always be + * clear.. + */ + + eecd = E1000_READ_REG(hw, EECD); + + eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + data = 0; + + for (i = 0; i < 16; i++) { + data = data << 1; + e1000_raise_ee_clk(hw, &eecd); + + eecd = E1000_READ_REG(hw, EECD); + + eecd &= ~(E1000_EECD_DI); + if (eecd & E1000_EECD_DO) + data |= 1; + + e1000_lower_ee_clk(hw, &eecd); + } + + return data; +} + +/****************************************************************************** + * Prepares EEPROM for access + * + * hw - Struct containing variables accessed by shared code + * + * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This + * function should be called before issuing a command to the EEPROM. + *****************************************************************************/ +static void +e1000_setup_eeprom(struct e1000_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + /* Clear SK and DI */ + eecd &= ~(E1000_EECD_SK | E1000_EECD_DI); + E1000_WRITE_REG(hw, EECD, eecd); + + /* Set CS */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); +} + +/****************************************************************************** + * Returns EEPROM to a "standby" state + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +e1000_standby_eeprom(struct e1000_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + + /* Deselct EEPROM */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); + + /* Clock high */ + eecd |= E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); + + /* Select EEPROM */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); + + /* Clock low */ + eecd &= ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(50); +} + +/****************************************************************************** + * Reads a 16 bit word from the EEPROM. + * + * hw - Struct containing variables accessed by shared code + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + *****************************************************************************/ +static int +e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t * data) +{ + uint32_t eecd; + uint32_t i = 0; + int large_eeprom = FALSE; + + /* Request EEPROM Access */ + if (hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + if (eecd & E1000_EECD_SIZE) + large_eeprom = TRUE; + eecd |= E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + eecd = E1000_READ_REG(hw, EECD); + while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { + i++; + udelay(10); + eecd = E1000_READ_REG(hw, EECD); + } + if (!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + return -E1000_ERR_EEPROM; + } + } + + /* Prepare the EEPROM for reading */ + e1000_setup_eeprom(hw); + + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3); + e1000_shift_out_ee_bits(hw, offset, (large_eeprom) ? 8 : 6); + + /* Read the data */ + *data = e1000_shift_in_ee_bits(hw); + + /* End this read operation */ + e1000_standby_eeprom(hw); + + /* Stop requesting EEPROM access */ + if (hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + } + + return 0; +} + +#if 0 +static void +e1000_eeprom_cleanup(struct e1000_hw *hw) +{ + uint32_t eecd; + + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + E1000_WRITE_REG(hw, EECD, eecd); + e1000_raise_ee_clk(hw, &eecd); + e1000_lower_ee_clk(hw, &eecd); +} + +static uint16_t +e1000_wait_eeprom_done(struct e1000_hw *hw) +{ + uint32_t eecd; + uint32_t i; + + e1000_standby_eeprom(hw); + for (i = 0; i < 200; i++) { + eecd = E1000_READ_REG(hw, EECD); + if (eecd & E1000_EECD_DO) + return (TRUE); + udelay(5); + } + return (FALSE); +} + +static int +e1000_write_eeprom(struct e1000_hw *hw, uint16_t Reg, uint16_t Data) +{ + uint32_t eecd; + int large_eeprom = FALSE; + int i = 0; + + /* Request EEPROM Access */ + if (hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + if (eecd & E1000_EECD_SIZE) + large_eeprom = TRUE; + eecd |= E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + eecd = E1000_READ_REG(hw, EECD); + while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { + i++; + udelay(5); + eecd = E1000_READ_REG(hw, EECD); + } + if (!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + return FALSE; + } + } + e1000_setup_eeprom(hw); + e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); + e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); + e1000_standby_eeprom(hw); + e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); + e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 8 : 6); + e1000_shift_out_ee_bits(hw, Data, 16); + if (!e1000_wait_eeprom_done(hw)) { + return FALSE; + } + e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); + e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); + e1000_eeprom_cleanup(hw); + + /* Stop requesting EEPROM access */ + if (hw->mac_type > e1000_82544) { + eecd = E1000_READ_REG(hw, EECD); + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + } + i = 0; + eecd = E1000_READ_REG(hw, EECD); + while (((eecd & E1000_EECD_GNT)) && (i < 500)) { + i++; + udelay(10); + eecd = E1000_READ_REG(hw, EECD); + } + if ((eecd & E1000_EECD_GNT)) { + DEBUGOUT("Could not release EEPROM grant\n"); + } + return TRUE; +} +#endif + +/****************************************************************************** + * Verifies that the EEPROM has a valid checksum + * + * hw - Struct containing variables accessed by shared code + * + * Reads the first 64 16 bit words of the EEPROM and sums the values read. + * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is + * valid. + *****************************************************************************/ +static int +e1000_validate_eeprom_checksum(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint16_t checksum = 0; + uint16_t i, eeprom_data; + + DEBUGFUNC(); + + for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { + if (e1000_read_eeprom(hw, i, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + checksum += eeprom_data; + } + + if (checksum == (uint16_t) EEPROM_SUM) { + return 0; + } else { + DEBUGOUT("EEPROM Checksum Invalid\n"); + return -E1000_ERR_EEPROM; + } +} +#endif /* #ifndef CONFIG_AP1000 */ + +/****************************************************************************** + * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the + * second function of dual function devices + * + * nic - Struct containing variables accessed by shared code + *****************************************************************************/ +static int +e1000_read_mac_addr(struct eth_device *nic) +{ +#ifndef CONFIG_AP1000 + struct e1000_hw *hw = nic->priv; + uint16_t offset; + uint16_t eeprom_data; + int i; + + DEBUGFUNC(); + + for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { + offset = i >> 1; + if (e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + nic->enetaddr[i] = eeprom_data & 0xff; + nic->enetaddr[i + 1] = (eeprom_data >> 8) & 0xff; + } + if ((hw->mac_type == e1000_82546) && + (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { + /* Invert the last bit if this is the second device */ + nic->enetaddr[5] += 1; + } +#else + /* + * The AP1000's e1000 has no eeprom; the MAC address is stored in the + * environment variables. Currently this does not support the addition + * of a PMC e1000 card, which is certainly a possibility, so this should + * be updated to properly use the env variable only for the onboard e1000 + */ + + int ii; + char *s, *e; + + DEBUGFUNC(); + + s = getenv ("ethaddr"); + if (s == NULL){ + return -E1000_ERR_EEPROM; + } + else{ + for(ii = 0; ii < 6; ii++) { + nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0; + if (s){ + s = (*e) ? e + 1 : e; + } + } + } +#endif + return 0; +} + +/****************************************************************************** + * Initializes receive address filters. + * + * hw - Struct containing variables accessed by shared code + * + * Places the MAC address in receive address register 0 and clears the rest + * of the receive addresss registers. Clears the multicast table. Assumes + * the receiver is in reset when the routine is called. + *****************************************************************************/ +static void +e1000_init_rx_addrs(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t i; + uint32_t addr_low; + uint32_t addr_high; + + DEBUGFUNC(); + + /* Setup the receive address. */ + DEBUGOUT("Programming MAC Address into RAR[0]\n"); + addr_low = (nic->enetaddr[0] | + (nic->enetaddr[1] << 8) | + (nic->enetaddr[2] << 16) | (nic->enetaddr[3] << 24)); + + addr_high = (nic->enetaddr[4] | (nic->enetaddr[5] << 8) | E1000_RAH_AV); + + E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low); + E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high); + + /* Zero out the other 15 receive addresses. */ + DEBUGOUT("Clearing RAR[1-15]\n"); + for (i = 1; i < E1000_RAR_ENTRIES; i++) { + E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); + E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); + } +} + +/****************************************************************************** + * Clears the VLAN filer table + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +e1000_clear_vfta(struct e1000_hw *hw) +{ + uint32_t offset; + + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) + E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); +} + +/****************************************************************************** + * Set the mac type member in the hw struct. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static int +e1000_set_mac_type(struct e1000_hw *hw) +{ + DEBUGFUNC(); + + switch (hw->device_id) { + case E1000_DEV_ID_82542: + switch (hw->revision_id) { + case E1000_82542_2_0_REV_ID: + hw->mac_type = e1000_82542_rev2_0; + break; + case E1000_82542_2_1_REV_ID: + hw->mac_type = e1000_82542_rev2_1; + break; + default: + /* Invalid 82542 revision ID */ + return -E1000_ERR_MAC_TYPE; + } + break; + case E1000_DEV_ID_82543GC_FIBER: + case E1000_DEV_ID_82543GC_COPPER: + hw->mac_type = e1000_82543; + break; + case E1000_DEV_ID_82544EI_COPPER: + case E1000_DEV_ID_82544EI_FIBER: + case E1000_DEV_ID_82544GC_COPPER: + case E1000_DEV_ID_82544GC_LOM: + hw->mac_type = e1000_82544; + break; + case E1000_DEV_ID_82540EM: + case E1000_DEV_ID_82540EM_LOM: + hw->mac_type = e1000_82540; + break; + case E1000_DEV_ID_82545EM_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + hw->mac_type = e1000_82545; + break; + case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82546EB_FIBER: + hw->mac_type = e1000_82546; + break; + default: + /* Should never have loaded on this device */ + return -E1000_ERR_MAC_TYPE; + } + return E1000_SUCCESS; +} + +/****************************************************************************** + * Reset the transmit and receive units; mask and clear all interrupts. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +void +e1000_reset_hw(struct e1000_hw *hw) +{ + uint32_t ctrl; + uint32_t ctrl_ext; + uint32_t icr; + uint32_t manc; + + DEBUGFUNC(); + + /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ + if (hw->mac_type == e1000_82542_rev2_0) { + DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); + pci_write_config_word(hw->pdev, PCI_COMMAND, + hw-> + pci_cmd_word & ~PCI_COMMAND_INVALIDATE); + } + + /* Clear interrupt mask to stop board from generating interrupts */ + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, IMC, 0xffffffff); + + /* Disable the Transmit and Receive units. Then delay to allow + * any pending transactions to complete before we hit the MAC with + * the global reset. + */ + E1000_WRITE_REG(hw, RCTL, 0); + E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); + + /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ + hw->tbi_compatibility_on = FALSE; + + /* Delay to allow any outstanding PCI transactions to complete before + * resetting the device + */ + mdelay(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); + +#if 0 + if (hw->mac_type > e1000_82543) + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); + else +#endif + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); + + /* 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 */ + mdelay(2); + } else { + /* Wait for EEPROM reload (it happens automatically) */ + mdelay(4); + /* Dissable HW ARPs on ASF enabled adapters */ + manc = E1000_READ_REG(hw, MANC); + manc &= ~(E1000_MANC_ARP_EN); + E1000_WRITE_REG(hw, MANC, manc); + } + + /* Clear interrupt mask to stop board from generating interrupts */ + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, IMC, 0xffffffff); + + /* Clear any pending interrupt events. */ + icr = E1000_READ_REG(hw, ICR); + + /* If MWI was previously enabled, reenable it. */ + if (hw->mac_type == e1000_82542_rev2_0) { + pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); + } +} + +/****************************************************************************** + * Performs basic configuration of the adapter. + * + * hw - Struct containing variables accessed by shared code + * + * Assumes that the controller has previously been reset and is in a + * post-reset uninitialized state. Initializes the receive address registers, + * multicast table, and VLAN filter table. Calls routines to setup link + * configuration and flow control settings. Clears all on-chip counters. Leaves + * the transmit and receive units disabled and uninitialized. + *****************************************************************************/ +static int +e1000_init_hw(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t ctrl, status; + uint32_t i; + int32_t ret_val; + uint16_t pcix_cmd_word; + uint16_t pcix_stat_hi_word; + uint16_t cmd_mmrbc; + uint16_t stat_mmrbc; + e1000_bus_type bus_type = e1000_bus_type_unknown; + + DEBUGFUNC(); +#if 0 + /* Initialize Identification LED */ + ret_val = e1000_id_led_init(hw); + if (ret_val < 0) { + DEBUGOUT("Error Initializing Identification LED\n"); + return ret_val; + } +#endif + /* 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; + } + + /* Disabling VLAN filtering. */ + DEBUGOUT("Initializing the IEEE VLAN\n"); + E1000_WRITE_REG(hw, VET, 0); + + e1000_clear_vfta(hw); + + /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ + if (hw->mac_type == e1000_82542_rev2_0) { + DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); + pci_write_config_word(hw->pdev, PCI_COMMAND, + hw-> + pci_cmd_word & ~PCI_COMMAND_INVALIDATE); + E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); + E1000_WRITE_FLUSH(hw); + mdelay(5); + } + + /* Setup the receive address. This involves initializing all of the Receive + * Address Registers (RARs 0 - 15). + */ + e1000_init_rx_addrs(nic); + + /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ + if (hw->mac_type == e1000_82542_rev2_0) { + E1000_WRITE_REG(hw, RCTL, 0); + E1000_WRITE_FLUSH(hw); + mdelay(1); + pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); + } + + /* Zero out the Multicast HASH table */ + DEBUGOUT("Zeroing the MTA\n"); + for (i = 0; i < E1000_MC_TBL_SIZE; i++) + E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); + +#if 0 + /* Set the PCI priority bit correctly in the CTRL register. This + * determines if the adapter gives priority to receives, or if it + * gives equal priority to transmits and receives. + */ + if (hw->dma_fairness) { + ctrl = E1000_READ_REG(hw, CTRL); + E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); + } +#endif + if (hw->mac_type >= e1000_82543) { + status = E1000_READ_REG(hw, STATUS); + bus_type = (status & E1000_STATUS_PCIX_MODE) ? + e1000_bus_type_pcix : e1000_bus_type_pci; + } + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if (bus_type == e1000_bus_type_pcix) { + pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, + &pcix_cmd_word); + pci_read_config_word(hw->pdev, 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; + pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, + pcix_cmd_word); + } + } + + /* Call a subroutine to configure the link and setup flow control. */ + ret_val = e1000_setup_link(nic); + + /* Set the transmit descriptor write-back policy */ + if (hw->mac_type > e1000_82544) { + ctrl = E1000_READ_REG(hw, TXDCTL); + ctrl = + (ctrl & ~E1000_TXDCTL_WTHRESH) | + E1000_TXDCTL_FULL_TX_DESC_WB; + E1000_WRITE_REG(hw, TXDCTL, ctrl); + } +#if 0 + /* Clear all of the statistics registers (clear on read). It is + * important that we do this after we have tried to establish link + * because the symbol error count will increment wildly if there + * is no link. + */ + e1000_clear_hw_cntrs(hw); +#endif + + return ret_val; +} + +/****************************************************************************** + * Configures flow control and link settings. + * + * hw - Struct containing variables accessed by shared code + * + * Determines which flow control settings to use. Calls the apropriate media- + * specific link configuration function. Configures the flow control settings. + * Assuming the adapter has a valid link partner, a valid link should be + * established. Assumes the hardware has previously been reset and the + * transmitter and receiver are not enabled. + *****************************************************************************/ +static int +e1000_setup_link(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t ctrl_ext; + int32_t ret_val; + uint16_t eeprom_data; + + DEBUGFUNC(); + +#ifndef CONFIG_AP1000 + /* Read and store word 0x0F of the EEPROM. This word contains bits + * that determine the hardware's default PAUSE (flow control) mode, + * a bit that determines whether the HW defaults to enabling or + * disabling auto-negotiation, and the direction of the + * SW defined pins. If there is no SW over-ride of the flow + * control setting, then the variable hw->fc will + * be initialized based on a value in the EEPROM. + */ + if (e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } +#else + /* we have to hardcode the proper value for our hardware. */ + /* this value is for the 82540EM pci card used for prototyping, and it works. */ + eeprom_data = 0xb220; +#endif + + if (hw->fc == e1000_fc_default) { + if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) + hw->fc = e1000_fc_none; + else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == + EEPROM_WORD0F_ASM_DIR) + hw->fc = e1000_fc_tx_pause; + else + hw->fc = e1000_fc_full; + } + + /* We want to save off the original Flow Control configuration just + * in case we get disconnected and then reconnected into a different + * hub or switch with different Flow Control capabilities. + */ + if (hw->mac_type == e1000_82542_rev2_0) + hw->fc &= (~e1000_fc_tx_pause); + + if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) + hw->fc &= (~e1000_fc_rx_pause); + + hw->original_fc = hw->fc; + + DEBUGOUT("After fix-ups FlowControl is now = %x\n", hw->fc); + + /* Take the 4 bits from EEPROM word 0x0F that determine the initial + * polarity value for the SW controlled pins, and setup the + * Extended Device Control reg with that info. + * This is needed because one of the SW controlled pins is used for + * signal detection. So this should be done before e1000_setup_pcs_link() + * or e1000_phy_setup() is called. + */ + if (hw->mac_type == e1000_82543) { + ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << + SWDPIO__EXT_SHIFT); + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + } + + /* Call the necessary subroutine to configure the link. */ + ret_val = (hw->media_type == e1000_media_type_fiber) ? + e1000_setup_fiber_link(nic) : e1000_setup_copper_link(nic); + if (ret_val < 0) { + return ret_val; + } + + /* Initialize the flow control address, type, and PAUSE timer + * registers to their default values. This is done even if flow + * control is disabled, because it does not hurt anything to + * initialize these registers. + */ + DEBUGOUT + ("Initializing the Flow Control address, type and timer regs\n"); + + E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); + E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); + E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); + E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); + + /* Set the flow control receive threshold registers. Normally, + * these registers will be set to a default threshold that may be + * adjusted later by the driver's runtime code. However, if the + * ability to transmit pause frames in not enabled, then these + * registers will be set to 0. + */ + if (!(hw->fc & e1000_fc_tx_pause)) { + E1000_WRITE_REG(hw, FCRTL, 0); + E1000_WRITE_REG(hw, FCRTH, 0); + } else { + /* We need to set up the Receive Threshold high and low water marks + * as well as (optionally) enabling the transmission of XON frames. + */ + if (hw->fc_send_xon) { + E1000_WRITE_REG(hw, FCRTL, + (hw->fc_low_water | E1000_FCRTL_XONE)); + E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); + } else { + E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water); + E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); + } + } + return ret_val; +} + +/****************************************************************************** + * Sets up link for a fiber based adapter + * + * hw - Struct containing variables accessed by shared code + * + * Manipulates Physical Coding Sublayer functions in order to configure + * link. Assumes the hardware has been previously reset and the transmitter + * and receiver are not enabled. + *****************************************************************************/ +static int +e1000_setup_fiber_link(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t ctrl; + uint32_t status; + uint32_t txcw = 0; + uint32_t i; + uint32_t signal; + int32_t ret_val; + + DEBUGFUNC(); + /* On adapters with a MAC newer that 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 + */ + ctrl = E1000_READ_REG(hw, CTRL); + if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) + signal = E1000_CTRL_SWDPIN1; + else + signal = 0; + + printf("signal for %s is %x (ctrl %08x)!!!!\n", nic->name, signal, + ctrl); + /* Take the link out of reset */ + ctrl &= ~(E1000_CTRL_LRST); + + e1000_config_collision_dist(hw); + + /* Check for a software override of the flow control settings, and setup + * the device accordingly. If auto-negotiation is enabled, then software + * will have to set the "PAUSE" bits to the correct value in the Tranmsit + * Config Word Register (TXCW) and re-start auto-negotiation. However, if + * auto-negotiation is disabled, then software will have to manually + * configure the two flow control enable bits in the CTRL register. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, but + * not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but we do + * not support receiving pause frames). + * 3: Both Rx and TX flow control (symmetric) are enabled. + */ + switch (hw->fc) { + case e1000_fc_none: + /* Flow control is completely disabled by a software over-ride. */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); + break; + case e1000_fc_rx_pause: + /* RX Flow control is enabled and TX Flow control is disabled by a + * software over-ride. Since there really isn't a way to advertise + * that we are capable of RX Pause ONLY, we will advertise that we + * support both symmetric and asymmetric RX PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + case e1000_fc_tx_pause: + /* TX Flow control is enabled, and RX Flow control is disabled, by a + * software over-ride. + */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); + break; + case e1000_fc_full: + /* Flow control (both RX and TX) is enabled by a software over-ride. */ + txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + return -E1000_ERR_CONFIG; + break; + } + + /* Since auto-negotiation is enabled, take the link out of reset (the link + * will be in reset, because we previously reset the chip). This will + * restart auto-negotiation. If auto-neogtiation is successful then the + * link-up status bit will be set and the flow control enable bits (RFCE + * and TFCE) will be set according to their negotiated value. + */ + DEBUGOUT("Auto-negotiation enabled (%#x)\n", txcw); + + E1000_WRITE_REG(hw, TXCW, txcw); + E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + + hw->txcw = txcw; + mdelay(1); + + /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" + * 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). + */ + if ((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { + DEBUGOUT("Looking for Link\n"); + for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { + mdelay(10); + status = E1000_READ_REG(hw, STATUS); + 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(nic); + if (ret_val < 0) { + DEBUGOUT("Error while checking for link\n"); + return ret_val; + } + hw->autoneg_failed = 0; + } else { + hw->autoneg_failed = 0; + DEBUGOUT("Valid Link Found\n"); + } + } else { + DEBUGOUT("No Signal Detected\n"); + return -E1000_ERR_NOLINK; + } + return 0; +} + +/****************************************************************************** +* Detects which PHY is present and the speed and duplex +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int +e1000_setup_copper_link(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t ctrl; + int32_t ret_val; + uint16_t i; + uint16_t phy_data; + + DEBUGFUNC(); + + ctrl = E1000_READ_REG(hw, CTRL); + /* With 82543, we need to force speed and duplex on the MAC equal to what + * the PHY speed and duplex configuration is. In addition, we need to + * perform a hardware reset on the PHY to take it out of reset. + */ + if (hw->mac_type > e1000_82543) { + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, CTRL, ctrl); + } else { + ctrl |= + (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); + E1000_WRITE_REG(hw, CTRL, ctrl); + e1000_phy_hw_reset(hw); + } + + /* Make sure we have a valid PHY */ + ret_val = e1000_detect_gig_phy(hw); + if (ret_val < 0) { + DEBUGOUT("Error, did not detect valid phy.\n"); + return ret_val; + } + DEBUGOUT("Phy ID = %x \n", hw->phy_id); + + /* 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; + +#if 0 + /* 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; + } +#else + phy_data |= M88E1000_PSCR_AUTO_X_MODE; +#endif + +#if 0 + /* 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; +#else + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; +#endif + 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 (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; + /* 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; + } + + /* 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; + } + + /* 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. + */ + /* 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; + + 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 (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; + } +#if 0 + /* 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"); + return ret_val; + } + } +#else + /* If we do not wait for autonegtation to complete I + * do not see a valid link status. + */ + ret_val = e1000_wait_autoneg(hw); + if (ret_val < 0) { + DEBUGOUT("Error while waiting for autoneg to complete\n"); + return ret_val; + } +#endif + + /* 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 (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 + * if we are on 82543. If we + * are on newer silicon, we only need to configure + * collision distance in the Transmit Control Register. + * 2) Set up flow control on the MAC to that established with + * the link partner. + */ + if (hw->mac_type >= e1000_82544) { + e1000_config_collision_dist(hw); + } else { + ret_val = e1000_config_mac_to_phy(hw); + if (ret_val < 0) { + DEBUGOUT + ("Error configuring MAC to PHY settings\n"); + return ret_val; + } + } + ret_val = e1000_config_fc_after_link_up(hw); + if (ret_val < 0) { + DEBUGOUT("Error Configuring Flow Control\n"); + return ret_val; + } + DEBUGOUT("Valid link established!!!\n"); + return 0; + } + udelay(10); + } + + DEBUGOUT("Unable to establish link!!!\n"); + return -E1000_ERR_NOLINK; +} + +/****************************************************************************** +* Configures PHY autoneg and flow control advertisement settings +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int +e1000_phy_setup_autoneg(struct e1000_hw *hw) +{ + uint16_t mii_autoneg_adv_reg; + uint16_t mii_1000t_ctrl_reg; + + DEBUGFUNC(); + + /* 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; + } + + /* 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; + } + + /* Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for + * autoneg_advertised software override. Since we can advertise + * a plethora of combinations, we need to check each bit + * individually. + */ + + /* First we clear all the 10/100 mb speed bits in the Auto-Neg + * Advertisement Register (Address 4) and the 1000 mb speed bits in + * the 1000Base-T Control Register (Address 9). + */ + mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; + mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; + + DEBUGOUT("autoneg_advertised %x\n", hw->autoneg_advertised); + + /* Do we want to advertise 10 Mb Half Duplex? */ + if (hw->autoneg_advertised & ADVERTISE_10_HALF) { + DEBUGOUT("Advertise 10mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; + } + + /* Do we want to advertise 10 Mb Full Duplex? */ + if (hw->autoneg_advertised & ADVERTISE_10_FULL) { + DEBUGOUT("Advertise 10mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; + } + + /* Do we want to advertise 100 Mb Half Duplex? */ + if (hw->autoneg_advertised & ADVERTISE_100_HALF) { + DEBUGOUT("Advertise 100mb Half duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; + } + + /* Do we want to advertise 100 Mb Full Duplex? */ + if (hw->autoneg_advertised & ADVERTISE_100_FULL) { + DEBUGOUT("Advertise 100mb Full duplex\n"); + mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; + } + + /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ + if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { + DEBUGOUT + ("Advertise 1000mb Half duplex requested, request denied!\n"); + } + + /* Do we want to advertise 1000 Mb Full Duplex? */ + if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { + DEBUGOUT("Advertise 1000mb Full duplex\n"); + mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; + } + + /* Check for a software override of the flow control settings, and + * setup the PHY advertisement registers accordingly. If + * auto-negotiation is enabled, then software will have to set the + * "PAUSE" bits to the correct value in the Auto-Negotiation + * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * but we do not support receiving pause frames). + * 3: Both Rx and TX flow control (symmetric) are enabled. + * other: No software override. The flow control configuration + * in the EEPROM is used. + */ + switch (hw->fc) { + case e1000_fc_none: /* 0 */ + /* Flow control (RX & TX) is completely disabled by a + * software over-ride. + */ + mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_rx_pause: /* 1 */ + /* RX Flow control is enabled, and TX Flow control is + * disabled, by a software over-ride. + */ + /* Since there really isn't a way to advertise that we are + * capable of RX Pause ONLY, we will advertise that we + * support both symmetric and asymmetric RX PAUSE. Later + * (in e1000_config_fc_after_link_up) we will disable the + *hw's ability to send PAUSE frames. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + case e1000_fc_tx_pause: /* 2 */ + /* TX Flow control is enabled, and RX Flow control is + * disabled, by a software over-ride. + */ + mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; + mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; + break; + case e1000_fc_full: /* 3 */ + /* Flow control (both RX and TX) is enabled by a software + * over-ride. + */ + mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + 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; + } + + DEBUGOUT("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; +} + +/****************************************************************************** +* Sets the collision distance in the Transmit Control register +* +* hw - Struct containing variables accessed by shared code +* +* Link should have been established previously. Reads the speed and duplex +* information from the Device Status register. +******************************************************************************/ +static void +e1000_config_collision_dist(struct e1000_hw *hw) +{ + uint32_t tctl; + + tctl = E1000_READ_REG(hw, TCTL); + + tctl &= ~E1000_TCTL_COLD; + tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; + + E1000_WRITE_REG(hw, TCTL, tctl); + E1000_WRITE_FLUSH(hw); +} + +/****************************************************************************** +* Sets MAC speed and duplex settings to reflect the those in the PHY +* +* hw - Struct containing variables accessed by shared code +* mii_reg - data to write to the MII control register +* +* The contents of the PHY register containing the needed information need to +* be passed in. +******************************************************************************/ +static int +e1000_config_mac_to_phy(struct e1000_hw *hw) +{ + uint32_t ctrl; + uint16_t phy_data; + + DEBUGFUNC(); + + /* Read the Device Control Register and set the bits to Force Speed + * and Duplex. + */ + ctrl = E1000_READ_REG(hw, CTRL); + ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); + + /* Set up duplex in the Device Control and Transmit Control + * registers depending on negotiated values. + */ + if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if (phy_data & M88E1000_PSSR_DPLX) + ctrl |= E1000_CTRL_FD; + else + ctrl &= ~E1000_CTRL_FD; + + e1000_config_collision_dist(hw); + + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) + ctrl |= E1000_CTRL_SPD_1000; + else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) + ctrl |= E1000_CTRL_SPD_100; + /* Write the configured values back to the Device Control Reg. */ + E1000_WRITE_REG(hw, CTRL, ctrl); + return 0; +} + +/****************************************************************************** + * Forces the MAC's flow control settings. + * + * hw - Struct containing variables accessed by shared code + * + * Sets the TFCE and RFCE bits in the device control register to reflect + * the adapter settings. TFCE and RFCE need to be explicitly set by + * software when a Copper PHY is used because autonegotiation is managed + * by the PHY rather than the MAC. Software must also configure these + * bits when link is forced on a fiber connection. + *****************************************************************************/ +static int +e1000_force_mac_fc(struct e1000_hw *hw) +{ + uint32_t ctrl; + + DEBUGFUNC(); + + /* Get the current configuration of the Device Control Register */ + ctrl = E1000_READ_REG(hw, CTRL); + + /* Because we didn't get link via the internal auto-negotiation + * mechanism (we either forced link or we got link via PHY + * auto-neg), we have to manually enable/disable transmit an + * receive flow control. + * + * The "Case" statement below enables/disable flow control + * according to the "hw->fc" parameter. + * + * The possible values of the "fc" parameter are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause + * frames but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames + * frames but we do not receive pause frames). + * 3: Both Rx and TX flow control (symmetric) is enabled. + * other: No other values should be possible at this point. + */ + + switch (hw->fc) { + case e1000_fc_none: + ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); + break; + case e1000_fc_rx_pause: + ctrl &= (~E1000_CTRL_TFCE); + ctrl |= E1000_CTRL_RFCE; + break; + case e1000_fc_tx_pause: + ctrl &= (~E1000_CTRL_RFCE); + ctrl |= E1000_CTRL_TFCE; + break; + case e1000_fc_full: + ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + return -E1000_ERR_CONFIG; + } + + /* Disable TX Flow Control for 82542 (rev 2.0) */ + if (hw->mac_type == e1000_82542_rev2_0) + ctrl &= (~E1000_CTRL_TFCE); + + E1000_WRITE_REG(hw, CTRL, ctrl); + return 0; +} + +/****************************************************************************** + * Configures flow control settings after link is established + * + * hw - Struct containing variables accessed by shared code + * + * Should be called immediately after a valid link has been established. + * Forces MAC flow control settings if link was forced. When in MII/GMII mode + * and autonegotiation is enabled, the MAC flow control settings will be set + * based on the flow control negotiated by the PHY. In TBI mode, the TFCE + * and RFCE bits will be automaticaly set to the negotiated flow control mode. + *****************************************************************************/ +static int +e1000_config_fc_after_link_up(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t mii_status_reg; + uint16_t mii_nway_adv_reg; + uint16_t mii_nway_lp_ability_reg; + uint16_t speed; + uint16_t duplex; + + DEBUGFUNC(); + + /* Check for the case where we have fiber media and auto-neg failed + * so we had to force link. In this case, we need to force the + * configuration of the MAC to match the "fc" parameter. + */ + if ((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) { + ret_val = e1000_force_mac_fc(hw); + if (ret_val < 0) { + DEBUGOUT("Error forcing flow control settings\n"); + return ret_val; + } + } + + /* Check for the case where we have copper media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if (hw->media_type == e1000_media_type_copper) { + /* Read the MII Status Register and check to see if AutoNeg + * 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 (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { + /* The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement Register + * (Address 4) and the Auto_Negotiation Base Page Ability + * 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; + } + + /* Two bits in the Auto Negotiation Advertisement Register + * (Address 4) and two bits in the Auto Negotiation Base + * Page Ability Register (Address 5) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | e1000_fc_none + * 0 | 1 | 0 | DC | e1000_fc_none + * 0 | 1 | 1 | 0 | e1000_fc_none + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * 1 | 0 | 0 | DC | e1000_fc_none + * 1 | DC | 1 | DC | e1000_fc_full + * 1 | 1 | 0 | 0 | e1000_fc_none + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + */ + /* Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | e1000_fc_full + * + */ + if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { + /* Now we need to check if the user selected RX ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->original_fc == e1000_fc_full) { + hw->fc = e1000_fc_full; + DEBUGOUT("Flow Control = FULL.\r\n"); + } else { + hw->fc = e1000_fc_rx_pause; + DEBUGOUT + ("Flow Control = RX PAUSE frames only.\r\n"); + } + } + /* For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * + */ + else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) + { + hw->fc = e1000_fc_tx_pause; + DEBUGOUT + ("Flow Control = TX PAUSE frames only.\r\n"); + } + /* For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + */ + else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) + { + hw->fc = e1000_fc_rx_pause; + DEBUGOUT + ("Flow Control = RX PAUSE frames only.\r\n"); + } + /* Per the IEEE spec, at this point flow control should be + * disabled. However, we want to consider that we could + * be connected to a legacy switch that doesn't advertise + * desired flow control, but can be forced on the link + * partner. So if we advertised no flow control, that is + * what we will resolve to. If we advertised some kind of + * receive capability (Rx Pause Only or Full Flow Control) + * and the link partner advertised none, we will configure + * ourselves to enable Rx Flow Control only. We can do + * this safely for two reasons: If the link partner really + * didn't want flow control enabled, and we enable Rx, no + * harm done since we won't be receiving any PAUSE frames + * anyway. If the intent on the link partner was to have + * flow control enabled, then by us enabling RX only, we + * can at least receive pause frames and process them. + * This is a good idea because in most cases, since we are + * predominantly a server NIC, more times than not we will + * be asked to delay transmission of packets than asking + * our link partner to pause transmission of frames. + */ + else if (hw->original_fc == e1000_fc_none || + hw->original_fc == e1000_fc_tx_pause) { + hw->fc = e1000_fc_none; + DEBUGOUT("Flow Control = NONE.\r\n"); + } else { + hw->fc = e1000_fc_rx_pause; + DEBUGOUT + ("Flow Control = RX PAUSE frames only.\r\n"); + } + + /* Now we need to do one last check... If we auto- + * negotiated to HALF DUPLEX, flow control should not be + * enabled per IEEE 802.3 spec. + */ + e1000_get_speed_and_duplex(hw, &speed, &duplex); + + if (duplex == HALF_DUPLEX) + hw->fc = e1000_fc_none; + + /* 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) { + DEBUGOUT + ("Error forcing flow control settings\n"); + return ret_val; + } + } else { + DEBUGOUT + ("Copper PHY and Auto Neg has not completed.\r\n"); + } + } + return 0; +} + +/****************************************************************************** + * Checks to see if the link status of the hardware has changed. + * + * hw - Struct containing variables accessed by shared code + * + * Called by any function that needs to check the link status of the adapter. + *****************************************************************************/ +static int +e1000_check_for_link(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + uint32_t rxcw; + uint32_t ctrl; + uint32_t status; + uint32_t rctl; + uint32_t signal; + int32_t ret_val; + uint16_t phy_data; + uint16_t lp_capability; + + DEBUGFUNC(); + + /* On adapters with a MAC newer that 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 + */ + ctrl = E1000_READ_REG(hw, CTRL); + if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) + signal = E1000_CTRL_SWDPIN1; + else + signal = 0; + + status = E1000_READ_REG(hw, STATUS); + rxcw = E1000_READ_REG(hw, RXCW); + DEBUGOUT("ctrl: %#08x status %#08x rxcw %#08x\n", ctrl, status, rxcw); + + /* If we have a copper PHY then we only want to go out to the PHY + * registers to see if Auto-Neg has completed and/or if our link + * status has changed. The get_link_status flag will be set if we + * receive a Link Status Change interrupt or we have Rx Sequence + * Errors. + */ + if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { + /* First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * 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 (phy_data & MII_SR_LINK_STATUS) { + hw->get_link_status = FALSE; + } else { + /* No link detected */ + return -E1000_ERR_NOLINK; + } + + /* 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 + * configuration. So we only need to configure Collision + * Distance in the MAC. Otherwise, we need to force + * speed/duplex on the MAC to the current PHY speed/duplex + * settings. + */ + if (hw->mac_type >= e1000_82544) + e1000_config_collision_dist(hw); + else { + ret_val = e1000_config_mac_to_phy(hw); + if (ret_val < 0) { + DEBUGOUT + ("Error configuring MAC to PHY settings\n"); + return ret_val; + } + } + + /* Configure Flow Control now that Auto-Neg has completed. First, we + * 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) { + DEBUGOUT("Error configuring flow control\n"); + return ret_val; + } + + /* At this point we know that we are on copper and we have + * auto-negotiated link. These are conditions for checking the link + * parter capability register. We use the link partner capability to + * determine if TBI Compatibility needs to be turned on or off. If + * the link partner advertises any speed in addition to Gigabit, then + * we assume that they are GMII-based, and TBI compatibility is not + * needed. If no other speeds are advertised, we assume the link + * 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 (lp_capability & (NWAY_LPAR_10T_HD_CAPS | + NWAY_LPAR_10T_FD_CAPS | + NWAY_LPAR_100TX_HD_CAPS | + NWAY_LPAR_100TX_FD_CAPS | + NWAY_LPAR_100T4_CAPS)) { + /* If our link partner advertises anything in addition to + * gigabit, we do not need to enable TBI compatibility. + */ + if (hw->tbi_compatibility_on) { + /* If we previously were in the mode, turn it off. */ + rctl = E1000_READ_REG(hw, RCTL); + rctl &= ~E1000_RCTL_SBP; + E1000_WRITE_REG(hw, RCTL, rctl); + hw->tbi_compatibility_on = FALSE; + } + } else { + /* If TBI compatibility is was previously off, turn it on. For + * compatibility with a TBI link partner, we will store bad + * packets. Some frames have an additional byte on the end and + * will look like CRC errors to to the hardware. + */ + if (!hw->tbi_compatibility_on) { + hw->tbi_compatibility_on = TRUE; + rctl = E1000_READ_REG(hw, RCTL); + rctl |= E1000_RCTL_SBP; + E1000_WRITE_REG(hw, RCTL, rctl); + } + } + } + } + /* If we don't have link (auto-negotiation failed or link partner cannot + * auto-negotiate), the cable is plugged in (we have signal), and our + * link partner is not trying to auto-negotiate with us (we are receiving + * idles or data), we need to force link up. We also need to give + * auto-negotiation time to complete, in case the cable was just plugged + * in. The autoneg_failed flag does this. + */ + else if ((hw->media_type == e1000_media_type_fiber) && + (!(status & E1000_STATUS_LU)) && + ((ctrl & E1000_CTRL_SWDPIN1) == signal) && + (!(rxcw & E1000_RXCW_C))) { + if (hw->autoneg_failed == 0) { + hw->autoneg_failed = 1; + return 0; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + + /* Disable auto-negotiation in the TXCW register */ + E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); + + /* Force link-up and also force full-duplex. */ + ctrl = E1000_READ_REG(hw, CTRL); + ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); + 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) { + DEBUGOUT("Error configuring flow control\n"); + return ret_val; + } + } + /* If we are forcing link and we are receiving /C/ ordered sets, re-enable + * auto-negotiation in the TXCW register and disable forced link in the + * Device Control register in an attempt to auto-negotiate with our link + * partner. + */ + else if ((hw->media_type == e1000_media_type_fiber) && + (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { + DEBUGOUT + ("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); + E1000_WRITE_REG(hw, TXCW, hw->txcw); + E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); + } + return 0; +} + +/****************************************************************************** + * Detects the current speed and duplex settings of the hardware. + * + * hw - Struct containing variables accessed by shared code + * speed - Speed of the connection + * duplex - Duplex setting of the connection + *****************************************************************************/ +static void +e1000_get_speed_and_duplex(struct e1000_hw *hw, + uint16_t * speed, uint16_t * duplex) +{ + uint32_t status; + + DEBUGFUNC(); + + if (hw->mac_type >= e1000_82543) { + status = E1000_READ_REG(hw, STATUS); + if (status & E1000_STATUS_SPEED_1000) { + *speed = SPEED_1000; + DEBUGOUT("1000 Mbs, "); + } else if (status & E1000_STATUS_SPEED_100) { + *speed = SPEED_100; + DEBUGOUT("100 Mbs, "); + } else { + *speed = SPEED_10; + DEBUGOUT("10 Mbs, "); + } + + if (status & E1000_STATUS_FD) { + *duplex = FULL_DUPLEX; + DEBUGOUT("Full Duplex\r\n"); + } else { + *duplex = HALF_DUPLEX; + DEBUGOUT(" Half Duplex\r\n"); + } + } else { + DEBUGOUT("1000 Mbs, Full Duplex\r\n"); + *speed = SPEED_1000; + *duplex = FULL_DUPLEX; + } +} + +/****************************************************************************** +* Blocks until autoneg completes or times out (~4.5 seconds) +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int +e1000_wait_autoneg(struct e1000_hw *hw) +{ + uint16_t i; + uint16_t phy_data; + + DEBUGFUNC(); + DEBUGOUT("Waiting for Auto-Neg to complete.\n"); + + /* We will wait for autoneg to complete or 4.5 seconds to expire. */ + for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { + /* 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 (phy_data & MII_SR_AUTONEG_COMPLETE) { + DEBUGOUT("Auto-Neg complete.\n"); + return 0; + } + mdelay(100); + } + DEBUGOUT("Auto-Neg timedout.\n"); + return -E1000_ERR_TIMEOUT; +} + +/****************************************************************************** +* Raises the Management Data Clock +* +* hw - Struct containing variables accessed by shared code +* ctrl - Device control register's current value +******************************************************************************/ +static void +e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) +{ + /* Raise the clock input to the Management Data Clock (by setting the MDC + * bit), and then delay 2 microseconds. + */ + E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); + E1000_WRITE_FLUSH(hw); + udelay(2); +} + +/****************************************************************************** +* Lowers the Management Data Clock +* +* hw - Struct containing variables accessed by shared code +* ctrl - Device control register's current value +******************************************************************************/ +static void +e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) +{ + /* Lower the clock input to the Management Data Clock (by clearing the MDC + * bit), and then delay 2 microseconds. + */ + E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); + E1000_WRITE_FLUSH(hw); + udelay(2); +} + +/****************************************************************************** +* Shifts data bits out to the PHY +* +* hw - Struct containing variables accessed by shared code +* data - Data to send out to the PHY +* count - Number of bits to shift out +* +* Bits are shifted out in MSB to LSB order. +******************************************************************************/ +static void +e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count) +{ + uint32_t ctrl; + uint32_t mask; + + /* We need to shift "count" number of bits out to the PHY. So, the value + * in the "data" parameter will be shifted out to the PHY one bit at a + * time. In order to do this, "data" must be broken down into bits. + */ + mask = 0x01; + mask <<= (count - 1); + + ctrl = E1000_READ_REG(hw, CTRL); + + /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ + ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); + + while (mask) { + /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and + * then raising and lowering the Management Data Clock. A "0" is + * shifted out to the PHY by setting the MDIO bit to "0" and then + * raising and lowering the clock. + */ + if (data & mask) + ctrl |= E1000_CTRL_MDIO; + else + ctrl &= ~E1000_CTRL_MDIO; + + E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + + udelay(2); + + e1000_raise_mdi_clk(hw, &ctrl); + e1000_lower_mdi_clk(hw, &ctrl); + + mask = mask >> 1; + } +} + +/****************************************************************************** +* Shifts data bits in from the PHY +* +* hw - Struct containing variables accessed by shared code +* +* Bits are shifted in in MSB to LSB order. +******************************************************************************/ +static uint16_t +e1000_shift_in_mdi_bits(struct e1000_hw *hw) +{ + uint32_t ctrl; + uint16_t data = 0; + uint8_t i; + + /* In order to read a register from the PHY, we need to shift in a total + * of 18 bits from the PHY. The first two bit (turnaround) times are used + * to avoid contention on the MDIO pin when a read operation is performed. + * These two bits are ignored by us and thrown away. Bits are "shifted in" + * by raising the input to the Management Data Clock (setting the MDC bit), + * and then reading the value of the MDIO bit. + */ + ctrl = E1000_READ_REG(hw, CTRL); + + /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */ + ctrl &= ~E1000_CTRL_MDIO_DIR; + ctrl &= ~E1000_CTRL_MDIO; + + E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + + /* Raise and Lower the clock before reading in the data. This accounts for + * the turnaround bits. The first clock occurred when we clocked out the + * last bit of the Register Address. + */ + e1000_raise_mdi_clk(hw, &ctrl); + e1000_lower_mdi_clk(hw, &ctrl); + + for (data = 0, i = 0; i < 16; i++) { + data = data << 1; + e1000_raise_mdi_clk(hw, &ctrl); + ctrl = E1000_READ_REG(hw, CTRL); + /* Check to see if we shifted in a "1". */ + if (ctrl & E1000_CTRL_MDIO) + data |= 1; + e1000_lower_mdi_clk(hw, &ctrl); + } + + e1000_raise_mdi_clk(hw, &ctrl); + e1000_lower_mdi_clk(hw, &ctrl); + + return data; +} + +/***************************************************************************** +* Reads the value from a PHY register +* +* hw - Struct containing variables accessed by shared code +* reg_addr - address of the PHY register to read +******************************************************************************/ +static int +e1000_read_phy_reg(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; + + if (reg_addr > MAX_PHY_REG_ADDRESS) { + DEBUGOUT("PHY Address %d is out of range\n", reg_addr); + return -E1000_ERR_PARAM; + } + + if (hw->mac_type > e1000_82543) { + /* Set up Op-code, Phy Address, and register address in the MDI + * Control register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | + (phy_addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_READ)); + + E1000_WRITE_REG(hw, MDIC, mdic); + + /* Poll the ready bit to see if the MDI read completed */ + for (i = 0; i < 64; i++) { + udelay(10); + mdic = E1000_READ_REG(hw, MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { + DEBUGOUT("MDI Read did not complete\n"); + return -E1000_ERR_PHY; + } + if (mdic & E1000_MDIC_ERROR) { + DEBUGOUT("MDI Error\n"); + return -E1000_ERR_PHY; + } + *phy_data = (uint16_t) mdic; + } else { + /* We must first send a preamble through the MDIO pin to signal the + * beginning of an MII instruction. This is done by sending 32 + * consecutive "1" bits. + */ + e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); + + /* Now combine the next few fields that are required for a read + * operation. We use this method instead of calling the + * e1000_shift_out_mdi_bits routine five different times. The format of + * a MII read instruction consists of a shift out of 14 bits and is + * defined as follows: + * + * followed by a shift in of 18 bits. This first two bits shifted in + * are TurnAround bits used to avoid contention on the MDIO pin when a + * READ operation is performed. These two bits are thrown away + * followed by a shift in of 16 bits which contains the desired data. + */ + mdic = ((reg_addr) | (phy_addr << 5) | + (PHY_OP_READ << 10) | (PHY_SOF << 12)); + + e1000_shift_out_mdi_bits(hw, mdic, 14); + + /* Now that we've shifted out the read command to the MII, we need to + * "shift in" the 16-bit value (18 total bits) of the requested PHY + * register address. + */ + *phy_data = e1000_shift_in_mdi_bits(hw); + } + return 0; +} + +/****************************************************************************** +* Writes a value to a PHY register +* +* hw - Struct containing variables accessed by shared code +* reg_addr - address of the PHY register to write +* data - data to write to the PHY +******************************************************************************/ +static int +e1000_write_phy_reg(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; + + if (reg_addr > MAX_PHY_REG_ADDRESS) { + DEBUGOUT("PHY Address %d is out of range\n", reg_addr); + return -E1000_ERR_PARAM; + } + + if (hw->mac_type > e1000_82543) { + /* Set up Op-code, Phy Address, register address, and data intended + * for the PHY register in the MDI Control register. The MAC will take + * care of interfacing with the PHY to send the desired data. + */ + mdic = (((uint32_t) phy_data) | + (reg_addr << E1000_MDIC_REG_SHIFT) | + (phy_addr << E1000_MDIC_PHY_SHIFT) | + (E1000_MDIC_OP_WRITE)); + + E1000_WRITE_REG(hw, MDIC, mdic); + + /* Poll the ready bit to see if the MDI read completed */ + for (i = 0; i < 64; i++) { + udelay(10); + mdic = E1000_READ_REG(hw, MDIC); + if (mdic & E1000_MDIC_READY) + break; + } + if (!(mdic & E1000_MDIC_READY)) { + DEBUGOUT("MDI Write did not complete\n"); + return -E1000_ERR_PHY; + } + } else { + /* We'll need to use the SW defined pins to shift the write command + * out to the PHY. We first send a preamble to the PHY to signal the + * beginning of the MII instruction. This is done by sending 32 + * consecutive "1" bits. + */ + e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); + + /* Now combine the remaining required fields that will indicate a + * write operation. We use this method instead of calling the + * e1000_shift_out_mdi_bits routine for each field in the command. The + * format of a MII write instruction is as follows: + * . + */ + mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | + (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); + mdic <<= 16; + mdic |= (uint32_t) phy_data; + + e1000_shift_out_mdi_bits(hw, mdic, 32); + } + return 0; +} + +/****************************************************************************** +* Returns the PHY to the power-on reset state +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static void +e1000_phy_hw_reset(struct e1000_hw *hw) +{ + uint32_t ctrl; + uint32_t ctrl_ext; + + DEBUGFUNC(); + + DEBUGOUT("Resetting Phy...\n"); + + if (hw->mac_type > e1000_82543) { + /* Read the device control register and assert the E1000_CTRL_PHY_RST + * bit. Then, take it out of reset. + */ + ctrl = E1000_READ_REG(hw, CTRL); + E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); + E1000_WRITE_FLUSH(hw); + mdelay(10); + E1000_WRITE_REG(hw, CTRL, ctrl); + E1000_WRITE_FLUSH(hw); + } else { + /* Read the Extended Device Control Register, assert the PHY_RESET_DIR + * bit to put the PHY into reset. Then, take it out of reset. + */ + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; + ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + mdelay(10); + ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + } + udelay(150); +} + +/****************************************************************************** +* Resets the PHY +* +* hw - Struct containing variables accessed by shared code +* +* Sets bit 15 of the MII Control regiser +******************************************************************************/ +static int +e1000_phy_reset(struct e1000_hw *hw) +{ + uint16_t phy_data; + + DEBUGFUNC(); + + 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); + return 0; +} + +/****************************************************************************** +* Probes the expected PHY address for known PHY IDs +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int +e1000_detect_gig_phy(struct e1000_hw *hw) +{ + uint16_t phy_id_high, phy_id_low; + int match = FALSE; + + DEBUGFUNC(); + + /* 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; + } + hw->phy_id = (uint32_t) (phy_id_high << 16); + udelay(2); + if (e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); + + switch (hw->mac_type) { + case e1000_82543: + if (hw->phy_id == M88E1000_E_PHY_ID) + match = TRUE; + break; + case e1000_82544: + if (hw->phy_id == M88E1000_I_PHY_ID) + match = TRUE; + break; + case e1000_82540: + case e1000_82545: + case e1000_82546: + if (hw->phy_id == M88E1011_I_PHY_ID) + match = TRUE; + break; + default: + DEBUGOUT("Invalid MAC type %d\n", hw->mac_type); + return -E1000_ERR_CONFIG; + } + if (match) { + DEBUGOUT("PHY ID 0x%X detected\n", hw->phy_id); + return 0; + } + DEBUGOUT("Invalid PHY ID 0x%X\n", hw->phy_id); + return -E1000_ERR_PHY; +} + +/** + * e1000_sw_init - Initialize general software structures (struct e1000_adapter) + * + * e1000_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ + +static int +e1000_sw_init(struct eth_device *nic, int cardnum) +{ + struct e1000_hw *hw = (typeof(hw)) nic->priv; + int result; + + /* PCI config space info */ + pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id); + pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id); + pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID, + &hw->subsystem_vendor_id); + pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id); + + pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id); + pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word); + + /* identify the MAC */ + result = e1000_set_mac_type(hw); + if (result) { + E1000_ERR("Unknown MAC Type\n"); + return result; + } + + /* lan a vs. lan b settings */ + if (hw->mac_type == e1000_82546) + /*this also works w/ multiple 82546 cards */ + /*but not if they're intermingled /w other e1000s */ + hw->lan_loc = (cardnum % 2) ? e1000_lan_b : e1000_lan_a; + else + hw->lan_loc = e1000_lan_a; + + /* flow control settings */ + hw->fc_high_water = E1000_FC_HIGH_THRESH; + hw->fc_low_water = E1000_FC_LOW_THRESH; + hw->fc_pause_time = E1000_FC_PAUSE_TIME; + hw->fc_send_xon = 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) { + DEBUGOUT("fiber interface\n"); + hw->media_type = e1000_media_type_fiber; + } else { + DEBUGOUT("copper interface\n"); + hw->media_type = e1000_media_type_copper; + } + } else { + hw->media_type = e1000_media_type_fiber; + } + + if (hw->mac_type < e1000_82543) + hw->report_tx_early = 0; + else + hw->report_tx_early = 1; + + hw->tbi_compatibility_en = TRUE; +#if 0 + hw->wait_autoneg_complete = FALSE; + hw->adaptive_ifs = TRUE; + + /* Copper options */ + if (hw->media_type == e1000_media_type_copper) { + hw->mdix = AUTO_ALL_MODES; + hw->disable_polarity_correction = FALSE; + } +#endif + return E1000_SUCCESS; +} + +void +fill_rx(struct e1000_hw *hw) +{ + struct e1000_rx_desc *rd; + + rx_last = rx_tail; + rd = rx_base + rx_tail; + rx_tail = (rx_tail + 1) % 8; + memset(rd, 0, 16); + rd->buffer_addr = cpu_to_le64((u32) & packet); + E1000_WRITE_REG(hw, RDT, rx_tail); +} + +/** + * e1000_configure_tx - Configure 8254x Transmit Unit after Reset + * @adapter: board private structure + * + * Configure the Tx unit of the MAC after a reset. + **/ + +static void +e1000_configure_tx(struct e1000_hw *hw) +{ + unsigned long ptr; + unsigned long tctl; + unsigned long tipg; + + ptr = (u32) tx_pool; + if (ptr & 0xf) + ptr = (ptr + 0x10) & (~0xf); + + tx_base = (typeof(tx_base)) ptr; + + E1000_WRITE_REG(hw, TDBAL, (u32) tx_base); + E1000_WRITE_REG(hw, TDBAH, 0); + + E1000_WRITE_REG(hw, TDLEN, 128); + + /* Setup the HW Tx Head and Tail descriptor pointers */ + E1000_WRITE_REG(hw, TDH, 0); + E1000_WRITE_REG(hw, TDT, 0); + tx_tail = 0; + + /* Set the default values for the Tx Inter Packet Gap timer */ + switch (hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + tipg = DEFAULT_82542_TIPG_IPGT; + tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + break; + default: + if (hw->media_type == e1000_media_type_fiber) + tipg = DEFAULT_82543_TIPG_IPGT_FIBER; + else + tipg = DEFAULT_82543_TIPG_IPGT_COPPER; + tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; + tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; + } + E1000_WRITE_REG(hw, TIPG, tipg); +#if 0 + /* Set the Tx Interrupt Delay register */ + E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); + if (hw->mac_type >= e1000_82540) + E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); +#endif + /* Program the Transmit Control Register */ + tctl = E1000_READ_REG(hw, TCTL); + tctl &= ~E1000_TCTL_CT; + tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | + (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + E1000_WRITE_REG(hw, TCTL, tctl); + + e1000_config_collision_dist(hw); +#if 0 + /* Setup Transmit Descriptor Settings for this adapter */ + adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE; + + if (adapter->hw.report_tx_early == 1) + adapter->txd_cmd |= E1000_TXD_CMD_RS; + else + adapter->txd_cmd |= E1000_TXD_CMD_RPS; +#endif +} + +/** + * e1000_setup_rctl - configure the receive control register + * @adapter: Board private structure + **/ +static void +e1000_setup_rctl(struct e1000_hw *hw) +{ + uint32_t rctl; + + rctl = E1000_READ_REG(hw, RCTL); + + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF; /* | + (hw.mc_filter_type << E1000_RCTL_MO_SHIFT); */ + + if (hw->tbi_compatibility_on == 1) + rctl |= E1000_RCTL_SBP; + else + rctl &= ~E1000_RCTL_SBP; + + rctl &= ~(E1000_RCTL_SZ_4096); +#if 0 + switch (adapter->rx_buffer_len) { + case E1000_RXBUFFER_2048: + default: +#endif + rctl |= E1000_RCTL_SZ_2048; + rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); +#if 0 + break; + case E1000_RXBUFFER_4096: + rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + break; + case E1000_RXBUFFER_8192: + rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + break; + case E1000_RXBUFFER_16384: + rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + break; + } +#endif + E1000_WRITE_REG(hw, RCTL, rctl); +} + +/** + * e1000_configure_rx - Configure 8254x Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Rx unit of the MAC after a reset. + **/ +static void +e1000_configure_rx(struct e1000_hw *hw) +{ + unsigned long ptr; + unsigned long rctl; +#if 0 + unsigned long rxcsum; +#endif + rx_tail = 0; + /* make sure receives are disabled while setting up the descriptors */ + rctl = E1000_READ_REG(hw, RCTL); + E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); +#if 0 + /* set the Receive Delay Timer Register */ + + E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); +#endif + if (hw->mac_type >= e1000_82540) { +#if 0 + E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); +#endif + /* Set the interrupt throttling rate. Value is calculated + * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) + E1000_WRITE_REG(hw, ITR, DEFAULT_ITR); + } + + /* Setup the Base and Length of the Rx Descriptor Ring */ + ptr = (u32) rx_pool; + if (ptr & 0xf) + ptr = (ptr + 0x10) & (~0xf); + rx_base = (typeof(rx_base)) ptr; + E1000_WRITE_REG(hw, RDBAL, (u32) rx_base); + E1000_WRITE_REG(hw, RDBAH, 0); + + E1000_WRITE_REG(hw, RDLEN, 128); + + /* Setup the HW Rx Head and Tail Descriptor Pointers */ + E1000_WRITE_REG(hw, RDH, 0); + E1000_WRITE_REG(hw, RDT, 0); +#if 0 + /* Enable 82543 Receive Checksum Offload for TCP and UDP */ + if ((adapter->hw.mac_type >= e1000_82543) && (adapter->rx_csum == TRUE)) { + rxcsum = E1000_READ_REG(hw, RXCSUM); + rxcsum |= E1000_RXCSUM_TUOFL; + E1000_WRITE_REG(hw, RXCSUM, rxcsum); + } +#endif + /* Enable Receives */ + + E1000_WRITE_REG(hw, RCTL, rctl); + fill_rx(hw); +} + +/************************************************************************** +POLL - Wait for a frame +***************************************************************************/ +static int +e1000_poll(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + struct e1000_rx_desc *rd; + /* return true if there's an ethernet packet ready to read */ + rd = rx_base + rx_last; + if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD) + return 0; + /*DEBUGOUT("recv: packet len=%d \n", rd->length); */ + NetReceive((uchar *)packet, le32_to_cpu(rd->length)); + fill_rx(hw); + return 1; +} + +/************************************************************************** +TRANSMIT - Transmit a frame +***************************************************************************/ +static int +e1000_transmit(struct eth_device *nic, volatile void *packet, int length) +{ + struct e1000_hw *hw = nic->priv; + struct e1000_tx_desc *txp; + int i = 0; + + txp = tx_base + tx_tail; + tx_tail = (tx_tail + 1) % 8; + + txp->buffer_addr = cpu_to_le64(virt_to_bus(packet)); + txp->lower.data = cpu_to_le32(E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | + E1000_TXD_CMD_IFCS | length); + txp->upper.data = 0; + E1000_WRITE_REG(hw, TDT, tx_tail); + + while (!(le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)) { + if (i++ > TOUT_LOOP) { + DEBUGOUT("e1000: tx timeout\n"); + return 0; + } + udelay(10); /* give the nic a chance to write to the register */ + } + return 1; +} + +/*reset function*/ +static inline int +e1000_reset(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + + e1000_reset_hw(hw); + if (hw->mac_type >= e1000_82544) { + E1000_WRITE_REG(hw, WUC, 0); + } + return e1000_init_hw(nic); +} + +/************************************************************************** +DISABLE - Turn off ethernet interface +***************************************************************************/ +static void +e1000_disable(struct eth_device *nic) +{ + struct e1000_hw *hw = nic->priv; + + /* Turn off the ethernet interface */ + E1000_WRITE_REG(hw, RCTL, 0); + E1000_WRITE_REG(hw, TCTL, 0); + + /* Clear the transmit ring */ + E1000_WRITE_REG(hw, TDH, 0); + E1000_WRITE_REG(hw, TDT, 0); + + /* Clear the receive ring */ + E1000_WRITE_REG(hw, RDH, 0); + E1000_WRITE_REG(hw, RDT, 0); + + /* put the card in its initial state */ +#if 0 + E1000_WRITE_REG(hw, CTRL, E1000_CTRL_RST); +#endif + mdelay(10); + +} + +/************************************************************************** +INIT - set up ethernet interface(s) +***************************************************************************/ +static int +e1000_init(struct eth_device *nic, bd_t * bis) +{ + struct e1000_hw *hw = nic->priv; + int ret_val = 0; + + ret_val = e1000_reset(nic); + if (ret_val < 0) { + if ((ret_val == -E1000_ERR_NOLINK) || + (ret_val == -E1000_ERR_TIMEOUT)) { + E1000_ERR("Valid Link not detected\n"); + } else { + E1000_ERR("Hardware Initialization Failed\n"); + } + return 0; + } + e1000_configure_tx(hw); + e1000_setup_rctl(hw); + e1000_configure_rx(hw); + return 1; +} + +/************************************************************************** +PROBE - Look for an adapter, this routine's visible to the outside +You should omit the last argument struct pci_device * for a non-PCI NIC +***************************************************************************/ +int +e1000_initialize(bd_t * bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *nic = NULL; + struct e1000_hw *hw = NULL; + u32 iobase; + int idx = 0; + u32 PciCommandWord; + + while (1) { /* Find PCI device(s) */ + if ((devno = pci_find_devices(supported, idx++)) < 0) { + break; + } + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0xf; /* Mask the bits that say "this is an io addr" */ + DEBUGOUT("e1000#%d: iobase 0x%08x\n", card_number, iobase); + + pci_write_config_dword(devno, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + /* Check if I/O accesses and Bus Mastering are enabled. */ + pci_read_config_dword(devno, PCI_COMMAND, &PciCommandWord); + if (!(PciCommandWord & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEM access.\n"); + continue; + } else if (!(PciCommandWord & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } + + nic = (struct eth_device *) malloc(sizeof (*nic)); + hw = (struct e1000_hw *) malloc(sizeof (*hw)); + hw->pdev = devno; + nic->priv = hw; + nic->iobase = bus_to_phys(devno, iobase); + + sprintf(nic->name, "e1000#%d", card_number); + + /* Are these variables needed? */ +#if 0 + hw->fc = e1000_fc_none; + hw->original_fc = e1000_fc_none; +#else + hw->fc = e1000_fc_default; + hw->original_fc = e1000_fc_default; +#endif + hw->autoneg_failed = 0; + hw->get_link_status = TRUE; + hw->hw_addr = (typeof(hw->hw_addr)) iobase; + hw->mac_type = e1000_undefined; + + /* MAC and Phy settings */ + if (e1000_sw_init(nic, card_number) < 0) { + free(hw); + free(nic); + return 0; + } +#ifndef CONFIG_AP1000 + if (e1000_validate_eeprom_checksum(nic) < 0) { + printf("The EEPROM Checksum Is Not Valid\n"); + free(hw); + free(nic); + return 0; + } +#endif + e1000_read_mac_addr(nic); + + E1000_WRITE_REG(hw, PBA, E1000_DEFAULT_PBA); + + printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n", + nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2], + nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); + + nic->init = e1000_init; + nic->recv = e1000_poll; + nic->send = e1000_transmit; + nic->halt = e1000_disable; + + eth_register(nic); + + card_number++; + } + return 1; +} + +#endif diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h new file mode 100644 index 0000000000..0fbdc90b1f --- /dev/null +++ b/drivers/net/e1000.h @@ -0,0 +1,1758 @@ +/******************************************************************************* + + + Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Linux NICS + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* e1000_hw.h + * Structures, enums, and macros for the MAC + */ + +#ifndef _E1000_HW_H_ +#define _E1000_HW_H_ + +#include +#include +#include +#include +#include + +#define E1000_ERR(args...) printf("e1000: " args) + +#ifdef E1000_DEBUG +#define E1000_DBG(args...) printf("e1000: " args) +#define DEBUGOUT(fmt,args...) printf(fmt ,##args) +#define DEBUGFUNC() printf("%s\n", __FUNCTION__); +#else +#define E1000_DBG(args...) +#define DEBUGFUNC() +#define DEBUGOUT(fmt,args...) +#endif + +/* Forward declarations of structures used by the shared code */ +struct e1000_hw; +struct e1000_hw_stats; + +typedef enum { + FALSE = 0, + TRUE = 1 +} boolean_t; + +/* Enumerated types specific to the e1000 hardware */ +/* Media Access Controlers */ +typedef enum { + e1000_undefined = 0, + e1000_82542_rev2_0, + e1000_82542_rev2_1, + e1000_82543, + e1000_82544, + e1000_82540, + e1000_82545, + e1000_82546, + e1000_num_macs +} e1000_mac_type; + +/* Media Types */ +typedef enum { + e1000_media_type_copper = 0, + e1000_media_type_fiber = 1, + e1000_num_media_types +} e1000_media_type; + +typedef enum { + e1000_10_half = 0, + e1000_10_full = 1, + e1000_100_half = 2, + e1000_100_full = 3 +} e1000_speed_duplex_type; + +typedef enum { + e1000_lan_a = 0, + e1000_lan_b = 1 +} e1000_lan_loc; + +/* Flow Control Settings */ +typedef enum { + e1000_fc_none = 0, + e1000_fc_rx_pause = 1, + e1000_fc_tx_pause = 2, + e1000_fc_full = 3, + e1000_fc_default = 0xFF +} e1000_fc_type; + +/* PCI bus types */ +typedef enum { + e1000_bus_type_unknown = 0, + e1000_bus_type_pci, + e1000_bus_type_pcix +} e1000_bus_type; + +/* PCI bus speeds */ +typedef enum { + e1000_bus_speed_unknown = 0, + e1000_bus_speed_33, + e1000_bus_speed_66, + e1000_bus_speed_100, + e1000_bus_speed_133, + e1000_bus_speed_reserved +} e1000_bus_speed; + +/* PCI bus widths */ +typedef enum { + e1000_bus_width_unknown = 0, + e1000_bus_width_32, + e1000_bus_width_64 +} e1000_bus_width; + +/* PHY status info structure and supporting enums */ +typedef enum { + e1000_cable_length_50 = 0, + e1000_cable_length_50_80, + e1000_cable_length_80_110, + e1000_cable_length_110_140, + e1000_cable_length_140, + e1000_cable_length_undefined = 0xFF +} e1000_cable_length; + +typedef enum { + e1000_10bt_ext_dist_enable_normal = 0, + e1000_10bt_ext_dist_enable_lower, + e1000_10bt_ext_dist_enable_undefined = 0xFF +} e1000_10bt_ext_dist_enable; + +typedef enum { + e1000_rev_polarity_normal = 0, + e1000_rev_polarity_reversed, + e1000_rev_polarity_undefined = 0xFF +} e1000_rev_polarity; + +typedef enum { + e1000_polarity_reversal_enabled = 0, + e1000_polarity_reversal_disabled, + e1000_polarity_reversal_undefined = 0xFF +} e1000_polarity_reversal; + +typedef enum { + e1000_auto_x_mode_manual_mdi = 0, + e1000_auto_x_mode_manual_mdix, + e1000_auto_x_mode_auto1, + e1000_auto_x_mode_auto2, + e1000_auto_x_mode_undefined = 0xFF +} e1000_auto_x_mode; + +typedef enum { + e1000_1000t_rx_status_not_ok = 0, + e1000_1000t_rx_status_ok, + e1000_1000t_rx_status_undefined = 0xFF +} e1000_1000t_rx_status; + +struct e1000_phy_info { + e1000_cable_length cable_length; + e1000_10bt_ext_dist_enable extended_10bt_distance; + e1000_rev_polarity cable_polarity; + e1000_polarity_reversal polarity_correction; + e1000_auto_x_mode mdix_mode; + e1000_1000t_rx_status local_rx; + e1000_1000t_rx_status remote_rx; +}; + +struct e1000_phy_stats { + uint32_t idle_errors; + uint32_t receive_errors; +}; + +/* Error Codes */ +#define E1000_SUCCESS 0 +#define E1000_ERR_EEPROM 1 +#define E1000_ERR_PHY 2 +#define E1000_ERR_CONFIG 3 +#define E1000_ERR_PARAM 4 +#define E1000_ERR_MAC_TYPE 5 +#define E1000_ERR_NOLINK 6 +#define E1000_ERR_TIMEOUT 7 + +/* PCI Device IDs */ +#define E1000_DEV_ID_82542 0x1000 +#define E1000_DEV_ID_82543GC_FIBER 0x1001 +#define E1000_DEV_ID_82543GC_COPPER 0x1004 +#define E1000_DEV_ID_82544EI_COPPER 0x1008 +#define E1000_DEV_ID_82544EI_FIBER 0x1009 +#define E1000_DEV_ID_82544GC_COPPER 0x100C +#define E1000_DEV_ID_82544GC_LOM 0x100D +#define E1000_DEV_ID_82540EM 0x100E +#define E1000_DEV_ID_82540EM_LOM 0x1015 +#define E1000_DEV_ID_82545EM_COPPER 0x100F +#define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82546EB_COPPER 0x1010 +#define E1000_DEV_ID_82546EB_FIBER 0x1012 +#define NUM_DEV_IDS 13 + +#define NODE_ADDRESS_SIZE 6 +#define ETH_LENGTH_OF_ADDRESS 6 + +/* MAC decode size is 128K - This is the size of BAR0 */ +#define MAC_DECODE_SIZE (128 * 1024) + +#define E1000_82542_2_0_REV_ID 2 +#define E1000_82542_2_1_REV_ID 3 + +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + +/* The sizes (in bytes) of a ethernet packet */ +#define ENET_HEADER_SIZE 14 +#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* With FCS */ +#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ +#define ETHERNET_FCS_SIZE 4 +#define MAXIMUM_ETHERNET_PACKET_SIZE \ + (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) +#define MINIMUM_ETHERNET_PACKET_SIZE \ + (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) +#define CRC_LENGTH ETHERNET_FCS_SIZE +#define MAX_JUMBO_FRAME_SIZE 0x3F00 + +/* 802.1q VLAN Packet Sizes */ +#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ + +/* Ethertype field values */ +#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ +#define ETHERNET_IP_TYPE 0x0800 /* IP packets */ +#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */ + +/* Packet Header defines */ +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 0x11 + +/* This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) + * o RXSEQ = Receive Sequence Error + */ +#define POLL_IMS_ENABLE_MASK ( \ + E1000_IMS_RXDMT0 | \ + E1000_IMS_RXSEQ) + +/* This defines the bits that are set in the Interrupt Mask + * Set/Read Register. Each bit is documented below: + * o RXT0 = Receiver Timer Interrupt (ring 0) + * o TXDW = Transmit Descriptor Written Back + * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) + * o RXSEQ = Receive Sequence Error + * o LSC = Link Status Change + */ +#define IMS_ENABLE_MASK ( \ + E1000_IMS_RXT0 | \ + E1000_IMS_TXDW | \ + E1000_IMS_RXDMT0 | \ + E1000_IMS_RXSEQ | \ + E1000_IMS_LSC) + +/* The 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. + */ +#define E1000_RAR_ENTRIES 16 + +#define MIN_NUMBER_OF_DESCRIPTORS 8 +#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 + +/* Receive Descriptor */ +struct e1000_rx_desc { + uint64_t buffer_addr; /* Address of the descriptor's data buffer */ + uint16_t length; /* Length of data DMAed into data buffer */ + uint16_t csum; /* Packet checksum */ + uint8_t status; /* Descriptor status */ + uint8_t errors; /* Descriptor Errors */ + uint16_t special; +}; + +/* Receive Decriptor bit definitions */ +#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ +#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ +#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ +#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ +#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ +#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ +#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ +#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ +#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ +#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ +#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ +#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ +#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ +#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ +#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ +#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ +#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */ +#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ +#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */ + +/* mask to determine if packets should be dropped due to frame errors */ +#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ + E1000_RXD_ERR_CE | \ + E1000_RXD_ERR_SE | \ + E1000_RXD_ERR_SEQ | \ + E1000_RXD_ERR_CXE | \ + E1000_RXD_ERR_RXE) + +/* Transmit Descriptor */ +struct e1000_tx_desc { + uint64_t buffer_addr; /* Address of the descriptor's data buffer */ + union { + uint32_t data; + struct { + uint16_t length; /* Data buffer length */ + uint8_t cso; /* Checksum offset */ + uint8_t cmd; /* Descriptor control */ + } flags; + } lower; + union { + uint32_t data; + struct { + uint8_t status; /* Descriptor status */ + uint8_t css; /* Checksum start */ + uint16_t special; + } fields; + } upper; +}; + +/* Transmit Descriptor bit definitions */ +#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ +#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ +#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ +#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ +#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ +#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ +#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ +#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ +#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ +#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ +#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ +#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ +#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ +#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ +#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ +#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ +#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ +#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ + +/* Offload Context Descriptor */ +struct e1000_context_desc { + union { + uint32_t ip_config; + struct { + uint8_t ipcss; /* IP checksum start */ + uint8_t ipcso; /* IP checksum offset */ + uint16_t ipcse; /* IP checksum end */ + } ip_fields; + } lower_setup; + union { + uint32_t tcp_config; + struct { + uint8_t tucss; /* TCP checksum start */ + uint8_t tucso; /* TCP checksum offset */ + uint16_t tucse; /* TCP checksum end */ + } tcp_fields; + } upper_setup; + uint32_t cmd_and_length; /* */ + union { + uint32_t data; + struct { + uint8_t status; /* Descriptor status */ + uint8_t hdr_len; /* Header length */ + uint16_t mss; /* Maximum segment size */ + } fields; + } tcp_seg_setup; +}; + +/* Offload data descriptor */ +struct e1000_data_desc { + uint64_t buffer_addr; /* Address of the descriptor's buffer address */ + union { + uint32_t data; + struct { + uint16_t length; /* Data buffer length */ + uint8_t typ_len_ext; /* */ + uint8_t cmd; /* */ + } flags; + } lower; + union { + uint32_t data; + struct { + uint8_t status; /* Descriptor status */ + uint8_t popts; /* Packet Options */ + uint16_t special; /* */ + } fields; + } upper; +}; + +/* Filters */ +#define E1000_NUM_UNICAST 16 /* Unicast filter entries */ +#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ +#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ + +/* Receive Address Register */ +struct e1000_rar { + volatile uint32_t low; /* receive address low */ + volatile uint32_t high; /* receive address high */ +}; + +/* The number of entries in the Multicast Table Array (MTA). */ +#define E1000_NUM_MTA_REGISTERS 128 + +/* IPv4 Address Table Entry */ +struct e1000_ipv4_at_entry { + volatile uint32_t ipv4_addr; /* IP Address (RW) */ + volatile uint32_t reserved; +}; + +/* Four wakeup IP addresses are supported */ +#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 +#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX +#define E1000_IP6AT_SIZE 1 + +/* IPv6 Address Table Entry */ +struct e1000_ipv6_at_entry { + volatile uint8_t ipv6_addr[16]; +}; + +/* Flexible Filter Length Table Entry */ +struct e1000_fflt_entry { + volatile uint32_t length; /* Flexible Filter Length (RW) */ + volatile uint32_t reserved; +}; + +/* Flexible Filter Mask Table Entry */ +struct e1000_ffmt_entry { + volatile uint32_t mask; /* Flexible Filter Mask (RW) */ + volatile uint32_t reserved; +}; + +/* Flexible Filter Value Table Entry */ +struct e1000_ffvt_entry { + volatile uint32_t value; /* Flexible Filter Value (RW) */ + volatile uint32_t reserved; +}; + +/* Four Flexible Filters are supported */ +#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 + +/* Each Flexible Filter is at most 128 (0x80) bytes in length */ +#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 + +#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX +#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX +#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX + +/* Register Set. (82543, 82544) + * + * Registers are defined to be 32 bits and should be accessed as 32 bit values. + * These registers are physically located on the NIC, but are mapped into the + * host memory address space. + * + * RW - register is both readable and writable + * RO - register is read only + * WO - register is write only + * R/clr - register is read only and is cleared when read + * A - register array + */ +#define E1000_CTRL 0x00000 /* Device Control - RW */ +#define E1000_STATUS 0x00008 /* Device Status - RO */ +#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ +#define E1000_EERD 0x00014 /* EEPROM Read - RW */ +#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ +#define E1000_MDIC 0x00020 /* MDI Control - RW */ +#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ +#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ +#define E1000_FCT 0x00030 /* Flow Control Type - RW */ +#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ +#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ +#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ +#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ +#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ +#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +#define E1000_RCTL 0x00100 /* RX Control - RW */ +#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ +#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ +#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ +#define E1000_TCTL 0x00400 /* TX Control - RW */ +#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ +#define E1000_TBT 0x00448 /* TX Burst Timer - RW */ +#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ +#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ +#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ +#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ +#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ +#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ +#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ +#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ +#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */ +#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */ +#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */ +#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */ +#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ +#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ +#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ +#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ +#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ +#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ +#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */ +#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */ +#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */ +#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ +#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ +#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ +#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ +#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ +#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ +#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ +#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ +#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ +#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ +#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ +#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ +#define E1000_COLC 0x04028 /* Collision Count - R/clr */ +#define E1000_DC 0x04030 /* Defer Count - R/clr */ +#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ +#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ +#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ +#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ +#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ +#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */ +#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */ +#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */ +#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */ +#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */ +#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */ +#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */ +#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */ +#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */ +#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */ +#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */ +#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */ +#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */ +#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */ +#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */ +#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */ +#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */ +#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */ +#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */ +#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */ +#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */ +#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */ +#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */ +#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */ +#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ +#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */ +#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */ +#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */ +#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */ +#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */ +#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */ +#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */ +#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */ +#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */ +#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */ +#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */ +#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */ +#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */ +#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */ +#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ +#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ +#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ +#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ +#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ +#define E1000_RA 0x05400 /* Receive Address - RW Array */ +#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ +#define E1000_WUC 0x05800 /* Wakeup Control - RW */ +#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ +#define E1000_WUS 0x05810 /* Wakeup Status - RO */ +#define E1000_MANC 0x05820 /* Management Control - RW */ +#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ +#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ +#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ +#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ +#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ +#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ +#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ +#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ + +/* Register Set (82542) + * + * Some of the 82542 registers are located at different offsets than they are + * in more current versions of the 8254x. Despite the difference in location, + * the registers function in the same manner. + */ +#define E1000_82542_CTRL E1000_CTRL +#define E1000_82542_STATUS E1000_STATUS +#define E1000_82542_EECD E1000_EECD +#define E1000_82542_EERD E1000_EERD +#define E1000_82542_CTRL_EXT E1000_CTRL_EXT +#define E1000_82542_MDIC E1000_MDIC +#define E1000_82542_FCAL E1000_FCAL +#define E1000_82542_FCAH E1000_FCAH +#define E1000_82542_FCT E1000_FCT +#define E1000_82542_VET E1000_VET +#define E1000_82542_RA 0x00040 +#define E1000_82542_ICR E1000_ICR +#define E1000_82542_ITR E1000_ITR +#define E1000_82542_ICS E1000_ICS +#define E1000_82542_IMS E1000_IMS +#define E1000_82542_IMC E1000_IMC +#define E1000_82542_RCTL E1000_RCTL +#define E1000_82542_RDTR 0x00108 +#define E1000_82542_RDBAL 0x00110 +#define E1000_82542_RDBAH 0x00114 +#define E1000_82542_RDLEN 0x00118 +#define E1000_82542_RDH 0x00120 +#define E1000_82542_RDT 0x00128 +#define E1000_82542_FCRTH 0x00160 +#define E1000_82542_FCRTL 0x00168 +#define E1000_82542_FCTTV E1000_FCTTV +#define E1000_82542_TXCW E1000_TXCW +#define E1000_82542_RXCW E1000_RXCW +#define E1000_82542_MTA 0x00200 +#define E1000_82542_TCTL E1000_TCTL +#define E1000_82542_TIPG E1000_TIPG +#define E1000_82542_TDBAL 0x00420 +#define E1000_82542_TDBAH 0x00424 +#define E1000_82542_TDLEN 0x00428 +#define E1000_82542_TDH 0x00430 +#define E1000_82542_TDT 0x00438 +#define E1000_82542_TIDV 0x00440 +#define E1000_82542_TBT E1000_TBT +#define E1000_82542_AIT E1000_AIT +#define E1000_82542_VFTA 0x00600 +#define E1000_82542_LEDCTL E1000_LEDCTL +#define E1000_82542_PBA E1000_PBA +#define E1000_82542_RXDCTL E1000_RXDCTL +#define E1000_82542_RADV E1000_RADV +#define E1000_82542_RSRPD E1000_RSRPD +#define E1000_82542_TXDMAC E1000_TXDMAC +#define E1000_82542_TXDCTL E1000_TXDCTL +#define E1000_82542_TADV E1000_TADV +#define E1000_82542_TSPMT E1000_TSPMT +#define E1000_82542_CRCERRS E1000_CRCERRS +#define E1000_82542_ALGNERRC E1000_ALGNERRC +#define E1000_82542_SYMERRS E1000_SYMERRS +#define E1000_82542_RXERRC E1000_RXERRC +#define E1000_82542_MPC E1000_MPC +#define E1000_82542_SCC E1000_SCC +#define E1000_82542_ECOL E1000_ECOL +#define E1000_82542_MCC E1000_MCC +#define E1000_82542_LATECOL E1000_LATECOL +#define E1000_82542_COLC E1000_COLC +#define E1000_82542_DC E1000_DC +#define E1000_82542_TNCRS E1000_TNCRS +#define E1000_82542_SEC E1000_SEC +#define E1000_82542_CEXTERR E1000_CEXTERR +#define E1000_82542_RLEC E1000_RLEC +#define E1000_82542_XONRXC E1000_XONRXC +#define E1000_82542_XONTXC E1000_XONTXC +#define E1000_82542_XOFFRXC E1000_XOFFRXC +#define E1000_82542_XOFFTXC E1000_XOFFTXC +#define E1000_82542_FCRUC E1000_FCRUC +#define E1000_82542_PRC64 E1000_PRC64 +#define E1000_82542_PRC127 E1000_PRC127 +#define E1000_82542_PRC255 E1000_PRC255 +#define E1000_82542_PRC511 E1000_PRC511 +#define E1000_82542_PRC1023 E1000_PRC1023 +#define E1000_82542_PRC1522 E1000_PRC1522 +#define E1000_82542_GPRC E1000_GPRC +#define E1000_82542_BPRC E1000_BPRC +#define E1000_82542_MPRC E1000_MPRC +#define E1000_82542_GPTC E1000_GPTC +#define E1000_82542_GORCL E1000_GORCL +#define E1000_82542_GORCH E1000_GORCH +#define E1000_82542_GOTCL E1000_GOTCL +#define E1000_82542_GOTCH E1000_GOTCH +#define E1000_82542_RNBC E1000_RNBC +#define E1000_82542_RUC E1000_RUC +#define E1000_82542_RFC E1000_RFC +#define E1000_82542_ROC E1000_ROC +#define E1000_82542_RJC E1000_RJC +#define E1000_82542_MGTPRC E1000_MGTPRC +#define E1000_82542_MGTPDC E1000_MGTPDC +#define E1000_82542_MGTPTC E1000_MGTPTC +#define E1000_82542_TORL E1000_TORL +#define E1000_82542_TORH E1000_TORH +#define E1000_82542_TOTL E1000_TOTL +#define E1000_82542_TOTH E1000_TOTH +#define E1000_82542_TPR E1000_TPR +#define E1000_82542_TPT E1000_TPT +#define E1000_82542_PTC64 E1000_PTC64 +#define E1000_82542_PTC127 E1000_PTC127 +#define E1000_82542_PTC255 E1000_PTC255 +#define E1000_82542_PTC511 E1000_PTC511 +#define E1000_82542_PTC1023 E1000_PTC1023 +#define E1000_82542_PTC1522 E1000_PTC1522 +#define E1000_82542_MPTC E1000_MPTC +#define E1000_82542_BPTC E1000_BPTC +#define E1000_82542_TSCTC E1000_TSCTC +#define E1000_82542_TSCTFC E1000_TSCTFC +#define E1000_82542_RXCSUM E1000_RXCSUM +#define E1000_82542_WUC E1000_WUC +#define E1000_82542_WUFC E1000_WUFC +#define E1000_82542_WUS E1000_WUS +#define E1000_82542_MANC E1000_MANC +#define E1000_82542_IPAV E1000_IPAV +#define E1000_82542_IP4AT E1000_IP4AT +#define E1000_82542_IP6AT E1000_IP6AT +#define E1000_82542_WUPL E1000_WUPL +#define E1000_82542_WUPM E1000_WUPM +#define E1000_82542_FFLT E1000_FFLT +#define E1000_82542_FFMT E1000_FFMT +#define E1000_82542_FFVT E1000_FFVT + +/* Statistics counters collected by the MAC */ +struct e1000_hw_stats { + uint64_t crcerrs; + uint64_t algnerrc; + uint64_t symerrs; + uint64_t rxerrc; + uint64_t mpc; + uint64_t scc; + uint64_t ecol; + uint64_t mcc; + uint64_t latecol; + uint64_t colc; + uint64_t dc; + uint64_t tncrs; + uint64_t sec; + uint64_t cexterr; + uint64_t rlec; + uint64_t xonrxc; + uint64_t xontxc; + uint64_t xoffrxc; + uint64_t xofftxc; + uint64_t fcruc; + uint64_t prc64; + uint64_t prc127; + uint64_t prc255; + uint64_t prc511; + uint64_t prc1023; + uint64_t prc1522; + uint64_t gprc; + uint64_t bprc; + uint64_t mprc; + uint64_t gptc; + uint64_t gorcl; + uint64_t gorch; + uint64_t gotcl; + uint64_t gotch; + uint64_t rnbc; + uint64_t ruc; + uint64_t rfc; + uint64_t roc; + uint64_t rjc; + uint64_t mgprc; + uint64_t mgpdc; + uint64_t mgptc; + uint64_t torl; + uint64_t torh; + uint64_t totl; + uint64_t toth; + uint64_t tpr; + uint64_t tpt; + uint64_t ptc64; + uint64_t ptc127; + uint64_t ptc255; + uint64_t ptc511; + uint64_t ptc1023; + uint64_t ptc1522; + uint64_t mptc; + uint64_t bptc; + uint64_t tsctc; + uint64_t tsctfc; +}; + +/* Structure containing variables used by the shared code (e1000_hw.c) */ +struct e1000_hw { + pci_dev_t pdev; + uint8_t *hw_addr; + e1000_mac_type mac_type; + e1000_media_type media_type; + e1000_lan_loc lan_loc; + e1000_fc_type fc; +#if 0 + e1000_bus_speed bus_speed; + e1000_bus_width bus_width; + e1000_bus_type bus_type; + uint32_t io_base; +#endif + uint32_t phy_id; + uint32_t phy_addr; + uint32_t original_fc; + uint32_t txcw; + uint32_t autoneg_failed; +#if 0 + uint32_t max_frame_size; + uint32_t min_frame_size; + uint32_t mc_filter_type; + uint32_t num_mc_addrs; + uint32_t collision_delta; + uint32_t tx_packet_delta; + uint32_t ledctl_default; + uint32_t ledctl_mode1; + uint32_t ledctl_mode2; +#endif + uint16_t autoneg_advertised; + uint16_t pci_cmd_word; + uint16_t fc_high_water; + uint16_t fc_low_water; + uint16_t fc_pause_time; +#if 0 + uint16_t current_ifs_val; + uint16_t ifs_min_val; + uint16_t ifs_max_val; + uint16_t ifs_step_size; + uint16_t ifs_ratio; +#endif + uint16_t device_id; + uint16_t vendor_id; + uint16_t subsystem_id; + uint16_t subsystem_vendor_id; + uint8_t revision_id; +#if 0 + uint8_t autoneg; + uint8_t mdix; + uint8_t forced_speed_duplex; + uint8_t wait_autoneg_complete; + uint8_t dma_fairness; +#endif +#if 0 + uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; + boolean_t disable_polarity_correction; +#endif + boolean_t get_link_status; + boolean_t tbi_compatibility_en; + boolean_t tbi_compatibility_on; + boolean_t fc_send_xon; + boolean_t report_tx_early; +#if 0 + boolean_t adaptive_ifs; + boolean_t ifs_params_forced; + boolean_t in_ifs_mode; +#endif +}; + +#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ +#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ + +/* Register Bit Masks */ +/* Device Control */ +#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ +#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ +#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ +#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ +#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ +#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ +#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ +#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ +#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ +#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ +#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ +#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ +#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ +#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ +#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ +#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ +#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ +#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ +#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ +#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ +#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ +#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ +#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ +#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ +#define E1000_CTRL_RST 0x04000000 /* Global reset */ +#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ +#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ +#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ +#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ +#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ + +/* Device Status */ +#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ +#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ +#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ +#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ +#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ +#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ +#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ +#define E1000_STATUS_SPEED_MASK 0x000000C0 +#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ +#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ +#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ +#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ +#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ +#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ +#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ +#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ +#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ + +/* Constants used to intrepret the masked PCI-X bus speed. */ +#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ +#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ +#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ + +/* EEPROM/Flash Control */ +#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */ +#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ +#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ +#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ +#define E1000_EECD_FWE_MASK 0x00000030 +#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ +#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ +#define E1000_EECD_FWE_SHIFT 4 +#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ +#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ +#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ +#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ + +/* EEPROM Read */ +#define E1000_EERD_START 0x00000001 /* Start Read */ +#define E1000_EERD_DONE 0x00000010 /* Read Done */ +#define E1000_EERD_ADDR_SHIFT 8 +#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */ +#define E1000_EERD_DATA_SHIFT 16 +#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ + +/* Extended Device Control */ +#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ +#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ +#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN +#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ +#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ +#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ +#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ +#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA +#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ +#define E1000_CTRL_EXT_SWDPIN6 0x00000040 /* SWDPIN 6 value */ +#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ +#define E1000_CTRL_EXT_SWDPIN7 0x00000080 /* SWDPIN 7 value */ +#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ +#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ +#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ +#define E1000_CTRL_EXT_SWDPIO6 0x00000400 /* SWDPIN 6 Input or output */ +#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ +#define E1000_CTRL_EXT_SWDPIO7 0x00000800 /* SWDPIN 7 Input or output */ +#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ +#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ +#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ +#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 +#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 +#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 +#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 +#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 +#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 + +/* MDI Control */ +#define E1000_MDIC_DATA_MASK 0x0000FFFF +#define E1000_MDIC_REG_MASK 0x001F0000 +#define E1000_MDIC_REG_SHIFT 16 +#define E1000_MDIC_PHY_MASK 0x03E00000 +#define E1000_MDIC_PHY_SHIFT 21 +#define E1000_MDIC_OP_WRITE 0x04000000 +#define E1000_MDIC_OP_READ 0x08000000 +#define E1000_MDIC_READY 0x10000000 +#define E1000_MDIC_INT_EN 0x20000000 +#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_MODE_LINK_10_1000 0x0 +#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 +#define E1000_LEDCTL_MODE_LINK_UP 0x2 +#define E1000_LEDCTL_MODE_ACTIVITY 0x3 +#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 +#define E1000_LEDCTL_MODE_LINK_10 0x5 +#define E1000_LEDCTL_MODE_LINK_100 0x6 +#define E1000_LEDCTL_MODE_LINK_1000 0x7 +#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 +#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 +#define E1000_LEDCTL_MODE_COLLISION 0xA +#define E1000_LEDCTL_MODE_BUS_SPEED 0xB +#define E1000_LEDCTL_MODE_BUS_SIZE 0xC +#define E1000_LEDCTL_MODE_PAUSED 0xD +#define E1000_LEDCTL_MODE_LED_ON 0xE +#define E1000_LEDCTL_MODE_LED_OFF 0xF + +/* Receive Address */ +#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 + +/* 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 + +/* 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 + +/* 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 + +/* 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 */ +/* 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 */ +/* 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 */ + +/* Receive Descriptor */ +#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ +#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ +#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */ +#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */ +#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */ + +/* Flow Control */ +#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ +#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ +#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ +#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ + +/* Receive Descriptor Control */ +#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ +#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ +#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ +#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ + +/* Transmit Descriptor Control */ +#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */ +#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */ +#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ +#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ +#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ + +/* Transmit Configuration Word */ +#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ +#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ +#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ +#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ +#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ +#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ +#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ +#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ +#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ +#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ + +/* Receive Configuration Word */ +#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ +#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ +#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ +#define E1000_RXCW_CC 0x10000000 /* Receive config change */ +#define E1000_RXCW_C 0x20000000 /* Receive config */ +#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ +#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ + +/* Transmit Control */ +#define E1000_TCTL_RST 0x00000001 /* software reset */ +#define E1000_TCTL_EN 0x00000002 /* enable tx */ +#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ +#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ +#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ +#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ +#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ +#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ +#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ +#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ + +/* Receive Checksum Control */ +#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ +#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ +#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ +#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ + +/* Definitions for power management and wakeup registers */ +/* Wake Up Control */ +#define E1000_WUC_APME 0x00000001 /* APM Enable */ +#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ +#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ +#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ + +/* Wake Up Filter Control */ +#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ +#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ +#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ +#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ +#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ +#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ +#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ +#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ +#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ +#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ +#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ +#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ +#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ +#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ +#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ + +/* Wake Up Status */ +#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */ +#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */ +#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */ +#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */ +#define E1000_WUS_BC 0x00000010 /* Broadcast Received */ +#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */ +#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */ +#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */ +#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */ +#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */ +#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */ +#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */ +#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ + +/* Management Control */ +#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ +#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ +#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ +#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ +#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ +#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ +#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ +#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ +#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ +#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery + * Filtering */ +#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ +#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ +#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ +#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ +#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ +#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ +#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ +#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ + +#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ +#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ + +/* Wake Up Packet Length */ +#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ + +#define E1000_MDALIGN 4096 + +/* EEPROM Commands */ +#define EEPROM_READ_OPCODE 0x6 /* EERPOM read opcode */ +#define EEPROM_WRITE_OPCODE 0x5 /* EERPOM write opcode */ +#define EEPROM_ERASE_OPCODE 0x7 /* EERPOM erase opcode */ +#define EEPROM_EWEN_OPCODE 0x13 /* EERPOM erase/write enable */ +#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ + +/* 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_FLASH_VERSION 0x0032 +#define EEPROM_CHECKSUM_REG 0x003F + +/* Word definitions for ID LED Settings */ +#define ID_LED_RESERVED_0000 0x0000 +#define ID_LED_RESERVED_FFFF 0xFFFF +#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ + (ID_LED_OFF1_OFF2 << 8) | \ + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_DEF1_DEF2)) +#define ID_LED_DEF1_DEF2 0x1 +#define ID_LED_DEF1_ON2 0x2 +#define ID_LED_DEF1_OFF2 0x3 +#define ID_LED_ON1_DEF2 0x4 +#define ID_LED_ON1_ON2 0x5 +#define ID_LED_ON1_OFF2 0x6 +#define ID_LED_OFF1_DEF2 0x7 +#define ID_LED_OFF1_ON2 0x8 +#define ID_LED_OFF1_OFF2 0x9 + +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define EEPROM_COMPAT_SERVER 0x0400 +#define EEPROM_COMPAT_CLIENT 0x0200 + +/* Mask bits for fields in Word 0x0a of the EEPROM */ +#define EEPROM_WORD0A_ILOS 0x0010 +#define EEPROM_WORD0A_SWDPIO 0x01E0 +#define EEPROM_WORD0A_LRST 0x0200 +#define EEPROM_WORD0A_FD 0x0400 +#define EEPROM_WORD0A_66MHZ 0x0800 + +/* Mask bits for fields in Word 0x0f of the EEPROM */ +#define EEPROM_WORD0F_PAUSE_MASK 0x3000 +#define EEPROM_WORD0F_PAUSE 0x1000 +#define EEPROM_WORD0F_ASM_DIR 0x2000 +#define EEPROM_WORD0F_ANE 0x0800 +#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 + +/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ +#define EEPROM_SUM 0xBABA + +/* EEPROM Map defines (WORD OFFSETS)*/ +#define EEPROM_NODE_ADDRESS_BYTE_0 0 +#define EEPROM_PBA_BYTE_1 8 + +/* EEPROM Map Sizes (Byte Counts) */ +#define PBA_SIZE 4 + +/* Collision related configuration parameters */ +#define E1000_COLLISION_THRESHOLD 16 +#define E1000_CT_SHIFT 4 +#define E1000_COLLISION_DISTANCE 64 +#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE +#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE +#define E1000_GB_HDX_COLLISION_DISTANCE 512 +#define E1000_COLD_SHIFT 12 + +/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define REQ_RX_DESCRIPTOR_MULTIPLE 8 + +/* Default values for the transmit IPG register */ +#define DEFAULT_82542_TIPG_IPGT 10 +#define DEFAULT_82543_TIPG_IPGT_FIBER 9 +#define DEFAULT_82543_TIPG_IPGT_COPPER 8 + +#define E1000_TIPG_IPGT_MASK 0x000003FF +#define E1000_TIPG_IPGR1_MASK 0x000FFC00 +#define E1000_TIPG_IPGR2_MASK 0x3FF00000 + +#define DEFAULT_82542_TIPG_IPGR1 2 +#define DEFAULT_82543_TIPG_IPGR1 8 +#define E1000_TIPG_IPGR1_SHIFT 10 + +#define DEFAULT_82542_TIPG_IPGR2 10 +#define DEFAULT_82543_TIPG_IPGR2 6 +#define E1000_TIPG_IPGR2_SHIFT 20 + +#define E1000_TXDMAC_DPP 0x00000001 + +/* Adaptive IFS defines */ +#define TX_THRESHOLD_START 8 +#define TX_THRESHOLD_INCREMENT 10 +#define TX_THRESHOLD_DECREMENT 1 +#define TX_THRESHOLD_STOP 190 +#define TX_THRESHOLD_DISABLE 0 +#define TX_THRESHOLD_TIMER_MS 10000 +#define MIN_NUM_XMITS 1000 +#define IFS_MAX 80 +#define IFS_STEP 10 +#define IFS_MIN 40 +#define IFS_RATIO 4 + +/* PBA constants */ +#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ +#define E1000_PBA_24K 0x0018 +#define E1000_PBA_40K 0x0028 +#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ + +/* Flow Control Constants */ +#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 +#define FLOW_CONTROL_TYPE 0x8808 + +/* The historical defaults for the flow control values are given below. */ +#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ +#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ +#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ + +/* Flow Control High-Watermark: 43464 bytes */ +#define E1000_FC_HIGH_THRESH 0xA9C8 +/* Flow Control Low-Watermark: 43456 bytes */ +#define E1000_FC_LOW_THRESH 0xA9C0 +/* Flow Control Pause Time: 858 usec */ +#define E1000_FC_PAUSE_TIME 0x0680 + +/* PCIX Config space */ +#define PCIX_COMMAND_REGISTER 0xE6 +#define PCIX_STATUS_REGISTER_LO 0xE8 +#define PCIX_STATUS_REGISTER_HI 0xEA + +#define PCIX_COMMAND_MMRBC_MASK 0x000C +#define PCIX_COMMAND_MMRBC_SHIFT 0x2 +#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 +#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 +#define PCIX_STATUS_HI_MMRBC_4K 0x3 +#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 + */ +#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 + */ +#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 + */ +#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 + */ +#define ILOS_SHIFT 3 + +#define RECEIVE_BUFFER_ALIGN_SIZE (256) + +/* The number of milliseconds we wait for auto-negotiation to complete */ +#define LINK_UP_TIMEOUT 500 + +#define E1000_TX_BUFFER_SIZE ((uint32_t)1514) + +/* The carrier extension symbol, as received by the NIC. */ +#define CARRIER_EXTENSION 0x0F + +/* TBI_ACCEPT macro definition: + * + * This macro requires: + * adapter = a pointer to struct e1000_hw + * status = the 8 bit status field of the RX descriptor with EOP set + * error = the 8 bit error field of the RX descriptor with EOP set + * length = the sum of all the length fields of the RX descriptors that + * make up the current frame + * last_byte = the last byte of the frame DMAed by the hardware + * max_frame_length = the maximum frame length we want to accept. + * min_frame_length = the minimum frame length we want to accept. + * + * This macro is a conditional that should be used in the interrupt + * handler's Rx processing routine when RxErrors have been detected. + * + * Typical use: + * ... + * if (TBI_ACCEPT) { + * accept_frame = TRUE; + * e1000_tbi_adjust_stats(adapter, MacAddress); + * frame_length--; + * } else { + * accept_frame = FALSE; + * } + * ... + */ + +#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \ + ((adapter)->tbi_compatibility_on && \ + (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ + ((last_byte) == CARRIER_EXTENSION) && \ + (((status) & E1000_RXD_STAT_VP) ? \ + (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \ + ((length) <= ((adapter)->max_frame_size + 1))) : \ + (((length) > (adapter)->min_frame_size) && \ + ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1))))) + +/* Structures, enums, and macros for the PHY */ + +/* Bit definitions for the Management Data IO (MDIO) and Management Data + * Clock (MDC) pins in the Device Control Register. + */ +#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 +#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 +#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 +#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 +#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 +#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 +#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR +#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA + +/* PHY 1000 MII Register/Bit Definitions */ +/* PHY Registers defined by IEEE */ +#define PHY_CTRL 0x00 /* Control Register */ +#define PHY_STATUS 0x01 /* Status Regiser */ +#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ +#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + +/* M88E1000 Specific Registers */ +#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ +#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ +#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ +#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ +#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ +#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ + +#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ + +/* 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 */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ + +/* PHY Status Register */ +#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ + +/* Autoneg Advertisement Register */ +#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ +#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ +#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ +#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Link Partner Ability Register (Base Page) */ +#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ +#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ +#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ +#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ +#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ +#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ +#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ +#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ +#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ +#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Autoneg Expansion Register */ +#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ +#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ +#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ +#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ +#define NWAY_ER_PAR_DETECT_FAULT 0x0100 /* LP is 100TX Full Duplex Capable */ + +/* Next Page TX Register */ +#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* Link Partner Next Page Register */ +#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ +#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* 1000BASE-T Control Register */ +#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ +#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ + /* 0=DTE device */ +#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ + /* 0=Configure PHY as Slave */ +#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ + /* 0=Automatic Master/Slave config */ +#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ +#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ +#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ +#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ + +/* 1000BASE-T Status Register */ +#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ +#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ +#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#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 + +/* Extended Status Register */ +#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ +#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ +#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ +#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ + +#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ +#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ + +#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ + /* (0=enable, 1=disable) */ + +/* M88E1000 PHY Specific Control Register */ +#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ +#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ +#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ +#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, + * 0=CLK125 toggling + */ +#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ + /* Manual MDI configuration */ +#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ +#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, + * 100BASE-TX/10BASE-T: + * MDI Mode + */ +#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled + * all speeds. + */ +#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 + /* 1=Enable Extended 10BASE-T distance + * (Lower 10BASE-T RX Threshold) + * 0=Normal 10BASE-T RX Threshold */ +#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 + /* 1=5-Bit interface in 100BASE-TX + * 0=MII interface in 100BASE-TX */ +#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ +#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ +#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ + +#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1 +#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5 +#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 + +/* M88E1000 PHY Specific Status Register */ +#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ +#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ +#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ +#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; + * 3=110-140M;4=>140M */ +#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ +#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ +#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ +#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ +#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ +#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ +#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ +#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ + +#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 +#define M88E1000_PSSR_MDIX_SHIFT 6 +#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 + +/* M88E1000 Extended PHY Specific Control Register */ +#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ +#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. + * Will assert lost lock and bring + * link down if idle not seen + * within 1ms in 1000BASE-T + */ +/* Number of times we will attempt to autonegotiate before downshifting if we + * are the master */ +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 +/* Number of times we will attempt to autonegotiate before downshifting if we + * are the slave */ +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 +#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 +#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ +#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ +#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ + +/* Bit definitions for valid PHY IDs. */ +#define M88E1000_E_PHY_ID 0x01410C50 +#define M88E1000_I_PHY_ID 0x01410C30 +#define M88E1011_I_PHY_ID 0x01410C20 +#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID +#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID + +/* Miscellaneous PHY bit definitions. */ +#define PHY_PREAMBLE 0xFFFFFFFF +#define PHY_SOF 0x01 +#define PHY_OP_READ 0x02 +#define PHY_OP_WRITE 0x01 +#define PHY_TURNAROUND 0x02 +#define PHY_PREAMBLE_SIZE 32 +#define MII_CR_SPEED_1000 0x0040 +#define MII_CR_SPEED_100 0x2000 +#define MII_CR_SPEED_10 0x0000 +#define E1000_PHY_ADDRESS 0x01 +#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ +#define PHY_REVISION_MASK 0xFFFFFFF0 +#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ +#define REG4_SPEED_MASK 0x01E0 +#define REG9_SPEED_MASK 0x0300 +#define ADVERTISE_10_HALF 0x0001 +#define ADVERTISE_10_FULL 0x0002 +#define ADVERTISE_100_HALF 0x0004 +#define ADVERTISE_100_FULL 0x0008 +#define ADVERTISE_1000_HALF 0x0010 +#define ADVERTISE_1000_FULL 0x0020 +#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ + +#endif /* _E1000_HW_H_ */ diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c new file mode 100644 index 0000000000..738146e661 --- /dev/null +++ b/drivers/net/eepro100.c @@ -0,0 +1,948 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_EEPRO100) + + /* Ethernet chip registers. + */ +#define SCBStatus 0 /* Rx/Command Unit Status *Word* */ +#define SCBIntAckByte 1 /* Rx/Command Unit STAT/ACK byte */ +#define SCBCmd 2 /* Rx/Command Unit Command *Word* */ +#define SCBIntrCtlByte 3 /* Rx/Command Unit Intr.Control Byte */ +#define SCBPointer 4 /* General purpose pointer. */ +#define SCBPort 8 /* Misc. commands and operands. */ +#define SCBflash 12 /* Flash memory control. */ +#define SCBeeprom 14 /* EEPROM memory control. */ +#define SCBCtrlMDI 16 /* MDI interface control. */ +#define SCBEarlyRx 20 /* Early receive byte count. */ +#define SCBGenControl 28 /* 82559 General Control Register */ +#define SCBGenStatus 29 /* 82559 General Status register */ + + /* 82559 SCB status word defnitions + */ +#define SCB_STATUS_CX 0x8000 /* CU finished command (transmit) */ +#define SCB_STATUS_FR 0x4000 /* frame received */ +#define SCB_STATUS_CNA 0x2000 /* CU left active state */ +#define SCB_STATUS_RNR 0x1000 /* receiver left ready state */ +#define SCB_STATUS_MDI 0x0800 /* MDI read/write cycle done */ +#define SCB_STATUS_SWI 0x0400 /* software generated interrupt */ +#define SCB_STATUS_FCP 0x0100 /* flow control pause interrupt */ + +#define SCB_INTACK_MASK 0xFD00 /* all the above */ + +#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA) +#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR) + + /* System control block commands + */ +/* CU Commands */ +#define CU_NOP 0x0000 +#define CU_START 0x0010 +#define CU_RESUME 0x0020 +#define CU_STATSADDR 0x0040 /* Load Dump Statistics ctrs addr */ +#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ +#define CU_ADDR_LOAD 0x0060 /* Base address to add to CU commands */ +#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ + +/* RUC Commands */ +#define RUC_NOP 0x0000 +#define RUC_START 0x0001 +#define RUC_RESUME 0x0002 +#define RUC_ABORT 0x0004 +#define RUC_ADDR_LOAD 0x0006 /* (seems not to clear on acceptance) */ +#define RUC_RESUMENR 0x0007 + +#define CU_CMD_MASK 0x00f0 +#define RU_CMD_MASK 0x0007 + +#define SCB_M 0x0100 /* 0 = enable interrupt, 1 = disable */ +#define SCB_SWI 0x0200 /* 1 - cause device to interrupt */ + +#define CU_STATUS_MASK 0x00C0 +#define RU_STATUS_MASK 0x003C + +#define RU_STATUS_IDLE (0<<2) +#define RU_STATUS_SUS (1<<2) +#define RU_STATUS_NORES (2<<2) +#define RU_STATUS_READY (4<<2) +#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2)) +#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2)) +#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2)) + + /* 82559 Port interface commands. + */ +#define I82559_RESET 0x00000000 /* Software reset */ +#define I82559_SELFTEST 0x00000001 /* 82559 Selftest command */ +#define I82559_SELECTIVE_RESET 0x00000002 +#define I82559_DUMP 0x00000003 +#define I82559_DUMP_WAKEUP 0x00000007 + + /* 82559 Eeprom interface. + */ +#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ +#define EE_CS 0x02 /* EEPROM chip select. */ +#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x01 +#define EE_WRITE_1 0x05 +#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ +#define EE_ENB (0x4800 | EE_CS) +#define EE_CMD_BITS 3 +#define EE_DATA_BITS 16 + + /* The EEPROM commands include the alway-set leading bit. + */ +#define EE_EWENB_CMD (4 << addr_len) +#define EE_WRITE_CMD (5 << addr_len) +#define EE_READ_CMD (6 << addr_len) +#define EE_ERASE_CMD (7 << addr_len) + + /* Receive frame descriptors. + */ +struct RxFD { + volatile u16 status; + volatile u16 control; + volatile u32 link; /* struct RxFD * */ + volatile u32 rx_buf_addr; /* void * */ + volatile u32 count; + + volatile u8 data[PKTSIZE_ALIGN]; +}; + +#define RFD_STATUS_C 0x8000 /* completion of received frame */ +#define RFD_STATUS_OK 0x2000 /* frame received with no errors */ + +#define RFD_CONTROL_EL 0x8000 /* 1=last RFD in RFA */ +#define RFD_CONTROL_S 0x4000 /* 1=suspend RU after receiving frame */ +#define RFD_CONTROL_H 0x0010 /* 1=RFD is a header RFD */ +#define RFD_CONTROL_SF 0x0008 /* 0=simplified, 1=flexible mode */ + +#define RFD_COUNT_MASK 0x3fff +#define RFD_COUNT_F 0x4000 +#define RFD_COUNT_EOF 0x8000 + +#define RFD_RX_CRC 0x0800 /* crc error */ +#define RFD_RX_ALIGNMENT 0x0400 /* alignment error */ +#define RFD_RX_RESOURCE 0x0200 /* out of space, no resources */ +#define RFD_RX_DMA_OVER 0x0100 /* DMA overrun */ +#define RFD_RX_SHORT 0x0080 /* short frame error */ +#define RFD_RX_LENGTH 0x0020 +#define RFD_RX_ERROR 0x0010 /* receive error */ +#define RFD_RX_NO_ADR_MATCH 0x0004 /* no address match */ +#define RFD_RX_IA_MATCH 0x0002 /* individual address does not match */ +#define RFD_RX_TCO 0x0001 /* TCO indication */ + + /* Transmit frame descriptors + */ +struct TxFD { /* Transmit frame descriptor set. */ + volatile u16 status; + volatile u16 command; + volatile u32 link; /* void * */ + volatile u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ + volatile s32 count; + + volatile u32 tx_buf_addr0; /* void *, frame to be transmitted. */ + volatile s32 tx_buf_size0; /* Length of Tx frame. */ + volatile u32 tx_buf_addr1; /* void *, frame to be transmitted. */ + volatile s32 tx_buf_size1; /* Length of Tx frame. */ +}; + +#define TxCB_CMD_TRANSMIT 0x0004 /* transmit command */ +#define TxCB_CMD_SF 0x0008 /* 0=simplified, 1=flexible mode */ +#define TxCB_CMD_NC 0x0010 /* 0=CRC insert by controller */ +#define TxCB_CMD_I 0x2000 /* generate interrupt on completion */ +#define TxCB_CMD_S 0x4000 /* suspend on completion */ +#define TxCB_CMD_EL 0x8000 /* last command block in CBL */ + +#define TxCB_COUNT_MASK 0x3fff +#define TxCB_COUNT_EOF 0x8000 + + /* The Speedo3 Rx and Tx frame/buffer descriptors. + */ +struct descriptor { /* A generic descriptor. */ + volatile u16 status; + volatile u16 command; + volatile u32 link; /* struct descriptor * */ + + unsigned char params[0]; +}; + +#define CFG_CMD_EL 0x8000 +#define CFG_CMD_SUSPEND 0x4000 +#define CFG_CMD_INT 0x2000 +#define CFG_CMD_IAS 0x0001 /* individual address setup */ +#define CFG_CMD_CONFIGURE 0x0002 /* configure */ + +#define CFG_STATUS_C 0x8000 +#define CFG_STATUS_OK 0x2000 + + /* Misc. + */ +#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 1 /* Number of TX descriptors */ + +#define TOUT_LOOP 1000000 + +#define ETH_ALEN 6 + +static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ +static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ +static int rx_next; /* RX descriptor ring pointer */ +static int tx_next; /* TX descriptor ring pointer */ +static int tx_threshold; + +/* + * The parameters for a CmdConfigure operation. + * There are so many options that it would be difficult to document + * each bit. We mostly use the default or recommended settings. + */ +static const char i82557_config_cmd[] = { + 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 0, 0x2E, 0, 0x60, 0, + 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ + 0x3f, 0x05, +}; +static const char i82558_config_cmd[] = { + 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 0, 0x2E, 0, 0x60, 0x08, 0x88, + 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ + 0x31, 0x05, +}; + +static void init_rx_ring (struct eth_device *dev); +static void purge_tx_ring (struct eth_device *dev); + +static void read_hw_addr (struct eth_device *dev, bd_t * bis); + +static int eepro100_init (struct eth_device *dev, bd_t * bis); +static int eepro100_send (struct eth_device *dev, volatile void *packet, + int length); +static int eepro100_recv (struct eth_device *dev); +static void eepro100_halt (struct eth_device *dev); + +#if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460) +#define bus_to_phys(a) (a) +#define phys_to_bus(a) (a) +#else +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#endif + +static inline int INW (struct eth_device *dev, u_long addr) +{ + return le16_to_cpu (*(volatile u16 *) (addr + dev->iobase)); +} + +static inline void OUTW (struct eth_device *dev, int command, u_long addr) +{ + *(volatile u16 *) ((addr + dev->iobase)) = cpu_to_le16 (command); +} + +static inline void OUTL (struct eth_device *dev, int command, u_long addr) +{ + *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command); +} + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +static inline int INL (struct eth_device *dev, u_long addr) +{ + return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase)); +} + +static int get_phyreg (struct eth_device *dev, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + int cmd; + int timeout = 50; + + /* read requested data */ + cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); + OUTL (dev, cmd, SCBCtrlMDI); + + do { + udelay(1000); + cmd = INL (dev, SCBCtrlMDI); + } while (!(cmd & (1 << 28)) && (--timeout)); + + if (timeout == 0) + return -1; + + *value = (unsigned short) (cmd & 0xffff); + + return 0; +} + +static int set_phyreg (struct eth_device *dev, unsigned char addr, + unsigned char reg, unsigned short value) +{ + int cmd; + int timeout = 50; + + /* write requested data */ + cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); + OUTL (dev, cmd | value, SCBCtrlMDI); + + while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) + udelay(1000); + + if (timeout == 0) + return -1; + + return 0; +} + +/* Check if given phyaddr is valid, i.e. there is a PHY connected. + * Do this by checking model value field from ID2 register. + */ +static struct eth_device* verify_phyaddr (char *devname, unsigned char addr) +{ + struct eth_device *dev; + unsigned short value; + unsigned char model; + + dev = eth_get_dev_by_name(devname); + if (dev == NULL) { + printf("%s: no such device\n", devname); + return NULL; + } + + /* read id2 register */ + if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) { + printf("%s: mii read timeout!\n", devname); + return NULL; + } + + /* get model */ + model = (unsigned char)((value >> 4) & 0x003f); + + if (model == 0) { + printf("%s: no PHY at address %d\n", devname, addr); + return NULL; + } + + return dev; +} + +static int eepro100_miiphy_read (char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + struct eth_device *dev; + + dev = verify_phyaddr(devname, addr); + if (dev == NULL) + return -1; + + if (get_phyreg(dev, addr, reg, value) != 0) { + printf("%s: mii read timeout!\n", devname); + return -1; + } + + return 0; +} + +static int eepro100_miiphy_write (char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + struct eth_device *dev; + + dev = verify_phyaddr(devname, addr); + if (dev == NULL) + return -1; + + if (set_phyreg(dev, addr, reg, value) != 0) { + printf("%s: mii write timeout!\n", devname); + return -1; + } + + return 0; +} + +#endif + +/* Wait for the chip get the command. +*/ +static int wait_for_eepro100 (struct eth_device *dev) +{ + int i; + + for (i = 0; INW (dev, SCBCmd) & (CU_CMD_MASK | RU_CMD_MASK); i++) { + if (i >= TOUT_LOOP) { + return 0; + } + } + + return 1; +} + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER}, + {} +}; + +int eepro100_initialize (bd_t * bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase, status; + int idx = 0; + + while (1) { + /* Find PCI device + */ + if ((devno = pci_find_devices (supported, idx++)) < 0) { + break; + } + + pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0xf; + +#ifdef DEBUG + printf ("eepro100: Intel i82559 PCI EtherExpressPro @0x%x\n", + iobase); +#endif + + pci_write_config_dword (devno, + PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Check if I/O accesses and Bus Mastering are enabled. + */ + pci_read_config_dword (devno, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf ("Error: Can not enable MEM access.\n"); + continue; + } + + if (!(status & PCI_COMMAND_MASTER)) { + printf ("Error: Can not enable Bus Mastering.\n"); + continue; + } + + dev = (struct eth_device *) malloc (sizeof *dev); + + sprintf (dev->name, "i82559#%d", card_number); + dev->priv = (void *) devno; /* this have to come before bus_to_phys() */ + dev->iobase = bus_to_phys (iobase); + dev->init = eepro100_init; + dev->halt = eepro100_halt; + dev->send = eepro100_send; + dev->recv = eepro100_recv; + + eth_register (dev); + +#if defined (CONFIG_MII) || defined(CONFIG_CMD_MII) + /* register mii command access routines */ + miiphy_register(dev->name, + eepro100_miiphy_read, eepro100_miiphy_write); +#endif + + card_number++; + + /* Set the latency timer for value. + */ + pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); + + udelay (10 * 1000); + + read_hw_addr (dev, bis); + } + + return card_number; +} + + +static int eepro100_init (struct eth_device *dev, bd_t * bis) +{ + int i, status = 0; + int tx_cur; + struct descriptor *ias_cmd, *cfg_cmd; + + /* Reset the ethernet controller + */ + OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); + udelay (20); + + OUTL (dev, I82559_RESET, SCBPort); + udelay (20); + + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + OUTL (dev, 0, SCBPointer); + OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + OUTL (dev, 0, SCBPointer); + OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + + /* Initialize Rx and Tx rings. + */ + init_rx_ring (dev); + purge_tx_ring (dev); + + /* Tell the adapter where the RX ring is located. + */ + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + + OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); + OUTW (dev, SCB_M | RUC_START, SCBCmd); + + /* Send the Configure frame */ + tx_cur = tx_next; + tx_next = ((tx_next + 1) % NUM_TX_DESC); + + cfg_cmd = (struct descriptor *) &tx_ring[tx_cur]; + cfg_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_CONFIGURE)); + cfg_cmd->status = 0; + cfg_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + + memcpy (cfg_cmd->params, i82558_config_cmd, + sizeof (i82558_config_cmd)); + + if (!wait_for_eepro100 (dev)) { + printf ("Error---CFG_CMD_CONFIGURE: Can not reset ethernet controller.\n"); + goto Done; + } + + OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); + OUTW (dev, SCB_M | CU_START, SCBCmd); + + for (i = 0; + !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); + i++) { + if (i >= TOUT_LOOP) { + printf ("%s: Tx error buffer not ready\n", dev->name); + goto Done; + } + } + + if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { + printf ("TX error status = 0x%08X\n", + le16_to_cpu (tx_ring[tx_cur].status)); + goto Done; + } + + /* Send the Individual Address Setup frame + */ + tx_cur = tx_next; + tx_next = ((tx_next + 1) % NUM_TX_DESC); + + ias_cmd = (struct descriptor *) &tx_ring[tx_cur]; + ias_cmd->command = cpu_to_le16 ((CFG_CMD_SUSPEND | CFG_CMD_IAS)); + ias_cmd->status = 0; + ias_cmd->link = cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + + memcpy (ias_cmd->params, dev->enetaddr, 6); + + /* Tell the adapter where the TX ring is located. + */ + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + + OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); + OUTW (dev, SCB_M | CU_START, SCBCmd); + + for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); + i++) { + if (i >= TOUT_LOOP) { + printf ("%s: Tx error buffer not ready\n", + dev->name); + goto Done; + } + } + + if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { + printf ("TX error status = 0x%08X\n", + le16_to_cpu (tx_ring[tx_cur].status)); + goto Done; + } + + status = 1; + + Done: + return status; +} + +static int eepro100_send (struct eth_device *dev, volatile void *packet, int length) +{ + int i, status = -1; + int tx_cur; + + if (length <= 0) { + printf ("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + tx_cur = tx_next; + tx_next = (tx_next + 1) % NUM_TX_DESC; + + tx_ring[tx_cur].command = cpu_to_le16 ( TxCB_CMD_TRANSMIT | + TxCB_CMD_SF | + TxCB_CMD_S | + TxCB_CMD_EL ); + tx_ring[tx_cur].status = 0; + tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold); + tx_ring[tx_cur].link = + cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_next])); + tx_ring[tx_cur].tx_desc_addr = + cpu_to_le32 (phys_to_bus ((u32) & tx_ring[tx_cur].tx_buf_addr0)); + tx_ring[tx_cur].tx_buf_addr0 = + cpu_to_le32 (phys_to_bus ((u_long) packet)); + tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length); + + if (!wait_for_eepro100 (dev)) { + printf ("%s: Tx error ethernet controller not ready.\n", + dev->name); + goto Done; + } + + /* Send the packet. + */ + OUTL (dev, phys_to_bus ((u32) & tx_ring[tx_cur]), SCBPointer); + OUTW (dev, SCB_M | CU_START, SCBCmd); + + for (i = 0; !(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_C); + i++) { + if (i >= TOUT_LOOP) { + printf ("%s: Tx error buffer not ready\n", dev->name); + goto Done; + } + } + + if (!(le16_to_cpu (tx_ring[tx_cur].status) & CFG_STATUS_OK)) { + printf ("TX error status = 0x%08X\n", + le16_to_cpu (tx_ring[tx_cur].status)); + goto Done; + } + + status = length; + + Done: + return status; +} + +static int eepro100_recv (struct eth_device *dev) +{ + u16 status, stat; + int rx_prev, length = 0; + + stat = INW (dev, SCBStatus); + OUTW (dev, stat & SCB_STATUS_RNR, SCBStatus); + + for (;;) { + status = le16_to_cpu (rx_ring[rx_next].status); + + if (!(status & RFD_STATUS_C)) { + break; + } + + /* Valid frame status. + */ + if ((status & RFD_STATUS_OK)) { + /* A valid frame received. + */ + length = le32_to_cpu (rx_ring[rx_next].count) & 0x3fff; + + /* Pass the packet up to the protocol + * layers. + */ + NetReceive (rx_ring[rx_next].data, length); + } else { + /* There was an error. + */ + printf ("RX error status = 0x%08X\n", status); + } + + rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S); + rx_ring[rx_next].status = 0; + rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); + + rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC; + rx_ring[rx_prev].control = 0; + + /* Update entry information. + */ + rx_next = (rx_next + 1) % NUM_RX_DESC; + } + + if (stat & SCB_STATUS_RNR) { + + printf ("%s: Receiver is not ready, restart it !\n", dev->name); + + /* Reinitialize Rx ring. + */ + init_rx_ring (dev); + + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not restart ethernet controller.\n"); + goto Done; + } + + OUTL (dev, phys_to_bus ((u32) & rx_ring[rx_next]), SCBPointer); + OUTW (dev, SCB_M | RUC_START, SCBCmd); + } + + Done: + return length; +} + +static void eepro100_halt (struct eth_device *dev) +{ + /* Reset the ethernet controller + */ + OUTL (dev, I82559_SELECTIVE_RESET, SCBPort); + udelay (20); + + OUTL (dev, I82559_RESET, SCBPort); + udelay (20); + + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + OUTL (dev, 0, SCBPointer); + OUTW (dev, SCB_M | RUC_ADDR_LOAD, SCBCmd); + + if (!wait_for_eepro100 (dev)) { + printf ("Error: Can not reset ethernet controller.\n"); + goto Done; + } + OUTL (dev, 0, SCBPointer); + OUTW (dev, SCB_M | CU_ADDR_LOAD, SCBCmd); + + Done: + return; +} + + /* SROM Read. + */ +static int read_eeprom (struct eth_device *dev, int location, int addr_len) +{ + unsigned short retval = 0; + int read_cmd = location | EE_READ_CMD; + int i; + + OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); + OUTW (dev, EE_ENB, SCBeeprom); + + /* Shift the read command bits out. */ + for (i = 12; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + + OUTW (dev, EE_ENB | dataval, SCBeeprom); + udelay (1); + OUTW (dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + udelay (1); + } + OUTW (dev, EE_ENB, SCBeeprom); + + for (i = 15; i >= 0; i--) { + OUTW (dev, EE_ENB | EE_SHIFT_CLK, SCBeeprom); + udelay (1); + retval = (retval << 1) | + ((INW (dev, SCBeeprom) & EE_DATA_READ) ? 1 : 0); + OUTW (dev, EE_ENB, SCBeeprom); + udelay (1); + } + + /* Terminate the EEPROM access. */ + OUTW (dev, EE_ENB & ~EE_CS, SCBeeprom); + return retval; +} + +#ifdef CONFIG_EEPRO100_SROM_WRITE +int eepro100_write_eeprom (struct eth_device* dev, int location, int addr_len, unsigned short data) +{ + unsigned short dataval; + int enable_cmd = 0x3f | EE_EWENB_CMD; + int write_cmd = location | EE_WRITE_CMD; + int i; + unsigned long datalong, tmplong; + + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB, SCBeeprom); + + /* Shift the enable command bits out. */ + for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) + { + dataval = (enable_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(dev, EE_ENB | dataval, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + udelay(1); + } + + OUTW(dev, EE_ENB, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB, SCBeeprom); + + + /* Shift the write command bits out. */ + for (i = (addr_len+EE_CMD_BITS-1); i >= 0; i--) + { + dataval = (write_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + OUTW(dev, EE_ENB | dataval, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + udelay(1); + } + + /* Write the data */ + datalong= (unsigned long) ((((data) & 0x00ff) << 8) | ( (data) >> 8)); + + for (i = 0; i< EE_DATA_BITS; i++) + { + /* Extract and move data bit to bit DI */ + dataval = ((datalong & 0x8000)>>13) ? EE_DATA_WRITE : 0; + + OUTW(dev, EE_ENB | dataval, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB | dataval | EE_SHIFT_CLK, SCBeeprom); + udelay(1); + OUTW(dev, EE_ENB | dataval, SCBeeprom); + udelay(1); + + datalong = datalong << 1; /* Adjust significant data bit*/ + } + + /* Finish up command (toggle CS) */ + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + udelay(1); /* delay for more than 250 ns */ + OUTW(dev, EE_ENB, SCBeeprom); + + /* Wait for programming ready (D0 = 1) */ + tmplong = 10; + do + { + dataval = INW(dev, SCBeeprom); + if (dataval & EE_DATA_READ) + break; + udelay(10000); + } + while (-- tmplong); + + if (tmplong == 0) + { + printf ("Write i82559 eeprom timed out (100 ms waiting for data ready.\n"); + return -1; + } + + /* Terminate the EEPROM access. */ + OUTW(dev, EE_ENB & ~EE_CS, SCBeeprom); + + return 0; +} +#endif + +static void init_rx_ring (struct eth_device *dev) +{ + int i; + + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = 0; + rx_ring[i].control = + (i == NUM_RX_DESC - 1) ? cpu_to_le16 (RFD_CONTROL_S) : 0; + rx_ring[i].link = + cpu_to_le32 (phys_to_bus + ((u32) & rx_ring[(i + 1) % NUM_RX_DESC])); + rx_ring[i].rx_buf_addr = 0xffffffff; + rx_ring[i].count = cpu_to_le32 (PKTSIZE_ALIGN << 16); + } + + rx_next = 0; +} + +static void purge_tx_ring (struct eth_device *dev) +{ + int i; + + tx_next = 0; + tx_threshold = 0x01208000; + + for (i = 0; i < NUM_TX_DESC; i++) { + tx_ring[i].status = 0; + tx_ring[i].command = 0; + tx_ring[i].link = 0; + tx_ring[i].tx_desc_addr = 0; + tx_ring[i].count = 0; + + tx_ring[i].tx_buf_addr0 = 0; + tx_ring[i].tx_buf_size0 = 0; + tx_ring[i].tx_buf_addr1 = 0; + tx_ring[i].tx_buf_size1 = 0; + } +} + +static void read_hw_addr (struct eth_device *dev, bd_t * bis) +{ + u16 eeprom[0x40]; + u16 sum = 0; + int i, j; + int addr_len = read_eeprom (dev, 0, 6) == 0xffff ? 8 : 6; + + for (j = 0, i = 0; i < 0x40; i++) { + u16 value = read_eeprom (dev, i, addr_len); + + eeprom[i] = value; + sum += value; + if (i < 3) { + dev->enetaddr[j++] = value; + dev->enetaddr[j++] = value >> 8; + } + } + + if (sum != 0xBABA) { + memset (dev->enetaddr, 0, ETH_ALEN); +#ifdef DEBUG + printf ("%s: Invalid EEPROM checksum %#4.4x, " + "check settings before activating this device!\n", + dev->name, sum); +#endif + } +} + +#endif diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c new file mode 100644 index 0000000000..98303aceee --- /dev/null +++ b/drivers/net/enc28j60.c @@ -0,0 +1,983 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#ifdef CONFIG_ENC28J60 +#include +#include +#include + +/* + * Control Registers in Bank 0 + */ + +#define CTL_REG_ERDPTL 0x00 +#define CTL_REG_ERDPTH 0x01 +#define CTL_REG_EWRPTL 0x02 +#define CTL_REG_EWRPTH 0x03 +#define CTL_REG_ETXSTL 0x04 +#define CTL_REG_ETXSTH 0x05 +#define CTL_REG_ETXNDL 0x06 +#define CTL_REG_ETXNDH 0x07 +#define CTL_REG_ERXSTL 0x08 +#define CTL_REG_ERXSTH 0x09 +#define CTL_REG_ERXNDL 0x0A +#define CTL_REG_ERXNDH 0x0B +#define CTL_REG_ERXRDPTL 0x0C +#define CTL_REG_ERXRDPTH 0x0D +#define CTL_REG_ERXWRPTL 0x0E +#define CTL_REG_ERXWRPTH 0x0F +#define CTL_REG_EDMASTL 0x10 +#define CTL_REG_EDMASTH 0x11 +#define CTL_REG_EDMANDL 0x12 +#define CTL_REG_EDMANDH 0x13 +#define CTL_REG_EDMADSTL 0x14 +#define CTL_REG_EDMADSTH 0x15 +#define CTL_REG_EDMACSL 0x16 +#define CTL_REG_EDMACSH 0x17 +/* these are common in all banks */ +#define CTL_REG_EIE 0x1B +#define CTL_REG_EIR 0x1C +#define CTL_REG_ESTAT 0x1D +#define CTL_REG_ECON2 0x1E +#define CTL_REG_ECON1 0x1F + +/* + * Control Registers in Bank 1 + */ + +#define CTL_REG_EHT0 0x00 +#define CTL_REG_EHT1 0x01 +#define CTL_REG_EHT2 0x02 +#define CTL_REG_EHT3 0x03 +#define CTL_REG_EHT4 0x04 +#define CTL_REG_EHT5 0x05 +#define CTL_REG_EHT6 0x06 +#define CTL_REG_EHT7 0x07 +#define CTL_REG_EPMM0 0x08 +#define CTL_REG_EPMM1 0x09 +#define CTL_REG_EPMM2 0x0A +#define CTL_REG_EPMM3 0x0B +#define CTL_REG_EPMM4 0x0C +#define CTL_REG_EPMM5 0x0D +#define CTL_REG_EPMM6 0x0E +#define CTL_REG_EPMM7 0x0F +#define CTL_REG_EPMCSL 0x10 +#define CTL_REG_EPMCSH 0x11 +#define CTL_REG_EPMOL 0x14 +#define CTL_REG_EPMOH 0x15 +#define CTL_REG_EWOLIE 0x16 +#define CTL_REG_EWOLIR 0x17 +#define CTL_REG_ERXFCON 0x18 +#define CTL_REG_EPKTCNT 0x19 + +/* + * Control Registers in Bank 2 + */ + +#define CTL_REG_MACON1 0x00 +#define CTL_REG_MACON2 0x01 +#define CTL_REG_MACON3 0x02 +#define CTL_REG_MACON4 0x03 +#define CTL_REG_MABBIPG 0x04 +#define CTL_REG_MAIPGL 0x06 +#define CTL_REG_MAIPGH 0x07 +#define CTL_REG_MACLCON1 0x08 +#define CTL_REG_MACLCON2 0x09 +#define CTL_REG_MAMXFLL 0x0A +#define CTL_REG_MAMXFLH 0x0B +#define CTL_REG_MAPHSUP 0x0D +#define CTL_REG_MICON 0x11 +#define CTL_REG_MICMD 0x12 +#define CTL_REG_MIREGADR 0x14 +#define CTL_REG_MIWRL 0x16 +#define CTL_REG_MIWRH 0x17 +#define CTL_REG_MIRDL 0x18 +#define CTL_REG_MIRDH 0x19 + +/* + * Control Registers in Bank 3 + */ + +#define CTL_REG_MAADR1 0x00 +#define CTL_REG_MAADR0 0x01 +#define CTL_REG_MAADR3 0x02 +#define CTL_REG_MAADR2 0x03 +#define CTL_REG_MAADR5 0x04 +#define CTL_REG_MAADR4 0x05 +#define CTL_REG_EBSTSD 0x06 +#define CTL_REG_EBSTCON 0x07 +#define CTL_REG_EBSTCSL 0x08 +#define CTL_REG_EBSTCSH 0x09 +#define CTL_REG_MISTAT 0x0A +#define CTL_REG_EREVID 0x12 +#define CTL_REG_ECOCON 0x15 +#define CTL_REG_EFLOCON 0x17 +#define CTL_REG_EPAUSL 0x18 +#define CTL_REG_EPAUSH 0x19 + + +/* + * PHY Register + */ + +#define PHY_REG_PHID1 0x02 +#define PHY_REG_PHID2 0x03 +/* taken from the Linux driver */ +#define PHY_REG_PHCON1 0x00 +#define PHY_REG_PHCON2 0x10 +#define PHY_REG_PHLCON 0x14 + +/* + * Receive Filter Register (ERXFCON) bits + */ + +#define ENC_RFR_UCEN 0x80 +#define ENC_RFR_ANDOR 0x40 +#define ENC_RFR_CRCEN 0x20 +#define ENC_RFR_PMEN 0x10 +#define ENC_RFR_MPEN 0x08 +#define ENC_RFR_HTEN 0x04 +#define ENC_RFR_MCEN 0x02 +#define ENC_RFR_BCEN 0x01 + +/* + * ECON1 Register Bits + */ + +#define ENC_ECON1_TXRST 0x80 +#define ENC_ECON1_RXRST 0x40 +#define ENC_ECON1_DMAST 0x20 +#define ENC_ECON1_CSUMEN 0x10 +#define ENC_ECON1_TXRTS 0x08 +#define ENC_ECON1_RXEN 0x04 +#define ENC_ECON1_BSEL1 0x02 +#define ENC_ECON1_BSEL0 0x01 + +/* + * ECON2 Register Bits + */ +#define ENC_ECON2_AUTOINC 0x80 +#define ENC_ECON2_PKTDEC 0x40 +#define ENC_ECON2_PWRSV 0x20 +#define ENC_ECON2_VRPS 0x08 + +/* + * EIR Register Bits + */ +#define ENC_EIR_PKTIF 0x40 +#define ENC_EIR_DMAIF 0x20 +#define ENC_EIR_LINKIF 0x10 +#define ENC_EIR_TXIF 0x08 +#define ENC_EIR_WOLIF 0x04 +#define ENC_EIR_TXERIF 0x02 +#define ENC_EIR_RXERIF 0x01 + +/* + * ESTAT Register Bits + */ + +#define ENC_ESTAT_INT 0x80 +#define ENC_ESTAT_LATECOL 0x10 +#define ENC_ESTAT_RXBUSY 0x04 +#define ENC_ESTAT_TXABRT 0x02 +#define ENC_ESTAT_CLKRDY 0x01 + +/* + * EIE Register Bits + */ + +#define ENC_EIE_INTIE 0x80 +#define ENC_EIE_PKTIE 0x40 +#define ENC_EIE_DMAIE 0x20 +#define ENC_EIE_LINKIE 0x10 +#define ENC_EIE_TXIE 0x08 +#define ENC_EIE_WOLIE 0x04 +#define ENC_EIE_TXERIE 0x02 +#define ENC_EIE_RXERIE 0x01 + +/* + * MACON1 Register Bits + */ +#define ENC_MACON1_LOOPBK 0x10 +#define ENC_MACON1_TXPAUS 0x08 +#define ENC_MACON1_RXPAUS 0x04 +#define ENC_MACON1_PASSALL 0x02 +#define ENC_MACON1_MARXEN 0x01 + + +/* + * MACON2 Register Bits + */ +#define ENC_MACON2_MARST 0x80 +#define ENC_MACON2_RNDRST 0x40 +#define ENC_MACON2_MARXRST 0x08 +#define ENC_MACON2_RFUNRST 0x04 +#define ENC_MACON2_MATXRST 0x02 +#define ENC_MACON2_TFUNRST 0x01 + +/* + * MACON3 Register Bits + */ +#define ENC_MACON3_PADCFG2 0x80 +#define ENC_MACON3_PADCFG1 0x40 +#define ENC_MACON3_PADCFG0 0x20 +#define ENC_MACON3_TXCRCEN 0x10 +#define ENC_MACON3_PHDRLEN 0x08 +#define ENC_MACON3_HFRMEN 0x04 +#define ENC_MACON3_FRMLNEN 0x02 +#define ENC_MACON3_FULDPX 0x01 + +/* + * MICMD Register Bits + */ +#define ENC_MICMD_MIISCAN 0x02 +#define ENC_MICMD_MIIRD 0x01 + +/* + * MISTAT Register Bits + */ +#define ENC_MISTAT_NVALID 0x04 +#define ENC_MISTAT_SCAN 0x02 +#define ENC_MISTAT_BUSY 0x01 + +/* + * PHID1 and PHID2 values + */ +#define ENC_PHID1_VALUE 0x0083 +#define ENC_PHID2_VALUE 0x1400 +#define ENC_PHID2_MASK 0xFC00 + + +#define ENC_SPI_SLAVE_CS 0x00010000 /* pin P1.16 */ +#define ENC_RESET 0x00020000 /* pin P1.17 */ + +#define FAILSAFE_VALUE 5000 + +/* + * Controller memory layout: + * + * 0x0000 - 0x17ff 6k bytes receive buffer + * 0x1800 - 0x1fff 2k bytes transmit buffer + */ +/* Use the lower memory for receiver buffer. See errata pt. 5 */ +#define ENC_RX_BUF_START 0x0000 +#define ENC_TX_BUF_START 0x1800 +/* taken from the Linux driver */ +#define ENC_RX_BUF_END 0x17ff +#define ENC_TX_BUF_END 0x1fff + +/* maximum frame length */ +#define ENC_MAX_FRM_LEN 1518 + +#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS) +#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS) +#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8); + + +static unsigned char encReadReg (unsigned char regNo); +static void encWriteReg (unsigned char regNo, unsigned char data); +static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c); +static void encReadBuff (unsigned short length, unsigned char *pBuff); +static void encWriteBuff (unsigned short length, unsigned char *pBuff); +static void encBitSet (unsigned char regNo, unsigned char data); +static void encBitClr (unsigned char regNo, unsigned char data); +static void encReset (void); +static void encInit (unsigned char *pEthAddr); +static unsigned short phyRead (unsigned char addr); +static void phyWrite(unsigned char, unsigned short); +static void encPoll (void); +static void encRx (void); + +#define m_nic_read(reg) encReadReg(reg) +#define m_nic_write(reg, data) encWriteReg(reg, data) +#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count) +#define m_nic_read_data(len, buf) encReadBuff((len), (buf)) +#define m_nic_write_data(len, buf) encWriteBuff((len), (buf)) + +/* bit field set */ +#define m_nic_bfs(reg, data) encBitSet(reg, data) + +/* bit field clear */ +#define m_nic_bfc(reg, data) encBitClr(reg, data) + +static unsigned char bank = 0; /* current bank in enc28j60 */ +static unsigned char next_pointer_lsb; +static unsigned char next_pointer_msb; + +static unsigned char buffer[ENC_MAX_FRM_LEN]; +static int rxResetCounter = 0; + +#define RX_RESET_COUNTER 1000; + +/*----------------------------------------------------------------------------- + * Always returns 0 + */ +int eth_init (bd_t * bis) +{ + unsigned char estatVal; + + /* configure GPIO */ + (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS; + (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET; + + /* CS and RESET active low */ + PUT32 (IO1SET, ENC_SPI_SLAVE_CS); + PUT32 (IO1SET, ENC_RESET); + + spi_init (); + + /* taken from the Linux driver - dangerous stuff here! */ + /* Wait for CLKRDY to become set (i.e., check that we can communicate with + the ENC) */ + do + { + estatVal = m_nic_read(CTL_REG_ESTAT); + } while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY)); + + /* initialize controller */ + encReset (); + encInit (bis->bi_enetaddr); + + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ + + return 0; +} + +int eth_send (volatile void *packet, int length) +{ + /* check frame length, etc. */ + /* TODO: */ + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + /* set EWRPT */ + m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff)); + m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8)); + + /* set ETXND */ + m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF); + m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8); + + /* set ETXST */ + m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF); + m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8); + + /* write packet */ + m_nic_write_data (length, (unsigned char *) packet); + + /* taken from the Linux driver */ + /* Verify that the internal transmit logic has not been altered by excessive + collisions. See Errata B4 12 and 14. + */ + if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) { + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST); + m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST); + } + m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF)); + + /* set ECON1.TXRTS */ + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS); + + return 0; +} + + +/***************************************************************************** + * This function resets the receiver only. This function may be called from + * interrupt-context. + */ +static void encReceiverReset (void) +{ + unsigned char econ1; + + econ1 = m_nic_read (CTL_REG_ECON1); + if ((econ1 & ENC_ECON1_RXRST) == 0) { + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST); + rxResetCounter = RX_RESET_COUNTER; + } +} + +/***************************************************************************** + * receiver reset timer + */ +static void encReceiverResetCallback (void) +{ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */ +} + +/*----------------------------------------------------------------------------- + * Check for received packets. Call NetReceive for each packet. The return + * value is ignored by the caller. + */ +int eth_rx (void) +{ + if (rxResetCounter > 0 && --rxResetCounter == 0) { + encReceiverResetCallback (); + } + + encPoll (); + + return 0; +} + +void eth_halt (void) +{ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */ +} + +/*****************************************************************************/ + +static void encPoll (void) +{ + unsigned char eir_reg; + volatile unsigned char estat_reg; + unsigned char pkt_cnt; + +#ifdef CONFIG_USE_IRQ + /* clear global interrupt enable bit in enc28j60 */ + m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE); +#endif + estat_reg = m_nic_read (CTL_REG_ESTAT); + + eir_reg = m_nic_read (CTL_REG_EIR); + + if (eir_reg & ENC_EIR_TXIF) { + /* clear TXIF bit in EIR */ + m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF); + } + + /* We have to use pktcnt and not pktif bit, see errata pt. 6 */ + + /* move to bank 1 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); + + /* read pktcnt */ + pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); + + if (pkt_cnt > 0) { + if ((eir_reg & ENC_EIR_PKTIF) == 0) { + /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */ + } + encRx (); + /* clear PKTIF bit in EIR, this should not need to be done but it + seems like we get problems if we do not */ + m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF); + } + + if (eir_reg & ENC_EIR_RXERIF) { + printf ("encPoll: rx error\n"); + m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF); + } + if (eir_reg & ENC_EIR_TXERIF) { + printf ("encPoll: tx error\n"); + m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF); + } + +#ifdef CONFIG_USE_IRQ + /* set global interrupt enable bit in enc28j60 */ + m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); +#endif +} + +static void encRx (void) +{ + unsigned short pkt_len; + unsigned short copy_len; + unsigned short status; + unsigned char eir_reg; + unsigned char pkt_cnt = 0; + unsigned short rxbuf_rdpt; + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); + m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); + + do { + m_nic_read_data (6, buffer); + next_pointer_lsb = buffer[0]; + next_pointer_msb = buffer[1]; + pkt_len = buffer[2]; + pkt_len |= (unsigned short) buffer[3] << 8; + status = buffer[4]; + status |= (unsigned short) buffer[5] << 8; + + if (pkt_len <= ENC_MAX_FRM_LEN) + copy_len = pkt_len; + else + copy_len = 0; + + if ((status & (1L << 7)) == 0) /* check Received Ok bit */ + copy_len = 0; + + /* taken from the Linux driver */ + /* check if next pointer is resonable */ + if ((((unsigned int)next_pointer_msb << 8) | + (unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START) + copy_len = 0; + + if (copy_len > 0) { + m_nic_read_data (copy_len, buffer); + } + + /* advance read pointer to next pointer */ + m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb); + m_nic_write (CTL_REG_ERDPTH, next_pointer_msb); + + /* decrease packet counter */ + m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC); + + /* taken from the Linux driver */ + /* Only odd values should be written to ERXRDPTL, + * see errata B4 pt.13 + */ + rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1; + if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 | + m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt > + (m_nic_read(CTL_REG_ERXNDH) << 8 | + m_nic_read(CTL_REG_ERXNDL)))) { + m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL)); + m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH)); + } else { + m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF); + m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8); + } + + /* move to bank 1 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0); + + /* read pktcnt */ + pkt_cnt = m_nic_read (CTL_REG_EPKTCNT); + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, + (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + if (copy_len == 0) { + eir_reg = m_nic_read (CTL_REG_EIR); + encReceiverReset (); + printf ("eth_rx: copy_len=0\n"); + continue; + } + + NetReceive ((unsigned char *) buffer, pkt_len); + + eir_reg = m_nic_read (CTL_REG_EIR); + } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */ +} + +static void encWriteReg (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x40 | regNo); /* write in regNo */ + spi_write (data); + + enc_disable (); + enc_enable (); + + spi_write (0x1f); /* write reg 0x1f */ + + enc_disable (); + spi_unlock (); +} + +static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c) +{ + unsigned char readback; + int i; + + spi_lock (); + + for (i = 0; i < c; i++) { + enc_cfg_spi (); + enc_enable (); + + spi_write (0x40 | regNo); /* write in regNo */ + spi_write (data); + + enc_disable (); + enc_enable (); + + spi_write (0x1f); /* write reg 0x1f */ + + enc_disable (); + + spi_unlock (); /* we must unlock spi first */ + + readback = encReadReg (regNo); + + spi_lock (); + + if (readback == data) + break; + } + spi_unlock (); + + if (i == c) { + printf ("enc28j60: write reg %d failed\n", regNo); + } +} + +static unsigned char encReadReg (unsigned char regNo) +{ + unsigned char rxByte; + + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x1f); /* read reg 0x1f */ + + bank = spi_read () & 0x3; + + enc_disable (); + enc_enable (); + + spi_write (regNo); + rxByte = spi_read (); + + /* check if MAC or MII register */ + if (((bank == 2) && (regNo <= 0x1a)) || + ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) { + /* ignore first byte and read another byte */ + rxByte = spi_read (); + } + + enc_disable (); + spi_unlock (); + + return rxByte; +} + +static void encReadBuff (unsigned short length, unsigned char *pBuff) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x20 | 0x1a); /* read buffer memory */ + + while (length--) { + if (pBuff != NULL) + *pBuff++ = spi_read (); + else + spi_write (0); + } + + enc_disable (); + spi_unlock (); +} + +static void encWriteBuff (unsigned short length, unsigned char *pBuff) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x60 | 0x1a); /* write buffer memory */ + + spi_write (0x00); /* control byte */ + + while (length--) + spi_write (*pBuff++); + + enc_disable (); + spi_unlock (); +} + +static void encBitSet (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0x80 | regNo); /* bit field set */ + spi_write (data); + + enc_disable (); + spi_unlock (); +} + +static void encBitClr (unsigned char regNo, unsigned char data) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0xA0 | regNo); /* bit field clear */ + spi_write (data); + + enc_disable (); + spi_unlock (); +} + +static void encReset (void) +{ + spi_lock (); + enc_cfg_spi (); + enc_enable (); + + spi_write (0xff); /* soft reset */ + + enc_disable (); + spi_unlock (); + + /* sleep 1 ms. See errata pt. 2 */ + udelay (1000); +} + +static void encInit (unsigned char *pEthAddr) +{ + unsigned short phid1 = 0; + unsigned short phid2 = 0; + + /* switch to bank 0 */ + m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0)); + + /* + * Setup the buffer space. The reset values are valid for the + * other pointers. + */ + /* We shall not write to ERXST, see errata pt. 5. Instead we + have to make sure that ENC_RX_BUS_START is 0. */ + m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1); + m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1); + + /* taken from the Linux driver */ + m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1); + m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1); + + m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1); + m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1); + + next_pointer_lsb = (ENC_RX_BUF_START & 0xFF); + next_pointer_msb = (ENC_RX_BUF_START >> 8); + + /* verify identification */ + phid1 = phyRead (PHY_REG_PHID1); + phid2 = phyRead (PHY_REG_PHID2); + + if (phid1 != ENC_PHID1_VALUE + || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) { + printf ("ERROR: failed to identify controller\n"); + printf ("phid1 = %x, phid2 = %x\n", + phid1, (phid2 & ENC_PHID2_MASK)); + printf ("should be phid1 = %x, phid2 = %x\n", + ENC_PHID1_VALUE, ENC_PHID2_VALUE); + } + + /* + * --- MAC Initialization --- + */ + + /* Pull MAC out of Reset */ + + /* switch to bank 2 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* enable MAC to receive frames */ + /* added some bits from the Linux driver */ + m_nic_write_retry (CTL_REG_MACON1 + ,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS) + ,10); + + /* configure pad, tx-crc and duplex */ + /* added a bit from the Linux driver */ + m_nic_write_retry (CTL_REG_MACON3 + ,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN) + ,10); + + /* added 4 new lines from the Linux driver */ + /* Allow infinite deferals if the medium is continously busy */ + m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10); + + /* Late collisions occur beyond 63 bytes */ + m_nic_write_retry(CTL_REG_MACLCON2, 63, 10); + + /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */ + m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10); + + /* + * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended + * 0x0c for half-duplex. Nothing for full-duplex + */ + m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10); + + /* set maximum frame length */ + m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10); + m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10); + + /* + * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex + * and 0x15 for full duplex. + */ + m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10); + + /* set MAC address */ + + /* switch to bank 3 */ + m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1)); + + m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1); + m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1); + m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1); + m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1); + m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1); + m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1); + + /* + * PHY Initialization taken from the Linux driver + */ + + /* Prevent automatic loopback of data beeing transmitted by setting + ENC_PHCON2_HDLDIS */ + phyWrite(PHY_REG_PHCON2, (1<<8)); + + /* LEDs configuration + * LEDA: LACFG = 0100 -> display link status + * LEDB: LBCFG = 0111 -> display TX & RX activity + * STRCH = 1 -> LED pulses + */ + phyWrite(PHY_REG_PHLCON, 0x0472); + + /* Reset PDPXMD-bit => half duplex */ + phyWrite(PHY_REG_PHCON1, 0); + + /* + * Receive settings + */ + +#ifdef CONFIG_USE_IRQ + /* enable interrupts */ + m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE); + m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE); +#endif +} + +/***************************************************************************** + * + * Description: + * Read PHY registers. + * + * NOTE! This function will change to Bank 2. + * + * Params: + * [in] addr address of the register to read + * + * Returns: + * The value in the register + */ +static unsigned short phyRead (unsigned char addr) +{ + unsigned short ret = 0; + + /* move to bank 2 */ + m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* write address to MIREGADR */ + m_nic_write (CTL_REG_MIREGADR, addr); + + /* set MICMD.MIIRD */ + m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD); + + /* taken from the Linux driver */ + /* move to bank 3 */ + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* poll MISTAT.BUSY bit until operation is complete */ + while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { + static int cnt = 0; + + if (cnt++ >= 1000) { + /* GJ - this seems extremely dangerous! */ + /* printf("#"); */ + cnt = 0; + } + } + + /* taken from the Linux driver */ + /* move to bank 2 */ + m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* clear MICMD.MIIRD */ + m_nic_write (CTL_REG_MICMD, 0); + + ret = (m_nic_read (CTL_REG_MIRDH) << 8); + ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF); + + return ret; +} + +/***************************************************************************** + * + * Taken from the Linux driver. + * Description: + * Write PHY registers. + * + * NOTE! This function will change to Bank 3. + * + * Params: + * [in] addr address of the register to write to + * [in] data to be written + * + * Returns: + * None + */ +static void phyWrite(unsigned char addr, unsigned short data) +{ + /* move to bank 2 */ + m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* write address to MIREGADR */ + m_nic_write(CTL_REG_MIREGADR, addr); + + m_nic_write(CTL_REG_MIWRL, data & 0xff); + m_nic_write(CTL_REG_MIWRH, data >> 8); + + /* move to bank 3 */ + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0); + m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1); + + /* poll MISTAT.BUSY bit until operation is complete */ + while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) { + static int cnt = 0; + + if(cnt++ >= 1000) { + cnt = 0; + } + } +} + +#endif /* CONFIG_ENC28J60 */ diff --git a/drivers/net/inca-ip_sw.c b/drivers/net/inca-ip_sw.c new file mode 100644 index 0000000000..e4aaed6afb --- /dev/null +++ b/drivers/net/inca-ip_sw.c @@ -0,0 +1,817 @@ +/* + * INCA-IP internal switch ethernet driver. + * + * (C) Copyright 2003-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_INCA_IP_SWITCH) + +#include +#include +#include +#include + + +#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 3 +#define TOUT_LOOP 1000000 + + +#define DELAY udelay(10000) + /* Sometimes the store word instruction hangs while writing to one + * of the Switch registers. Moving the instruction into a separate + * function somehow makes the problem go away. + */ +static void SWORD(volatile u32 * reg, u32 value) +{ + *reg = value; +} + +#define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value; +#define DMA_READ_REG(reg, value) value = (u32)*((volatile u32*)reg) +#define SW_WRITE_REG(reg, value) \ + SWORD(reg, value);\ + DELAY;\ + SWORD(reg, value); + +#define SW_READ_REG(reg, value) \ + value = (u32)*((volatile u32*)reg);\ + DELAY;\ + value = (u32)*((volatile u32*)reg); + +#define INCA_DMA_TX_POLLING_TIME 0x07 +#define INCA_DMA_RX_POLLING_TIME 0x07 + +#define INCA_DMA_TX_HOLD 0x80000000 +#define INCA_DMA_TX_EOP 0x40000000 +#define INCA_DMA_TX_SOP 0x20000000 +#define INCA_DMA_TX_ICPT 0x10000000 +#define INCA_DMA_TX_IEOP 0x08000000 + +#define INCA_DMA_RX_C 0x80000000 +#define INCA_DMA_RX_SOP 0x40000000 +#define INCA_DMA_RX_EOP 0x20000000 + +#define INCA_SWITCH_PHY_SPEED_10H 0x1 +#define INCA_SWITCH_PHY_SPEED_10F 0x5 +#define INCA_SWITCH_PHY_SPEED_100H 0x2 +#define INCA_SWITCH_PHY_SPEED_100F 0x6 + +/************************ Auto MDIX settings ************************/ +#define INCA_IP_AUTO_MDIX_LAN_PORTS_DIR INCA_IP_Ports_P1_DIR +#define INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL INCA_IP_Ports_P1_ALTSEL +#define INCA_IP_AUTO_MDIX_LAN_PORTS_OUT INCA_IP_Ports_P1_OUT +#define INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX 16 + +#define WAIT_SIGNAL_RETRIES 100 +#define WAIT_LINK_RETRIES 100 +#define LINK_RETRY_DELAY 2000 /* ms */ +/********************************************************************/ + +typedef struct +{ + union { + struct { + volatile u32 HOLD :1; + volatile u32 ICpt :1; + volatile u32 IEop :1; + volatile u32 offset :3; + volatile u32 reserved0 :4; + volatile u32 NFB :22; + }field; + + volatile u32 word; + }params; + + volatile u32 nextRxDescPtr; + + volatile u32 RxDataPtr; + + union { + struct { + volatile u32 C :1; + volatile u32 Sop :1; + volatile u32 Eop :1; + volatile u32 reserved3 :12; + volatile u32 NBT :17; + }field; + + volatile u32 word; + }status; + +} inca_rx_descriptor_t; + + +typedef struct +{ + union { + struct { + volatile u32 HOLD :1; + volatile u32 Eop :1; + volatile u32 Sop :1; + volatile u32 ICpt :1; + volatile u32 IEop :1; + volatile u32 reserved0 :5; + volatile u32 NBA :22; + }field; + + volatile u32 word; + }params; + + volatile u32 nextTxDescPtr; + + volatile u32 TxDataPtr; + + volatile u32 C :1; + volatile u32 reserved3 :31; + +} inca_tx_descriptor_t; + + +static inca_rx_descriptor_t rx_ring[NUM_RX_DESC] __attribute__ ((aligned(16))); +static inca_tx_descriptor_t tx_ring[NUM_TX_DESC] __attribute__ ((aligned(16))); + +static int tx_new, rx_new, tx_hold, rx_hold; +static int tx_old_hold = -1; +static int initialized = 0; + + +static int inca_switch_init(struct eth_device *dev, bd_t * bis); +static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length); +static int inca_switch_recv(struct eth_device *dev); +static void inca_switch_halt(struct eth_device *dev); +static void inca_init_switch_chip(void); +static void inca_dma_init(void); +static int inca_amdix(void); + + +int inca_switch_initialize(bd_t * bis) +{ + struct eth_device *dev; + +#if 0 + printf("Entered inca_switch_initialize()\n"); +#endif + + if (!(dev = (struct eth_device *) malloc (sizeof *dev))) { + printf("Failed to allocate memory\n"); + return 0; + } + memset(dev, 0, sizeof(*dev)); + + inca_dma_init(); + + inca_init_switch_chip(); + +#if defined(CONFIG_INCA_IP_SWITCH_AMDIX) + inca_amdix(); +#endif + + sprintf(dev->name, "INCA-IP Switch"); + dev->init = inca_switch_init; + dev->halt = inca_switch_halt; + dev->send = inca_switch_send; + dev->recv = inca_switch_recv; + + eth_register(dev); + +#if 0 + printf("Leaving inca_switch_initialize()\n"); +#endif + + return 1; +} + + +static int inca_switch_init(struct eth_device *dev, bd_t * bis) +{ + int i; + u32 v, regValue; + u16 wTmp; + +#if 0 + printf("Entering inca_switch_init()\n"); +#endif + + /* Set MAC address. + */ + wTmp = (u16)dev->enetaddr[0]; + regValue = (wTmp << 8) | dev->enetaddr[1]; + + SW_WRITE_REG(INCA_IP_Switch_PMAC_SA1, regValue); + + wTmp = (u16)dev->enetaddr[2]; + regValue = (wTmp << 8) | dev->enetaddr[3]; + regValue = regValue << 16; + wTmp = (u16)dev->enetaddr[4]; + regValue |= (wTmp<<8) | dev->enetaddr[5]; + + SW_WRITE_REG(INCA_IP_Switch_PMAC_SA2, regValue); + + /* Initialize the descriptor rings. + */ + for (i = 0; i < NUM_RX_DESC; i++) { + inca_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_ring[i]); + memset(rx_desc, 0, sizeof(rx_ring[i])); + + /* Set maximum size of receive buffer. + */ + rx_desc->params.field.NFB = PKTSIZE_ALIGN; + + /* Set the offset of the receive buffer. Zero means + * that the offset mechanism is not used. + */ + rx_desc->params.field.offset = 0; + + /* Check if it is the last descriptor. + */ + if (i == (NUM_RX_DESC - 1)) { + /* Let the last descriptor point to the first + * one. + */ + rx_desc->nextRxDescPtr = KSEG1ADDR((u32)rx_ring); + } else { + /* Set the address of the next descriptor. + */ + rx_desc->nextRxDescPtr = (u32)KSEG1ADDR(&rx_ring[i+1]); + } + + rx_desc->RxDataPtr = (u32)KSEG1ADDR(NetRxPackets[i]); + } + +#if 0 + printf("rx_ring = 0x%08X 0x%08X\n", (u32)rx_ring, (u32)&rx_ring[0]); + printf("tx_ring = 0x%08X 0x%08X\n", (u32)tx_ring, (u32)&tx_ring[0]); +#endif + + for (i = 0; i < NUM_TX_DESC; i++) { + inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[i]); + + memset(tx_desc, 0, sizeof(tx_ring[i])); + + tx_desc->params.word = 0; + tx_desc->params.field.HOLD = 1; + tx_desc->C = 1; + + /* Check if it is the last descriptor. + */ + if (i == (NUM_TX_DESC - 1)) { + /* Let the last descriptor point to the + * first one. + */ + tx_desc->nextTxDescPtr = KSEG1ADDR((u32)tx_ring); + } else { + /* Set the address of the next descriptor. + */ + tx_desc->nextTxDescPtr = (u32)KSEG1ADDR(&tx_ring[i+1]); + } + } + + /* Initialize RxDMA. + */ + DMA_READ_REG(INCA_IP_DMA_DMA_RXISR, v); +#if 0 + printf("RX status = 0x%08X\n", v); +#endif + + /* Writing to the FRDA of CHANNEL. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXFRDA0, (u32)rx_ring); + + /* Writing to the COMMAND REG. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_INIT); + + /* Initialize TxDMA. + */ + DMA_READ_REG(INCA_IP_DMA_DMA_TXISR, v); +#if 0 + printf("TX status = 0x%08X\n", v); +#endif + + /* Writing to the FRDA of CHANNEL. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXFRDA0, (u32)tx_ring); + + tx_new = rx_new = 0; + + tx_hold = NUM_TX_DESC - 1; + rx_hold = NUM_RX_DESC - 1; + +#if 0 + rx_ring[rx_hold].params.field.HOLD = 1; +#endif + /* enable spanning tree forwarding, enable the CPU port */ + /* ST_PT: + * CPS (CPU port status) 0x3 (forwarding) + * LPS (LAN port status) 0x3 (forwarding) + * PPS (PC port status) 0x3 (forwarding) + */ + SW_WRITE_REG(INCA_IP_Switch_ST_PT,0x3f); + +#if 0 + printf("Leaving inca_switch_init()\n"); +#endif + + return 0; +} + + +static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length) +{ + int i; + int res = -1; + u32 command; + u32 regValue; + inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[tx_new]); + +#if 0 + printf("Entered inca_switch_send()\n"); +#endif + + if (length <= 0) { + printf ("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + for(i = 0; tx_desc->C == 0; i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx error buffer not ready\n", dev->name); + goto Done; + } + } + + if (tx_old_hold >= 0) { + KSEG1ADDR(&tx_ring[tx_old_hold])->params.field.HOLD = 1; + } + tx_old_hold = tx_hold; + + tx_desc->params.word = + (INCA_DMA_TX_SOP | INCA_DMA_TX_EOP | INCA_DMA_TX_HOLD); + + tx_desc->C = 0; + tx_desc->TxDataPtr = (u32)packet; + tx_desc->params.field.NBA = length; + + KSEG1ADDR(&tx_ring[tx_hold])->params.field.HOLD = 0; + + tx_hold = tx_new; + tx_new = (tx_new + 1) % NUM_TX_DESC; + + + if (! initialized) { + command = INCA_IP_DMA_DMA_TXCCR0_INIT; + initialized = 1; + } else { + command = INCA_IP_DMA_DMA_TXCCR0_HR; + } + + DMA_READ_REG(INCA_IP_DMA_DMA_TXCCR0, regValue); + regValue |= command; +#if 0 + printf("regValue = 0x%x\n", regValue); +#endif + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, regValue); + +#if 1 + for(i = 0; KSEG1ADDR(&tx_ring[tx_hold])->C == 0; i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx buffer not ready\n", dev->name); + goto Done; + } + } +#endif + res = length; +Done: +#if 0 + printf("Leaving inca_switch_send()\n"); +#endif + return res; +} + + +static int inca_switch_recv(struct eth_device *dev) +{ + int length = 0; + inca_rx_descriptor_t * rx_desc; + +#if 0 + printf("Entered inca_switch_recv()\n"); +#endif + + for (;;) { + rx_desc = KSEG1ADDR(&rx_ring[rx_new]); + + if (rx_desc->status.field.C == 0) { + break; + } + +#if 0 + rx_ring[rx_new].params.field.HOLD = 1; +#endif + + if (! rx_desc->status.field.Eop) { + printf("Partly received packet!!!\n"); + break; + } + + length = rx_desc->status.field.NBT; + rx_desc->status.word &= + ~(INCA_DMA_RX_EOP | INCA_DMA_RX_SOP | INCA_DMA_RX_C); +#if 0 +{ + int i; + for (i=0;iparams.field.HOLD = 0; + + rx_hold = rx_new; + + rx_new = (rx_new + 1) % NUM_RX_DESC; + } + +#if 0 + printf("Leaving inca_switch_recv()\n"); +#endif + + return length; +} + + +static void inca_switch_halt(struct eth_device *dev) +{ +#if 0 + printf("Entered inca_switch_halt()\n"); +#endif + +#if 1 + initialized = 0; +#endif +#if 1 + /* Disable forwarding to the CPU port. + */ + SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf); + + /* Close RxDMA channel. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); + + /* Close TxDMA channel. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_TXCCR0_OFF); + + +#endif +#if 0 + printf("Leaving inca_switch_halt()\n"); +#endif +} + + +static void inca_init_switch_chip(void) +{ + u32 regValue; + + /* To workaround a problem with collision counter + * (see Errata sheet). + */ + SW_WRITE_REG(INCA_IP_Switch_PC_TX_CTL, 0x00000001); + SW_WRITE_REG(INCA_IP_Switch_LAN_TX_CTL, 0x00000001); + +#if 1 + /* init MDIO configuration: + * MDS (Poll speed): 0x01 (4ms) + * PHY_LAN_ADDR: 0x06 + * PHY_PC_ADDR: 0x05 + * UEP (Use External PHY): 0x00 (Internal PHY is used) + * PS (Port Select): 0x00 (PT/UMM for LAN) + * PT (PHY Test): 0x00 (no test mode) + * UMM (Use MDIO Mode): 0x00 (state machine is disabled) + */ + SW_WRITE_REG(INCA_IP_Switch_MDIO_CFG, 0x4c50); + + /* init PHY: + * SL (Auto Neg. Speed for LAN) + * SP (Auto Neg. Speed for PC) + * LL (Link Status for LAN) + * LP (Link Status for PC) + * DL (Duplex Status for LAN) + * DP (Duplex Status for PC) + * PL (Auto Neg. Pause Status for LAN) + * PP (Auto Neg. Pause Status for PC) + */ + SW_WRITE_REG (INCA_IP_Switch_EPHY, 0xff); + + /* MDIO_ACC: + * RA (Request/Ack) 0x01 (Request) + * RW (Read/Write) 0x01 (Write) + * PHY_ADDR 0x05 (PC) + * REG_ADDR 0x00 (PHY_BCR: basic control register) + * PHY_DATA 0x8000 + * Reset - software reset + * LB (loop back) - normal + * SS (speed select) - 10 Mbit/s + * ANE (auto neg. enable) - enable + * PD (power down) - normal + * ISO (isolate) - normal + * RAN (restart auto neg.) - normal + * DM (duplex mode) - half duplex + * CT (collision test) - enable + */ + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0a09000); + + /* MDIO_ACC: + * RA (Request/Ack) 0x01 (Request) + * RW (Read/Write) 0x01 (Write) + * PHY_ADDR 0x06 (LAN) + * REG_ADDR 0x00 (PHY_BCR: basic control register) + * PHY_DATA 0x8000 + * Reset - software reset + * LB (loop back) - normal + * SS (speed select) - 10 Mbit/s + * ANE (auto neg. enable) - enable + * PD (power down) - normal + * ISO (isolate) - normal + * RAN (restart auto neg.) - normal + * DM (duplex mode) - half duplex + * CT (collision test) - enable + */ + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, 0xc0c09000); + +#endif + + /* Make sure the CPU port is disabled for now. We + * don't want packets to get stacked for us until + * we enable DMA and are prepared to receive them. + */ + SW_WRITE_REG(INCA_IP_Switch_ST_PT,0xf); + + SW_READ_REG(INCA_IP_Switch_ARL_CTL, regValue); + + /* CRC GEN is enabled. + */ + regValue |= 0x00000200; + SW_WRITE_REG(INCA_IP_Switch_ARL_CTL, regValue); + + /* ADD TAG is disabled. + */ + SW_READ_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue); + regValue &= ~0x00000002; + SW_WRITE_REG(INCA_IP_Switch_PMAC_HD_CTL, regValue); +} + + +static void inca_dma_init(void) +{ + /* Switch off all DMA channels. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR1, INCA_IP_DMA_DMA_RXCCR1_OFF); + + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, INCA_IP_DMA_DMA_RXCCR0_OFF); + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR1, INCA_IP_DMA_DMA_TXCCR1_OFF); + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR2, INCA_IP_DMA_DMA_TXCCR2_OFF); + + /* Setup TX channel polling time. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXPOLL, INCA_DMA_TX_POLLING_TIME); + + /* Setup RX channel polling time. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXPOLL, INCA_DMA_RX_POLLING_TIME); + + /* ERRATA: write reset value into the DMA RX IMR register. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXIMR, 0xFFFFFFFF); + + /* Just in case: disable all transmit interrupts also. + */ + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXIMR, 0xFFFFFFFF); + + DMA_WRITE_REG(INCA_IP_DMA_DMA_TXISR, 0xFFFFFFFF); + DMA_WRITE_REG(INCA_IP_DMA_DMA_RXISR, 0xFFFFFFFF); +} + +#if defined(CONFIG_INCA_IP_SWITCH_AMDIX) +static int inca_amdix(void) +{ + u32 phyReg1 = 0; + u32 phyReg4 = 0; + u32 phyReg5 = 0; + u32 phyReg6 = 0; + u32 phyReg31 = 0; + u32 regEphy = 0; + int mdi_flag; + int retries; + + /* Setup GPIO pins. + */ + *INCA_IP_AUTO_MDIX_LAN_PORTS_DIR |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); + *INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); + +#if 0 + /* Wait for signal. + */ + retries = WAIT_SIGNAL_RETRIES; + while (--retries) { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (17 << 16)); /* PHY_MCSR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); + } while (phyReg1 & (1 << 31)); + + if (phyReg1 & (1 << 1)) { + /* Signal detected */ + break; + } + } + + if (!retries) + goto Fail; +#endif + + /* Set MDI mode. + */ + *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); + mdi_flag = 1; + + /* Wait for link. + */ + retries = WAIT_LINK_RETRIES; + while (--retries) { + udelay(LINK_RETRY_DELAY * 1000); + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (1 << 16)); /* PHY_BSR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); + } while (phyReg1 & (1 << 31)); + + if (phyReg1 & (1 << 2)) { + /* Link is up */ + break; + } else if (mdi_flag) { + /* Set MDIX mode */ + *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT |= (1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); + mdi_flag = 0; + } else { + /* Set MDI mode */ + *INCA_IP_AUTO_MDIX_LAN_PORTS_OUT &= ~(1 << INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX); + mdi_flag = 1; + } + } + + if (!retries) { + goto Fail; + } else { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (1 << 16)); /* PHY_BSR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg1); + } while (phyReg1 & (1 << 31)); + + /* Auto-negotiation / Parallel detection complete + */ + if (phyReg1 & (1 << 5)) { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (31 << 16)); /* PHY_SCSR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg31); + } while (phyReg31 & (1 << 31)); + + switch ((phyReg31 >> 2) & 0x7) { + case INCA_SWITCH_PHY_SPEED_10H: + /* 10Base-T Half-duplex */ + regEphy = 0; + break; + case INCA_SWITCH_PHY_SPEED_10F: + /* 10Base-T Full-duplex */ + regEphy = INCA_IP_Switch_EPHY_DL; + break; + case INCA_SWITCH_PHY_SPEED_100H: + /* 100Base-TX Half-duplex */ + regEphy = INCA_IP_Switch_EPHY_SL; + break; + case INCA_SWITCH_PHY_SPEED_100F: + /* 100Base-TX Full-duplex */ + regEphy = INCA_IP_Switch_EPHY_SL | INCA_IP_Switch_EPHY_DL; + break; + } + + /* In case of Auto-negotiation, + * update the negotiated PAUSE support status + */ + if (phyReg1 & (1 << 3)) { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (6 << 16)); /* PHY_ANER */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg6); + } while (phyReg6 & (1 << 31)); + + /* We are Autoneg-able. + * Is Link partner also able to autoneg? + */ + if (phyReg6 & (1 << 0)) { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (4 << 16)); /* PHY_ANAR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg4); + } while (phyReg4 & (1 << 31)); + + /* We advertise PAUSE capab. + * Does link partner also advertise it? + */ + if (phyReg4 & (1 << 10)) { + SW_WRITE_REG(INCA_IP_Switch_MDIO_ACC, + (0x1 << 31) | /* RA */ + (0x0 << 30) | /* Read */ + (0x6 << 21) | /* LAN */ + (5 << 16)); /* PHY_ANLPAR */ + do { + SW_READ_REG(INCA_IP_Switch_MDIO_ACC, phyReg5); + } while (phyReg5 & (1 << 31)); + + /* Link partner is PAUSE capab. + */ + if (phyReg5 & (1 << 10)) { + regEphy |= INCA_IP_Switch_EPHY_PL; + } + } + } + + } + + /* Link is up */ + regEphy |= INCA_IP_Switch_EPHY_LL; + + SW_WRITE_REG(INCA_IP_Switch_EPHY, regEphy); + } + } + + return 0; + +Fail: + printf("No Link on LAN port\n"); + return -1; +} +#endif /* CONFIG_INCA_IP_SWITCH_AMDIX */ + +#endif diff --git a/drivers/net/ks8695eth.c b/drivers/net/ks8695eth.c new file mode 100644 index 0000000000..b598dd7f23 --- /dev/null +++ b/drivers/net/ks8695eth.c @@ -0,0 +1,238 @@ +/* + * ks8695eth.c -- KS8695 ethernet driver + * + * (C) Copyright 2004-2005, Greg Ungerer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/****************************************************************************/ + +#include + +#ifdef CONFIG_DRIVER_KS8695ETH +#include +#include +#include +#include + +/****************************************************************************/ + +/* + * Hardware register access to the KS8695 LAN ethernet port + * (well, it is the 4 port switch really). + */ +#define ks8695_read(a) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) +#define ks8695_write(a,v) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) = (v) + +/****************************************************************************/ + +/* + * Define the descriptor in-memory data structures. + */ +struct ks8695_txdesc { + uint32_t owner; + uint32_t ctrl; + uint32_t addr; + uint32_t next; +}; + +struct ks8695_rxdesc { + uint32_t status; + uint32_t ctrl; + uint32_t addr; + uint32_t next; +}; + +/****************************************************************************/ + +/* + * Allocate local data structures to use for receiving and sending + * packets. Just to keep it all nice and simple. + */ + +#define TXDESCS 4 +#define RXDESCS 4 +#define BUFSIZE 2048 + +volatile struct ks8695_txdesc ks8695_tx[TXDESCS] __attribute__((aligned(256))); +volatile struct ks8695_rxdesc ks8695_rx[RXDESCS] __attribute__((aligned(256))); +volatile uint8_t ks8695_bufs[BUFSIZE*(TXDESCS+RXDESCS)] __attribute__((aligned(2048)));; + +/****************************************************************************/ + +/* + * Ideally we want to use the MAC address stored in flash. + * But we do some sanity checks in case they are not present + * first. + */ +unsigned char eth_mac[] = { + 0x00, 0x13, 0xc6, 0x00, 0x00, 0x00 +}; + +void ks8695_getmac(void) +{ + unsigned char *fp; + int i; + + /* Check if flash MAC is valid */ + fp = (unsigned char *) 0x0201c000; + for (i = 0; (i < 6); i++) { + if ((fp[i] != 0) && (fp[i] != 0xff)) + break; + } + + /* If we found a valid looking MAC address then use it */ + if (i < 6) + memcpy(ð_mac[0], fp, 6); +} + +/****************************************************************************/ + +void eth_reset(bd_t *bd) +{ + int i; + + debug ("%s(%d): eth_reset()\n", __FILE__, __LINE__); + + /* Reset the ethernet engines first */ + ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); + ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); + + ks8695_getmac(); + + /* Set MAC address */ + ks8695_write(KS8695_LAN_MAC_LOW, (eth_mac[5] | (eth_mac[4] << 8) | + (eth_mac[3] << 16) | (eth_mac[2] << 24))); + ks8695_write(KS8695_LAN_MAC_HIGH, (eth_mac[1] | (eth_mac[0] << 8))); + + /* Turn the 4 port switch on */ + i = ks8695_read(KS8695_SWITCH_CTRL0); + ks8695_write(KS8695_SWITCH_CTRL0, (i | 0x1)); + /* ks8695_write(KS8695_WAN_CONTROL, 0x3f000066); */ + + /* Initialize descriptor rings */ + for (i = 0; (i < TXDESCS); i++) { + ks8695_tx[i].owner = 0; + ks8695_tx[i].ctrl = 0; + ks8695_tx[i].addr = (uint32_t) &ks8695_bufs[i*BUFSIZE]; + ks8695_tx[i].next = (uint32_t) &ks8695_tx[i+1]; + } + ks8695_tx[TXDESCS-1].ctrl = 0x02000000; + ks8695_tx[TXDESCS-1].next = (uint32_t) &ks8695_tx[0]; + + for (i = 0; (i < RXDESCS); i++) { + ks8695_rx[i].status = 0x80000000; + ks8695_rx[i].ctrl = BUFSIZE - 4; + ks8695_rx[i].addr = (uint32_t) &ks8695_bufs[(i+TXDESCS)*BUFSIZE]; + ks8695_rx[i].next = (uint32_t) &ks8695_rx[i+1]; + } + ks8695_rx[RXDESCS-1].ctrl |= 0x00080000; + ks8695_rx[RXDESCS-1].next = (uint32_t) &ks8695_rx[0]; + + /* The KS8695 is pretty slow reseting the ethernets... */ + udelay(2000000); + + /* Enable the ethernet engine */ + ks8695_write(KS8695_LAN_TX_LIST, (uint32_t) &ks8695_tx[0]); + ks8695_write(KS8695_LAN_RX_LIST, (uint32_t) &ks8695_rx[0]); + ks8695_write(KS8695_LAN_DMA_TX, 0x3); + ks8695_write(KS8695_LAN_DMA_RX, 0x71); + ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); + + printf("KS8695 ETHERNET: "); + for (i = 0; (i < 5); i++) { + bd->bi_enetaddr[i] = eth_mac[i]; + printf("%02x:", eth_mac[i]); + } + bd->bi_enetaddr[i] = eth_mac[i]; + printf("%02x\n", eth_mac[i]); +} + +/****************************************************************************/ + +int eth_init(bd_t *bd) +{ + debug ("%s(%d): eth_init()\n", __FILE__, __LINE__); + + eth_reset(bd); + return 0; +} + +/****************************************************************************/ + +void eth_halt(void) +{ + debug ("%s(%d): eth_halt()\n", __FILE__, __LINE__); + + /* Reset the ethernet engines */ + ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); + ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); +} + +/****************************************************************************/ + +int eth_rx(void) +{ + volatile struct ks8695_rxdesc *dp; + int i, len = 0; + + debug ("%s(%d): eth_rx()\n", __FILE__, __LINE__); + + for (i = 0; (i < RXDESCS); i++) { + dp= &ks8695_rx[i]; + if ((dp->status & 0x80000000) == 0) { + len = (dp->status & 0x7ff) - 4; + NetReceive((void *) dp->addr, len); + dp->status = 0x80000000; + ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); + break; + } + } + + return len; +} + +/****************************************************************************/ + +int eth_send(volatile void *packet, int len) +{ + volatile struct ks8695_txdesc *dp; + static int next = 0; + + debug ("%s(%d): eth_send(packet=%x,len=%d)\n", __FILE__, __LINE__, + packet, len); + + dp = &ks8695_tx[next]; + memcpy((void *) dp->addr, (void *) packet, len); + + if (len < 64) { + memset((void *) (dp->addr + len), 0, 64-len); + len = 64; + } + + dp->ctrl = len | 0xe0000000; + dp->owner = 0x80000000; + + ks8695_write(KS8695_LAN_DMA_TX, 0x3); + ks8695_write(KS8695_LAN_DMA_TX_START, 0x1); + + if (++next >= TXDESCS) + next = 0; + + return len; +} + +#endif /* CONFIG_DRIVER_KS8695ETH */ diff --git a/drivers/net/lan91c96.c b/drivers/net/lan91c96.c new file mode 100644 index 0000000000..ecdcbd9b32 --- /dev/null +++ b/drivers/net/lan91c96.c @@ -0,0 +1,967 @@ +/*------------------------------------------------------------------------ + * lan91c96.c + * This is a driver for SMSC's LAN91C96 single-chip Ethernet device, based + * on the SMC91111 driver from U-boot. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Rolf Offermanns + * + * Copyright (C) 2001 Standard Microsystems Corporation (SMSC) + * Developed by Simple Network Magic Corporation (SNMC) + * Copyright (C) 1996 by Erik Stahlman (ES) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Information contained in this file was obtained from the LAN91C96 + * manual from SMC. To get a copy, if you really want one, you can find + * information under www.smsc.com. + * + * + * "Features" of the SMC chip: + * 6144 byte packet memory. ( for the 91C96 ) + * EEPROM for configuration + * AUI/TP selection ( mine has 10Base2/10BaseT select ) + * + * Arguments: + * io = for the base address + * irq = for the IRQ + * + * author: + * Erik Stahlman ( erik@vt.edu ) + * Daris A Nevil ( dnevil@snmc.com ) + * + * + * Hardware multicast code from Peter Cammaert ( pc@denkart.be ) + * + * Sources: + * o SMSC LAN91C96 databook (www.smsc.com) + * o smc91111.c (u-boot driver) + * o smc9194.c (linux kernel driver) + * o lan91c96.c (Intel Diagnostic Manager driver) + * + * History: + * 04/30/03 Mathijs Haarman Modified smc91111.c (u-boot version) + * for lan91c96 + *--------------------------------------------------------------------------- + */ + +#include +#include +#include "lan91c96.h" +#include + +#ifdef CONFIG_DRIVER_LAN91C96 + +#if defined(CONFIG_CMD_NET) + +/*------------------------------------------------------------------------ + * + * Configuration options, for the experienced user to change. + * + -------------------------------------------------------------------------*/ + +/* Use power-down feature of the chip */ +#define POWER_DOWN 0 + +/* + * Wait time for memory to be free. This probably shouldn't be + * tuned that much, as waiting for this means nothing else happens + * in the system +*/ +#define MEMORY_WAIT_TIME 16 + +#define SMC_DEBUG 0 + +#if (SMC_DEBUG > 2 ) +#define PRINTK3(args...) printf(args) +#else +#define PRINTK3(args...) +#endif + +#if SMC_DEBUG > 1 +#define PRINTK2(args...) printf(args) +#else +#define PRINTK2(args...) +#endif + +#ifdef SMC_DEBUG +#define PRINTK(args...) printf(args) +#else +#define PRINTK(args...) +#endif + + +/*------------------------------------------------------------------------ + * + * The internal workings of the driver. If you are changing anything + * here with the SMC stuff, you should have the datasheet and know + * what you are doing. + * + *------------------------------------------------------------------------ + */ +#define CARDNAME "LAN91C96" + +#define SMC_BASE_ADDRESS CONFIG_LAN91C96_BASE + +#define SMC_DEV_NAME "LAN91C96" +#define SMC_ALLOC_MAX_TRY 5 +#define SMC_TX_TIMEOUT 30 + +#define ETH_ZLEN 60 + +#ifdef CONFIG_LAN91C96_USE_32_BIT +#define USE_32_BIT 1 +#else +#undef USE_32_BIT +#endif + +/*----------------------------------------------------------------- + * + * The driver can be entered at any of the following entry points. + * + *----------------------------------------------------------------- + */ + +extern int eth_init (bd_t * bd); +extern void eth_halt (void); +extern int eth_rx (void); +extern int eth_send (volatile void *packet, int length); +#if 0 +static int smc_hw_init (void); +#endif + +/* + * This is called by register_netdev(). It is responsible for + * checking the portlist for the SMC9000 series chipset. If it finds + * one, then it will initialize the device, find the hardware information, + * and sets up the appropriate device parameters. + * NOTE: Interrupts are *OFF* when this procedure is called. + * + * NB:This shouldn't be static since it is referred to externally. + */ +int smc_init (void); + +/* + * This is called by unregister_netdev(). It is responsible for + * cleaning up before the driver is finally unregistered and discarded. + */ +void smc_destructor (void); + +/* + * The kernel calls this function when someone wants to use the device, + * typically 'ifconfig ethX up'. + */ +static int smc_open (bd_t *bd); + + +/* + * This is called by the kernel in response to 'ifconfig ethX down'. It + * is responsible for cleaning up everything that the open routine + * does, and maybe putting the card into a powerdown state. + */ +static int smc_close (void); + +/* + * This is a separate procedure to handle the receipt of a packet, to + * leave the interrupt code looking slightly cleaner + */ +static int smc_rcv (void); + +/* See if a MAC address is defined in the current environment. If so use it. If not + . print a warning and set the environment and other globals with the default. + . If an EEPROM is present it really should be consulted. +*/ +int smc_get_ethaddr(bd_t *bd); +int get_rom_mac(unsigned char *v_rom_mac); + +/* ------------------------------------------------------------ + * Internal routines + * ------------------------------------------------------------ + */ + +static unsigned char smc_mac_addr[] = { 0xc0, 0x00, 0x00, 0x1b, 0x62, 0x9c }; + +/* + * This function must be called before smc_open() if you want to override + * the default mac address. + */ + +void smc_set_mac_addr (const unsigned char *addr) +{ + int i; + + for (i = 0; i < sizeof (smc_mac_addr); i++) { + smc_mac_addr[i] = addr[i]; + } +} + +/* + * smc_get_macaddr is no longer used. If you want to override the default + * mac address, call smc_get_mac_addr as a part of the board initialisation. + */ + +#if 0 +void smc_get_macaddr (byte * addr) +{ + /* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */ + unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010); + int i; + + + for (i = 0; i < 6; i++) { + addr[0] = *(dnp1110_mac + 0); + addr[1] = *(dnp1110_mac + 1); + addr[2] = *(dnp1110_mac + 2); + addr[3] = *(dnp1110_mac + 3); + addr[4] = *(dnp1110_mac + 4); + addr[5] = *(dnp1110_mac + 5); + } +} +#endif /* 0 */ + +/*********************************************** + * Show available memory * + ***********************************************/ +void dump_memory_info (void) +{ + word mem_info; + word old_bank; + + old_bank = SMC_inw (LAN91C96_BANK_SELECT) & 0xF; + + SMC_SELECT_BANK (0); + mem_info = SMC_inw (LAN91C96_MIR); + PRINTK2 ("Memory: %4d available\n", (mem_info >> 8) * 2048); + + SMC_SELECT_BANK (old_bank); +} + +/* + * A rather simple routine to print out a packet for debugging purposes. + */ +#if SMC_DEBUG > 2 +static void print_packet (byte *, int); +#endif + +/* #define tx_done(dev) 1 */ + + +/* this does a soft reset on the device */ +static void smc_reset (void); + +/* Enable Interrupts, Receive, and Transmit */ +static void smc_enable (void); + +/* this puts the device in an inactive state */ +static void smc_shutdown (void); + + +static int poll4int (byte mask, int timeout) +{ + int tmo = get_timer (0) + timeout * CFG_HZ; + int is_timeout = 0; + word old_bank = SMC_inw (LAN91C96_BANK_SELECT); + + PRINTK2 ("Polling...\n"); + SMC_SELECT_BANK (2); + while ((SMC_inw (LAN91C96_INT_STATS) & mask) == 0) { + if (get_timer (0) >= tmo) { + is_timeout = 1; + break; + } + } + + /* restore old bank selection */ + SMC_SELECT_BANK (old_bank); + + if (is_timeout) + return 1; + else + return 0; +} + +/* + * Function: smc_reset( void ) + * Purpose: + * This sets the SMC91111 chip to its normal state, hopefully from whatever + * mess that any other DOS driver has put it in. + * + * Maybe I should reset more registers to defaults in here? SOFTRST should + * do that for me. + * + * Method: + * 1. send a SOFT RESET + * 2. wait for it to finish + * 3. enable autorelease mode + * 4. reset the memory management unit + * 5. clear all interrupts + * +*/ +static void smc_reset (void) +{ + PRINTK2 ("%s:smc_reset\n", SMC_DEV_NAME); + + /* This resets the registers mostly to defaults, but doesn't + affect EEPROM. That seems unnecessary */ + SMC_SELECT_BANK (0); + SMC_outw (LAN91C96_RCR_SOFT_RST, LAN91C96_RCR); + + udelay (10); + + /* Disable transmit and receive functionality */ + SMC_outw (0, LAN91C96_RCR); + SMC_outw (0, LAN91C96_TCR); + + /* set the control register */ + SMC_SELECT_BANK (1); + SMC_outw (SMC_inw (LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8, + LAN91C96_CONTROL); + + /* Disable all interrupts */ + SMC_outb (0, LAN91C96_INT_MASK); +} + +/* + * Function: smc_enable + * Purpose: let the chip talk to the outside work + * Method: + * 1. Initialize the Memory Configuration Register + * 2. Enable the transmitter + * 3. Enable the receiver +*/ +static void smc_enable () +{ + PRINTK2 ("%s:smc_enable\n", SMC_DEV_NAME); + SMC_SELECT_BANK (0); + + /* Initialize the Memory Configuration Register. See page + 49 of the LAN91C96 data sheet for details. */ + SMC_outw (LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR); + + /* Initialize the Transmit Control Register */ + SMC_outw (LAN91C96_TCR_TXENA, LAN91C96_TCR); + /* Initialize the Receive Control Register + * FIXME: + * The promiscuous bit set because I could not receive ARP reply + * packets from the server when I send a ARP request. It only works + * when I set the promiscuous bit + */ + SMC_outw (LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR); +} + +/* + * Function: smc_shutdown + * Purpose: closes down the SMC91xxx chip. + * Method: + * 1. zero the interrupt mask + * 2. clear the enable receive flag + * 3. clear the enable xmit flags + * + * TODO: + * (1) maybe utilize power down mode. + * Why not yet? Because while the chip will go into power down mode, + * the manual says that it will wake up in response to any I/O requests + * in the register space. Empirical results do not show this working. + */ +static void smc_shutdown () +{ + PRINTK2 (CARDNAME ":smc_shutdown\n"); + + /* no more interrupts for me */ + SMC_SELECT_BANK (2); + SMC_outb (0, LAN91C96_INT_MASK); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK (0); + SMC_outb (0, LAN91C96_RCR); + SMC_outb (0, LAN91C96_TCR); +} + + +/* + * Function: smc_hardware_send_packet(struct net_device * ) + * Purpose: + * This sends the actual packet to the SMC9xxx chip. + * + * Algorithm: + * First, see if a saved_skb is available. + * ( this should NOT be called if there is no 'saved_skb' + * Now, find the packet number that the chip allocated + * Point the data pointers at it in memory + * Set the length word in the chip's memory + * Dump the packet to chip memory + * Check if a last byte is needed ( odd length packet ) + * if so, set the control flag right + * Tell the card to send it + * Enable the transmit interrupt, so I know if it failed + * Free the kernel data if I actually sent it. + */ +static int smc_send_packet (volatile void *packet, int packet_length) +{ + byte packet_no; + unsigned long ioaddr; + byte *buf; + int length; + int numPages; + int try = 0; + int time_out; + byte status; + + + PRINTK3 ("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); + + length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; + + /* allocate memory + ** The MMU wants the number of pages to be the number of 256 bytes + ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + ** + ** The 91C111 ignores the size bits, but the code is left intact + ** for backwards and future compatibility. + ** + ** Pkt size for allocating is data length +6 (for additional status + ** words, length and ctl!) + ** + ** If odd size then last byte is included in this header. + */ + numPages = ((length & 0xfffe) + 6); + numPages >>= 8; /* Divide by 256 */ + + if (numPages > 7) { + printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); + return 0; + } + + /* now, try to allocate the memory */ + + SMC_SELECT_BANK (2); + SMC_outw (LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU); + + again: + try++; + time_out = MEMORY_WAIT_TIME; + do { + status = SMC_inb (LAN91C96_INT_STATS); + if (status & LAN91C96_IST_ALLOC_INT) { + + SMC_outb (LAN91C96_IST_ALLOC_INT, LAN91C96_INT_STATS); + break; + } + } while (--time_out); + + if (!time_out) { + PRINTK2 ("%s: memory allocation, try %d failed ...\n", + SMC_DEV_NAME, try); + if (try < SMC_ALLOC_MAX_TRY) + goto again; + else + return 0; + } + + PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", + SMC_DEV_NAME, try); + + /* I can send the packet now.. */ + + ioaddr = SMC_BASE_ADDRESS; + + buf = (byte *) packet; + + /* If I get here, I _know_ there is a packet slot waiting for me */ + packet_no = SMC_inb (LAN91C96_ARR); + if (packet_no & LAN91C96_ARR_FAILED) { + /* or isn't there? BAD CHIP! */ + printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); + return 0; + } + + /* we have a packet address, so tell the card to use it */ + SMC_outb (packet_no, LAN91C96_PNR); + + /* point to the beginning of the packet */ + SMC_outw (LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); + + PRINTK3 ("%s: Trying to xmit packet of length %x\n", + SMC_DEV_NAME, length); + +#if SMC_DEBUG > 2 + printf ("Transmitting Packet\n"); + print_packet (buf, length); +#endif + + /* send the packet length ( +6 for status, length and ctl byte ) + and the status word ( set to zeros ) */ +#ifdef USE_32_BIT + SMC_outl ((length + 6) << 16, LAN91C96_DATA_HIGH); +#else + SMC_outw (0, LAN91C96_DATA_HIGH); + /* send the packet length ( +6 for status words, length, and ctl */ + SMC_outw ((length + 6), LAN91C96_DATA_HIGH); +#endif /* USE_32_BIT */ + + /* send the actual data + * I _think_ it's faster to send the longs first, and then + * mop up by sending the last word. It depends heavily + * on alignment, at least on the 486. Maybe it would be + * a good idea to check which is optimal? But that could take + * almost as much time as is saved? + */ +#ifdef USE_32_BIT + SMC_outsl (LAN91C96_DATA_HIGH, buf, length >> 2); + if (length & 0x2) + SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), + LAN91C96_DATA_HIGH); +#else + SMC_outsw (LAN91C96_DATA_HIGH, buf, (length) >> 1); +#endif /* USE_32_BIT */ + + /* Send the last byte, if there is one. */ + if ((length & 1) == 0) { + SMC_outw (0, LAN91C96_DATA_HIGH); + } else { + SMC_outw (buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH); + } + + /* and let the chipset deal with it */ + SMC_outw (LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU); + + /* poll for TX INT */ + if (poll4int (LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) { + /* sending failed */ + PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); + + /* release packet */ + SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); + + /* wait for MMU getting ready (low) */ + while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { + udelay (10); + } + + PRINTK2 ("MMU ready\n"); + + + return 0; + } else { + /* ack. int */ + SMC_outw (LAN91C96_IST_TX_INT, LAN91C96_INT_STATS); + + PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, length); + + /* release packet */ + SMC_outw (LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU); + + /* wait for MMU getting ready (low) */ + while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) { + udelay (10); + } + + PRINTK2 ("MMU ready\n"); + } + + return length; +} + +/*------------------------------------------------------------------------- + * smc_destructor( struct net_device * dev ) + * Input parameters: + * dev, pointer to the device structure + * + * Output: + * None. + *-------------------------------------------------------------------------- + */ +void smc_destructor () +{ + PRINTK2 (CARDNAME ":smc_destructor\n"); +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc .. + * + */ +static int smc_open (bd_t *bd) +{ + int i, err; /* used to set hw ethernet address */ + + PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME); + + /* reset the hardware */ + + smc_reset (); + smc_enable (); + + SMC_SELECT_BANK (1); + + err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ + if (err < 0) { + memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ + return (-1); /* upper code ignores this, but NOT bi_enetaddr */ + } +#ifdef USE_32_BIT + for (i = 0; i < 6; i += 2) { + word address; + + address = smc_mac_addr[i + 1] << 8; + address |= smc_mac_addr[i]; + SMC_outw (address, LAN91C96_IA0 + i); + } +#else + for (i = 0; i < 6; i++) + SMC_outb (smc_mac_addr[i], LAN91C96_IA0 + i); +#endif + return 0; +} + +/*------------------------------------------------------------- + * + * smc_rcv - receive a packet from the card + * + * There is ( at least ) a packet waiting to be read from + * chip-memory. + * + * o Read the status + * o If an error, record it + * o otherwise, read in the packet + *------------------------------------------------------------- + */ +static int smc_rcv () +{ + int packet_number; + word status; + word packet_length; + int is_error = 0; + +#ifdef USE_32_BIT + dword stat_len; +#endif + + + SMC_SELECT_BANK (2); + packet_number = SMC_inw (LAN91C96_FIFO); + + if (packet_number & LAN91C96_FIFO_RXEMPTY) { + return 0; + } + + PRINTK3 ("%s:smc_rcv\n", SMC_DEV_NAME); + /* start reading from the start of the packet */ + SMC_outw (LAN91C96_PTR_READ | LAN91C96_PTR_RCV | + LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER); + + /* First two words are status and packet_length */ +#ifdef USE_32_BIT + stat_len = SMC_inl (LAN91C96_DATA_HIGH); + status = stat_len & 0xffff; + packet_length = stat_len >> 16; +#else + status = SMC_inw (LAN91C96_DATA_HIGH); + packet_length = SMC_inw (LAN91C96_DATA_HIGH); +#endif + + packet_length &= 0x07ff; /* mask off top bits */ + + PRINTK2 ("RCV: STATUS %4x LENGTH %4x\n", status, packet_length); + + if (!(status & FRAME_FILTER)) { + /* Adjust for having already read the first two words */ + packet_length -= 4; /*4; */ + + + /* set odd length for bug in LAN91C111, */ + /* which never sets RS_ODDFRAME */ + /* TODO ? */ + + +#ifdef USE_32_BIT + PRINTK3 (" Reading %d dwords (and %d bytes) \n", + packet_length >> 2, packet_length & 3); + /* QUESTION: Like in the TX routine, do I want + to send the DWORDs or the bytes first, or some + mixture. A mixture might improve already slow PIO + performance */ + SMC_insl (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 2); + /* read the left over bytes */ + if (packet_length & 3) { + int i; + + byte *tail = (byte *) (NetRxPackets[0] + (packet_length & ~3)); + dword leftover = SMC_inl (LAN91C96_DATA_HIGH); + + for (i = 0; i < (packet_length & 3); i++) + *tail++ = (byte) (leftover >> (8 * i)) & 0xff; + } +#else + PRINTK3 (" Reading %d words and %d byte(s) \n", + (packet_length >> 1), packet_length & 1); + SMC_insw (LAN91C96_DATA_HIGH, NetRxPackets[0], packet_length >> 1); + +#endif /* USE_32_BIT */ + +#if SMC_DEBUG > 2 + printf ("Receiving Packet\n"); + print_packet (NetRxPackets[0], packet_length); +#endif + } else { + /* error ... */ + /* TODO ? */ + is_error = 1; + } + + while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) + udelay (1); /* Wait until not busy */ + + /* error or good, tell the card to get rid of this packet */ + SMC_outw (LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU); + + while (SMC_inw (LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY) + udelay (1); /* Wait until not busy */ + + if (!is_error) { + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], packet_length); + return packet_length; + } else { + return 0; + } + +} + +/*---------------------------------------------------- + * smc_close + * + * this makes the board clean up everything that it can + * and not talk to the outside world. Caused by + * an 'ifconfig ethX down' + * + -----------------------------------------------------*/ +static int smc_close () +{ + PRINTK2 ("%s:smc_close\n", SMC_DEV_NAME); + + /* clear everything */ + smc_shutdown (); + + return 0; +} + +#if SMC_DEBUG > 2 +static void print_packet (byte * buf, int length) +{ +#if 0 + int i; + int remainder; + int lines; + + printf ("Packet of length %d \n", length); + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines; i++) { + int cur; + + for (cur = 0; cur < 8; cur++) { + byte a, b; + + a = *(buf++); + b = *(buf++); + printf ("%02x%02x ", a, b); + } + printf ("\n"); + } + for (i = 0; i < remainder / 2; i++) { + byte a, b; + + a = *(buf++); + b = *(buf++); + printf ("%02x%02x ", a, b); + } + printf ("\n"); +#endif /* 0 */ +} +#endif /* SMC_DEBUG > 2 */ + +int eth_init (bd_t * bd) +{ + return (smc_open(bd)); +} + +void eth_halt () +{ + smc_close (); +} + +int eth_rx () +{ + return smc_rcv (); +} + +int eth_send (volatile void *packet, int length) +{ + return smc_send_packet (packet, length); +} + + +#if 0 +/*------------------------------------------------------------------------- + * smc_hw_init() + * + * Function: + * Reset and enable the device, check if the I/O space location + * is correct + * + * Input parameters: + * None + * + * Output: + * 0 --> success + * 1 --> error + *-------------------------------------------------------------------------- + */ +static int smc_hw_init () +{ + unsigned short status_test; + + /* The attribute register of the LAN91C96 is located at address + 0x0e000000 on the lubbock platform */ + volatile unsigned *attaddr = (unsigned *) (0x0e000000); + + /* first reset, then enable the device. Sequence is critical */ + attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_SRESET; + udelay (100); + attaddr[LAN91C96_ECOR] &= ~LAN91C96_ECOR_SRESET; + attaddr[LAN91C96_ECOR] |= LAN91C96_ECOR_ENABLE; + + /* force 16-bit mode */ + attaddr[LAN91C96_ECSR] &= ~LAN91C96_ECSR_IOIS8; + udelay (100); + + /* check if the I/O address is correct, the upper byte of the + bank select register should read 0x33 */ + + status_test = SMC_inw (LAN91C96_BANK_SELECT); + if ((status_test & 0xFF00) != 0x3300) { + printf ("Failed to initialize ethernetchip\n"); + return 1; + } + return 0; +} +#endif /* 0 */ + +#endif /* COMMANDS & CFG_NET */ + + +/* smc_get_ethaddr (bd_t * bd) + * + * This checks both the environment and the ROM for an ethernet address. If + * found, the environment takes precedence. + */ + +int smc_get_ethaddr (bd_t * bd) +{ + int env_size = 0; + int rom_valid = 0; + int env_present = 0; + int reg = 0; + char *s = NULL; + char *e = NULL; + char *v_mac, es[] = "11:22:33:44:55:66"; + char s_env_mac[64]; + uchar v_env_mac[6]; + uchar v_rom_mac[6]; + + env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); + if (env_size != sizeof(es)) { /* Ignore if env is bad or not set */ + printf ("\n*** Warning: ethaddr is not set properly, ignoring!!\n"); + } else { + env_present = 1; + s = s_env_mac; + + for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ + v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + } + + rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ + + if (!env_present) { /* if NO env */ + if (rom_valid) { /* but ROM is valid */ + v_mac = (char *)v_rom_mac; + sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", + v_mac[0], v_mac[1], v_mac[2], v_mac[3], + v_mac[4], v_mac[5]); + setenv ("ethaddr", s_env_mac); + } else { /* no env, bad ROM */ + printf ("\n*** ERROR: ethaddr is NOT set !!\n"); + return (-1); + } + } else { /* good env, don't care ROM */ + v_mac = (char *)v_env_mac; /* always use a good env over a ROM */ + } + + if (env_present && rom_valid) { /* if both env and ROM are good */ + if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { + printf ("\nWarning: MAC addresses don't match:\n"); + printf ("\tHW MAC address: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_rom_mac[0], v_rom_mac[1], + v_rom_mac[2], v_rom_mac[3], + v_rom_mac[4], v_rom_mac[5] ); + printf ("\t\"ethaddr\" value: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_env_mac[0], v_env_mac[1], + v_env_mac[2], v_env_mac[3], + v_env_mac[4], v_env_mac[5]) ; + debug ("### Set MAC addr from environment\n"); + } + } + memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ + smc_set_mac_addr ((unsigned char *)v_mac); /* use old function to update smc default */ + PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], + v_mac[2], v_mac[3], v_mac[4], v_mac[5]); + return (0); +} + +/* + * get_rom_mac() + * Note, this has omly been tested for the OMAP730 P2. + */ + +int get_rom_mac (unsigned char *v_rom_mac) +{ +#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ + char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; + + memcpy (v_rom_mac, hw_mac_addr, 6); + return (1); +#else + int i; + SMC_SELECT_BANK (1); + for (i=0; i<6; i++) + { + v_rom_mac[i] = SMC_inb (LAN91C96_IA0 + i); + } + return (1); +#endif +} + +#endif /* CONFIG_DRIVER_LAN91C96 */ diff --git a/drivers/net/lan91c96.h b/drivers/net/lan91c96.h new file mode 100644 index 0000000000..7d33a821f3 --- /dev/null +++ b/drivers/net/lan91c96.h @@ -0,0 +1,643 @@ +/*------------------------------------------------------------------------ + * lan91c96.h + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Rolf Offermanns + * Copyright (C) 2001 Standard Microsystems Corporation (SMSC) + * Developed by Simple Network Magic Corporation (SNMC) + * Copyright (C) 1996 by Erik Stahlman (ES) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file contains register information and access macros for + * the LAN91C96 single chip ethernet controller. It is a modified + * version of the smc9111.h file. + * + * Information contained in this file was obtained from the LAN91C96 + * manual from SMC. To get a copy, if you really want one, you can find + * information under www.smsc.com. + * + * Authors + * Erik Stahlman ( erik@vt.edu ) + * Daris A Nevil ( dnevil@snmc.com ) + * + * History + * 04/30/03 Mathijs Haarman Modified smc91111.h (u-boot version) + * for lan91c96 + *------------------------------------------------------------------------- + */ +#ifndef _LAN91C96_H_ +#define _LAN91C96_H_ + +#include +#include +#include + +/* + * This function may be called by the board specific initialisation code + * in order to override the default mac address. + */ + +void smc_set_mac_addr(const unsigned char *addr); + + +/* I want some simple types */ + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long int dword; + +/* + * DEBUGGING LEVELS + * + * 0 for normal operation + * 1 for slightly more details + * >2 for various levels of increasingly useless information + * 2 for interrupt tracking, status flags + * 3 for packet info + * 4 for complete packet dumps + */ +/*#define SMC_DEBUG 0 */ + +/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ + +#define SMC_IO_EXTENT 16 + +#ifdef CONFIG_PXA250 + +#ifdef CONFIG_LUBBOCK +#define SMC_IO_SHIFT 2 +#undef USE_32_BIT + +#else +#define SMC_IO_SHIFT 0 +#endif + +#define SMCREG(r) (SMC_BASE_ADDRESS+((r)<>= 8; \ + else __v &= 0xff; \ + __v; }) + +#define SMC_outl(d,r) (*((volatile dword *)SMCREG(r)) = d) +#define SMC_outw(d,r) (*((volatile word *)SMCREG(r)) = d) +#define SMC_outb(d,r) ({ word __d = (byte)(d); \ + word __w = SMC_inw((r)&~1); \ + __w &= ((r)&1) ? 0x00FF : 0xFF00; \ + __w |= ((r)&1) ? __d<<8 : __d; \ + SMC_outw(__w,(r)&~1); \ + }) + +#define SMC_outsl(r,b,l) ({ int __i; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outl( *(__b2 + __i), r ); \ + } \ + }) + +#define SMC_outsw(r,b,l) ({ int __i; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outw( *(__b2 + __i), r ); \ + } \ + }) + +#define SMC_insl(r,b,l) ({ int __i ; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inl(r); \ + SMC_inl(0); \ + }; \ + }) + +#define SMC_insw(r,b,l) ({ int __i ; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inw(r); \ + SMC_inw(0); \ + }; \ + }) + +#define SMC_insb(r,b,l) ({ int __i ; \ + byte *__b2; \ + __b2 = (byte *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inb(r); \ + SMC_inb(0); \ + }; \ + }) + +#else /* if not CONFIG_PXA250 */ + +/* + * We have only 16 Bit PCMCIA access on Socket 0 + */ + +#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) +#define SMC_inb(r) (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF) + +#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) +#define SMC_outb(d,r) ({ word __d = (byte)(d); \ + word __w = SMC_inw((r)&~1); \ + __w &= ((r)&1) ? 0x00FF : 0xFF00; \ + __w |= ((r)&1) ? __d<<8 : __d; \ + SMC_outw(__w,(r)&~1); \ + }) +#if 0 +#define SMC_outsw(r,b,l) outsw(SMC_BASE_ADDRESS+(r), (b), (l)) +#else +#define SMC_outsw(r,b,l) ({ int __i; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outw( *(__b2 + __i), r); \ + } \ + }) +#endif + +#if 0 +#define SMC_insw(r,b,l) insw(SMC_BASE_ADDRESS+(r), (b), (l)) +#else +#define SMC_insw(r,b,l) ({ int __i ; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inw(r); \ + SMC_inw(0); \ + }; \ + }) +#endif + +#endif + +/* + **************************************************************************** + * Bank Select Field + **************************************************************************** + */ +#define LAN91C96_BANK_SELECT 14 /* Bank Select Register */ +#define LAN91C96_BANKSELECT (0x3UC << 0) +#define BANK0 0x00 +#define BANK1 0x01 +#define BANK2 0x02 +#define BANK3 0x03 +#define BANK4 0x04 + +/* + **************************************************************************** + * EEPROM Addresses. + **************************************************************************** + */ +#define EEPROM_MAC_OFFSET_1 0x6020 +#define EEPROM_MAC_OFFSET_2 0x6021 +#define EEPROM_MAC_OFFSET_3 0x6022 + +/* + **************************************************************************** + * Bank 0 Register Map in I/O Space + **************************************************************************** + */ +#define LAN91C96_TCR 0 /* Transmit Control Register */ +#define LAN91C96_EPH_STATUS 2 /* EPH Status Register */ +#define LAN91C96_RCR 4 /* Receive Control Register */ +#define LAN91C96_COUNTER 6 /* Counter Register */ +#define LAN91C96_MIR 8 /* Memory Information Register */ +#define LAN91C96_MCR 10 /* Memory Configuration Register */ + +/* + **************************************************************************** + * Transmit Control Register - Bank 0 - Offset 0 + **************************************************************************** + */ +#define LAN91C96_TCR_TXENA (0x1U << 0) +#define LAN91C96_TCR_LOOP (0x1U << 1) +#define LAN91C96_TCR_FORCOL (0x1U << 2) +#define LAN91C96_TCR_TXP_EN (0x1U << 3) +#define LAN91C96_TCR_PAD_EN (0x1U << 7) +#define LAN91C96_TCR_NOCRC (0x1U << 8) +#define LAN91C96_TCR_MON_CSN (0x1U << 10) +#define LAN91C96_TCR_FDUPLX (0x1U << 11) +#define LAN91C96_TCR_STP_SQET (0x1U << 12) +#define LAN91C96_TCR_EPH_LOOP (0x1U << 13) +#define LAN91C96_TCR_ETEN_TYPE (0x1U << 14) +#define LAN91C96_TCR_FDSE (0x1U << 15) + +/* + **************************************************************************** + * EPH Status Register - Bank 0 - Offset 2 + **************************************************************************** + */ +#define LAN91C96_EPHSR_TX_SUC (0x1U << 0) +#define LAN91C96_EPHSR_SNGL_COL (0x1U << 1) +#define LAN91C96_EPHSR_MUL_COL (0x1U << 2) +#define LAN91C96_EPHSR_LTX_MULT (0x1U << 3) +#define LAN91C96_EPHSR_16COL (0x1U << 4) +#define LAN91C96_EPHSR_SQET (0x1U << 5) +#define LAN91C96_EPHSR_LTX_BRD (0x1U << 6) +#define LAN91C96_EPHSR_TX_DEFR (0x1U << 7) +#define LAN91C96_EPHSR_WAKEUP (0x1U << 8) +#define LAN91C96_EPHSR_LATCOL (0x1U << 9) +#define LAN91C96_EPHSR_LOST_CARR (0x1U << 10) +#define LAN91C96_EPHSR_EXC_DEF (0x1U << 11) +#define LAN91C96_EPHSR_CTR_ROL (0x1U << 12) + +#define LAN91C96_EPHSR_LINK_OK (0x1U << 14) +#define LAN91C96_EPHSR_TX_UNRN (0x1U << 15) + +#define LAN91C96_EPHSR_ERRORS (LAN91C96_EPHSR_SNGL_COL | \ + LAN91C96_EPHSR_MUL_COL | \ + LAN91C96_EPHSR_16COL | \ + LAN91C96_EPHSR_SQET | \ + LAN91C96_EPHSR_TX_DEFR | \ + LAN91C96_EPHSR_LATCOL | \ + LAN91C96_EPHSR_LOST_CARR | \ + LAN91C96_EPHSR_EXC_DEF | \ + LAN91C96_EPHSR_LINK_OK | \ + LAN91C96_EPHSR_TX_UNRN) + +/* + **************************************************************************** + * Receive Control Register - Bank 0 - Offset 4 + **************************************************************************** + */ +#define LAN91C96_RCR_RX_ABORT (0x1U << 0) +#define LAN91C96_RCR_PRMS (0x1U << 1) +#define LAN91C96_RCR_ALMUL (0x1U << 2) +#define LAN91C96_RCR_RXEN (0x1U << 8) +#define LAN91C96_RCR_STRIP_CRC (0x1U << 9) +#define LAN91C96_RCR_FILT_CAR (0x1U << 14) +#define LAN91C96_RCR_SOFT_RST (0x1U << 15) + +/* + **************************************************************************** + * Counter Register - Bank 0 - Offset 6 + **************************************************************************** + */ +#define LAN91C96_ECR_SNGL_COL (0xFU << 0) +#define LAN91C96_ECR_MULT_COL (0xFU << 5) +#define LAN91C96_ECR_DEF_TX (0xFU << 8) +#define LAN91C96_ECR_EXC_DEF_TX (0xFU << 12) + +/* + **************************************************************************** + * Memory Information Register - Bank 0 - OFfset 8 + **************************************************************************** + */ +#define LAN91C96_MIR_SIZE (0x18 << 0) /* 6144 bytes */ + +/* + **************************************************************************** + * Memory Configuration Register - Bank 0 - Offset 10 + **************************************************************************** + */ +#define LAN91C96_MCR_MEM_RES (0xFFU << 0) +#define LAN91C96_MCR_MEM_MULT (0x3U << 9) +#define LAN91C96_MCR_HIGH_ID (0x3U << 12) + +#define LAN91C96_MCR_TRANSMIT_PAGES 0x6 + +/* + **************************************************************************** + * Bank 1 Register Map in I/O Space + **************************************************************************** + */ +#define LAN91C96_CONFIG 0 /* Configuration Register */ +#define LAN91C96_BASE 2 /* Base Address Register */ +#define LAN91C96_IA0 4 /* Individual Address Register - 0 */ +#define LAN91C96_IA1 5 /* Individual Address Register - 1 */ +#define LAN91C96_IA2 6 /* Individual Address Register - 2 */ +#define LAN91C96_IA3 7 /* Individual Address Register - 3 */ +#define LAN91C96_IA4 8 /* Individual Address Register - 4 */ +#define LAN91C96_IA5 9 /* Individual Address Register - 5 */ +#define LAN91C96_GEN_PURPOSE 10 /* General Address Registers */ +#define LAN91C96_CONTROL 12 /* Control Register */ + +/* + **************************************************************************** + * Configuration Register - Bank 1 - Offset 0 + **************************************************************************** + */ +#define LAN91C96_CR_INT_SEL0 (0x1U << 1) +#define LAN91C96_CR_INT_SEL1 (0x1U << 2) +#define LAN91C96_CR_RES (0x3U << 3) +#define LAN91C96_CR_DIS_LINK (0x1U << 6) +#define LAN91C96_CR_16BIT (0x1U << 7) +#define LAN91C96_CR_AUI_SELECT (0x1U << 8) +#define LAN91C96_CR_SET_SQLCH (0x1U << 9) +#define LAN91C96_CR_FULL_STEP (0x1U << 10) +#define LAN91C96_CR_NO_WAIT (0x1U << 12) + +/* + **************************************************************************** + * Base Address Register - Bank 1 - Offset 2 + **************************************************************************** + */ +#define LAN91C96_BAR_RA_BITS (0x27U << 0) +#define LAN91C96_BAR_ROM_SIZE (0x1U << 6) +#define LAN91C96_BAR_A_BITS (0xFFU << 8) + +/* + **************************************************************************** + * Control Register - Bank 1 - Offset 12 + **************************************************************************** + */ +#define LAN91C96_CTR_STORE (0x1U << 0) +#define LAN91C96_CTR_RELOAD (0x1U << 1) +#define LAN91C96_CTR_EEPROM (0x1U << 2) +#define LAN91C96_CTR_TE_ENABLE (0x1U << 5) +#define LAN91C96_CTR_CR_ENABLE (0x1U << 6) +#define LAN91C96_CTR_LE_ENABLE (0x1U << 7) +#define LAN91C96_CTR_BIT_8 (0x1U << 8) +#define LAN91C96_CTR_AUTO_RELEASE (0x1U << 11) +#define LAN91C96_CTR_WAKEUP_EN (0x1U << 12) +#define LAN91C96_CTR_PWRDN (0x1U << 13) +#define LAN91C96_CTR_RCV_BAD (0x1U << 14) + +/* + **************************************************************************** + * Bank 2 Register Map in I/O Space + **************************************************************************** + */ +#define LAN91C96_MMU 0 /* MMU Command Register */ +#define LAN91C96_AUTO_TX_START 1 /* Auto Tx Start Register */ +#define LAN91C96_PNR 2 /* Packet Number Register */ +#define LAN91C96_ARR 3 /* Allocation Result Register */ +#define LAN91C96_FIFO 4 /* FIFO Ports Register */ +#define LAN91C96_POINTER 6 /* Pointer Register */ +#define LAN91C96_DATA_HIGH 8 /* Data High Register */ +#define LAN91C96_DATA_LOW 10 /* Data Low Register */ +#define LAN91C96_INT_STATS 12 /* Interrupt Status Register - RO */ +#define LAN91C96_INT_ACK 12 /* Interrupt Acknowledge Register -WO */ +#define LAN91C96_INT_MASK 13 /* Interrupt Mask Register */ + +/* + **************************************************************************** + * MMU Command Register - Bank 2 - Offset 0 + **************************************************************************** + */ +#define LAN91C96_MMUCR_NO_BUSY (0x1U << 0) +#define LAN91C96_MMUCR_N1 (0x1U << 1) +#define LAN91C96_MMUCR_N2 (0x1U << 2) +#define LAN91C96_MMUCR_COMMAND (0xFU << 4) +#define LAN91C96_MMUCR_ALLOC_TX (0x2U << 4) /* WXYZ = 0010 */ +#define LAN91C96_MMUCR_RESET_MMU (0x4U << 4) /* WXYZ = 0100 */ +#define LAN91C96_MMUCR_REMOVE_RX (0x6U << 4) /* WXYZ = 0110 */ +#define LAN91C96_MMUCR_REMOVE_TX (0x7U << 4) /* WXYZ = 0111 */ +#define LAN91C96_MMUCR_RELEASE_RX (0x8U << 4) /* WXYZ = 1000 */ +#define LAN91C96_MMUCR_RELEASE_TX (0xAU << 4) /* WXYZ = 1010 */ +#define LAN91C96_MMUCR_ENQUEUE (0xCU << 4) /* WXYZ = 1100 */ +#define LAN91C96_MMUCR_RESET_TX (0xEU << 4) /* WXYZ = 1110 */ + +/* + **************************************************************************** + * Auto Tx Start Register - Bank 2 - Offset 1 + **************************************************************************** + */ +#define LAN91C96_AUTOTX (0xFFU << 0) + +/* + **************************************************************************** + * Packet Number Register - Bank 2 - Offset 2 + **************************************************************************** + */ +#define LAN91C96_PNR_TX (0x1FU << 0) + +/* + **************************************************************************** + * Allocation Result Register - Bank 2 - Offset 3 + **************************************************************************** + */ +#define LAN91C96_ARR_ALLOC_PN (0x7FU << 0) +#define LAN91C96_ARR_FAILED (0x1U << 7) + +/* + **************************************************************************** + * FIFO Ports Register - Bank 2 - Offset 4 + **************************************************************************** + */ +#define LAN91C96_FIFO_TX_DONE_PN (0x1FU << 0) +#define LAN91C96_FIFO_TEMPTY (0x1U << 7) +#define LAN91C96_FIFO_RX_DONE_PN (0x1FU << 8) +#define LAN91C96_FIFO_RXEMPTY (0x1U << 15) + +/* + **************************************************************************** + * Pointer Register - Bank 2 - Offset 6 + **************************************************************************** + */ +#define LAN91C96_PTR_LOW (0xFFU << 0) +#define LAN91C96_PTR_HIGH (0x7U << 8) +#define LAN91C96_PTR_AUTO_TX (0x1U << 11) +#define LAN91C96_PTR_ETEN (0x1U << 12) +#define LAN91C96_PTR_READ (0x1U << 13) +#define LAN91C96_PTR_AUTO_INCR (0x1U << 14) +#define LAN91C96_PTR_RCV (0x1U << 15) + +#define LAN91C96_PTR_RX_FRAME (LAN91C96_PTR_RCV | \ + LAN91C96_PTR_AUTO_INCR | \ + LAN91C96_PTR_READ) + +/* + **************************************************************************** + * Data Register - Bank 2 - Offset 8 + **************************************************************************** + */ +#define LAN91C96_CONTROL_CRC (0x1U << 4) /* CRC bit */ +#define LAN91C96_CONTROL_ODD (0x1U << 5) /* ODD bit */ + +/* + **************************************************************************** + * Interrupt Status Register - Bank 2 - Offset 12 + **************************************************************************** + */ +#define LAN91C96_IST_RCV_INT (0x1U << 0) +#define LAN91C96_IST_TX_INT (0x1U << 1) +#define LAN91C96_IST_TX_EMPTY_INT (0x1U << 2) +#define LAN91C96_IST_ALLOC_INT (0x1U << 3) +#define LAN91C96_IST_RX_OVRN_INT (0x1U << 4) +#define LAN91C96_IST_EPH_INT (0x1U << 5) +#define LAN91C96_IST_ERCV_INT (0x1U << 6) +#define LAN91C96_IST_RX_IDLE_INT (0x1U << 7) + +/* + **************************************************************************** + * Interrupt Acknowledge Register - Bank 2 - Offset 12 + **************************************************************************** + */ +#define LAN91C96_ACK_TX_INT (0x1U << 1) +#define LAN91C96_ACK_TX_EMPTY_INT (0x1U << 2) +#define LAN91C96_ACK_RX_OVRN_INT (0x1U << 4) +#define LAN91C96_ACK_ERCV_INT (0x1U << 6) + +/* + **************************************************************************** + * Interrupt Mask Register - Bank 2 - Offset 13 + **************************************************************************** + */ +#define LAN91C96_MSK_RCV_INT (0x1U << 0) +#define LAN91C96_MSK_TX_INT (0x1U << 1) +#define LAN91C96_MSK_TX_EMPTY_INT (0x1U << 2) +#define LAN91C96_MSK_ALLOC_INT (0x1U << 3) +#define LAN91C96_MSK_RX_OVRN_INT (0x1U << 4) +#define LAN91C96_MSK_EPH_INT (0x1U << 5) +#define LAN91C96_MSK_ERCV_INT (0x1U << 6) +#define LAN91C96_MSK_TX_IDLE_INT (0x1U << 7) + +/* + **************************************************************************** + * Bank 3 Register Map in I/O Space + ************************************************************************** + */ +#define LAN91C96_MGMT_MDO (0x1U << 0) +#define LAN91C96_MGMT_MDI (0x1U << 1) +#define LAN91C96_MGMT_MCLK (0x1U << 2) +#define LAN91C96_MGMT_MDOE (0x1U << 3) +#define LAN91C96_MGMT_LOW_ID (0x3U << 4) +#define LAN91C96_MGMT_IOS0 (0x1U << 8) +#define LAN91C96_MGMT_IOS1 (0x1U << 9) +#define LAN91C96_MGMT_IOS2 (0x1U << 10) +#define LAN91C96_MGMT_nXNDEC (0x1U << 11) +#define LAN91C96_MGMT_HIGH_ID (0x3U << 12) + +/* + **************************************************************************** + * Revision Register - Bank 3 - Offset 10 + **************************************************************************** + */ +#define LAN91C96_REV_REVID (0xFU << 0) +#define LAN91C96_REV_CHIPID (0xFU << 4) + +/* + **************************************************************************** + * Early RCV Register - Bank 3 - Offset 12 + **************************************************************************** + */ +#define LAN91C96_ERCV_THRESHOLD (0x1FU << 0) +#define LAN91C96_ERCV_RCV_DISCRD (0x1U << 7) + +/* + **************************************************************************** + * PCMCIA Configuration Registers + **************************************************************************** + */ +#define LAN91C96_ECOR 0x8000 /* Ethernet Configuration Register */ +#define LAN91C96_ECSR 0x8002 /* Ethernet Configuration and Status */ + +/* + **************************************************************************** + * PCMCIA Ethernet Configuration Option Register (ECOR) + **************************************************************************** + */ +#define LAN91C96_ECOR_ENABLE (0x1U << 0) +#define LAN91C96_ECOR_WR_ATTRIB (0x1U << 2) +#define LAN91C96_ECOR_LEVEL_REQ (0x1U << 6) +#define LAN91C96_ECOR_SRESET (0x1U << 7) + +/* + **************************************************************************** + * PCMCIA Ethernet Configuration and Status Register (ECSR) + **************************************************************************** + */ +#define LAN91C96_ECSR_INTR (0x1U << 1) +#define LAN91C96_ECSR_PWRDWN (0x1U << 2) +#define LAN91C96_ECSR_IOIS8 (0x1U << 5) + +/* + **************************************************************************** + * Receive Frame Status Word - See page 38 of the LAN91C96 specification. + **************************************************************************** + */ +#define LAN91C96_TOO_SHORT (0x1U << 10) +#define LAN91C96_TOO_LONG (0x1U << 11) +#define LAN91C96_ODD_FRM (0x1U << 12) +#define LAN91C96_BAD_CRC (0x1U << 13) +#define LAN91C96_BROD_CAST (0x1U << 14) +#define LAN91C96_ALGN_ERR (0x1U << 15) + +#define FRAME_FILTER (LAN91C96_TOO_SHORT | LAN91C96_TOO_LONG | LAN91C96_BAD_CRC | LAN91C96_ALGN_ERR) + +/* + **************************************************************************** + * Default MAC Address + **************************************************************************** + */ +#define MAC_DEF_HI 0x0800 +#define MAC_DEF_MED 0x3333 +#define MAC_DEF_LO 0x0100 + +/* + **************************************************************************** + * Default I/O Signature - 0x33 + **************************************************************************** + */ +#define LAN91C96_LOW_SIGNATURE (0x33U << 0) +#define LAN91C96_HIGH_SIGNATURE (0x33U << 8) +#define LAN91C96_SIGNATURE (LAN91C96_HIGH_SIGNATURE | LAN91C96_LOW_SIGNATURE) + +#define LAN91C96_MAX_PAGES 6 /* Maximum number of 256 pages. */ +#define ETHERNET_MAX_LENGTH 1514 + + +/*------------------------------------------------------------------------- + * I define some macros to make it easier to do somewhat common + * or slightly complicated, repeated tasks. + *------------------------------------------------------------------------- + */ + +/* select a register bank, 0 to 3 */ + +#define SMC_SELECT_BANK(x) { SMC_outw( x, LAN91C96_BANK_SELECT ); } + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) {\ + unsigned char mask;\ + SMC_SELECT_BANK(2);\ + mask = SMC_inb( LAN91C96_INT_MASK );\ + mask |= (x);\ + SMC_outb( mask, LAN91C96_INT_MASK ); \ +} + +/* this disables an interrupt from the interrupt mask register */ + +#define SMC_DISABLE_INT(x) {\ + unsigned char mask;\ + SMC_SELECT_BANK(2);\ + mask = SMC_inb( LAN91C96_INT_MASK );\ + mask &= ~(x);\ + SMC_outb( mask, LAN91C96_INT_MASK ); \ +} + +/*---------------------------------------------------------------------- + * Define the interrupts that I want to receive from the card + * + * I want: + * LAN91C96_IST_EPH_INT, for nasty errors + * LAN91C96_IST_RCV_INT, for happy received packets + * LAN91C96_IST_RX_OVRN_INT, because I have to kick the receiver + *------------------------------------------------------------------------- + */ +#define SMC_INTERRUPT_MASK (LAN91C96_IST_EPH_INT | LAN91C96_IST_RX_OVRN_INT | LAN91C96_IST_RCV_INT) + +#endif /* _LAN91C96_H_ */ diff --git a/drivers/net/macb.c b/drivers/net/macb.c new file mode 100644 index 0000000000..95cdc496cb --- /dev/null +++ b/drivers/net/macb.c @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#if defined(CONFIG_MACB) \ + && (defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_MII)) + +/* + * The u-boot networking stack is a little weird. It seems like the + * networking core allocates receive buffers up front without any + * regard to the hardware that's supposed to actually receive those + * packets. + * + * The MACB receives packets into 128-byte receive buffers, so the + * buffers allocated by the core isn't very practical to use. We'll + * allocate our own, but we need one such buffer in case a packet + * wraps around the DMA ring so that we have to copy it. + * + * Therefore, define CFG_RX_ETH_BUFFER to 1 in the board-specific + * configuration header. This way, the core allocates one RX buffer + * and one TX buffer, each of which can hold a ethernet packet of + * maximum size. + * + * For some reason, the networking core unconditionally specifies a + * 32-byte packet "alignment" (which really should be called + * "padding"). MACB shouldn't need that, but we'll refrain from any + * core modifications here... + */ + +#include +#include + +#include +#include +#include +#include + +#include "macb.h" + +#define barrier() asm volatile("" ::: "memory") + +#define CFG_MACB_RX_BUFFER_SIZE 4096 +#define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128) +#define CFG_MACB_TX_RING_SIZE 16 +#define CFG_MACB_TX_TIMEOUT 1000 +#define CFG_MACB_AUTONEG_TIMEOUT 5000000 + +struct macb_dma_desc { + u32 addr; + u32 ctrl; +}; + +#define RXADDR_USED 0x00000001 +#define RXADDR_WRAP 0x00000002 + +#define RXBUF_FRMLEN_MASK 0x00000fff +#define RXBUF_FRAME_START 0x00004000 +#define RXBUF_FRAME_END 0x00008000 +#define RXBUF_TYPEID_MATCH 0x00400000 +#define RXBUF_ADDR4_MATCH 0x00800000 +#define RXBUF_ADDR3_MATCH 0x01000000 +#define RXBUF_ADDR2_MATCH 0x02000000 +#define RXBUF_ADDR1_MATCH 0x04000000 +#define RXBUF_BROADCAST 0x80000000 + +#define TXBUF_FRMLEN_MASK 0x000007ff +#define TXBUF_FRAME_END 0x00008000 +#define TXBUF_NOCRC 0x00010000 +#define TXBUF_EXHAUSTED 0x08000000 +#define TXBUF_UNDERRUN 0x10000000 +#define TXBUF_MAXRETRY 0x20000000 +#define TXBUF_WRAP 0x40000000 +#define TXBUF_USED 0x80000000 + +struct macb_device { + void *regs; + + unsigned int rx_tail; + unsigned int tx_head; + unsigned int tx_tail; + + void *rx_buffer; + void *tx_buffer; + struct macb_dma_desc *rx_ring; + struct macb_dma_desc *tx_ring; + + unsigned long rx_buffer_dma; + unsigned long rx_ring_dma; + unsigned long tx_ring_dma; + + const struct device *dev; + struct eth_device netdev; + unsigned short phy_addr; +}; +#define to_macb(_nd) container_of(_nd, struct macb_device, netdev) + +static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 1) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2) + | MACB_BF(DATA, value)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); +} + +static u16 macb_mdio_read(struct macb_device *macb, u8 reg) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 2) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + frame = macb_readl(macb, MAN); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + return MACB_BFEXT(DATA, frame); +} + +#if defined(CONFIG_CMD_NET) + +static int macb_send(struct eth_device *netdev, volatile void *packet, + int length) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr, ctrl; + unsigned int tx_head = macb->tx_head; + int i; + + paddr = dma_map_single(packet, length, DMA_TO_DEVICE); + + ctrl = length & TXBUF_FRMLEN_MASK; + ctrl |= TXBUF_FRAME_END; + if (tx_head == (CFG_MACB_TX_RING_SIZE - 1)) { + ctrl |= TXBUF_WRAP; + macb->tx_head = 0; + } else + macb->tx_head++; + + macb->tx_ring[tx_head].ctrl = ctrl; + macb->tx_ring[tx_head].addr = paddr; + barrier(); + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); + + /* + * I guess this is necessary because the networking core may + * re-use the transmit buffer as soon as we return... + */ + for (i = 0; i <= CFG_MACB_TX_TIMEOUT; i++) { + barrier(); + ctrl = macb->tx_ring[tx_head].ctrl; + if (ctrl & TXBUF_USED) + break; + udelay(1); + } + + dma_unmap_single(packet, length, paddr); + + if (i <= CFG_MACB_TX_TIMEOUT) { + if (ctrl & TXBUF_UNDERRUN) + printf("%s: TX underrun\n", netdev->name); + if (ctrl & TXBUF_EXHAUSTED) + printf("%s: TX buffers exhausted in mid frame\n", + netdev->name); + } else { + printf("%s: TX timeout\n", netdev->name); + } + + /* No one cares anyway */ + return 0; +} + +static void reclaim_rx_buffers(struct macb_device *macb, + unsigned int new_tail) +{ + unsigned int i; + + i = macb->rx_tail; + while (i > new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + if (i > CFG_MACB_RX_RING_SIZE) + i = 0; + } + + while (i < new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + } + + barrier(); + macb->rx_tail = new_tail; +} + +static int macb_recv(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + unsigned int rx_tail = macb->rx_tail; + void *buffer; + int length; + int wrapped = 0; + u32 status; + + for (;;) { + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) + return -1; + + status = macb->rx_ring[rx_tail].ctrl; + if (status & RXBUF_FRAME_START) { + if (rx_tail != macb->rx_tail) + reclaim_rx_buffers(macb, rx_tail); + wrapped = 0; + } + + if (status & RXBUF_FRAME_END) { + buffer = macb->rx_buffer + 128 * macb->rx_tail; + length = status & RXBUF_FRMLEN_MASK; + if (wrapped) { + unsigned int headlen, taillen; + + headlen = 128 * (CFG_MACB_RX_RING_SIZE + - macb->rx_tail); + taillen = length - headlen; + memcpy((void *)NetRxPackets[0], + buffer, headlen); + memcpy((void *)NetRxPackets[0] + headlen, + macb->rx_buffer, taillen); + buffer = (void *)NetRxPackets[0]; + } + + NetReceive(buffer, length); + if (++rx_tail >= CFG_MACB_RX_RING_SIZE) + rx_tail = 0; + reclaim_rx_buffers(macb, rx_tail); + } else { + if (++rx_tail >= CFG_MACB_RX_RING_SIZE) { + wrapped = 1; + rx_tail = 0; + } + } + barrier(); + } + + return 0; +} + +static void macb_phy_reset(struct macb_device *macb) +{ + struct eth_device *netdev = &macb->netdev; + int i; + u16 status, adv; + + adv = ADVERTISE_CSMA | ADVERTISE_ALL; + macb_mdio_write(macb, MII_ADVERTISE, adv); + printf("%s: Starting autonegotiation...\n", netdev->name); + macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE + | BMCR_ANRESTART)); + + for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_ANEGCOMPLETE) + break; + udelay(100); + } + + if (status & BMSR_ANEGCOMPLETE) + printf("%s: Autonegotiation complete\n", netdev->name); + else + printf("%s: Autonegotiation timed out (status=0x%04x)\n", + netdev->name, status); +} + +static int macb_phy_init(struct macb_device *macb) +{ + struct eth_device *netdev = &macb->netdev; + u32 ncfgr; + u16 phy_id, status, adv, lpa; + int media, speed, duplex; + int i; + + /* Check if the PHY is up to snuff... */ + phy_id = macb_mdio_read(macb, MII_PHYSID1); + if (phy_id == 0xffff) { + printf("%s: No PHY present\n", netdev->name); + return 0; + } + + status = macb_mdio_read(macb, MII_BMSR); + if (!(status & BMSR_LSTATUS)) { + /* Try to re-negotiate if we don't have link already. */ + macb_phy_reset(macb); + + for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_LSTATUS) + break; + udelay(100); + } + } + + if (!(status & BMSR_LSTATUS)) { + printf("%s: link down (status: 0x%04x)\n", + netdev->name, status); + return 0; + } else { + adv = macb_mdio_read(macb, MII_ADVERTISE); + lpa = macb_mdio_read(macb, MII_LPA); + media = mii_nway_result(lpa & adv); + speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) + ? 1 : 0); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", + netdev->name, + speed ? "100" : "10", + duplex ? "full" : "half", + lpa); + + ncfgr = macb_readl(macb, NCFGR); + ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + if (speed) + ncfgr |= MACB_BIT(SPD); + if (duplex) + ncfgr |= MACB_BIT(FD); + macb_writel(macb, NCFGR, ncfgr); + return 1; + } +} + +static int macb_init(struct eth_device *netdev, bd_t *bd) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr; + u32 hwaddr_bottom; + u16 hwaddr_top; + int i; + + /* + * macb_halt should have been called at some point before now, + * so we'll assume the controller is idle. + */ + + /* initialize DMA descriptors */ + paddr = macb->rx_buffer_dma; + for (i = 0; i < CFG_MACB_RX_RING_SIZE; i++) { + if (i == (CFG_MACB_RX_RING_SIZE - 1)) + paddr |= RXADDR_WRAP; + macb->rx_ring[i].addr = paddr; + macb->rx_ring[i].ctrl = 0; + paddr += 128; + } + for (i = 0; i < CFG_MACB_TX_RING_SIZE; i++) { + macb->tx_ring[i].addr = 0; + if (i == (CFG_MACB_TX_RING_SIZE - 1)) + macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; + else + macb->tx_ring[i].ctrl = TXBUF_USED; + } + macb->rx_tail = macb->tx_head = macb->tx_tail = 0; + + macb_writel(macb, RBQP, macb->rx_ring_dma); + macb_writel(macb, TBQP, macb->tx_ring_dma); + + /* set hardware address */ + hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr)); + macb_writel(macb, SA1B, hwaddr_bottom); + hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))); + macb_writel(macb, SA1T, hwaddr_top); + + /* choose RMII or MII mode. This depends on the board */ +#ifdef CONFIG_RMII + macb_writel(macb, USRIO, 0); +#else + macb_writel(macb, USRIO, MACB_BIT(MII)); +#endif + + if (!macb_phy_init(macb)) + return 0; + + /* Enable TX and RX */ + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); + + return 1; +} + +static void macb_halt(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + u32 ncr, tsr; + + /* Halt the controller and wait for any ongoing transmission to end. */ + ncr = macb_readl(macb, NCR); + ncr |= MACB_BIT(THALT); + macb_writel(macb, NCR, ncr); + + do { + tsr = macb_readl(macb, TSR); + } while (tsr & MACB_BIT(TGO)); + + /* Disable TX and RX, and clear statistics */ + macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); +} + +int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) +{ + struct macb_device *macb; + struct eth_device *netdev; + unsigned long macb_hz; + u32 ncfgr; + + macb = malloc(sizeof(struct macb_device)); + if (!macb) { + printf("Error: Failed to allocate memory for MACB%d\n", id); + return -1; + } + memset(macb, 0, sizeof(struct macb_device)); + + netdev = &macb->netdev; + + macb->rx_buffer = dma_alloc_coherent(CFG_MACB_RX_BUFFER_SIZE, + &macb->rx_buffer_dma); + macb->rx_ring = dma_alloc_coherent(CFG_MACB_RX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->rx_ring_dma); + macb->tx_ring = dma_alloc_coherent(CFG_MACB_TX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->tx_ring_dma); + + macb->regs = regs; + macb->phy_addr = phy_addr; + + sprintf(netdev->name, "macb%d", id); + netdev->init = macb_init; + netdev->halt = macb_halt; + netdev->send = macb_send; + netdev->recv = macb_recv; + + /* + * Do some basic initialization so that we at least can talk + * to the PHY + */ + macb_hz = get_macb_pclk_rate(id); + if (macb_hz < 20000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV8); + else if (macb_hz < 40000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV16); + else if (macb_hz < 80000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV32); + else + ncfgr = MACB_BF(CLK, MACB_CLK_DIV64); + + macb_writel(macb, NCFGR, ncfgr); + + eth_register(netdev); + + return 0; +} + +#endif + +#if defined(CONFIG_CMD_MII) + +int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + int iflag; + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl |= MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 2) + | MACB_BF(PHYA, addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2)); + macb_writel(&macb, EMACB_MAN, frame); + + do { + netstat = macb_readl(&macb, EMACB_NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + frame = macb_readl(&macb, EMACB_MAN); + *value = MACB_BFEXT(DATA, frame); + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + return 0; +} + +int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + int iflag; + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl |= MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 1) + | MACB_BF(PHYA, addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2) + | MACB_BF(DATA, value)); + macb_writel(&macb, EMACB_MAN, frame); + + do { + netstat = macb_readl(&macb, EMACB_NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + return 0; +} + +#endif + +#endif /* CONFIG_MACB */ diff --git a/drivers/net/macb.h b/drivers/net/macb.h new file mode 100644 index 0000000000..c778e4ee49 --- /dev/null +++ b/drivers/net/macb.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __DRIVERS_MACB_H__ +#define __DRIVERS_MACB_H__ + +/* MACB register offsets */ +#define MACB_NCR 0x0000 +#define MACB_NCFGR 0x0004 +#define MACB_NSR 0x0008 +#define MACB_TSR 0x0014 +#define MACB_RBQP 0x0018 +#define MACB_TBQP 0x001c +#define MACB_RSR 0x0020 +#define MACB_ISR 0x0024 +#define MACB_IER 0x0028 +#define MACB_IDR 0x002c +#define MACB_IMR 0x0030 +#define MACB_MAN 0x0034 +#define MACB_PTR 0x0038 +#define MACB_PFR 0x003c +#define MACB_FTO 0x0040 +#define MACB_SCF 0x0044 +#define MACB_MCF 0x0048 +#define MACB_FRO 0x004c +#define MACB_FCSE 0x0050 +#define MACB_ALE 0x0054 +#define MACB_DTF 0x0058 +#define MACB_LCOL 0x005c +#define MACB_EXCOL 0x0060 +#define MACB_TUND 0x0064 +#define MACB_CSE 0x0068 +#define MACB_RRE 0x006c +#define MACB_ROVR 0x0070 +#define MACB_RSE 0x0074 +#define MACB_ELE 0x0078 +#define MACB_RJA 0x007c +#define MACB_USF 0x0080 +#define MACB_STE 0x0084 +#define MACB_RLE 0x0088 +#define MACB_TPF 0x008c +#define MACB_HRB 0x0090 +#define MACB_HRT 0x0094 +#define MACB_SA1B 0x0098 +#define MACB_SA1T 0x009c +#define MACB_SA2B 0x00a0 +#define MACB_SA2T 0x00a4 +#define MACB_SA3B 0x00a8 +#define MACB_SA3T 0x00ac +#define MACB_SA4B 0x00b0 +#define MACB_SA4T 0x00b4 +#define MACB_TID 0x00b8 +#define MACB_TPQ 0x00bc +#define MACB_USRIO 0x00c0 +#define MACB_WOL 0x00c4 + +/* Bitfields in NCR */ +#define MACB_LB_OFFSET 0 +#define MACB_LB_SIZE 1 +#define MACB_LLB_OFFSET 1 +#define MACB_LLB_SIZE 1 +#define MACB_RE_OFFSET 2 +#define MACB_RE_SIZE 1 +#define MACB_TE_OFFSET 3 +#define MACB_TE_SIZE 1 +#define MACB_MPE_OFFSET 4 +#define MACB_MPE_SIZE 1 +#define MACB_CLRSTAT_OFFSET 5 +#define MACB_CLRSTAT_SIZE 1 +#define MACB_INCSTAT_OFFSET 6 +#define MACB_INCSTAT_SIZE 1 +#define MACB_WESTAT_OFFSET 7 +#define MACB_WESTAT_SIZE 1 +#define MACB_BP_OFFSET 8 +#define MACB_BP_SIZE 1 +#define MACB_TSTART_OFFSET 9 +#define MACB_TSTART_SIZE 1 +#define MACB_THALT_OFFSET 10 +#define MACB_THALT_SIZE 1 +#define MACB_NCR_TPF_OFFSET 11 +#define MACB_NCR_TPF_SIZE 1 +#define MACB_TZQ_OFFSET 12 +#define MACB_TZQ_SIZE 1 + +/* Bitfields in NCFGR */ +#define MACB_SPD_OFFSET 0 +#define MACB_SPD_SIZE 1 +#define MACB_FD_OFFSET 1 +#define MACB_FD_SIZE 1 +#define MACB_BIT_RATE_OFFSET 2 +#define MACB_BIT_RATE_SIZE 1 +#define MACB_JFRAME_OFFSET 3 +#define MACB_JFRAME_SIZE 1 +#define MACB_CAF_OFFSET 4 +#define MACB_CAF_SIZE 1 +#define MACB_NBC_OFFSET 5 +#define MACB_NBC_SIZE 1 +#define MACB_NCFGR_MTI_OFFSET 6 +#define MACB_NCFGR_MTI_SIZE 1 +#define MACB_UNI_OFFSET 7 +#define MACB_UNI_SIZE 1 +#define MACB_BIG_OFFSET 8 +#define MACB_BIG_SIZE 1 +#define MACB_EAE_OFFSET 9 +#define MACB_EAE_SIZE 1 +#define MACB_CLK_OFFSET 10 +#define MACB_CLK_SIZE 2 +#define MACB_RTY_OFFSET 12 +#define MACB_RTY_SIZE 1 +#define MACB_PAE_OFFSET 13 +#define MACB_PAE_SIZE 1 +#define MACB_RBOF_OFFSET 14 +#define MACB_RBOF_SIZE 2 +#define MACB_RLCE_OFFSET 16 +#define MACB_RLCE_SIZE 1 +#define MACB_DRFCS_OFFSET 17 +#define MACB_DRFCS_SIZE 1 +#define MACB_EFRHD_OFFSET 18 +#define MACB_EFRHD_SIZE 1 +#define MACB_IRXFCS_OFFSET 19 +#define MACB_IRXFCS_SIZE 1 + +/* Bitfields in NSR */ +#define MACB_NSR_LINK_OFFSET 0 +#define MACB_NSR_LINK_SIZE 1 +#define MACB_MDIO_OFFSET 1 +#define MACB_MDIO_SIZE 1 +#define MACB_IDLE_OFFSET 2 +#define MACB_IDLE_SIZE 1 + +/* Bitfields in TSR */ +#define MACB_UBR_OFFSET 0 +#define MACB_UBR_SIZE 1 +#define MACB_COL_OFFSET 1 +#define MACB_COL_SIZE 1 +#define MACB_TSR_RLE_OFFSET 2 +#define MACB_TSR_RLE_SIZE 1 +#define MACB_TGO_OFFSET 3 +#define MACB_TGO_SIZE 1 +#define MACB_BEX_OFFSET 4 +#define MACB_BEX_SIZE 1 +#define MACB_COMP_OFFSET 5 +#define MACB_COMP_SIZE 1 +#define MACB_UND_OFFSET 6 +#define MACB_UND_SIZE 1 + +/* Bitfields in RSR */ +#define MACB_BNA_OFFSET 0 +#define MACB_BNA_SIZE 1 +#define MACB_REC_OFFSET 1 +#define MACB_REC_SIZE 1 +#define MACB_OVR_OFFSET 2 +#define MACB_OVR_SIZE 1 + +/* Bitfields in ISR/IER/IDR/IMR */ +#define MACB_MFD_OFFSET 0 +#define MACB_MFD_SIZE 1 +#define MACB_RCOMP_OFFSET 1 +#define MACB_RCOMP_SIZE 1 +#define MACB_RXUBR_OFFSET 2 +#define MACB_RXUBR_SIZE 1 +#define MACB_TXUBR_OFFSET 3 +#define MACB_TXUBR_SIZE 1 +#define MACB_ISR_TUND_OFFSET 4 +#define MACB_ISR_TUND_SIZE 1 +#define MACB_ISR_RLE_OFFSET 5 +#define MACB_ISR_RLE_SIZE 1 +#define MACB_TXERR_OFFSET 6 +#define MACB_TXERR_SIZE 1 +#define MACB_TCOMP_OFFSET 7 +#define MACB_TCOMP_SIZE 1 +#define MACB_ISR_LINK_OFFSET 9 +#define MACB_ISR_LINK_SIZE 1 +#define MACB_ISR_ROVR_OFFSET 10 +#define MACB_ISR_ROVR_SIZE 1 +#define MACB_HRESP_OFFSET 11 +#define MACB_HRESP_SIZE 1 +#define MACB_PFR_OFFSET 12 +#define MACB_PFR_SIZE 1 +#define MACB_PTZ_OFFSET 13 +#define MACB_PTZ_SIZE 1 + +/* Bitfields in MAN */ +#define MACB_DATA_OFFSET 0 +#define MACB_DATA_SIZE 16 +#define MACB_CODE_OFFSET 16 +#define MACB_CODE_SIZE 2 +#define MACB_REGA_OFFSET 18 +#define MACB_REGA_SIZE 5 +#define MACB_PHYA_OFFSET 23 +#define MACB_PHYA_SIZE 5 +#define MACB_RW_OFFSET 28 +#define MACB_RW_SIZE 2 +#define MACB_SOF_OFFSET 30 +#define MACB_SOF_SIZE 2 + +/* Bitfields in USRIO */ +#define MACB_MII_OFFSET 0 +#define MACB_MII_SIZE 1 +#define MACB_EAM_OFFSET 1 +#define MACB_EAM_SIZE 1 +#define MACB_TX_PAUSE_OFFSET 2 +#define MACB_TX_PAUSE_SIZE 1 +#define MACB_TX_PAUSE_ZERO_OFFSET 3 +#define MACB_TX_PAUSE_ZERO_SIZE 1 + +/* Bitfields in WOL */ +#define MACB_IP_OFFSET 0 +#define MACB_IP_SIZE 16 +#define MACB_MAG_OFFSET 16 +#define MACB_MAG_SIZE 1 +#define MACB_ARP_OFFSET 17 +#define MACB_ARP_SIZE 1 +#define MACB_SA1_OFFSET 18 +#define MACB_SA1_SIZE 1 +#define MACB_WOL_MTI_OFFSET 19 +#define MACB_WOL_MTI_SIZE 1 + +/* Constants for CLK */ +#define MACB_CLK_DIV8 0 +#define MACB_CLK_DIV16 1 +#define MACB_CLK_DIV32 2 +#define MACB_CLK_DIV64 3 + +/* Constants for MAN register */ +#define MACB_MAN_SOF 1 +#define MACB_MAN_WRITE 1 +#define MACB_MAN_READ 2 +#define MACB_MAN_CODE 2 + +/* Bit manipulation macros */ +#define MACB_BIT(name) \ + (1 << MACB_##name##_OFFSET) +#define MACB_BF(name,value) \ + (((value) & ((1 << MACB_##name##_SIZE) - 1)) \ + << MACB_##name##_OFFSET) +#define MACB_BFEXT(name,value)\ + (((value) >> MACB_##name##_OFFSET) \ + & ((1 << MACB_##name##_SIZE) - 1)) +#define MACB_BFINS(name,value,old) \ + (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \ + << MACB_##name##_OFFSET)) \ + | MACB_BF(name,value)) + +/* Register access macros */ +#define macb_readl(port,reg) \ + readl((port)->regs + MACB_##reg) +#define macb_writel(port,reg,value) \ + writel((value), (port)->regs + MACB_##reg) + +#endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c new file mode 100644 index 0000000000..075d6c52c4 --- /dev/null +++ b/drivers/net/natsemi.c @@ -0,0 +1,882 @@ +/* + natsemi.c: A U-Boot driver for the NatSemi DP8381x series. + Author: Mark A. Rakes (mark_rakes@vivato.net) + + Adapted from an Etherboot driver written by: + + Copyright (C) 2001 Entity Cyber, Inc. + + This development of this Etherboot driver was funded by + + Sicom Systems: http://www.sicompos.com/ + + Author: Marty Connor (mdc@thinguin.org) + Adapted from a Linux driver which was written by Donald Becker + + This software may be used and distributed according to the terms + of the GNU Public License (GPL), incorporated herein by reference. + + Original Copyright Notice: + + Written/copyright 1999-2001 by Donald Becker. + + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. License for under other terms may be + available. Contact the original author for details. + + The original author may be reached as becker@scyld.com, or at + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 + + Support information and updates available at + http://www.scyld.com/network/netsemi.html + + References: + http://www.scyld.com/expert/100mbps.html + http://www.scyld.com/expert/NWay.html + Datasheet is available from: + http://www.national.com/pf/DP/DP83815.html +*/ + +/* Revision History + * October 2002 mar 1.0 + * Initial U-Boot Release. Tested with Netgear FA311 board + * and dp83815 chipset on custom board +*/ + +/* Includes */ +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_NATSEMI) + +/* defines */ +#define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/ + +#define DSIZE 0x00000FFF +#define ETH_ALEN 6 +#define CRC_SIZE 4 +#define TOUT_LOOP 500000 +#define TX_BUF_SIZE 1536 +#define RX_BUF_SIZE 1536 +#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ + +/* Offsets to the device registers. + Unlike software-only systems, device drivers interact with complex hardware. + It's not useful to define symbolic names for every register bit in the + device. */ +enum register_offsets { + ChipCmd = 0x00, + ChipConfig = 0x04, + EECtrl = 0x08, + IntrMask = 0x14, + IntrEnable = 0x18, + TxRingPtr = 0x20, + TxConfig = 0x24, + RxRingPtr = 0x30, + RxConfig = 0x34, + ClkRun = 0x3C, + RxFilterAddr = 0x48, + RxFilterData = 0x4C, + SiliconRev = 0x58, + PCIPM = 0x44, + BasicControl = 0x80, + BasicStatus = 0x84, + /* These are from the spec, around page 78... on a separate table. */ + PGSEL = 0xCC, + PMDCSR = 0xE4, + TSTDAT = 0xFC, + DSPCFG = 0xF4, + SDCFG = 0x8C +}; + +/* Bit in ChipCmd. */ +enum ChipCmdBits { + ChipReset = 0x100, + RxReset = 0x20, + TxReset = 0x10, + RxOff = 0x08, + RxOn = 0x04, + TxOff = 0x02, + TxOn = 0x01 +}; + +enum ChipConfigBits { + LinkSts = 0x80000000, + HundSpeed = 0x40000000, + FullDuplex = 0x20000000, + TenPolarity = 0x10000000, + AnegDone = 0x08000000, + AnegEnBothBoth = 0x0000E000, + AnegDis100Full = 0x0000C000, + AnegEn100Both = 0x0000A000, + AnegDis100Half = 0x00008000, + AnegEnBothHalf = 0x00006000, + AnegDis10Full = 0x00004000, + AnegEn10Both = 0x00002000, + DuplexMask = 0x00008000, + SpeedMask = 0x00004000, + AnegMask = 0x00002000, + AnegDis10Half = 0x00000000, + ExtPhy = 0x00001000, + PhyRst = 0x00000400, + PhyDis = 0x00000200, + BootRomDisable = 0x00000004, + BEMode = 0x00000001, +}; + +enum TxConfig_bits { + TxDrthMask = 0x3f, + TxFlthMask = 0x3f00, + TxMxdmaMask = 0x700000, + TxMxdma_512 = 0x0, + TxMxdma_4 = 0x100000, + TxMxdma_8 = 0x200000, + TxMxdma_16 = 0x300000, + TxMxdma_32 = 0x400000, + TxMxdma_64 = 0x500000, + TxMxdma_128 = 0x600000, + TxMxdma_256 = 0x700000, + TxCollRetry = 0x800000, + TxAutoPad = 0x10000000, + TxMacLoop = 0x20000000, + TxHeartIgn = 0x40000000, + TxCarrierIgn = 0x80000000 +}; + +enum RxConfig_bits { + RxDrthMask = 0x3e, + RxMxdmaMask = 0x700000, + RxMxdma_512 = 0x0, + RxMxdma_4 = 0x100000, + RxMxdma_8 = 0x200000, + RxMxdma_16 = 0x300000, + RxMxdma_32 = 0x400000, + RxMxdma_64 = 0x500000, + RxMxdma_128 = 0x600000, + RxMxdma_256 = 0x700000, + RxAcceptLong = 0x8000000, + RxAcceptTx = 0x10000000, + RxAcceptRunt = 0x40000000, + RxAcceptErr = 0x80000000 +}; + +/* Bits in the RxMode register. */ +enum rx_mode_bits { + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0xC0000000, + AcceptMulticast = 0x00200000, + AcceptAllMulticast = 0x20000000, + AcceptAllPhys = 0x10000000, + AcceptMyPhys = 0x08000000 +}; + +typedef struct _BufferDesc { + u32 link; + vu_long cmdsts; + u32 bufptr; + u32 software_use; +} BufferDesc; + +/* Bits in network_desc.status */ +enum desc_status_bits { + DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, + DescNoCRC = 0x10000000, DescPktOK = 0x08000000, + DescSizeMask = 0xfff, + + DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000, + DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000, + DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000, + DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000, + + DescRxAbort = 0x04000000, DescRxOver = 0x02000000, + DescRxDest = 0x01800000, DescRxLong = 0x00400000, + DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000, + DescRxCRC = 0x00080000, DescRxAlign = 0x00040000, + DescRxLoop = 0x00020000, DesRxColl = 0x00010000, +}; + +/* Globals */ +#ifdef NATSEMI_DEBUG +static int natsemi_debug = 0; /* 1 verbose debugging, 0 normal */ +#endif +static u32 SavedClkRun; +static unsigned int cur_rx; +static unsigned int advertising; +static unsigned int rx_config; +static unsigned int tx_config; + +/* Note: transmit and receive buffers and descriptors must be + longword aligned */ +static BufferDesc txd __attribute__ ((aligned(4))); +static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4))); + +static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4))); +static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] + __attribute__ ((aligned(4))); + +/* Function Prototypes */ +#if 0 +static void write_eeprom(struct eth_device *dev, long addr, int location, + short value); +#endif +static int read_eeprom(struct eth_device *dev, long addr, int location); +static int mdio_read(struct eth_device *dev, int phy_id, int location); +static int natsemi_init(struct eth_device *dev, bd_t * bis); +static void natsemi_reset(struct eth_device *dev); +static void natsemi_init_rxfilter(struct eth_device *dev); +static void natsemi_init_txd(struct eth_device *dev); +static void natsemi_init_rxd(struct eth_device *dev); +static void natsemi_set_rx_mode(struct eth_device *dev); +static void natsemi_check_duplex(struct eth_device *dev); +static int natsemi_send(struct eth_device *dev, volatile void *packet, + int length); +static int natsemi_poll(struct eth_device *dev); +static void natsemi_disable(struct eth_device *dev); + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815}, + {} +}; + +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) + +static inline int +INW(struct eth_device *dev, u_long addr) +{ + return le16_to_cpu(*(vu_short *) (addr + dev->iobase)); +} + +static int +INL(struct eth_device *dev, u_long addr) +{ + return le32_to_cpu(*(vu_long *) (addr + dev->iobase)); +} + +static inline void +OUTW(struct eth_device *dev, int command, u_long addr) +{ + *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command); +} + +static inline void +OUTL(struct eth_device *dev, int command, u_long addr) +{ + *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command); +} + +/* + * Function: natsemi_initialize + * + * Description: Retrieves the MAC address of the card, and sets up some + * globals required by other routines, and initializes the NIC, making it + * ready to send and receive packets. + * + * Side effects: + * leaves the natsemi initialized, and ready to recieve packets. + * + * Returns: struct eth_device *: pointer to NIC data structure + */ + +int +natsemi_initialize(bd_t * bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase, status, chip_config; + int i, idx = 0; + int prev_eedata; + u32 tmp; + + while (1) { + /* Find PCI device(s) */ + if ((devno = pci_find_devices(supported, idx++)) < 0) { + break; + } + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0x3; /* bit 1: unused and bit 0: I/O Space Indicator */ + + pci_write_config_dword(devno, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Check if I/O accesses and Bus Mastering are enabled. */ + pci_read_config_dword(devno, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEM access.\n"); + continue; + } else if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } + + dev = (struct eth_device *) malloc(sizeof *dev); + + sprintf(dev->name, "dp83815#%d", card_number); + dev->iobase = bus_to_phys(iobase); +#ifdef NATSEMI_DEBUG + printf("natsemi: NatSemi ns8381[56] @ %#x\n", dev->iobase); +#endif + dev->priv = (void *) devno; + dev->init = natsemi_init; + dev->halt = natsemi_disable; + dev->send = natsemi_send; + dev->recv = natsemi_poll; + + eth_register(dev); + + card_number++; + + /* Set the latency timer for value. */ + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); + + udelay(10 * 1000); + + /* natsemi has a non-standard PM control register + * in PCI config space. Some boards apparently need + * to be brought to D0 in this manner. */ + pci_read_config_dword(devno, PCIPM, &tmp); + if (tmp & (0x03 | 0x100)) { + /* D0 state, disable PME assertion */ + u32 newtmp = tmp & ~(0x03 | 0x100); + pci_write_config_dword(devno, PCIPM, newtmp); + } + + printf("natsemi: EEPROM contents:\n"); + for (i = 0; i <= EEPROM_SIZE; i++) { + short eedata = read_eeprom(dev, EECtrl, i); + printf(" %04hx", eedata); + } + printf("\n"); + + /* get MAC address */ + prev_eedata = read_eeprom(dev, EECtrl, 6); + for (i = 0; i < 3; i++) { + int eedata = read_eeprom(dev, EECtrl, i + 7); + dev->enetaddr[i*2] = (eedata << 1) + (prev_eedata >> 15); + dev->enetaddr[i*2+1] = eedata >> 7; + prev_eedata = eedata; + } + + /* Reset the chip to erase any previous misconfiguration. */ + OUTL(dev, ChipReset, ChipCmd); + + advertising = mdio_read(dev, 1, 4); + chip_config = INL(dev, ChipConfig); +#ifdef NATSEMI_DEBUG + printf("%s: Transceiver status %#08X advertising %#08X\n", + dev->name, (int) INL(dev, BasicStatus), advertising); + printf("%s: Transceiver default autoneg. %s 10%s %s duplex.\n", + dev->name, chip_config & AnegMask ? "enabled, advertise" : + "disabled, force", chip_config & SpeedMask ? "0" : "", + chip_config & DuplexMask ? "full" : "half"); +#endif + chip_config |= AnegEnBothBoth; +#ifdef NATSEMI_DEBUG + printf("%s: changed to autoneg. %s 10%s %s duplex.\n", + dev->name, chip_config & AnegMask ? "enabled, advertise" : + "disabled, force", chip_config & SpeedMask ? "0" : "", + chip_config & DuplexMask ? "full" : "half"); +#endif + /*write new autoneg bits, reset phy*/ + OUTL(dev, (chip_config | PhyRst), ChipConfig); + /*un-reset phy*/ + OUTL(dev, chip_config, ChipConfig); + + /* Disable PME: + * The PME bit is initialized from the EEPROM contents. + * PCI cards probably have PME disabled, but motherboard + * implementations may have PME set to enable WakeOnLan. + * With PME set the chip will scan incoming packets but + * nothing will be written to memory. */ + SavedClkRun = INL(dev, ClkRun); + OUTL(dev, SavedClkRun & ~0x100, ClkRun); + } + return card_number; +} + +/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. + The EEPROM code is for common 93c06/46 EEPROMs w/ 6bit addresses. */ + +/* Delay between EEPROM clock transitions. + No extra delay is needed with 33Mhz PCI, but future 66Mhz + access may need a delay. */ +#define eeprom_delay(ee_addr) INL(dev, ee_addr) + +enum EEPROM_Ctrl_Bits { + EE_ShiftClk = 0x04, + EE_DataIn = 0x01, + EE_ChipSelect = 0x08, + EE_DataOut = 0x02 +}; + +#define EE_Write0 (EE_ChipSelect) +#define EE_Write1 (EE_ChipSelect | EE_DataIn) +/* The EEPROM commands include the alway-set leading bit. */ +enum EEPROM_Cmds { + EE_WrEnCmd = (4 << 6), EE_WriteCmd = (5 << 6), + EE_ReadCmd = (6 << 6), EE_EraseCmd = (7 << 6), +}; + +#if 0 +static void +write_eeprom(struct eth_device *dev, long addr, int location, short value) +{ + int i; + int ee_addr = (typeof(ee_addr))addr; + short wren_cmd = EE_WrEnCmd | 0x30; /*wren is 100 + 11XXXX*/ + short write_cmd = location | EE_WriteCmd; + +#ifdef NATSEMI_DEBUG + printf("write_eeprom: %08x, %04hx, %04hx\n", + dev->iobase + ee_addr, write_cmd, value); +#endif + /* Shift the write enable command bits out. */ + for (i = 9; i >= 0; i--) { + short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0; + OUTL(dev, cmdval, ee_addr); + eeprom_delay(ee_addr); + OUTL(dev, cmdval | EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + } + + OUTL(dev, 0, ee_addr); /*bring chip select low*/ + OUTL(dev, EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + + /* Shift the write command bits out. */ + for (i = 9; i >= 0; i--) { + short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0; + OUTL(dev, cmdval, ee_addr); + eeprom_delay(ee_addr); + OUTL(dev, cmdval | EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + } + + for (i = 0; i < 16; i++) { + short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0; + OUTL(dev, cmdval, ee_addr); + eeprom_delay(ee_addr); + OUTL(dev, cmdval | EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + } + + OUTL(dev, 0, ee_addr); /*bring chip select low*/ + OUTL(dev, EE_ShiftClk, ee_addr); + for (i = 0; i < 200000; i++) { + OUTL(dev, EE_Write0, ee_addr); /*poll for done*/ + if (INL(dev, ee_addr) & EE_DataOut) { + break; /*finished*/ + } + } + eeprom_delay(ee_addr); + + /* Terminate the EEPROM access. */ + OUTL(dev, EE_Write0, ee_addr); + OUTL(dev, 0, ee_addr); + return; +} +#endif + +static int +read_eeprom(struct eth_device *dev, long addr, int location) +{ + int i; + int retval = 0; + int ee_addr = (typeof(ee_addr))addr; + int read_cmd = location | EE_ReadCmd; + + OUTL(dev, EE_Write0, ee_addr); + + /* Shift the read command bits out. */ + for (i = 10; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; + OUTL(dev, dataval, ee_addr); + eeprom_delay(ee_addr); + OUTL(dev, dataval | EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + } + OUTL(dev, EE_ChipSelect, ee_addr); + eeprom_delay(ee_addr); + + for (i = 0; i < 16; i++) { + OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr); + eeprom_delay(ee_addr); + retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0; + OUTL(dev, EE_ChipSelect, ee_addr); + eeprom_delay(ee_addr); + } + + /* Terminate the EEPROM access. */ + OUTL(dev, EE_Write0, ee_addr); + OUTL(dev, 0, ee_addr); +#ifdef NATSEMI_DEBUG + if (natsemi_debug) + printf("read_eeprom: %08x, %08x, retval %08x\n", + dev->iobase + ee_addr, read_cmd, retval); +#endif + return retval; +} + +/* MII transceiver control section. + The 83815 series has an internal transceiver, and we present the + management registers as if they were MII connected. */ + +static int +mdio_read(struct eth_device *dev, int phy_id, int location) +{ + if (phy_id == 1 && location < 32) + return INL(dev, BasicControl+(location<<2))&0xffff; + else + return 0xffff; +} + +/* Function: natsemi_init + * + * Description: resets the ethernet controller chip and configures + * registers and data structures required for sending and receiving packets. + * + * Arguments: struct eth_device *dev: NIC data structure + * + * returns: int. + */ + +static int +natsemi_init(struct eth_device *dev, bd_t * bis) +{ + + natsemi_reset(dev); + + /* Disable PME: + * The PME bit is initialized from the EEPROM contents. + * PCI cards probably have PME disabled, but motherboard + * implementations may have PME set to enable WakeOnLan. + * With PME set the chip will scan incoming packets but + * nothing will be written to memory. */ + OUTL(dev, SavedClkRun & ~0x100, ClkRun); + + natsemi_init_rxfilter(dev); + natsemi_init_txd(dev); + natsemi_init_rxd(dev); + + /* Configure the PCI bus bursts and FIFO thresholds. */ + tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002); + rx_config = RxMxdma_256 | 0x20; + +#ifdef NATSEMI_DEBUG + printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); + printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config); +#endif + OUTL(dev, tx_config, TxConfig); + OUTL(dev, rx_config, RxConfig); + + natsemi_check_duplex(dev); + natsemi_set_rx_mode(dev); + + OUTL(dev, (RxOn | TxOn), ChipCmd); + return 1; +} + +/* + * Function: natsemi_reset + * + * Description: soft resets the controller chip + * + * Arguments: struct eth_device *dev: NIC data structure + * + * Returns: void. + */ +static void +natsemi_reset(struct eth_device *dev) +{ + OUTL(dev, ChipReset, ChipCmd); + + /* On page 78 of the spec, they recommend some settings for "optimum + performance" to be done in sequence. These settings optimize some + of the 100Mbit autodetection circuitry. Also, we only want to do + this for rev C of the chip. */ + if (INL(dev, SiliconRev) == 0x302) { + OUTW(dev, 0x0001, PGSEL); + OUTW(dev, 0x189C, PMDCSR); + OUTW(dev, 0x0000, TSTDAT); + OUTW(dev, 0x5040, DSPCFG); + OUTW(dev, 0x008C, SDCFG); + } + /* Disable interrupts using the mask. */ + OUTL(dev, 0, IntrMask); + OUTL(dev, 0, IntrEnable); +} + +/* Function: natsemi_init_rxfilter + * + * Description: sets receive filter address to our MAC address + * + * Arguments: struct eth_device *dev: NIC data structure + * + * returns: void. + */ + +static void +natsemi_init_rxfilter(struct eth_device *dev) +{ + int i; + + for (i = 0; i < ETH_ALEN; i += 2) { + OUTL(dev, i, RxFilterAddr); + OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), + RxFilterData); + } +} + +/* + * Function: natsemi_init_txd + * + * Description: initializes the Tx descriptor + * + * Arguments: struct eth_device *dev: NIC data structure + * + * returns: void. + */ + +static void +natsemi_init_txd(struct eth_device *dev) +{ + txd.link = (u32) 0; + txd.cmdsts = (u32) 0; + txd.bufptr = (u32) & txb[0]; + + /* load Transmit Descriptor Register */ + OUTL(dev, (u32) & txd, TxRingPtr); +#ifdef NATSEMI_DEBUG + printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n", + INL(dev, TxRingPtr)); +#endif +} + +/* Function: natsemi_init_rxd + * + * Description: initializes the Rx descriptor ring + * + * Arguments: struct eth_device *dev: NIC data structure + * + * Returns: void. + */ + +static void +natsemi_init_rxd(struct eth_device *dev) +{ + int i; + + cur_rx = 0; + + /* init RX descriptor */ + for (i = 0; i < NUM_RX_DESC; i++) { + rxd[i].link = + cpu_to_le32((i + 1 < + NUM_RX_DESC) ? (u32) & rxd[i + + 1] : (u32) & + rxd[0]); + rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); + rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]); +#ifdef NATSEMI_DEBUG + printf + ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n", + i, &rxd[i], le32_to_cpu(rxd[i].link), + rxd[i].cmdsts, rxd[i].bufptr); +#endif + } + + /* load Receive Descriptor Register */ + OUTL(dev, (u32) & rxd[0], RxRingPtr); + +#ifdef NATSEMI_DEBUG + printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", + INL(dev, RxRingPtr)); +#endif +} + +/* Function: natsemi_set_rx_mode + * + * Description: + * sets the receive mode to accept all broadcast packets and packets + * with our MAC address, and reject all multicast packets. + * + * Arguments: struct eth_device *dev: NIC data structure + * + * Returns: void. + */ + +static void +natsemi_set_rx_mode(struct eth_device *dev) +{ + u32 rx_mode = AcceptBroadcast | AcceptMyPhys; + + OUTL(dev, rx_mode, RxFilterAddr); +} + +static void +natsemi_check_duplex(struct eth_device *dev) +{ + int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0; + +#ifdef NATSEMI_DEBUG + printf("%s: Setting %s-duplex based on negotiated link" + " capability.\n", dev->name, duplex ? "full" : "half"); +#endif + if (duplex) { + rx_config |= RxAcceptTx; + tx_config |= (TxCarrierIgn | TxHeartIgn); + } else { + rx_config &= ~RxAcceptTx; + tx_config &= ~(TxCarrierIgn | TxHeartIgn); + } + OUTL(dev, tx_config, TxConfig); + OUTL(dev, rx_config, RxConfig); +} + +/* Function: natsemi_send + * + * Description: transmits a packet and waits for completion or timeout. + * + * Returns: void. */ +static int +natsemi_send(struct eth_device *dev, volatile void *packet, int length) +{ + u32 i, status = 0; + u32 tx_status = 0; + vu_long *res = (vu_long *)&tx_status; + + /* Stop the transmitter */ + OUTL(dev, TxOff, ChipCmd); + +#ifdef NATSEMI_DEBUG + if (natsemi_debug) + printf("natsemi_send: sending %d bytes\n", (int) length); +#endif + + /* set the transmit buffer descriptor and enable Transmit State Machine */ + txd.link = cpu_to_le32(0); + txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet)); + txd.cmdsts = cpu_to_le32(DescOwn | length); + + /* load Transmit Descriptor Register */ + OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr); +#ifdef NATSEMI_DEBUG + if (natsemi_debug) + printf("natsemi_send: TX descriptor register loaded with: %#08X\n", + INL(dev, TxRingPtr)); +#endif + /* restart the transmitter */ + OUTL(dev, TxOn, ChipCmd); + + for (i = 0; + (*res = le32_to_cpu(txd.cmdsts)) & DescOwn; + i++) { + if (i >= TOUT_LOOP) { + printf + ("%s: tx error buffer not ready: txd.cmdsts == %#X\n", + dev->name, tx_status); + goto Done; + } + } + + if (!(tx_status & DescPktOK)) { + printf("natsemi_send: Transmit error, Tx status %X.\n", + tx_status); + goto Done; + } + + status = 1; + Done: + return status; +} + +/* Function: natsemi_poll + * + * Description: checks for a received packet and returns it if found. + * + * Arguments: struct eth_device *dev: NIC data structure + * + * Returns: 1 if packet was received. + * 0 if no packet was received. + * + * Side effects: + * Returns (copies) the packet to the array dev->packet. + * Returns the length of the packet. + */ + +static int +natsemi_poll(struct eth_device *dev) +{ + int retstat = 0; + int length = 0; + u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); + + if (!(rx_status & (u32) DescOwn)) + return retstat; +#ifdef NATSEMI_DEBUG + if (natsemi_debug) + printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", + cur_rx, rx_status); +#endif + length = (rx_status & DSIZE) - CRC_SIZE; + + if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { + printf + ("natsemi_poll: Corrupted packet received, buffer status = %X\n", + rx_status); + retstat = 0; + } else { /* give packet to higher level routine */ + NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); + retstat = 1; + } + + /* return the descriptor and buffer to receive ring */ + rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); + rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]); + + if (++cur_rx == NUM_RX_DESC) + cur_rx = 0; + + /* re-enable the potentially idle receive state machine */ + OUTL(dev, RxOn, ChipCmd); + + return retstat; +} + +/* Function: natsemi_disable + * + * Description: Turns off interrupts and stops Tx and Rx engines + * + * Arguments: struct eth_device *dev: NIC data structure + * + * Returns: void. + */ + +static void +natsemi_disable(struct eth_device *dev) +{ + /* Disable interrupts using the mask. */ + OUTL(dev, 0, IntrMask); + OUTL(dev, 0, IntrEnable); + + /* Stop the chip's Tx and Rx processes. */ + OUTL(dev, RxOff | TxOff, ChipCmd); + + /* Restore PME enable bit */ + OUTL(dev, SavedClkRun, ClkRun); +} + +#endif diff --git a/drivers/net/ne2000.c b/drivers/net/ne2000.c new file mode 100644 index 0000000000..c978d62ef3 --- /dev/null +++ b/drivers/net/ne2000.c @@ -0,0 +1,940 @@ +/* +Ported to U-Boot by Christian Pellegrin + +Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and +eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world +are GPL, so this is, of course, GPL. + + +========================================================================== + +dev/if_dp83902a.c + +Ethernet device driver for NS DP83902a ethernet controller + +========================================================================== +####ECOSGPLCOPYRIGHTBEGIN#### +------------------------------------------- +This file is part of eCos, the Embedded Configurable Operating System. +Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. + +eCos is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 or (at your option) any later version. + +eCos is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with eCos; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +As a special exception, if other files instantiate templates or use macros +or inline functions from this file, or you compile this file and link it +with other works to produce a work based on this file, this file does not +by itself cause the resulting work to be covered by the GNU General Public +License. However the source code for this file must still be made available +in accordance with section (3) of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based on +this file might be covered by the GNU General Public License. + +Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +at http://sources.redhat.com/ecos/ecos-license/ +------------------------------------------- +####ECOSGPLCOPYRIGHTEND#### +####BSDCOPYRIGHTBEGIN#### + +------------------------------------------- + +Portions of this software may have been derived from OpenBSD or other sources, +and are covered by the appropriate copyright disclaimers included herein. + +------------------------------------------- + +####BSDCOPYRIGHTEND#### +========================================================================== +#####DESCRIPTIONBEGIN#### + +Author(s): gthomas +Contributors: gthomas, jskov, rsandifo +Date: 2001-06-13 +Purpose: +Description: + +FIXME: Will fail if pinged with large packets (1520 bytes) +Add promisc config +Add SNMP + +####DESCRIPTIONEND#### + + +========================================================================== + +*/ + +#include +#include +#include +#include + +#ifdef CONFIG_DRIVER_NE2000 + +/* wor around udelay resetting OCR */ +static void my_udelay(long us) { + long tmo; + + tmo = get_timer (0) + us * CFG_HZ / 1000000; /* will this be much greater than 0 ? */ + while (get_timer (0) < tmo); +} + +#define mdelay(n) my_udelay((n)*1000) + +/* forward definition of function used for the uboot interface */ +void uboot_push_packet_len(int len); +void uboot_push_tx_done(int key, int val); + +/* timeout for tx/rx in s */ +#define TOUT 5 + +#define ETHER_ADDR_LEN 6 + +/* + ------------------------------------------------------------------------ + Debugging details + + Set to perms of: + 0 disables all debug output + 1 for process debug output + 2 for added data IO output: get_reg, put_reg + 4 for packet allocation/free output + 8 for only startup status, so we can tell we're installed OK +*/ +/*#define DEBUG 0xf*/ +#define DEBUG 0 + +#if DEBUG & 1 +#define DEBUG_FUNCTION() do { printf("%s\n", __FUNCTION__); } while (0) +#define DEBUG_LINE() do { printf("%d\n", __LINE__); } while (0) +#else +#define DEBUG_FUNCTION() do {} while(0) +#define DEBUG_LINE() do {} while(0) +#endif + +#include "ne2000.h" + +#if DEBUG & 1 +#define PRINTK(args...) printf(args) +#else +#define PRINTK(args...) +#endif + +static dp83902a_priv_data_t nic; /* just one instance of the card supported */ + +static bool +dp83902a_init(void) +{ + dp83902a_priv_data_t *dp = &nic; + cyg_uint8* base; + int i; + + DEBUG_FUNCTION(); + + base = dp->base; + if (!base) return false; /* No device found */ + + DEBUG_LINE(); + + /* Prepare ESA */ + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); /* Select page 1 */ + /* Use the address from the serial EEPROM */ + for (i = 0; i < 6; i++) + DP_IN(base, DP_P1_PAR0+i, dp->esa[i]); + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); /* Select page 0 */ + + printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", + "eeprom", + dp->esa[0], + dp->esa[1], + dp->esa[2], + dp->esa[3], + dp->esa[4], + dp->esa[5] ); + + return true; +} + +static void +dp83902a_stop(void) +{ + dp83902a_priv_data_t *dp = &nic; + cyg_uint8 *base = dp->base; + + DEBUG_FUNCTION(); + + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ + DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ + DP_OUT(base, DP_IMR, 0x00); /* Disable all interrupts */ + + dp->running = false; +} + +/* + This function is called to "start up" the interface. It may be called + multiple times, even when the hardware is already running. It will be + called whenever something "hardware oriented" changes and should leave + the hardware ready to send/receive packets. +*/ +static void +dp83902a_start(unsigned char * enaddr) +{ + dp83902a_priv_data_t *dp = &nic; + cyg_uint8 *base = dp->base; + int i; + + DEBUG_FUNCTION(); + + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ + DP_OUT(base, DP_DCR, DP_DCR_INIT); + DP_OUT(base, DP_RBCH, 0); /* Remote byte count */ + DP_OUT(base, DP_RBCL, 0); + DP_OUT(base, DP_RCR, DP_RCR_MON); /* Accept no packets */ + DP_OUT(base, DP_TCR, DP_TCR_LOCAL); /* Transmitter [virtually] off */ + DP_OUT(base, DP_TPSR, dp->tx_buf1); /* Transmitter start page */ + dp->tx1 = dp->tx2 = 0; + dp->tx_next = dp->tx_buf1; + dp->tx_started = false; + DP_OUT(base, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */ + DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); /* Receive ring boundary */ + DP_OUT(base, DP_PSTOP, dp->rx_buf_end); /* Receive ring end page */ + dp->rx_next = dp->rx_buf_start-1; + DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ + DP_OUT(base, DP_IMR, DP_IMR_All); /* Enable all interrupts */ + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); /* Select page 1 */ + DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); /* Current page - next free page for Rx */ + for (i = 0; i < ETHER_ADDR_LEN; i++) { + DP_OUT(base, DP_P1_PAR0+i, enaddr[i]); + } + /* Enable and start device */ + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); + DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */ + DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */ + dp->running = true; +} + +/* + This routine is called to start the transmitter. It is split out from the + data handling routine so it may be called either when data becomes first + available or when an Tx interrupt occurs +*/ + +static void +dp83902a_start_xmit(int start_page, int len) +{ + dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic; + cyg_uint8 *base = dp->base; + + DEBUG_FUNCTION(); + +#if DEBUG & 1 + printf("Tx pkt %d len %d\n", start_page, len); + if (dp->tx_started) + printf("TX already started?!?\n"); +#endif + + DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE)); + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); + DP_OUT(base, DP_TBCL, len & 0xFF); + DP_OUT(base, DP_TBCH, len >> 8); + DP_OUT(base, DP_TPSR, start_page); + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); + + dp->tx_started = true; +} + +/* + This routine is called to send data to the hardware. It is known a-priori + that there is free buffer space (dp->tx_next). +*/ +static void +dp83902a_send(unsigned char *data, int total_len, unsigned long key) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + int len, start_page, pkt_len, i, isr; +#if DEBUG & 4 + int dx; +#endif + + DEBUG_FUNCTION(); + + len = pkt_len = total_len; + if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; + + start_page = dp->tx_next; + if (dp->tx_next == dp->tx_buf1) { + dp->tx1 = start_page; + dp->tx1_len = pkt_len; + dp->tx1_key = key; + dp->tx_next = dp->tx_buf2; + } else { + dp->tx2 = start_page; + dp->tx2_len = pkt_len; + dp->tx2_key = key; + dp->tx_next = dp->tx_buf1; + } + +#if DEBUG & 5 + printf("TX prep page %d len %d\n", start_page, pkt_len); +#endif + + DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ + { + /* Dummy read. The manual sez something slightly different, */ + /* but the code is extended a bit to do what Hitachi's monitor */ + /* does (i.e., also read data). */ + + cyg_uint16 tmp; + int len = 1; + + DP_OUT(base, DP_RSAL, 0x100-len); + DP_OUT(base, DP_RSAH, (start_page-1) & 0xff); + DP_OUT(base, DP_RBCL, len); + DP_OUT(base, DP_RBCH, 0); + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); + DP_IN_DATA(dp->data, tmp); + } + +#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA + /* Stall for a bit before continuing to work around random data */ + /* corruption problems on some platforms. */ + CYGACC_CALL_IF_DELAY_US(1); +#endif + + /* Send data to device buffer(s) */ + DP_OUT(base, DP_RSAL, 0); + DP_OUT(base, DP_RSAH, start_page); + DP_OUT(base, DP_RBCL, pkt_len & 0xFF); + DP_OUT(base, DP_RBCH, pkt_len >> 8); + DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START); + + /* Put data into buffer */ +#if DEBUG & 4 + printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len); + dx = 0; +#endif + while (len > 0) { +#if DEBUG & 4 + printf(" %02x", *data); + if (0 == (++dx % 16)) printf("\n "); +#endif + DP_OUT_DATA(dp->data, *data++); + len--; + } +#if DEBUG & 4 + printf("\n"); +#endif + if (total_len < pkt_len) { +#if DEBUG & 4 + printf(" + %d bytes of padding\n", pkt_len - total_len); +#endif + /* Padding to 802.3 length was required */ + for (i = total_len; i < pkt_len;) { + i++; + DP_OUT_DATA(dp->data, 0); + } + } + +#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA + /* After last data write, delay for a bit before accessing the */ + /* device again, or we may get random data corruption in the last */ + /* datum (on some platforms). */ + CYGACC_CALL_IF_DELAY_US(1); +#endif + + /* Wait for DMA to complete */ + do { + DP_IN(base, DP_ISR, isr); + } while ((isr & DP_ISR_RDC) == 0); + /* Then disable DMA */ + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); + + /* Start transmit if not already going */ + if (!dp->tx_started) { + if (start_page == dp->tx1) { + dp->tx_int = 1; /* Expecting interrupt from BUF1 */ + } else { + dp->tx_int = 2; /* Expecting interrupt from BUF2 */ + } + dp83902a_start_xmit(start_page, pkt_len); + } +} + +/* + This function is called when a packet has been received. It's job is + to prepare to unload the packet from the hardware. Once the length of + the packet is known, the upper layer of the driver can be told. When + the upper layer is ready to unload the packet, the internal function + 'dp83902a_recv' will be called to actually fetch it from the hardware. +*/ +static void +dp83902a_RxEvent(void) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + unsigned char rsr; + unsigned char rcv_hdr[4]; + int i, len, pkt, cur; + + DEBUG_FUNCTION(); + + DP_IN(base, DP_RSR, rsr); + while (true) { + /* Read incoming packet header */ + DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START); + DP_IN(base, DP_P1_CURP, cur); + DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); + DP_IN(base, DP_BNDRY, pkt); + + pkt += 1; + if (pkt == dp->rx_buf_end) + pkt = dp->rx_buf_start; + + if (pkt == cur) { + break; + } + DP_OUT(base, DP_RBCL, sizeof(rcv_hdr)); + DP_OUT(base, DP_RBCH, 0); + DP_OUT(base, DP_RSAL, 0); + DP_OUT(base, DP_RSAH, pkt); + if (dp->rx_next == pkt) { + if (cur == dp->rx_buf_start) + DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); + else + DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */ + return; + } + dp->rx_next = pkt; + DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ + DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); +#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA + CYGACC_CALL_IF_DELAY_US(10); +#endif + + for (i = 0; i < sizeof(rcv_hdr);) { + DP_IN_DATA(dp->data, rcv_hdr[i++]); + } + +#if DEBUG & 5 + printf("rx hdr %02x %02x %02x %02x\n", + rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]); +#endif + len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr); + uboot_push_packet_len(len); + if (rcv_hdr[1] == dp->rx_buf_start) + DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); + else + DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); /* Update pointer */ + } +} + +/* + This function is called as a result of the "eth_drv_recv()" call above. + It's job is to actually fetch data for a packet from the hardware once + memory buffers have been allocated for the packet. Note that the buffers + may come in pieces, using a scatter-gather list. This allows for more + efficient processing in the upper layers of the stack. +*/ +static void +dp83902a_recv(unsigned char *data, int len) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + int i, mlen; + cyg_uint8 saved_char = 0; + bool saved; +#if DEBUG & 4 + int dx; +#endif + + DEBUG_FUNCTION(); + +#if DEBUG & 5 + printf("Rx packet %d length %d\n", dp->rx_next, len); +#endif + + /* Read incoming packet data */ + DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); + DP_OUT(base, DP_RBCL, len & 0xFF); + DP_OUT(base, DP_RBCH, len >> 8); + DP_OUT(base, DP_RSAL, 4); /* Past header */ + DP_OUT(base, DP_RSAH, dp->rx_next); + DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ + DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); +#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA + CYGACC_CALL_IF_DELAY_US(10); +#endif + + saved = false; + for (i = 0; i < 1; i++) { + if (data) { + mlen = len; +#if DEBUG & 4 + printf(" sg buf %08lx len %08x \n", (unsigned long) data, mlen); + dx = 0; +#endif + while (0 < mlen) { + /* Saved byte from previous loop? */ + if (saved) { + *data++ = saved_char; + mlen--; + saved = false; + continue; + } + + { + cyg_uint8 tmp; + DP_IN_DATA(dp->data, tmp); +#if DEBUG & 4 + printf(" %02x", tmp); + if (0 == (++dx % 16)) printf("\n "); +#endif + *data++ = tmp;; + mlen--; + } + } +#if DEBUG & 4 + printf("\n"); +#endif + } + } +} + +static void +dp83902a_TxEvent(void) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + unsigned char tsr; + unsigned long key; + + DEBUG_FUNCTION(); + + DP_IN(base, DP_TSR, tsr); + if (dp->tx_int == 1) { + key = dp->tx1_key; + dp->tx1 = 0; + } else { + key = dp->tx2_key; + dp->tx2 = 0; + } + /* Start next packet if one is ready */ + dp->tx_started = false; + if (dp->tx1) { + dp83902a_start_xmit(dp->tx1, dp->tx1_len); + dp->tx_int = 1; + } else if (dp->tx2) { + dp83902a_start_xmit(dp->tx2, dp->tx2_len); + dp->tx_int = 2; + } else { + dp->tx_int = 0; + } + /* Tell higher level we sent this packet */ + uboot_push_tx_done(key, 0); +} + +/* Read the tally counters to clear them. Called in response to a CNT */ +/* interrupt. */ +static void +dp83902a_ClearCounters(void) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + cyg_uint8 cnt1, cnt2, cnt3; + + DP_IN(base, DP_FER, cnt1); + DP_IN(base, DP_CER, cnt2); + DP_IN(base, DP_MISSED, cnt3); + DP_OUT(base, DP_ISR, DP_ISR_CNT); +} + +/* Deal with an overflow condition. This code follows the procedure set */ +/* out in section 7.0 of the datasheet. */ +static void +dp83902a_Overflow(void) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic; + cyg_uint8 *base = dp->base; + cyg_uint8 isr; + + /* Issue a stop command and wait 1.6ms for it to complete. */ + DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA); + CYGACC_CALL_IF_DELAY_US(1600); + + /* Clear the remote byte counter registers. */ + DP_OUT(base, DP_RBCL, 0); + DP_OUT(base, DP_RBCH, 0); + + /* Enter loopback mode while we clear the buffer. */ + DP_OUT(base, DP_TCR, DP_TCR_LOCAL); + DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA); + + /* Read in as many packets as we can and acknowledge any and receive */ + /* interrupts. Since the buffer has overflowed, a receive event of */ + /* some kind will have occured. */ + dp83902a_RxEvent(); + DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE); + + /* Clear the overflow condition and leave loopback mode. */ + DP_OUT(base, DP_ISR, DP_ISR_OFLW); + DP_OUT(base, DP_TCR, DP_TCR_NORMAL); + + /* If a transmit command was issued, but no transmit event has occured, */ + /* restart it here. */ + DP_IN(base, DP_ISR, isr); + if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) { + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); + } +} + +static void +dp83902a_poll(void) +{ + struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; + cyg_uint8 *base = dp->base; + unsigned char isr; + + DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START); + DP_IN(base, DP_ISR, isr); + while (0 != isr) { + /* The CNT interrupt triggers when the MSB of one of the error */ + /* counters is set. We don't much care about these counters, but */ + /* we should read their values to reset them. */ + if (isr & DP_ISR_CNT) { + dp83902a_ClearCounters(); + } + /* Check for overflow. It's a special case, since there's a */ + /* particular procedure that must be followed to get back into */ + /* a running state.a */ + if (isr & DP_ISR_OFLW) { + dp83902a_Overflow(); + } else { + /* Other kinds of interrupts can be acknowledged simply by */ + /* clearing the relevant bits of the ISR. Do that now, then */ + /* handle the interrupts we care about. */ + DP_OUT(base, DP_ISR, isr); /* Clear set bits */ + if (!dp->running) break; /* Is this necessary? */ + /* Check for tx_started on TX event since these may happen */ + /* spuriously it seems. */ + if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) { + dp83902a_TxEvent(); + } + if (isr & (DP_ISR_RxP|DP_ISR_RxE)) { + dp83902a_RxEvent(); + } + } + DP_IN(base, DP_ISR, isr); + } +} + +/* find prom (taken from pc_net_cs.c from Linux) */ + +#include "8390.h" + +typedef struct hw_info_t { + u_int offset; + u_char a0, a1, a2; + u_int flags; +} hw_info_t; + +#define DELAY_OUTPUT 0x01 +#define HAS_MISC_REG 0x02 +#define USE_BIG_BUF 0x04 +#define HAS_IBM_MISC 0x08 +#define IS_DL10019 0x10 +#define IS_DL10022 0x20 +#define HAS_MII 0x40 +#define USE_SHMEM 0x80 /* autodetected */ + +#define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */ +#define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */ +#define MII_PHYID_REV_MASK 0xfffffff0 +#define MII_PHYID_REG1 0x02 +#define MII_PHYID_REG2 0x03 + +static hw_info_t hw_info[] = { + { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, + { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, + { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, + { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, + DELAY_OUTPUT | HAS_IBM_MISC }, + { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, + { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, + { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, + { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, + { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, + { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, + { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, + { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, + { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, + { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, + { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, + { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, + { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, + { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, + { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, + HAS_MISC_REG | HAS_IBM_MISC }, + { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, + { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, + { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, + { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, + DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, + { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, + { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, + { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, + { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, + { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }, + { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 } +}; + +#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) + +static hw_info_t default_info = { 0, 0, 0, 0, 0 }; + +unsigned char dev_addr[6]; + +#define PCNET_CMD 0x00 +#define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ +#define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ +#define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */ + +unsigned long nic_base; + +static void pcnet_reset_8390(void) +{ + int i, r; + + PRINTK("nic base is %lx\n", nic_base); + + n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); + PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); + n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD); + PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); + n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); + PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); + n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); + + n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET); + + for (i = 0; i < 100; i++) { + if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0) + break; + PRINTK("got %x in reset\n", r); + my_udelay(100); + } + n2k_outb(ENISR_RESET, EN0_ISR); /* Ack intr. */ + + if (i == 100) + printf("pcnet_reset_8390() did not complete.\n"); +} /* pcnet_reset_8390 */ + +static hw_info_t * get_prom(void ) { + unsigned char prom[32]; + int i, j; + struct { + u_char value, offset; + } program_seq[] = { + {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ + {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ + {0x00, EN0_RCNTLO}, /* Clear the count regs. */ + {0x00, EN0_RCNTHI}, + {0x00, EN0_IMR}, /* Mask completion irq. */ + {0xFF, EN0_ISR}, + {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ + {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ + {32, EN0_RCNTLO}, + {0x00, EN0_RCNTHI}, + {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ + {0x00, EN0_RSARHI}, + {E8390_RREAD+E8390_START, E8390_CMD}, + }; + + PRINTK("trying to get MAC via prom reading\n"); + + pcnet_reset_8390(); + + mdelay(10); + + for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) + n2k_outb(program_seq[i].value, program_seq[i].offset); + + PRINTK("PROM:"); + for (i = 0; i < 32; i++) { + prom[i] = n2k_inb(PCNET_DATAPORT); + PRINTK(" %02x", prom[i]); + } + PRINTK("\n"); + for (i = 0; i < NR_INFO; i++) { + if ((prom[0] == hw_info[i].a0) && + (prom[2] == hw_info[i].a1) && + (prom[4] == hw_info[i].a2)) { + PRINTK("matched board %d\n", i); + break; + } + } + if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) { + for (j = 0; j < 6; j++) + dev_addr[j] = prom[j<<1]; + PRINTK("on exit i is %d/%ld\n", i, NR_INFO); + PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n", + dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]); + return (i < NR_INFO) ? hw_info+i : &default_info; + } + return NULL; +} + +/* U-boot specific routines */ + + +static unsigned char *pbuf = NULL; + +static int pkey = -1; +static int initialized=0; + +void uboot_push_packet_len(int len) { + PRINTK("pushed len = %d\n", len); + if (len>=2000) { + printf("NE2000: packet too big\n"); + return; + } + dp83902a_recv(&pbuf[0], len); + + /*Just pass it to the upper layer*/ + NetReceive(&pbuf[0], len); +} + +void uboot_push_tx_done(int key, int val) { + PRINTK("pushed key = %d\n", key); + pkey = key; +} + +int eth_init(bd_t *bd) { + static hw_info_t * r; + char ethaddr[20]; + + PRINTK("### eth_init\n"); + + if (!pbuf) { + pbuf = malloc(2000); + if (!pbuf) { + printf("Cannot allocate rx buffer\n"); + return -1; + } + } + +#ifdef CONFIG_DRIVER_NE2000_CCR + { + volatile unsigned char *p = (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR; + + PRINTK("CCR before is %x\n", *p); + *p = CONFIG_DRIVER_NE2000_VAL; + PRINTK("CCR after is %x\n", *p); + } +#endif + + nic_base = CONFIG_DRIVER_NE2000_BASE; + nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE; + + r = get_prom(); + if (!r) + return -1; + + sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + dev_addr[0], dev_addr[1], + dev_addr[2], dev_addr[3], + dev_addr[4], dev_addr[5]) ; + PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr); + setenv ("ethaddr", ethaddr); + + +#define DP_DATA 0x10 + nic.data = nic.base + DP_DATA; + nic.tx_buf1 = 0x40; + nic.tx_buf2 = 0x48; + nic.rx_buf_start = 0x50; + nic.rx_buf_end = 0x80; + + if (dp83902a_init() == false) + return -1; + dp83902a_start(dev_addr); + initialized=1; + return 0; +} + +void eth_halt() { + + PRINTK("### eth_halt\n"); + if(initialized) + dp83902a_stop(); + initialized=0; +} + +int eth_rx() { +dp83902a_poll(); +return 1; +} + +int eth_send(volatile void *packet, int length) { + int tmo; + + PRINTK("### eth_send\n"); + + pkey = -1; + + dp83902a_send((unsigned char *) packet, length, 666); + tmo = get_timer (0) + TOUT * CFG_HZ; + while(1) { + dp83902a_poll(); + if (pkey != -1) { + PRINTK("Packet sucesfully sent\n"); + return 0; + } + if (get_timer (0) >= tmo) { + printf("transmission error (timoeut)\n"); + return 0; + } + + } + return 0; +} +#endif diff --git a/drivers/net/ne2000.h b/drivers/net/ne2000.h new file mode 100644 index 0000000000..c13d9f0bbb --- /dev/null +++ b/drivers/net/ne2000.h @@ -0,0 +1,279 @@ +/* +Ported to U-Boot by Christian Pellegrin + +Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and +eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world +are GPL, so this is, of course, GPL. + + +========================================================================== + + dev/dp83902a.h + + National Semiconductor DP83902a ethernet chip + +========================================================================== +####ECOSGPLCOPYRIGHTBEGIN#### + ------------------------------------------- + This file is part of eCos, the Embedded Configurable Operating System. + Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. + + eCos is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 or (at your option) any later version. + + eCos is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with eCos; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + As a special exception, if other files instantiate templates or use macros + or inline functions from this file, or you compile this file and link it + with other works to produce a work based on this file, this file does not + by itself cause the resulting work to be covered by the GNU General Public + License. However the source code for this file must still be made available + in accordance with section (3) of the GNU General Public License. + + This exception does not invalidate any other reasons why a work based on + this file might be covered by the GNU General Public License. + + Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. + at http://sources.redhat.com/ecos/ecos-license/ + ------------------------------------------- +####ECOSGPLCOPYRIGHTEND#### +####BSDCOPYRIGHTBEGIN#### + + ------------------------------------------- + + Portions of this software may have been derived from OpenBSD or other sources, + and are covered by the appropriate copyright disclaimers included herein. + + ------------------------------------------- + +####BSDCOPYRIGHTEND#### +========================================================================== +#####DESCRIPTIONBEGIN#### + + Author(s): gthomas + Contributors: gthomas, jskov + Date: 2001-06-13 + Purpose: + Description: + +####DESCRIPTIONEND#### + +========================================================================== + +*/ + +/* + ------------------------------------------------------------------------ + Macros for accessing DP registers + These can be overridden by the platform header +*/ + +#define DP_IN(_b_, _o_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_))) +#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = (_d_) + +#define DP_IN_DATA(_b_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_))) +#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned char *) ((_b_))) = (_d_) + + +/* here is all the data */ + +#define cyg_uint8 unsigned char +#define cyg_uint16 unsigned short +#define bool int + +#define false 0 +#define true 1 + +#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1 +#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X) + +typedef struct dp83902a_priv_data { + cyg_uint8* base; + cyg_uint8* data; + cyg_uint8* reset; + int tx_next; /* First free Tx page */ + int tx_int; /* Expecting interrupt from this buffer */ + int rx_next; /* First free Rx page */ + int tx1, tx2; /* Page numbers for Tx buffers */ + unsigned long tx1_key, tx2_key; /* Used to ack when packet sent */ + int tx1_len, tx2_len; + bool tx_started, running, hardwired_esa; + cyg_uint8 esa[6]; + void* plf_priv; + + /* Buffer allocation */ + int tx_buf1, tx_buf2; + int rx_buf_start, rx_buf_end; +} dp83902a_priv_data_t; + +/* + ------------------------------------------------------------------------ + Some forward declarations +*/ +static void dp83902a_poll(void); + +/* ------------------------------------------------------------------------ */ +/* Register offsets */ + +#define DP_CR 0x00 +#define DP_CLDA0 0x01 +#define DP_PSTART 0x01 /* write */ +#define DP_CLDA1 0x02 +#define DP_PSTOP 0x02 /* write */ +#define DP_BNDRY 0x03 +#define DP_TSR 0x04 +#define DP_TPSR 0x04 /* write */ +#define DP_NCR 0x05 +#define DP_TBCL 0x05 /* write */ +#define DP_FIFO 0x06 +#define DP_TBCH 0x06 /* write */ +#define DP_ISR 0x07 +#define DP_CRDA0 0x08 +#define DP_RSAL 0x08 /* write */ +#define DP_CRDA1 0x09 +#define DP_RSAH 0x09 /* write */ +#define DP_RBCL 0x0a /* write */ +#define DP_RBCH 0x0b /* write */ +#define DP_RSR 0x0c +#define DP_RCR 0x0c /* write */ +#define DP_FER 0x0d +#define DP_TCR 0x0d /* write */ +#define DP_CER 0x0e +#define DP_DCR 0x0e /* write */ +#define DP_MISSED 0x0f +#define DP_IMR 0x0f /* write */ +#define DP_DATAPORT 0x10 /* "eprom" data port */ + +#define DP_P1_CR 0x00 +#define DP_P1_PAR0 0x01 +#define DP_P1_PAR1 0x02 +#define DP_P1_PAR2 0x03 +#define DP_P1_PAR3 0x04 +#define DP_P1_PAR4 0x05 +#define DP_P1_PAR5 0x06 +#define DP_P1_CURP 0x07 +#define DP_P1_MAR0 0x08 +#define DP_P1_MAR1 0x09 +#define DP_P1_MAR2 0x0a +#define DP_P1_MAR3 0x0b +#define DP_P1_MAR4 0x0c +#define DP_P1_MAR5 0x0d +#define DP_P1_MAR6 0x0e +#define DP_P1_MAR7 0x0f + +#define DP_P2_CR 0x00 +#define DP_P2_PSTART 0x01 +#define DP_P2_CLDA0 0x01 /* write */ +#define DP_P2_PSTOP 0x02 +#define DP_P2_CLDA1 0x02 /* write */ +#define DP_P2_RNPP 0x03 +#define DP_P2_TPSR 0x04 +#define DP_P2_LNPP 0x05 +#define DP_P2_ACH 0x06 +#define DP_P2_ACL 0x07 +#define DP_P2_RCR 0x0c +#define DP_P2_TCR 0x0d +#define DP_P2_DCR 0x0e +#define DP_P2_IMR 0x0f + +/* Command register - common to all pages */ + +#define DP_CR_STOP 0x01 /* Stop: software reset */ +#define DP_CR_START 0x02 /* Start: initialize device */ +#define DP_CR_TXPKT 0x04 /* Transmit packet */ +#define DP_CR_RDMA 0x08 /* Read DMA (recv data from device) */ +#define DP_CR_WDMA 0x10 /* Write DMA (send data to device) */ +#define DP_CR_SEND 0x18 /* Send packet */ +#define DP_CR_NODMA 0x20 /* Remote (or no) DMA */ +#define DP_CR_PAGE0 0x00 /* Page select */ +#define DP_CR_PAGE1 0x40 +#define DP_CR_PAGE2 0x80 +#define DP_CR_PAGEMSK 0x3F /* Used to mask out page bits */ + +/* Data configuration register */ + +#define DP_DCR_WTS 0x01 /* 1=16 bit word transfers */ +#define DP_DCR_BOS 0x02 /* 1=Little Endian */ +#define DP_DCR_LAS 0x04 /* 1=Single 32 bit DMA mode */ +#define DP_DCR_LS 0x08 /* 1=normal mode, 0=loopback */ +#define DP_DCR_ARM 0x10 /* 0=no send command (program I/O) */ +#define DP_DCR_FIFO_1 0x00 /* FIFO threshold */ +#define DP_DCR_FIFO_2 0x20 +#define DP_DCR_FIFO_4 0x40 +#define DP_DCR_FIFO_6 0x60 + +#define DP_DCR_INIT (DP_DCR_LS|DP_DCR_FIFO_4) + +/* Interrupt status register */ + +#define DP_ISR_RxP 0x01 /* Packet received */ +#define DP_ISR_TxP 0x02 /* Packet transmitted */ +#define DP_ISR_RxE 0x04 /* Receive error */ +#define DP_ISR_TxE 0x08 /* Transmit error */ +#define DP_ISR_OFLW 0x10 /* Receive overflow */ +#define DP_ISR_CNT 0x20 /* Tally counters need emptying */ +#define DP_ISR_RDC 0x40 /* Remote DMA complete */ +#define DP_ISR_RESET 0x80 /* Device has reset (shutdown, error) */ + +/* Interrupt mask register */ + +#define DP_IMR_RxP 0x01 /* Packet received */ +#define DP_IMR_TxP 0x02 /* Packet transmitted */ +#define DP_IMR_RxE 0x04 /* Receive error */ +#define DP_IMR_TxE 0x08 /* Transmit error */ +#define DP_IMR_OFLW 0x10 /* Receive overflow */ +#define DP_IMR_CNT 0x20 /* Tall counters need emptying */ +#define DP_IMR_RDC 0x40 /* Remote DMA complete */ + +#define DP_IMR_All 0x3F /* Everything but remote DMA */ + +/* Receiver control register */ + +#define DP_RCR_SEP 0x01 /* Save bad(error) packets */ +#define DP_RCR_AR 0x02 /* Accept runt packets */ +#define DP_RCR_AB 0x04 /* Accept broadcast packets */ +#define DP_RCR_AM 0x08 /* Accept multicast packets */ +#define DP_RCR_PROM 0x10 /* Promiscuous mode */ +#define DP_RCR_MON 0x20 /* Monitor mode - 1=accept no packets */ + +/* Receiver status register */ + +#define DP_RSR_RxP 0x01 /* Packet received */ +#define DP_RSR_CRC 0x02 /* CRC error */ +#define DP_RSR_FRAME 0x04 /* Framing error */ +#define DP_RSR_FO 0x08 /* FIFO overrun */ +#define DP_RSR_MISS 0x10 /* Missed packet */ +#define DP_RSR_PHY 0x20 /* 0=pad match, 1=mad match */ +#define DP_RSR_DIS 0x40 /* Receiver disabled */ +#define DP_RSR_DFR 0x80 /* Receiver processing deferred */ + +/* Transmitter control register */ + +#define DP_TCR_NOCRC 0x01 /* 1=inhibit CRC */ +#define DP_TCR_NORMAL 0x00 /* Normal transmitter operation */ +#define DP_TCR_LOCAL 0x02 /* Internal NIC loopback */ +#define DP_TCR_INLOOP 0x04 /* Full internal loopback */ +#define DP_TCR_OUTLOOP 0x08 /* External loopback */ +#define DP_TCR_ATD 0x10 /* Auto transmit disable */ +#define DP_TCR_OFFSET 0x20 /* Collision offset adjust */ + +/* Transmit status register */ + +#define DP_TSR_TxP 0x01 /* Packet transmitted */ +#define DP_TSR_COL 0x04 /* Collision (at least one) */ +#define DP_TSR_ABT 0x08 /* Aborted because of too many collisions */ +#define DP_TSR_CRS 0x10 /* Lost carrier */ +#define DP_TSR_FU 0x20 /* FIFO underrun */ +#define DP_TSR_CDH 0x40 /* Collision Detect Heartbeat */ +#define DP_TSR_OWC 0x80 /* Collision outside normal window */ + +#define IEEE_8023_MAX_FRAME 1518 /* Largest possible ethernet frame */ +#define IEEE_8023_MIN_FRAME 64 /* Smallest possible ethernet frame */ diff --git a/drivers/net/netarm_eth.c b/drivers/net/netarm_eth.c new file mode 100644 index 0000000000..a99ee5da2e --- /dev/null +++ b/drivers/net/netarm_eth.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2004 IMMS gGmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * author(s): Thomas Elste, + * (some parts derived from uCLinux Netarm Ethernet Driver) + */ + + +#include + +#ifdef CONFIG_DRIVER_NETARMETH +#include +#include +#include "netarm_eth.h" +#include + + +#if defined(CONFIG_CMD_NET) + +static int na_mii_poll_busy (void); + +static void na_get_mac_addr (void) +{ + unsigned short p[3]; + char *m_addr; + char ethaddr[20]; + + m_addr = (char *) p; + + p[0] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_1); + p[1] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_2); + p[2] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_3); + + sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + m_addr[0], m_addr[1], + m_addr[2], m_addr[3], m_addr[4], m_addr[5]); + + printf ("HW-MAC Address: %s\n", ethaddr); + + /* set env, todo: check if already an adress is set */ + setenv ("ethaddr", ethaddr); +} + + +static void na_mii_write (int reg, int value) +{ + int mii_addr; + + /* Select register */ + mii_addr = CFG_ETH_PHY_ADDR + reg; + SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr); + /* Write value */ + SET_EADDR (NETARM_ETH_MII_WRITE, value); + na_mii_poll_busy (); +} + +static unsigned int na_mii_read (int reg) +{ + int mii_addr, val; + + /* Select register */ + mii_addr = CFG_ETH_PHY_ADDR + reg; + SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr); + /* do one management cycle */ + SET_EADDR (NETARM_ETH_MII_CMD, + GET_EADDR (NETARM_ETH_MII_CMD) | NETARM_ETH_MIIC_RSTAT); + na_mii_poll_busy (); + /* Return read value */ + val = GET_EADDR (NETARM_ETH_MII_READ); + return val; +} + +static int na_mii_poll_busy (void) +{ + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + while (get_timer_masked () < NA_MII_POLL_BUSY_DELAY) { + if (!(GET_EADDR (NETARM_ETH_MII_IND) & NETARM_ETH_MIII_BUSY)) { + return 1; + } + } + printf ("na_mii_busy timeout\n"); + return (0); +} + +static int na_mii_identify_phy (void) +{ + int id_reg_a = 0; + + /* get phy id register */ + id_reg_a = na_mii_read (MII_PHY_ID); + + if (id_reg_a == 0x0043) { + /* This must be an Enable or a Lucent LU3X31 PHY chip */ + return 1; + } else if (id_reg_a == 0x0013) { + /* it is an Intel LXT971A */ + return 1; + } + return (0); +} + +static int na_mii_negotiate (void) +{ + int i = 0; + + /* Enable auto-negotiation */ + na_mii_write (MII_PHY_AUTONEGADV, 0x01e1); + /* FIXME: 0x01E1 is 100Mb half and full duplex, 0x0061 is 10Mb only */ + /* Restart auto-negotiation */ + na_mii_write (MII_PHY_CONTROL, 0x1200); + + /* status register is 0xffff after setting the autoneg restart bit */ + while (na_mii_read (MII_PHY_STATUS) == 0xffff) { + i++; + } + + /* na_mii_read uses the timer already, so we can't use it again for + timeout checking. + Instead we just try some times. + */ + for (i = 0; i < 40000; i++) { + if ((na_mii_read (MII_PHY_STATUS) & 0x0024) == 0x0024) { + return 0; + } + } + /* + printf("*Warning* autonegotiation timeout, status: 0x%x\n",na_mii_read(MII_PHY_STATUS)); + */ + return (1); +} + +static unsigned int na_mii_check_speed (void) +{ + unsigned int status; + + /* Read Status register */ + status = na_mii_read (MII_PHY_STATUS); + /* Check link status. If 0, default to 100 Mbps. */ + if ((status & 0x0004) == 0) { + printf ("*Warning* no link detected, set default speed to 100Mbs\n"); + return 1; + } else { + if ((na_mii_read (17) & 0x4000) != 0) { + printf ("100Mbs link detected\n"); + return 1; + } else { + printf ("10Mbs link detected\n"); + return 0; + } + } + return 0; +} + +static int reset_eth (void) +{ + int pt; + + na_get_mac_addr (); + pt = na_mii_identify_phy (); + + /* reset the phy */ + na_mii_write (MII_PHY_CONTROL, 0x8000); + reset_timer_masked (); + while (get_timer_masked () < NA_MII_NEGOTIATE_DELAY) { + if ((na_mii_read (MII_PHY_STATUS) & 0x8000) == 0) { + break; + } + } + if (get_timer_masked () >= NA_MII_NEGOTIATE_DELAY) + printf ("phy reset timeout\n"); + + /* set the PCS reg */ + SET_EADDR (NETARM_ETH_PCS_CFG, NETARM_ETH_PCSC_CLKS_25M | + NETARM_ETH_PCSC_ENJAB | NETARM_ETH_PCSC_NOCFR); + + na_mii_negotiate (); + na_mii_check_speed (); + + /* Delay 10 millisecond. (Maybe this should be 1 second.) */ + udelay (10000); + + /* Turn receive on. + Enable statistics register autozero on read. + Do not insert MAC address on transmit. + Do not enable special test modes. */ + SET_EADDR (NETARM_ETH_STL_CFG, + (NETARM_ETH_STLC_AUTOZ | NETARM_ETH_STLC_RXEN)); + + /* Set the inter-packet gap delay to 0.96us for MII. + The NET+ARM H/W Reference Guide indicates that the Back-to-back IPG + Gap Timer Register should be set to 0x15 and the Non Back-to-back IPG + Gap Timer Register should be set to 0x00000C12 for the MII PHY. */ + SET_EADDR (NETARM_ETH_B2B_IPG_GAP_TMR, 0x15); + SET_EADDR (NETARM_ETH_NB2B_IPG_GAP_TMR, 0x00000C12); + + /* Add CRC to end of packets. + Pad packets to minimum length of 64 bytes. + Allow unlimited length transmit packets. + Receive all broadcast packets. + NOTE: Multicast addressing is NOT enabled here currently. */ + SET_EADDR (NETARM_ETH_MAC_CFG, + (NETARM_ETH_MACC_CRCEN | + NETARM_ETH_MACC_PADEN | NETARM_ETH_MACC_HUGEN)); + SET_EADDR (NETARM_ETH_SAL_FILTER, NETARM_ETH_SALF_BROAD); + + /* enable fifos */ + SET_EADDR (NETARM_ETH_GEN_CTRL, + (NETARM_ETH_GCR_ERX | NETARM_ETH_GCR_ETX)); + + return (0); +} + + +extern int eth_init (bd_t * bd) +{ + reset_eth (); + return 0; +} + +extern void eth_halt (void) +{ + SET_EADDR (NETARM_ETH_GEN_CTRL, 0); +} + +/* Get a data block via Ethernet */ +extern int eth_rx (void) +{ + int i; + unsigned short rxlen; + unsigned int *addr; + unsigned int rxstatus, lastrxlen; + char *pa; + + /* RXBR is 1, data block was received */ + if ((GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXBR) == 0) + return 0; + + /* get status register and the length of received block */ + rxstatus = GET_EADDR (NETARM_ETH_RX_STAT); + rxlen = (rxstatus & NETARM_ETH_RXSTAT_SIZE) >> 16; + + if (rxlen == 0) + return 0; + + /* clear RXBR to make fifo available */ + SET_EADDR (NETARM_ETH_GEN_STAT, + GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_RXBR); + + /* clear TXBC to make fifo available */ + /* According to NETARM50 data manual you just have to clear + RXBR but that has no effect. Only after clearing TXBC the + Fifo becomes readable. */ + SET_EADDR (NETARM_ETH_GEN_STAT, + GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_TXBC); + + addr = (unsigned int *) NetRxPackets[0]; + pa = (char *) NetRxPackets[0]; + + /* read the fifo */ + for (i = 0; i < rxlen / 4; i++) { + *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1); + addr++; + } + + if (GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXREGR) { + /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */ + lastrxlen = + (GET_EADDR (NETARM_ETH_GEN_STAT) & + NETARM_ETH_GST_RXFDB) >> 28; + *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1); + switch (lastrxlen) { + case 1: + *addr &= 0xff000000; + break; + case 2: + *addr &= 0xffff0000; + break; + case 3: + *addr &= 0xffffff00; + break; + } + } + + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], rxlen); + + return rxlen; +} + +/* Send a data block via Ethernet. */ +extern int eth_send (volatile void *packet, int length) +{ + int i, length32; + char *pa; + unsigned int *pa32, lastp = 0, rest; + + pa = (char *) packet; + pa32 = (unsigned int *) packet; + length32 = length / 4; + rest = length % 4; + + /* make sure there's no garbage in the last word */ + switch (rest) { + case 0: + lastp = pa32[length32]; + length32--; + break; + case 1: + lastp = pa32[length32] & 0x000000ff; + break; + case 2: + lastp = pa32[length32] & 0x0000ffff; + break; + case 3: + lastp = pa32[length32] & 0x00ffffff; + break; + } + + /* write to the fifo */ + for (i = 0; i < length32; i++) + SET_EADDR (NETARM_ETH_FIFO_DAT1, pa32[i]); + + /* the last word is written to an extra register, this + starts the transmission */ + SET_EADDR (NETARM_ETH_FIFO_DAT2, lastp); + + /* NETARM_ETH_TXSTAT_TXOK should be checked, to know if the transmission + went fine. But we can't use the timer for a timeout loop because + of it is used already in upper layers. So we just try some times. */ + i = 0; + while (i < 50000) { + if ((GET_EADDR (NETARM_ETH_TX_STAT) & NETARM_ETH_TXSTAT_TXOK) + == NETARM_ETH_TXSTAT_TXOK) + return 0; + i++; + } + + printf ("eth_send timeout\n"); + return 1; +} + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_NETARMETH */ diff --git a/drivers/net/netarm_eth.h b/drivers/net/netarm_eth.h new file mode 100644 index 0000000000..8edab82da3 --- /dev/null +++ b/drivers/net/netarm_eth.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003 IMMS gGmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * author(s): Thomas Elste, + */ + +#include +#include + +#ifdef CONFIG_DRIVER_NETARMETH + +#define SET_EADDR(ad,val) *(volatile unsigned int*)(ad + NETARM_ETH_MODULE_BASE) = val +#define GET_EADDR(ad) (*(volatile unsigned int*)(ad + NETARM_ETH_MODULE_BASE)) + +#define NA_MII_POLL_BUSY_DELAY 900 + +/* MII negotiation timeout value + 500 jiffies = 5 seconds */ +#define NA_MII_NEGOTIATE_DELAY 30 + +/* Registers in the physical layer chip */ +#define MII_PHY_CONTROL 0 +#define MII_PHY_STATUS 1 +#define MII_PHY_ID 2 +#define MII_PHY_AUTONEGADV 4 + +#endif /* CONFIG_DRIVER_NETARMETH */ diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c new file mode 100644 index 0000000000..69089f92ce --- /dev/null +++ b/drivers/net/netconsole.c @@ -0,0 +1,267 @@ +/* + * (C) Copyright 2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#ifdef CONFIG_NETCONSOLE + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static char input_buffer[512]; +static int input_size = 0; /* char count in input buffer */ +static int input_offset = 0; /* offset to valid chars in input buffer */ +static int input_recursion = 0; +static int output_recursion = 0; +static int net_timeout; +static uchar nc_ether[6]; /* server enet address */ +static IPaddr_t nc_ip; /* server ip */ +static short nc_port; /* source/target port */ +static const char *output_packet; /* used by first send udp */ +static int output_packet_len = 0; + +static void nc_wait_arp_handler (uchar * pkt, unsigned dest, unsigned src, + unsigned len) +{ + NetState = NETLOOP_SUCCESS; /* got arp reply - quit net loop */ +} + +static void nc_handler (uchar * pkt, unsigned dest, unsigned src, + unsigned len) +{ + if (input_size) + NetState = NETLOOP_SUCCESS; /* got input - quit net loop */ +} + +static void nc_timeout (void) +{ + NetState = NETLOOP_SUCCESS; +} + +void NcStart (void) +{ + if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) { + /* going to check for input packet */ + NetSetHandler (nc_handler); + NetSetTimeout (net_timeout, nc_timeout); + } else { + /* send arp request */ + uchar *pkt; + NetSetHandler (nc_wait_arp_handler); + pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; + memcpy (pkt, output_packet, output_packet_len); + NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len); + } +} + +int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + int end, chunk; + + if (dest != nc_port || !len) + return 0; /* not for us */ + + if (input_size == sizeof input_buffer) + return 1; /* no space */ + if (len > sizeof input_buffer - input_size) + len = sizeof input_buffer - input_size; + + end = input_offset + input_size; + if (end > sizeof input_buffer) + end -= sizeof input_buffer; + + chunk = len; + if (end + len > sizeof input_buffer) { + chunk = sizeof input_buffer - end; + memcpy(input_buffer, pkt + chunk, len - chunk); + } + memcpy (input_buffer + end, pkt, chunk); + + input_size += len; + + return 1; +} + +static void nc_send_packet (const char *buf, int len) +{ + struct eth_device *eth; + int inited = 0; + uchar *pkt; + uchar *ether; + IPaddr_t ip; + + if ((eth = eth_get_dev ()) == NULL) { + return; + } + + if (!memcmp (nc_ether, NetEtherNullAddr, 6)) { + if (eth->state == ETH_STATE_ACTIVE) + return; /* inside net loop */ + output_packet = buf; + output_packet_len = len; + NetLoop (NETCONS); /* wait for arp reply and send packet */ + output_packet_len = 0; + return; + } + + if (eth->state != ETH_STATE_ACTIVE) { + if (eth_init (gd->bd) < 0) + return; + inited = 1; + } + pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; + memcpy (pkt, buf, len); + ether = nc_ether; + ip = nc_ip; + NetSendUDPPacket (ether, ip, nc_port, nc_port, len); + + if (inited) + eth_halt (); +} + +int nc_start (void) +{ + int netmask, our_ip; + + nc_port = 6666; /* default port */ + + if (getenv ("ncip")) { + char *p; + + nc_ip = getenv_IPaddr ("ncip"); + if (!nc_ip) + return -1; /* ncip is 0.0.0.0 */ + if ((p = strchr (getenv ("ncip"), ':')) != NULL) + nc_port = simple_strtoul (p + 1, NULL, 10); + } else + nc_ip = ~0; /* ncip is not set */ + + our_ip = getenv_IPaddr ("ipaddr"); + netmask = getenv_IPaddr ("netmask"); + + if (nc_ip == ~0 || /* 255.255.255.255 */ + ((netmask & our_ip) == (netmask & nc_ip) && /* on the same net */ + (netmask | nc_ip) == ~0)) /* broadcast to our net */ + memset (nc_ether, 0xff, sizeof nc_ether); + else + memset (nc_ether, 0, sizeof nc_ether); /* force arp request */ + + return 0; +} + +void nc_putc (char c) +{ + if (output_recursion) + return; + output_recursion = 1; + + nc_send_packet (&c, 1); + + output_recursion = 0; +} + +void nc_puts (const char *s) +{ + int len; + + if (output_recursion) + return; + output_recursion = 1; + + if ((len = strlen (s)) > 512) + len = 512; + + nc_send_packet (s, len); + + output_recursion = 0; +} + +int nc_getc (void) +{ + uchar c; + + input_recursion = 1; + + net_timeout = 0; /* no timeout */ + while (!input_size) + NetLoop (NETCONS); + + input_recursion = 0; + + c = input_buffer[input_offset++]; + + if (input_offset >= sizeof input_buffer) + input_offset -= sizeof input_buffer; + input_size--; + + return c; +} + +int nc_tstc (void) +{ + struct eth_device *eth; + + if (input_recursion) + return 0; + + if (input_size) + return 1; + + eth = eth_get_dev (); + if (eth && eth->state == ETH_STATE_ACTIVE) + return 0; /* inside net loop */ + + input_recursion = 1; + + net_timeout = 1; + NetLoop (NETCONS); /* kind of poll */ + + input_recursion = 0; + + return input_size != 0; +} + +int drv_nc_init (void) +{ + device_t dev; + int rc; + + memset (&dev, 0, sizeof (dev)); + + strcpy (dev.name, "nc"); + dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.start = nc_start; + dev.putc = nc_putc; + dev.puts = nc_puts; + dev.getc = nc_getc; + dev.tstc = nc_tstc; + + rc = device_register (&dev); + + return (rc == 0) ? 1 : rc; +} + +#endif /* CONFIG_NETCONSOLE */ diff --git a/drivers/net/nicext.h b/drivers/net/nicext.h new file mode 100644 index 0000000000..4074972c07 --- /dev/null +++ b/drivers/net/nicext.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright(c) 2000-2001 Broadcom Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * Name: nicext.h + * + * Description: Broadcom Network Interface Card Extension (NICE) is an + * extension to Linux NET device kernel mode drivers. + * NICE is designed to provide additional functionalities, + * such as receive packet intercept. To support Broadcom NICE, + * the network device driver can be modified by adding an + * device ioctl handler and by indicating receiving packets + * to the NICE receive handler. Broadcom NICE will only be + * enabled by a NICE-aware intermediate driver, such as + * Broadcom Advanced Server Program Driver (BASP). When NICE + * is not enabled, the modified network device drivers + * functions exactly as other non-NICE aware drivers. + * + * Author: Frankie Fan + * + * Created: September 17, 2000 + * + ****************************************************************************/ +#ifndef _nicext_h_ +#define _nicext_h_ + +/* + * ioctl for NICE + */ +#define SIOCNICE SIOCDEVPRIVATE+7 + +/* + * SIOCNICE: + * + * The following structure needs to be less than IFNAMSIZ (16 bytes) because + * we're overloading ifreq.ifr_ifru. + * + * If 16 bytes is not enough, we should consider relaxing this because + * this is no field after ifr_ifru in the ifreq structure. But we may + * run into future compatiability problem in case of changing struct ifreq. + */ +struct nice_req +{ + __u32 cmd; + + union + { +#ifdef __KERNEL__ + /* cmd = NICE_CMD_SET_RX or NICE_CMD_GET_RX */ + struct + { + void (*nrqus1_rx)( struct sk_buff*, void* ); + void* nrqus1_ctx; + } nrqu_nrqus1; + + /* cmd = NICE_CMD_QUERY_SUPPORT */ + struct + { + __u32 nrqus2_magic; + __u32 nrqus2_support_rx:1; + __u32 nrqus2_support_vlan:1; + __u32 nrqus2_support_get_speed:1; + } nrqu_nrqus2; +#endif + + /* cmd = NICE_CMD_GET_SPEED */ + struct + { + unsigned int nrqus3_speed; /* 0 if link is down, */ + /* otherwise speed in Mbps */ + } nrqu_nrqus3; + + /* cmd = NICE_CMD_BLINK_LED */ + struct + { + unsigned int nrqus4_blink_time; /* blink duration in seconds */ + } nrqu_nrqus4; + + } nrq_nrqu; +}; + +#define nrq_rx nrq_nrqu.nrqu_nrqus1.nrqus1_rx +#define nrq_ctx nrq_nrqu.nrqu_nrqus1.nrqus1_ctx +#define nrq_support_rx nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx +#define nrq_magic nrq_nrqu.nrqu_nrqus2.nrqus2_magic +#define nrq_support_vlan nrq_nrqu.nrqu_nrqus2.nrqus2_support_vlan +#define nrq_support_get_speed nrq_nrqu.nrqu_nrqus2.nrqus2_support_get_speed +#define nrq_speed nrq_nrqu.nrqu_nrqus3.nrqus3_speed +#define nrq_blink_time nrq_nrqu.nrqu_nrqus4.nrqus4_blink_time + +/* + * magic constants + */ +#define NICE_REQUESTOR_MAGIC 0x4543494E /* NICE in ascii */ +#define NICE_DEVICE_MAGIC 0x4E494345 /* ECIN in ascii */ + +/* + * command field + */ +#define NICE_CMD_QUERY_SUPPORT 0x00000001 +#define NICE_CMD_SET_RX 0x00000002 +#define NICE_CMD_GET_RX 0x00000003 +#define NICE_CMD_GET_SPEED 0x00000004 +#define NICE_CMD_BLINK_LED 0x00000005 + +#endif /* _nicext_h_ */ diff --git a/drivers/net/ns7520_eth.c b/drivers/net/ns7520_eth.c new file mode 100644 index 0000000000..a5a20dfd72 --- /dev/null +++ b/drivers/net/ns7520_eth.c @@ -0,0 +1,859 @@ +/*********************************************************************** + * + * Copyright (C) 2005 by Videon Central, Inc. + * + * $Id$ + * @Author: Arthur Shipkowski + * @Descr: Ethernet driver for the NS7520. Uses polled Ethernet, like + * the older netarmeth driver. Note that attempting to filter + * broadcast and multicast out in the SAFR register will cause + * bad things due to released errata. + * @References: [1] NS7520 Hardware Reference, December 2003 + * [2] Intel LXT971 Datasheet #249414 Rev. 02 + * + ***********************************************************************/ + +#include + +#if defined(CONFIG_DRIVER_NS7520_ETHERNET) + +#include /* NetSendPacket */ +#include +#include + +#include "ns7520_eth.h" /* for Ethernet and PHY */ + +/** + * Send an error message to the terminal. + */ +#define ERROR(x) \ +do { \ + char *__foo = strrchr(__FILE__, '/'); \ + \ + printf("%s: %d: %s(): ", (__foo == NULL ? __FILE__ : (__foo + 1)), \ + __LINE__, __FUNCTION__); \ + printf x; printf("\n"); \ +} while (0); + +/* some definition to make transistion to linux easier */ + +#define NS7520_DRIVER_NAME "eth" +#define KERN_WARNING "Warning:" +#define KERN_ERR "Error:" +#define KERN_INFO "Info:" + +#if 1 +# define DEBUG +#endif + +#ifdef DEBUG +# define printk printf + +# define DEBUG_INIT 0x0001 +# define DEBUG_MINOR 0x0002 +# define DEBUG_RX 0x0004 +# define DEBUG_TX 0x0008 +# define DEBUG_INT 0x0010 +# define DEBUG_POLL 0x0020 +# define DEBUG_LINK 0x0040 +# define DEBUG_MII 0x0100 +# define DEBUG_MII_LOW 0x0200 +# define DEBUG_MEM 0x0400 +# define DEBUG_ERROR 0x4000 +# define DEBUG_ERROR_CRIT 0x8000 + +static int nDebugLvl = DEBUG_ERROR_CRIT; + +# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \ + printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \ + printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\ + printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\ + printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0) +# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \ + printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0); +# define ASSERT( expr, func ) if( !( expr ) ) { \ + printf( "Assertion failed! %s:line %d %s\n", \ + (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \ + func } +#else /* DEBUG */ +# define printk(...) +# define DEBUG_ARGS0( FLG, a0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) +# define DEBUG_FN( n ) +# define ASSERT(expr, func) +#endif /* DEBUG */ + +#define NS7520_MII_NEG_DELAY (5*CFG_HZ) /* in s */ +#define TX_TIMEOUT (5*CFG_HZ) /* in s */ +#define RX_STALL_WORKAROUND_CNT 100 + +static int ns7520_eth_reset(void); + +static void ns7520_link_auto_negotiate(void); +static void ns7520_link_update_egcr(void); +static void ns7520_link_print_changed(void); + +/* the PHY stuff */ + +static char ns7520_mii_identify_phy(void); +static unsigned short ns7520_mii_read(unsigned short uiRegister); +static void ns7520_mii_write(unsigned short uiRegister, + unsigned short uiData); +static unsigned int ns7520_mii_get_clock_divisor(unsigned int + unMaxMDIOClk); +static unsigned int ns7520_mii_poll_busy(void); + +static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; +static unsigned int uiLastLinkStatus; +static PhyType phyDetected = PHY_NONE; + +/*********************************************************************** + * @Function: eth_init + * @Return: -1 on failure otherwise 0 + * @Descr: Initializes the ethernet engine and uses either FS Forth's default + * MAC addr or the one in environment + ***********************************************************************/ + +int eth_init(bd_t * pbis) +{ + unsigned char aucMACAddr[6]; + char *pcTmp = getenv("ethaddr"); + char *pcEnd; + int i; + + DEBUG_FN(DEBUG_INIT); + + /* no need to check for hardware */ + + if (!ns7520_eth_reset()) + return -1; + + if (NULL == pcTmp) + return -1; + + for (i = 0; i < 6; i++) { + aucMACAddr[i] = + pcTmp ? simple_strtoul(pcTmp, &pcEnd, 16) : 0; + pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd; + } + + /* configure ethernet address */ + + *get_eth_reg_addr(NS7520_ETH_SA1) = + aucMACAddr[5] << 8 | aucMACAddr[4]; + *get_eth_reg_addr(NS7520_ETH_SA2) = + aucMACAddr[3] << 8 | aucMACAddr[2]; + *get_eth_reg_addr(NS7520_ETH_SA3) = + aucMACAddr[1] << 8 | aucMACAddr[0]; + + /* enable hardware */ + + *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN; + *get_eth_reg_addr(NS7520_ETH_SUPP) = NS7520_ETH_SUPP_JABBER; + *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN; + + /* the linux kernel may give packets < 60 bytes, for example arp */ + *get_eth_reg_addr(NS7520_ETH_MAC2) = NS7520_ETH_MAC2_CRCEN | + NS7520_ETH_MAC2_PADEN | NS7520_ETH_MAC2_HUGE; + + /* Broadcast/multicast allowed; if you don't set this even unicast chokes */ + /* Based on NS7520 errata documentation */ + *get_eth_reg_addr(NS7520_ETH_SAFR) = + NS7520_ETH_SAFR_BROAD | NS7520_ETH_SAFR_PRM; + + /* enable receive and transmit FIFO, use 10/100 Mbps MII */ + *get_eth_reg_addr(NS7520_ETH_EGCR) |= + NS7520_ETH_EGCR_ETXWM_75 | + NS7520_ETH_EGCR_ERX | + NS7520_ETH_EGCR_ERXREG | + NS7520_ETH_EGCR_ERXBR | NS7520_ETH_EGCR_ETX; + + return 0; +} + +/*********************************************************************** + * @Function: eth_send + * @Return: -1 on timeout otherwise 1 + * @Descr: sends one frame by DMA + ***********************************************************************/ + +int eth_send(volatile void *pPacket, int nLen) +{ + int i, length32, retval = 1; + char *pa; + unsigned int *pa32, lastp = 0, rest; + unsigned int status; + + pa = (char *) pPacket; + pa32 = (unsigned int *) pPacket; + length32 = nLen / 4; + rest = nLen % 4; + + /* make sure there's no garbage in the last word */ + switch (rest) { + case 0: + lastp = pa32[length32 - 1]; + length32--; + break; + case 1: + lastp = pa32[length32] & 0x000000ff; + break; + case 2: + lastp = pa32[length32] & 0x0000ffff; + break; + case 3: + lastp = pa32[length32] & 0x00ffffff; + break; + } + + while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) & + NS7520_ETH_EGSR_TXREGE) + == 0) { + } + + /* write to the fifo */ + for (i = 0; i < length32; i++) + *get_eth_reg_addr(NS7520_ETH_FIFO) = pa32[i]; + + /* the last word is written to an extra register, this + starts the transmission */ + *get_eth_reg_addr(NS7520_ETH_FIFOL) = lastp; + + /* Wait for it to be done */ + while ((*get_eth_reg_addr(NS7520_ETH_EGSR) & NS7520_ETH_EGSR_TXBC) + == 0) { + } + status = (*get_eth_reg_addr(NS7520_ETH_ETSR)); + *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_TXBC; /* Clear it now */ + + if (status & NS7520_ETH_ETSR_TXOK) { + retval = 0; /* We're OK! */ + } else if (status & NS7520_ETH_ETSR_TXDEF) { + printf("Deferred, we'll see.\n"); + retval = 0; + } else if (status & NS7520_ETH_ETSR_TXAL) { + printf("Late collision error, %d collisions.\n", + (*get_eth_reg_addr(NS7520_ETH_ETSR)) & + NS7520_ETH_ETSR_TXCOLC); + } else if (status & NS7520_ETH_ETSR_TXAEC) { + printf("Excessive collisions: %d\n", + (*get_eth_reg_addr(NS7520_ETH_ETSR)) & + NS7520_ETH_ETSR_TXCOLC); + } else if (status & NS7520_ETH_ETSR_TXAED) { + printf("Excessive deferral on xmit.\n"); + } else if (status & NS7520_ETH_ETSR_TXAUR) { + printf("Packet underrun.\n"); + } else if (status & NS7520_ETH_ETSR_TXAJ) { + printf("Jumbo packet error.\n"); + } else { + printf("Error: Should never get here.\n"); + } + + return (retval); +} + +/*********************************************************************** + * @Function: eth_rx + * @Return: size of last frame in bytes or 0 if no frame available + * @Descr: gives one frame to U-Boot which has been copied by DMA engine already + * to NetRxPackets[ 0 ]. + ***********************************************************************/ + +int eth_rx(void) +{ + int i; + unsigned short rxlen; + unsigned short totrxlen = 0; + unsigned int *addr; + unsigned int rxstatus, lastrxlen; + char *pa; + + /* If RXBR is 1, data block was received */ + while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) & + NS7520_ETH_EGSR_RXBR) == NS7520_ETH_EGSR_RXBR) { + + /* get status register and the length of received block */ + rxstatus = *get_eth_reg_addr(NS7520_ETH_ERSR); + rxlen = (rxstatus & NS7520_ETH_ERSR_RXSIZE) >> 16; + + /* clear RXBR to make fifo available */ + *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_RXBR; + + if (rxstatus & NS7520_ETH_ERSR_ROVER) { + printf("Receive overrun, resetting FIFO.\n"); + *get_eth_reg_addr(NS7520_ETH_EGCR) &= + ~NS7520_ETH_EGCR_ERX; + udelay(20); + *get_eth_reg_addr(NS7520_ETH_EGCR) |= + NS7520_ETH_EGCR_ERX; + } + if (rxlen == 0) { + printf("Nothing.\n"); + return 0; + } + + addr = (unsigned int *) NetRxPackets[0]; + pa = (char *) NetRxPackets[0]; + + /* read the fifo */ + for (i = 0; i < rxlen / 4; i++) { + *addr = *get_eth_reg_addr(NS7520_ETH_FIFO); + addr++; + } + + if ((*get_eth_reg_addr(NS7520_ETH_EGSR)) & + NS7520_ETH_EGSR_RXREGR) { + /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */ + lastrxlen = + ((*get_eth_reg_addr(NS7520_ETH_EGSR)) & + NS7520_ETH_EGSR_RXFDB_MA) >> 28; + *addr = *get_eth_reg_addr(NS7520_ETH_FIFO); + switch (lastrxlen) { + case 1: + *addr &= 0xff000000; + break; + case 2: + *addr &= 0xffff0000; + break; + case 3: + *addr &= 0xffffff00; + break; + } + } + + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[0], rxlen - 4); + totrxlen += rxlen - 4; + } + + return totrxlen; +} + +/*********************************************************************** + * @Function: eth_halt + * @Return: n/a + * @Descr: stops the ethernet engine + ***********************************************************************/ + +void eth_halt(void) +{ + DEBUG_FN(DEBUG_INIT); + + *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_RXEN; + *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~(NS7520_ETH_EGCR_ERX | + NS7520_ETH_EGCR_ERXDMA | + NS7520_ETH_EGCR_ERXREG | + NS7520_ETH_EGCR_ERXBR | + NS7520_ETH_EGCR_ETX | + NS7520_ETH_EGCR_ETXDMA); +} + +/*********************************************************************** + * @Function: ns7520_eth_reset + * @Return: 0 on failure otherwise 1 + * @Descr: resets the ethernet interface and the PHY, + * performs auto negotiation or fixed modes + ***********************************************************************/ + +static int ns7520_eth_reset(void) +{ + DEBUG_FN(DEBUG_MINOR); + + /* Reset important registers */ + *get_eth_reg_addr(NS7520_ETH_EGCR) = 0; /* Null it out! */ + *get_eth_reg_addr(NS7520_ETH_MAC1) &= NS7520_ETH_MAC1_SRST; + *get_eth_reg_addr(NS7520_ETH_MAC2) = 0; + /* Reset MAC */ + *get_eth_reg_addr(NS7520_ETH_EGCR) |= NS7520_ETH_EGCR_MAC_RES; + udelay(5); + *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~NS7520_ETH_EGCR_MAC_RES; + + /* reset and initialize PHY */ + + *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_SRST; + + /* we don't support hot plugging of PHY, therefore we don't reset + phyDetected and nPhyMaxMdioClock here. The risk is if the setting is + incorrect the first open + may detect the PHY correctly but succeding will fail + For reseting the PHY and identifying we have to use the standard + MDIO CLOCK value 2.5 MHz only after hardware reset + After having identified the PHY we will do faster */ + + *get_eth_reg_addr(NS7520_ETH_MCFG) = + ns7520_mii_get_clock_divisor(nPhyMaxMdioClock); + + /* reset PHY */ + ns7520_mii_write(PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET); + ns7520_mii_write(PHY_COMMON_CTRL, 0); + + udelay(3000); /* [2] p.70 says at least 300us reset recovery time. */ + + /* MII clock has been setup to default, ns7520_mii_identify_phy should + work for all */ + + if (!ns7520_mii_identify_phy()) { + printk(KERN_ERR NS7520_DRIVER_NAME + ": Unsupported PHY, aborting\n"); + return 0; + } + + /* now take the highest MDIO clock possible after detection */ + *get_eth_reg_addr(NS7520_ETH_MCFG) = + ns7520_mii_get_clock_divisor(nPhyMaxMdioClock); + + /* PHY has been detected, so there can be no abort reason and we can + finish initializing ethernet */ + + uiLastLinkStatus = 0xff; /* undefined */ + + ns7520_link_auto_negotiate(); + + if (phyDetected == PHY_LXT971A) + /* set LED2 to link mode */ + ns7520_mii_write(PHY_LXT971_LED_CFG, + (PHY_LXT971_LED_CFG_LINK_ACT << + PHY_LXT971_LED_CFG_SHIFT_LED2) | + (PHY_LXT971_LED_CFG_TRANSMIT << + PHY_LXT971_LED_CFG_SHIFT_LED1)); + + return 1; +} + +/*********************************************************************** + * @Function: ns7520_link_auto_negotiate + * @Return: void + * @Descr: performs auto-negotation of link. + ***********************************************************************/ + +static void ns7520_link_auto_negotiate(void) +{ + unsigned long ulStartJiffies; + unsigned short uiStatus; + + DEBUG_FN(DEBUG_LINK); + + /* run auto-negotation */ + /* define what we are capable of */ + ns7520_mii_write(PHY_COMMON_AUTO_ADV, + PHY_COMMON_AUTO_ADV_100BTXFD | + PHY_COMMON_AUTO_ADV_100BTX | + PHY_COMMON_AUTO_ADV_10BTFD | + PHY_COMMON_AUTO_ADV_10BT | + PHY_COMMON_AUTO_ADV_802_3); + /* start auto-negotiation */ + ns7520_mii_write(PHY_COMMON_CTRL, + PHY_COMMON_CTRL_AUTO_NEG | + PHY_COMMON_CTRL_RES_AUTO); + + /* wait for completion */ + + ulStartJiffies = get_timer(0); + while (get_timer(0) < ulStartJiffies + NS7520_MII_NEG_DELAY) { + uiStatus = ns7520_mii_read(PHY_COMMON_STAT); + if ((uiStatus & + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) + == + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) { + /* lucky we are, auto-negotiation succeeded */ + ns7520_link_print_changed(); + ns7520_link_update_egcr(); + return; + } + } + + DEBUG_ARGS0(DEBUG_LINK, "auto-negotiation timed out\n"); + /* ignore invalid link settings */ +} + +/*********************************************************************** + * @Function: ns7520_link_update_egcr + * @Return: void + * @Descr: updates the EGCR and MAC2 link status after mode change or + * auto-negotation + ***********************************************************************/ + +static void ns7520_link_update_egcr(void) +{ + unsigned int unEGCR; + unsigned int unMAC2; + unsigned int unIPGT; + + DEBUG_FN(DEBUG_LINK); + + unEGCR = *get_eth_reg_addr(NS7520_ETH_EGCR); + unMAC2 = *get_eth_reg_addr(NS7520_ETH_MAC2); + unIPGT = + *get_eth_reg_addr(NS7520_ETH_IPGT) & ~NS7520_ETH_IPGT_IPGT; + + unEGCR &= ~NS7520_ETH_EGCR_EFULLD; + unMAC2 &= ~NS7520_ETH_MAC2_FULLD; + if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE) + == PHY_LXT971_STAT2_DUPLEX_MODE) { + unEGCR |= NS7520_ETH_EGCR_EFULLD; + unMAC2 |= NS7520_ETH_MAC2_FULLD; + unIPGT |= 0x15; /* see [1] p. 167 */ + } else + unIPGT |= 0x12; /* see [1] p. 167 */ + + *get_eth_reg_addr(NS7520_ETH_MAC2) = unMAC2; + *get_eth_reg_addr(NS7520_ETH_EGCR) = unEGCR; + *get_eth_reg_addr(NS7520_ETH_IPGT) = unIPGT; +} + +/*********************************************************************** + * @Function: ns7520_link_print_changed + * @Return: void + * @Descr: checks whether the link status has changed and if so prints + * the new mode + ***********************************************************************/ + +static void ns7520_link_print_changed(void) +{ + unsigned short uiStatus; + unsigned short uiControl; + + DEBUG_FN(DEBUG_LINK); + + uiControl = ns7520_mii_read(PHY_COMMON_CTRL); + + if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == + PHY_COMMON_CTRL_AUTO_NEG) { + /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */ + uiStatus = ns7520_mii_read(PHY_COMMON_STAT); + + if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) { + printk(KERN_WARNING NS7520_DRIVER_NAME + ": link down\n"); + /* @TODO Linux: carrier_off */ + } else { + /* @TODO Linux: carrier_on */ + if (phyDetected == PHY_LXT971A) { + uiStatus = + ns7520_mii_read(PHY_LXT971_STAT2); + uiStatus &= + (PHY_LXT971_STAT2_100BTX | + PHY_LXT971_STAT2_DUPLEX_MODE | + PHY_LXT971_STAT2_AUTO_NEG); + + /* mask out all uninteresting parts */ + } + /* other PHYs must store there link information in + uiStatus as PHY_LXT971 */ + } + } else { + /* mode has been forced, so uiStatus should be the same as the + last link status, enforce printing */ + uiStatus = uiLastLinkStatus; + uiLastLinkStatus = 0xff; + } + + if (uiStatus != uiLastLinkStatus) { + /* save current link status */ + uiLastLinkStatus = uiStatus; + + /* print new link status */ + + printk(KERN_INFO NS7520_DRIVER_NAME + ": link mode %i Mbps %s duplex %s\n", + (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10, + (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" : + "half", + (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" : + ""); + } +} + +/*********************************************************************** + * the MII low level stuff + ***********************************************************************/ + +/*********************************************************************** + * @Function: ns7520_mii_identify_phy + * @Return: 1 if supported PHY has been detected otherwise 0 + * @Descr: checks for supported PHY and prints the IDs. + ***********************************************************************/ + +static char ns7520_mii_identify_phy(void) +{ + unsigned short uiID1; + unsigned short uiID2; + unsigned char *szName; + char cRes = 0; + + DEBUG_FN(DEBUG_MII); + + phyDetected = (PhyType) uiID1 = ns7520_mii_read(PHY_COMMON_ID1); + + switch (phyDetected) { + case PHY_LXT971A: + szName = "LXT971A"; + uiID2 = ns7520_mii_read(PHY_COMMON_ID2); + nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK; + cRes = 1; + break; + case PHY_NONE: + default: + /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong + address or reset sets the wrong NS7520_ETH_MCFG_CLKS */ + + uiID2 = 0; + szName = "unknown"; + nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; + phyDetected = PHY_NONE; + } + + printk(KERN_INFO NS7520_DRIVER_NAME + ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName); + + return cRes; +} + +/*********************************************************************** + * @Function: ns7520_mii_read + * @Return: the data read from PHY register uiRegister + * @Descr: the data read may be invalid if timed out. If so, a message + * is printed but the invalid data is returned. + * The fixed device address is being used. + ***********************************************************************/ + +static unsigned short ns7520_mii_read(unsigned short uiRegister) +{ + DEBUG_FN(DEBUG_MII_LOW); + + /* write MII register to be read */ + *get_eth_reg_addr(NS7520_ETH_MADR) = + CONFIG_PHY_ADDR << 8 | uiRegister; + + *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ; + + if (!ns7520_mii_poll_busy()) + printk(KERN_WARNING NS7520_DRIVER_NAME + ": MII still busy in read\n"); + /* continue to read */ + + *get_eth_reg_addr(NS7520_ETH_MCMD) = 0; + + return (unsigned short) (*get_eth_reg_addr(NS7520_ETH_MRDD)); +} + +/*********************************************************************** + * @Function: ns7520_mii_write + * @Return: nothing + * @Descr: writes the data to the PHY register. In case of a timeout, + * no special handling is performed but a message printed + * The fixed device address is being used. + ***********************************************************************/ + +static void ns7520_mii_write(unsigned short uiRegister, + unsigned short uiData) +{ + DEBUG_FN(DEBUG_MII_LOW); + + /* write MII register to be written */ + *get_eth_reg_addr(NS7520_ETH_MADR) = + CONFIG_PHY_ADDR << 8 | uiRegister; + + *get_eth_reg_addr(NS7520_ETH_MWTD) = uiData; + + if (!ns7520_mii_poll_busy()) { + printf(KERN_WARNING NS7520_DRIVER_NAME + ": MII still busy in write\n"); + } +} + +/*********************************************************************** + * @Function: ns7520_mii_get_clock_divisor + * @Return: the clock divisor that should be used in NS7520_ETH_MCFG_CLKS + * @Descr: if no clock divisor can be calculated for the + * current SYSCLK and the maximum MDIO Clock, a warning is printed + * and the greatest divisor is taken + ***********************************************************************/ + +static unsigned int ns7520_mii_get_clock_divisor(unsigned int unMaxMDIOClk) +{ + struct { + unsigned int unSysClkDivisor; + unsigned int unClks; /* field for NS7520_ETH_MCFG_CLKS */ + } PHYClockDivisors[] = { + { + 4, NS7520_ETH_MCFG_CLKS_4}, { + 6, NS7520_ETH_MCFG_CLKS_6}, { + 8, NS7520_ETH_MCFG_CLKS_8}, { + 10, NS7520_ETH_MCFG_CLKS_10}, { + 14, NS7520_ETH_MCFG_CLKS_14}, { + 20, NS7520_ETH_MCFG_CLKS_20}, { + 28, NS7520_ETH_MCFG_CLKS_28} + }; + + int nIndexSysClkDiv; + int nArraySize = + sizeof(PHYClockDivisors) / sizeof(PHYClockDivisors[0]); + unsigned int unClks = NS7520_ETH_MCFG_CLKS_28; /* defaults to + greatest div */ + + DEBUG_FN(DEBUG_INIT); + + for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize; + nIndexSysClkDiv++) { + /* find first sysclock divisor that isn't higher than 2.5 MHz + clock */ + if (NETARM_XTAL_FREQ / + PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <= + unMaxMDIOClk) { + unClks = PHYClockDivisors[nIndexSysClkDiv].unClks; + break; + } + } + + DEBUG_ARGS2(DEBUG_INIT, + "Taking MDIO Clock bit mask 0x%0x for max clock %i\n", + unClks, unMaxMDIOClk); + + /* return greatest divisor */ + return unClks; +} + +/*********************************************************************** + * @Function: ns7520_mii_poll_busy + * @Return: 0 if timed out otherwise the remaing timeout + * @Descr: waits until the MII has completed a command or it times out + * code may be interrupted by hard interrupts. + * It is not checked what happens on multiple actions when + * the first is still being busy and we timeout. + ***********************************************************************/ + +static unsigned int ns7520_mii_poll_busy(void) +{ + unsigned int unTimeout = 1000; + + DEBUG_FN(DEBUG_MII_LOW); + + while (((*get_eth_reg_addr(NS7520_ETH_MIND) & NS7520_ETH_MIND_BUSY) + == NS7520_ETH_MIND_BUSY) && unTimeout) + unTimeout--; + + return unTimeout; +} + +/* ---------------------------------------------------------------------------- + * Net+ARM ethernet MII functionality. + */ +#if defined(CONFIG_MII) + +/** + * Maximum MII address we support + */ +#define MII_ADDRESS_MAX (31) + +/** + * Maximum MII register address we support + */ +#define MII_REGISTER_MAX (31) + +/** + * Ethernet MII interface return values for public functions. + */ +enum mii_status { + MII_STATUS_SUCCESS = 0, + MII_STATUS_FAILURE = 1, +}; + +/** + * Read a 16-bit value from an MII register. + */ +extern int ns7520_miiphy_read(char *devname, unsigned char const addr, + unsigned char const reg, unsigned short *const value) +{ + int ret = MII_STATUS_FAILURE; + + /* Parameter checks */ + if (addr > MII_ADDRESS_MAX) { + ERROR(("invalid addr, 0x%02X", addr)); + goto miiphy_read_failed_0; + } + + if (reg > MII_REGISTER_MAX) { + ERROR(("invalid reg, 0x%02X", reg)); + goto miiphy_read_failed_0; + } + + if (value == NULL) { + ERROR(("NULL value")); + goto miiphy_read_failed_0; + } + + DEBUG_FN(DEBUG_MII_LOW); + + /* write MII register to be read */ + *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg; + + *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ; + + if (!ns7520_mii_poll_busy()) + printk(KERN_WARNING NS7520_DRIVER_NAME + ": MII still busy in read\n"); + /* continue to read */ + + *get_eth_reg_addr(NS7520_ETH_MCMD) = 0; + + *value = (*get_eth_reg_addr(NS7520_ETH_MRDD)); + ret = MII_STATUS_SUCCESS; + /* Fall through */ + + miiphy_read_failed_0: + return (ret); +} + +/** + * Write a 16-bit value to an MII register. + */ +extern int ns7520_miiphy_write(char *devname, unsigned char const addr, + unsigned char const reg, unsigned short const value) +{ + int ret = MII_STATUS_FAILURE; + + /* Parameter checks */ + if (addr > MII_ADDRESS_MAX) { + ERROR(("invalid addr, 0x%02X", addr)); + goto miiphy_write_failed_0; + } + + if (reg > MII_REGISTER_MAX) { + ERROR(("invalid reg, 0x%02X", reg)); + goto miiphy_write_failed_0; + } + + /* write MII register to be written */ + *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg; + + *get_eth_reg_addr(NS7520_ETH_MWTD) = value; + + if (!ns7520_mii_poll_busy()) { + printf(KERN_WARNING NS7520_DRIVER_NAME + ": MII still busy in write\n"); + } + + ret = MII_STATUS_SUCCESS; + /* Fall through */ + + miiphy_write_failed_0: + return (ret); +} +#endif /* defined(CONFIG_MII) */ +#endif /* CONFIG_DRIVER_NS7520_ETHERNET */ + +int ns7520_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_DRIVER_NS7520_ETHERNET) +#if defined(CONFIG_MII) + miiphy_register("ns7520phy", ns7520_miiphy_read, ns7520_miiphy_write); +#endif +#endif + return 0; +} diff --git a/drivers/net/ns8382x.c b/drivers/net/ns8382x.c new file mode 100644 index 0000000000..f8b143a01a --- /dev/null +++ b/drivers/net/ns8382x.c @@ -0,0 +1,863 @@ +/* + ns8382x.c: A U-Boot driver for the NatSemi DP8382[01]. + ported by: Mark A. Rakes (mark_rakes@vivato.net) + + Adapted from: + 1. an Etherboot driver for DP8381[56] written by: + Copyright (C) 2001 Entity Cyber, Inc. + + This development of this Etherboot driver was funded by + Sicom Systems: http://www.sicompos.com/ + + Author: Marty Connor (mdc@thinguin.org) + Adapted from a Linux driver which was written by Donald Becker + + This software may be used and distributed according to the terms + of the GNU Public License (GPL), incorporated herein by reference. + + 2. A Linux driver by Donald Becker, ns820.c: + Written/copyright 1999-2002 by Donald Becker. + + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. License for under other terms may be + available. Contact the original author for details. + + The original author may be reached as becker@scyld.com, or at + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 + + Support information and updates available at + http://www.scyld.com/network/netsemi.html + + Datasheets available from: + http://www.national.com/pf/DP/DP83820.html + http://www.national.com/pf/DP/DP83821.html +*/ + +/* Revision History + * October 2002 mar 1.0 + * Initial U-Boot Release. + * Tested with Netgear GA622T (83820) + * and SMC9452TX (83821) + * NOTE: custom boards with these chips may (likely) require + * a programmed EEPROM device (if present) in order to work + * correctly. +*/ + +/* Includes */ +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_NS8382X) + +/* defines */ +#define DSIZE 0x00000FFF +#define ETH_ALEN 6 +#define CRC_SIZE 4 +#define TOUT_LOOP 500000 +#define TX_BUF_SIZE 1536 +#define RX_BUF_SIZE 1536 +#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ + +enum register_offsets { + ChipCmd = 0x00, + ChipConfig = 0x04, + EECtrl = 0x08, + IntrMask = 0x14, + IntrEnable = 0x18, + TxRingPtr = 0x20, + TxRingPtrHi = 0x24, + TxConfig = 0x28, + RxRingPtr = 0x30, + RxRingPtrHi = 0x34, + RxConfig = 0x38, + PriQueue = 0x3C, + RxFilterAddr = 0x48, + RxFilterData = 0x4C, + ClkRun = 0xCC, + PCIPM = 0x44, +}; + +enum ChipCmdBits { + ChipReset = 0x100, + RxReset = 0x20, + TxReset = 0x10, + RxOff = 0x08, + RxOn = 0x04, + TxOff = 0x02, + TxOn = 0x01 +}; + +enum ChipConfigBits { + LinkSts = 0x80000000, + GigSpeed = 0x40000000, + HundSpeed = 0x20000000, + FullDuplex = 0x10000000, + TBIEn = 0x01000000, + Mode1000 = 0x00400000, + T64En = 0x00004000, + D64En = 0x00001000, + M64En = 0x00000800, + PhyRst = 0x00000400, + PhyDis = 0x00000200, + ExtStEn = 0x00000100, + BEMode = 0x00000001, +}; +#define SpeedStatus_Polarity ( GigSpeed | HundSpeed | FullDuplex) + +enum TxConfig_bits { + TxDrthMask = 0x000000ff, + TxFlthMask = 0x0000ff00, + TxMxdmaMask = 0x00700000, + TxMxdma_8 = 0x00100000, + TxMxdma_16 = 0x00200000, + TxMxdma_32 = 0x00300000, + TxMxdma_64 = 0x00400000, + TxMxdma_128 = 0x00500000, + TxMxdma_256 = 0x00600000, + TxMxdma_512 = 0x00700000, + TxMxdma_1024 = 0x00000000, + TxCollRetry = 0x00800000, + TxAutoPad = 0x10000000, + TxMacLoop = 0x20000000, + TxHeartIgn = 0x40000000, + TxCarrierIgn = 0x80000000 +}; + +enum RxConfig_bits { + RxDrthMask = 0x0000003e, + RxMxdmaMask = 0x00700000, + RxMxdma_8 = 0x00100000, + RxMxdma_16 = 0x00200000, + RxMxdma_32 = 0x00300000, + RxMxdma_64 = 0x00400000, + RxMxdma_128 = 0x00500000, + RxMxdma_256 = 0x00600000, + RxMxdma_512 = 0x00700000, + RxMxdma_1024 = 0x00000000, + RxAcceptLenErr = 0x04000000, + RxAcceptLong = 0x08000000, + RxAcceptTx = 0x10000000, + RxStripCRC = 0x20000000, + RxAcceptRunt = 0x40000000, + RxAcceptErr = 0x80000000, +}; + +/* Bits in the RxMode register. */ +enum rx_mode_bits { + RxFilterEnable = 0x80000000, + AcceptAllBroadcast = 0x40000000, + AcceptAllMulticast = 0x20000000, + AcceptAllUnicast = 0x10000000, + AcceptPerfectMatch = 0x08000000, +}; + +typedef struct _BufferDesc { + u32 link; + u32 bufptr; + vu_long cmdsts; + u32 extsts; /*not used here */ +} BufferDesc; + +/* Bits in network_desc.status */ +enum desc_status_bits { + DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, + DescNoCRC = 0x10000000, DescPktOK = 0x08000000, + DescSizeMask = 0xfff, + + DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000, + DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000, + DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000, + DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000, + + DescRxAbort = 0x04000000, DescRxOver = 0x02000000, + DescRxDest = 0x01800000, DescRxLong = 0x00400000, + DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000, + DescRxCRC = 0x00080000, DescRxAlign = 0x00040000, + DescRxLoop = 0x00020000, DesRxColl = 0x00010000, +}; + +/* Bits in MEAR */ +enum mii_reg_bits { + MDIO_ShiftClk = 0x0040, + MDIO_EnbOutput = 0x0020, + MDIO_Data = 0x0010, +}; + +/* PHY Register offsets. */ +enum phy_reg_offsets { + BMCR = 0x00, + BMSR = 0x01, + PHYIDR1 = 0x02, + PHYIDR2 = 0x03, + ANAR = 0x04, + KTCR = 0x09, +}; + +/* basic mode control register bits */ +enum bmcr_bits { + Bmcr_Reset = 0x8000, + Bmcr_Loop = 0x4000, + Bmcr_Speed0 = 0x2000, + Bmcr_AutoNegEn = 0x1000, /*if set ignores Duplex, Speed[01] */ + Bmcr_RstAutoNeg = 0x0200, + Bmcr_Duplex = 0x0100, + Bmcr_Speed1 = 0x0040, + Bmcr_Force10H = 0x0000, + Bmcr_Force10F = 0x0100, + Bmcr_Force100H = 0x2000, + Bmcr_Force100F = 0x2100, + Bmcr_Force1000H = 0x0040, + Bmcr_Force1000F = 0x0140, +}; + +/* auto negotiation advertisement register */ +enum anar_bits { + anar_adv_100F = 0x0100, + anar_adv_100H = 0x0080, + anar_adv_10F = 0x0040, + anar_adv_10H = 0x0020, + anar_ieee_8023 = 0x0001, +}; + +/* 1K-base T control register */ +enum ktcr_bits { + ktcr_adv_1000H = 0x0100, + ktcr_adv_1000F = 0x0200, +}; + +/* Globals */ +static u32 SavedClkRun; +static unsigned int cur_rx; +static unsigned int rx_config; +static unsigned int tx_config; + +/* Note: transmit and receive buffers and descriptors must be + long long word aligned */ +static BufferDesc txd __attribute__ ((aligned(8))); +static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(8))); +static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(8))); +static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] + __attribute__ ((aligned(8))); + +/* Function Prototypes */ +static int mdio_read(struct eth_device *dev, int phy_id, int addr); +static void mdio_write(struct eth_device *dev, int phy_id, int addr, int value); +static void mdio_sync(struct eth_device *dev, u32 offset); +static int ns8382x_init(struct eth_device *dev, bd_t * bis); +static void ns8382x_reset(struct eth_device *dev); +static void ns8382x_init_rxfilter(struct eth_device *dev); +static void ns8382x_init_txd(struct eth_device *dev); +static void ns8382x_init_rxd(struct eth_device *dev); +static void ns8382x_set_rx_mode(struct eth_device *dev); +static void ns8382x_check_duplex(struct eth_device *dev); +static int ns8382x_send(struct eth_device *dev, volatile void *packet, + int length); +static int ns8382x_poll(struct eth_device *dev); +static void ns8382x_disable(struct eth_device *dev); + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83820}, + {} +}; + +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) + +static inline int +INW(struct eth_device *dev, u_long addr) +{ + return le16_to_cpu(*(vu_short *) (addr + dev->iobase)); +} + +static int +INL(struct eth_device *dev, u_long addr) +{ + return le32_to_cpu(*(vu_long *) (addr + dev->iobase)); +} + +static inline void +OUTW(struct eth_device *dev, int command, u_long addr) +{ + *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command); +} + +static inline void +OUTL(struct eth_device *dev, int command, u_long addr) +{ + *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command); +} + +/* Function: ns8382x_initialize + * Description: Retrieves the MAC address of the card, and sets up some + * globals required by other routines, and initializes the NIC, making it + * ready to send and receive packets. + * Side effects: initializes ns8382xs, ready to recieve packets. + * Returns: int: number of cards found + */ + +int +ns8382x_initialize(bd_t * bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase, status; + int i, idx = 0; + u32 phyAddress; + u32 tmp; + u32 chip_config; + + while (1) { /* Find PCI device(s) */ + if ((devno = pci_find_devices(supported, idx++)) < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0x3; /* 1: unused and 0:I/O Space Indicator */ + +#ifdef NS8382X_DEBUG + printf("ns8382x: NatSemi dp8382x @ 0x%x\n", iobase); +#endif + + pci_write_config_dword(devno, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Check if I/O accesses and Bus Mastering are enabled. */ + pci_read_config_dword(devno, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_MEMORY)) { + printf("Error: Can not enable MEM access.\n"); + continue; + } else if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } + + dev = (struct eth_device *) malloc(sizeof *dev); + + sprintf(dev->name, "dp8382x#%d", card_number); + dev->iobase = bus_to_phys(iobase); + dev->priv = (void *) devno; + dev->init = ns8382x_init; + dev->halt = ns8382x_disable; + dev->send = ns8382x_send; + dev->recv = ns8382x_poll; + + /* ns8382x has a non-standard PM control register + * in PCI config space. Some boards apparently need + * to be brought to D0 in this manner. */ + pci_read_config_dword(devno, PCIPM, &tmp); + if (tmp & (0x03 | 0x100)) { /* D0 state, disable PME assertion */ + u32 newtmp = tmp & ~(0x03 | 0x100); + pci_write_config_dword(devno, PCIPM, newtmp); + } + + /* get MAC address */ + for (i = 0; i < 3; i++) { + u32 data; + char *mac = (char *)&dev->enetaddr[i * 2]; + + OUTL(dev, i * 2, RxFilterAddr); + data = INL(dev, RxFilterData); + *mac++ = data; + *mac++ = data >> 8; + } + /* get PHY address, can't be zero */ + for (phyAddress = 1; phyAddress < 32; phyAddress++) { + u32 rev, phy1; + + phy1 = mdio_read(dev, phyAddress, PHYIDR1); + if (phy1 == 0x2000) { /*check for 83861/91 */ + rev = mdio_read(dev, phyAddress, PHYIDR2); + if ((rev & ~(0x000f)) == 0x00005c50 || + (rev & ~(0x000f)) == 0x00005c60) { +#ifdef NS8382X_DEBUG + printf("phy rev is %x\n", rev); + printf("phy address is %x\n", + phyAddress); +#endif + break; + } + } + } + + /* set phy to autonegotiate && advertise everything */ + mdio_write(dev, phyAddress, KTCR, + (ktcr_adv_1000H | ktcr_adv_1000F)); + mdio_write(dev, phyAddress, ANAR, + (anar_adv_100F | anar_adv_100H | anar_adv_10H | + anar_adv_10F | anar_ieee_8023)); + mdio_write(dev, phyAddress, BMCR, 0x0); /*restore */ + mdio_write(dev, phyAddress, BMCR, + (Bmcr_AutoNegEn | Bmcr_RstAutoNeg)); + /* Reset the chip to erase any previous misconfiguration. */ + OUTL(dev, (ChipReset), ChipCmd); + + chip_config = INL(dev, ChipConfig); + /* reset the phy */ + OUTL(dev, (chip_config | PhyRst), ChipConfig); + /* power up and initialize transceiver */ + OUTL(dev, (chip_config & ~(PhyDis)), ChipConfig); + + mdio_sync(dev, EECtrl); +#ifdef NS8382X_DEBUG + { + u32 chpcfg = + INL(dev, ChipConfig) ^ SpeedStatus_Polarity; + + printf("%s: Transceiver 10%s %s duplex.\n", dev->name, + (chpcfg & GigSpeed) ? "00" : (chpcfg & HundSpeed) + ? "0" : "", + chpcfg & FullDuplex ? "full" : "half"); + printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + dev->enetaddr[0], dev->enetaddr[1], + dev->enetaddr[2], dev->enetaddr[3], + dev->enetaddr[4], dev->enetaddr[5]); + } +#endif + /* Disable PME: + * The PME bit is initialized from the EEPROM contents. + * PCI cards probably have PME disabled, but motherboard + * implementations may have PME set to enable WakeOnLan. + * With PME set the chip will scan incoming packets but + * nothing will be written to memory. */ + SavedClkRun = INL(dev, ClkRun); + OUTL(dev, SavedClkRun & ~0x100, ClkRun); + + eth_register(dev); + + card_number++; + + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x60); + + udelay(10 * 1000); + } + return card_number; +} + +/* MII transceiver control section. + Read and write MII registers using software-generated serial MDIO + protocol. See the MII specifications or DP83840A data sheet for details. + + The maximum data clock rate is 2.5 Mhz. To meet minimum timing we + must flush writes to the PCI bus with a PCI read. */ +#define mdio_delay(mdio_addr) INL(dev, mdio_addr) + +#define MDIO_EnbIn (0) +#define MDIO_WRITE0 (MDIO_EnbOutput) +#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput) + +/* Generate the preamble required for initial synchronization and + a few older transceivers. */ +static void +mdio_sync(struct eth_device *dev, u32 offset) +{ + int bits = 32; + + /* Establish sync by sending at least 32 logic ones. */ + while (--bits >= 0) { + OUTL(dev, MDIO_WRITE1, offset); + mdio_delay(offset); + OUTL(dev, MDIO_WRITE1 | MDIO_ShiftClk, offset); + mdio_delay(offset); + } +} + +static int +mdio_read(struct eth_device *dev, int phy_id, int addr) +{ + int mii_cmd = (0xf6 << 10) | (phy_id << 5) | addr; + int i, retval = 0; + + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; + + OUTL(dev, dataval, EECtrl); + mdio_delay(EECtrl); + OUTL(dev, dataval | MDIO_ShiftClk, EECtrl); + mdio_delay(EECtrl); + } + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + OUTL(dev, MDIO_EnbIn, EECtrl); + mdio_delay(EECtrl); + retval = + (retval << 1) | ((INL(dev, EECtrl) & MDIO_Data) ? 1 : 0); + OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl); + mdio_delay(EECtrl); + } + return (retval >> 1) & 0xffff; +} + +static void +mdio_write(struct eth_device *dev, int phy_id, int addr, int value) +{ + int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (addr << 18) | value; + int i; + + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; + + OUTL(dev, dataval, EECtrl); + mdio_delay(EECtrl); + OUTL(dev, dataval | MDIO_ShiftClk, EECtrl); + mdio_delay(EECtrl); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + OUTL(dev, MDIO_EnbIn, EECtrl); + mdio_delay(EECtrl); + OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl); + mdio_delay(EECtrl); + } + return; +} + +/* Function: ns8382x_init + * Description: resets the ethernet controller chip and configures + * registers and data structures required for sending and receiving packets. + * Arguments: struct eth_device *dev: NIC data structure + * returns: int. + */ + +static int +ns8382x_init(struct eth_device *dev, bd_t * bis) +{ + u32 config; + + ns8382x_reset(dev); + + /* Disable PME: + * The PME bit is initialized from the EEPROM contents. + * PCI cards probably have PME disabled, but motherboard + * implementations may have PME set to enable WakeOnLan. + * With PME set the chip will scan incoming packets but + * nothing will be written to memory. */ + OUTL(dev, SavedClkRun & ~0x100, ClkRun); + + ns8382x_init_rxfilter(dev); + ns8382x_init_txd(dev); + ns8382x_init_rxd(dev); + + /*set up ChipConfig */ + config = INL(dev, ChipConfig); + /*turn off 64 bit ops && Ten-bit interface + * && big-endian mode && extended status */ + config &= ~(TBIEn | Mode1000 | T64En | D64En | M64En | BEMode | PhyDis | ExtStEn); + OUTL(dev, config, ChipConfig); + + /* Configure the PCI bus bursts and FIFO thresholds. */ + tx_config = TxCarrierIgn | TxHeartIgn | TxAutoPad + | TxCollRetry | TxMxdma_1024 | (0x1002); + rx_config = RxMxdma_1024 | 0x20; +#ifdef NS8382X_DEBUG + printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); + printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config); +#endif + OUTL(dev, tx_config, TxConfig); + OUTL(dev, rx_config, RxConfig); + + /*turn off priority queueing */ + OUTL(dev, 0x0, PriQueue); + + ns8382x_check_duplex(dev); + ns8382x_set_rx_mode(dev); + + OUTL(dev, (RxOn | TxOn), ChipCmd); + return 1; +} + +/* Function: ns8382x_reset + * Description: soft resets the controller chip + * Arguments: struct eth_device *dev: NIC data structure + * Returns: void. + */ +static void +ns8382x_reset(struct eth_device *dev) +{ + OUTL(dev, ChipReset, ChipCmd); + while (INL(dev, ChipCmd)) + /*wait until done */ ; + OUTL(dev, 0, IntrMask); + OUTL(dev, 0, IntrEnable); +} + +/* Function: ns8382x_init_rxfilter + * Description: sets receive filter address to our MAC address + * Arguments: struct eth_device *dev: NIC data structure + * returns: void. + */ + +static void +ns8382x_init_rxfilter(struct eth_device *dev) +{ + int i; + + for (i = 0; i < ETH_ALEN; i += 2) { + OUTL(dev, i, RxFilterAddr); + OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), + RxFilterData); + } +} + +/* Function: ns8382x_init_txd + * Description: initializes the Tx descriptor + * Arguments: struct eth_device *dev: NIC data structure + * returns: void. + */ + +static void +ns8382x_init_txd(struct eth_device *dev) +{ + txd.link = (u32) 0; + txd.bufptr = cpu_to_le32((u32) & txb[0]); + txd.cmdsts = (u32) 0; + txd.extsts = (u32) 0; + + OUTL(dev, 0x0, TxRingPtrHi); + OUTL(dev, phys_to_bus((u32)&txd), TxRingPtr); +#ifdef NS8382X_DEBUG + printf("ns8382x_init_txd: TX descriptor register loaded with: %#08X (&txd: %p)\n", + INL(dev, TxRingPtr), &txd); +#endif +} + +/* Function: ns8382x_init_rxd + * Description: initializes the Rx descriptor ring + * Arguments: struct eth_device *dev: NIC data structure + * Returns: void. + */ + +static void +ns8382x_init_rxd(struct eth_device *dev) +{ + int i; + + OUTL(dev, 0x0, RxRingPtrHi); + + cur_rx = 0; + for (i = 0; i < NUM_RX_DESC; i++) { + rxd[i].link = + cpu_to_le32((i + 1 < + NUM_RX_DESC) ? (u32) & rxd[i + + 1] : (u32) & + rxd[0]); + rxd[i].extsts = cpu_to_le32((u32) 0x0); + rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); + rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]); +#ifdef NS8382X_DEBUG + printf + ("ns8382x_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n", + i, &rxd[i], le32_to_cpu(rxd[i].link), + le32_to_cpu(rxd[i].cmdsts), le32_to_cpu(rxd[i].bufptr)); +#endif + } + OUTL(dev, phys_to_bus((u32) & rxd), RxRingPtr); + +#ifdef NS8382X_DEBUG + printf("ns8382x_init_rxd: RX descriptor register loaded with: %X\n", + INL(dev, RxRingPtr)); +#endif +} + +/* Function: ns8382x_set_rx_mode + * Description: + * sets the receive mode to accept all broadcast packets and packets + * with our MAC address, and reject all multicast packets. + * Arguments: struct eth_device *dev: NIC data structure + * Returns: void. + */ + +static void +ns8382x_set_rx_mode(struct eth_device *dev) +{ + u32 rx_mode = 0x0; + /*spec says RxFilterEnable has to be 0 for rest of + * this stuff to be properly configured. Linux driver + * seems to support this*/ +/* OUTL(dev, rx_mode, RxFilterAddr);*/ + rx_mode = (RxFilterEnable | AcceptAllBroadcast | AcceptPerfectMatch); + OUTL(dev, rx_mode, RxFilterAddr); + printf("ns8382x_set_rx_mode: set to %X\n", rx_mode); + /*now we turn RxFilterEnable back on */ + /*rx_mode |= RxFilterEnable; + OUTL(dev, rx_mode, RxFilterAddr);*/ +} + +static void +ns8382x_check_duplex(struct eth_device *dev) +{ + int gig = 0; + int hun = 0; + int duplex = 0; + int config = (INL(dev, ChipConfig) ^ SpeedStatus_Polarity); + + duplex = (config & FullDuplex) ? 1 : 0; + gig = (config & GigSpeed) ? 1 : 0; + hun = (config & HundSpeed) ? 1 : 0; +#ifdef NS8382X_DEBUG + printf("%s: Setting 10%s %s-duplex based on negotiated link" + " capability.\n", dev->name, (gig) ? "00" : (hun) ? "0" : "", + duplex ? "full" : "half"); +#endif + if (duplex) { + rx_config |= RxAcceptTx; + tx_config |= (TxCarrierIgn | TxHeartIgn); + } else { + rx_config &= ~RxAcceptTx; + tx_config &= ~(TxCarrierIgn | TxHeartIgn); + } +#ifdef NS8382X_DEBUG + printf("%s: Resetting TxConfig Register %#08X\n", dev->name, tx_config); + printf("%s: Resetting RxConfig Register %#08X\n", dev->name, rx_config); +#endif + OUTL(dev, tx_config, TxConfig); + OUTL(dev, rx_config, RxConfig); + + /*if speed is 10 or 100, remove MODE1000, + * if it's 1000, then set it */ + config = INL(dev, ChipConfig); + if (gig) + config |= Mode1000; + else + config &= ~Mode1000; + +#ifdef NS8382X_DEBUG + printf("%s: %setting Mode1000\n", dev->name, (gig) ? "S" : "Uns"); +#endif + OUTL(dev, config, ChipConfig); +} + +/* Function: ns8382x_send + * Description: transmits a packet and waits for completion or timeout. + * Returns: void. */ +static int +ns8382x_send(struct eth_device *dev, volatile void *packet, int length) +{ + u32 i, status = 0; + vu_long tx_stat = 0; + + /* Stop the transmitter */ + OUTL(dev, TxOff, ChipCmd); +#ifdef NS8382X_DEBUG + printf("ns8382x_send: sending %d bytes\n", (int)length); +#endif + + /* set the transmit buffer descriptor and enable Transmit State Machine */ + txd.link = cpu_to_le32(0x0); + txd.bufptr = cpu_to_le32(phys_to_bus((u32)packet)); + txd.extsts = cpu_to_le32(0x0); + txd.cmdsts = cpu_to_le32(DescOwn | length); + + /* load Transmit Descriptor Register */ + OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr); +#ifdef NS8382X_DEBUG + printf("ns8382x_send: TX descriptor register loaded with: %#08X\n", + INL(dev, TxRingPtr)); + printf("\ttxd.link:%X\tbufp:%X\texsts:%X\tcmdsts:%X\n", + le32_to_cpu(txd.link), le32_to_cpu(txd.bufptr), + le32_to_cpu(txd.extsts), le32_to_cpu(txd.cmdsts)); +#endif + /* restart the transmitter */ + OUTL(dev, TxOn, ChipCmd); + + for (i = 0; (tx_stat = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) { + if (i >= TOUT_LOOP) { + printf ("%s: tx error buffer not ready: txd.cmdsts %#X\n", + dev->name, tx_stat); + goto Done; + } + } + + if (!(tx_stat & DescPktOK)) { + printf("ns8382x_send: Transmit error, Tx status %X.\n", tx_stat); + goto Done; + } +#ifdef NS8382X_DEBUG + printf("ns8382x_send: tx_stat: %#08X\n", tx_stat); +#endif + + status = 1; + Done: + return status; +} + +/* Function: ns8382x_poll + * Description: checks for a received packet and returns it if found. + * Arguments: struct eth_device *dev: NIC data structure + * Returns: 1 if packet was received. + * 0 if no packet was received. + * Side effects: + * Returns (copies) the packet to the array dev->packet. + * Returns the length of the packet. + */ + +static int +ns8382x_poll(struct eth_device *dev) +{ + int retstat = 0; + int length = 0; + vu_long rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); + + if (!(rx_status & (u32) DescOwn)) + return retstat; +#ifdef NS8382X_DEBUG + printf("ns8382x_poll: got a packet: cur_rx:%u, status:%lx\n", + cur_rx, rx_status); +#endif + length = (rx_status & DSIZE) - CRC_SIZE; + + if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { + /* corrupted packet received */ + printf("ns8382x_poll: Corrupted packet, status:%lx\n", rx_status); + retstat = 0; + } else { + /* give packet to higher level routine */ + NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); + retstat = 1; + } + + /* return the descriptor and buffer to receive ring */ + rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); + rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]); + + if (++cur_rx == NUM_RX_DESC) + cur_rx = 0; + + /* re-enable the potentially idle receive state machine */ + OUTL(dev, RxOn, ChipCmd); + + return retstat; +} + +/* Function: ns8382x_disable + * Description: Turns off interrupts and stops Tx and Rx engines + * Arguments: struct eth_device *dev: NIC data structure + * Returns: void. + */ + +static void +ns8382x_disable(struct eth_device *dev) +{ + /* Disable interrupts using the mask. */ + OUTL(dev, 0, IntrMask); + OUTL(dev, 0, IntrEnable); + + /* Stop the chip's Tx and Rx processes. */ + OUTL(dev, (RxOff | TxOff), ChipCmd); + + /* Restore PME enable bit */ + OUTL(dev, SavedClkRun, ClkRun); +} + +#endif diff --git a/drivers/net/ns9750_eth.c b/drivers/net/ns9750_eth.c new file mode 100644 index 0000000000..067ff8efab --- /dev/null +++ b/drivers/net/ns9750_eth.c @@ -0,0 +1,797 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_eth.c,v 1.2 2004/02/24 14:09:39 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Ethernet driver for the NS9750. Uses DMA Engine with polling + * interrupt status. But interrupts are not enabled. + * Only one tx buffer descriptor and the RXA buffer descriptor are used + * Currently no transmit lockup handling is included. eth_send has a 5s + * timeout for sending frames. No retransmits are performed when an + * error occurs. + * @References: [1] NS9750 Hardware Reference, December 2003 + * [2] Intel LXT971 Datasheet #249414 Rev. 02 + * [3] NS7520 Linux Ethernet Driver + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ***********************************************************************/ + +#include +#include /* NetSendPacket */ + +#include "ns9750_eth.h" /* for Ethernet and PHY */ + +#ifdef CONFIG_DRIVER_NS9750_ETHERNET + +/* some definition to make transistion to linux easier */ + +#define NS9750_DRIVER_NAME "eth" +#define KERN_WARNING "Warning:" +#define KERN_ERR "Error:" +#define KERN_INFO "Info:" + +#if 0 +# define DEBUG +#endif + +#ifdef DEBUG +# define printk printf + +# define DEBUG_INIT 0x0001 +# define DEBUG_MINOR 0x0002 +# define DEBUG_RX 0x0004 +# define DEBUG_TX 0x0008 +# define DEBUG_INT 0x0010 +# define DEBUG_POLL 0x0020 +# define DEBUG_LINK 0x0040 +# define DEBUG_MII 0x0100 +# define DEBUG_MII_LOW 0x0200 +# define DEBUG_MEM 0x0400 +# define DEBUG_ERROR 0x4000 +# define DEBUG_ERROR_CRIT 0x8000 + +static int nDebugLvl = DEBUG_ERROR_CRIT; + +# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \ + printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \ + printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\ + printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\ + printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0) +# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \ + printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0); +# define ASSERT( expr, func ) if( !( expr ) ) { \ + printf( "Assertion failed! %s:line %d %s\n", \ + (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \ + func } +#else /* DEBUG */ +# define printk(...) +# define DEBUG_ARGS0( FLG, a0 ) +# define DEBUG_ARGS1( FLG, a0, a1 ) +# define DEBUG_ARGS2( FLG, a0, a1, a2 ) +# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) +# define DEBUG_FN( n ) +# define ASSERT(expr, func) +#endif /* DEBUG */ + +#define NS9750_MII_NEG_DELAY (5*CFG_HZ) /* in s */ +#define TX_TIMEOUT (5*CFG_HZ) /* in s */ + +/* @TODO move it to eeprom.h */ +#define FS_EEPROM_AUTONEG_MASK 0x7 +#define FS_EEPROM_AUTONEG_SPEED_MASK 0x1 +#define FS_EEPROM_AUTONEG_SPEED_10 0x0 +#define FS_EEPROM_AUTONEG_SPEED_100 0x1 +#define FS_EEPROM_AUTONEG_DUPLEX_MASK 0x2 +#define FS_EEPROM_AUTONEG_DUPLEX_HALF 0x0 +#define FS_EEPROM_AUTONEG_DUPLEX_FULL 0x2 +#define FS_EEPROM_AUTONEG_ENABLE_MASK 0x4 +#define FS_EEPROM_AUTONEG_DISABLE 0x0 +#define FS_EEPROM_AUTONEG_ENABLE 0x4 + +/* buffer descriptors taken from [1] p.306 */ +typedef struct +{ + unsigned int* punSrc; + unsigned int unLen; /* 11 bits */ + unsigned int* punDest; /* unused */ + union { + unsigned int unReg; + struct { + unsigned uStatus : 16; + unsigned uRes : 12; + unsigned uFull : 1; + unsigned uEnable : 1; + unsigned uInt : 1; + unsigned uWrap : 1; + } bits; + } s; +} rx_buffer_desc_t; + +typedef struct +{ + unsigned int* punSrc; + unsigned int unLen; /* 10 bits */ + unsigned int* punDest; /* unused */ + union { + unsigned int unReg; /* only 32bit accesses may done to NS9750 + * eth engine */ + struct { + unsigned uStatus : 16; + unsigned uRes : 12; + unsigned uFull : 1; + unsigned uLast : 1; + unsigned uInt : 1; + unsigned uWrap : 1; + } bits; + } s; +} tx_buffer_desc_t; + +static int ns9750_eth_reset( void ); + +static void ns9750_link_force( void ); +static void ns9750_link_auto_negotiate( void ); +static void ns9750_link_update_egcr( void ); +static void ns9750_link_print_changed( void ); + +/* the PHY stuff */ + +static char ns9750_mii_identify_phy( void ); +static unsigned short ns9750_mii_read( unsigned short uiRegister ); +static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData ); +static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk ); +static unsigned int ns9750_mii_poll_busy( void ); + +static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; +static unsigned char ucLinkMode = FS_EEPROM_AUTONEG_ENABLE; +static unsigned int uiLastLinkStatus; +static PhyType phyDetected = PHY_NONE; + +/* we use only one tx buffer descriptor */ +static tx_buffer_desc_t* pTxBufferDesc = + (tx_buffer_desc_t*) get_eth_reg_addr( NS9750_ETH_TXBD ); + +/* we use only one rx buffer descriptor of the 4 */ +static rx_buffer_desc_t aRxBufferDesc[ 4 ]; + +/*********************************************************************** + * @Function: eth_init + * @Return: -1 on failure otherwise 0 + * @Descr: Initializes the ethernet engine and uses either FS Forth's default + * MAC addr or the one in environment + ***********************************************************************/ + +int eth_init (bd_t * pbis) +{ + /* This default MAC Addr is reserved by FS Forth-Systeme for the case of + EEPROM failures */ + unsigned char aucMACAddr[6] = { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 }; + char *pcTmp = getenv ("ethaddr"); + char *pcEnd; + int i; + + DEBUG_FN (DEBUG_INIT); + + /* no need to check for hardware */ + + if (!ns9750_eth_reset ()) + return -1; + + if (pcTmp != NULL) + for (i = 0; i < 6; i++) { + aucMACAddr[i] = + pcTmp ? simple_strtoul (pcTmp, &pcEnd, + 16) : 0; + pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd; + } + + /* configure ethernet address */ + + *get_eth_reg_addr (NS9750_ETH_SA1) = + aucMACAddr[5] << 8 | aucMACAddr[4]; + *get_eth_reg_addr (NS9750_ETH_SA2) = + aucMACAddr[3] << 8 | aucMACAddr[2]; + *get_eth_reg_addr (NS9750_ETH_SA3) = + aucMACAddr[1] << 8 | aucMACAddr[0]; + + /* enable hardware */ + + *get_eth_reg_addr (NS9750_ETH_MAC1) = NS9750_ETH_MAC1_RXEN; + + /* the linux kernel may give packets < 60 bytes, for example arp */ + *get_eth_reg_addr (NS9750_ETH_MAC2) = NS9750_ETH_MAC2_CRCEN | + NS9750_ETH_MAC2_PADEN | NS9750_ETH_MAC2_HUGE; + + /* enable receive and transmit FIFO, use 10/100 Mbps MII */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) = + NS9750_ETH_EGCR1_ETXWM | + NS9750_ETH_EGCR1_ERX | + NS9750_ETH_EGCR1_ERXDMA | + NS9750_ETH_EGCR1_ETX | + NS9750_ETH_EGCR1_ETXDMA | NS9750_ETH_EGCR1_ITXA; + + /* prepare DMA descriptors */ + for (i = 0; i < 4; i++) { + aRxBufferDesc[i].punSrc = 0; + aRxBufferDesc[i].unLen = 0; + aRxBufferDesc[i].s.bits.uWrap = 1; + aRxBufferDesc[i].s.bits.uInt = 1; + aRxBufferDesc[i].s.bits.uEnable = 0; + aRxBufferDesc[i].s.bits.uFull = 0; + } + + /* NetRxPackets[ 0 ] is initialized before eth_init is called and never + changes. NetRxPackets is 32bit aligned */ + aRxBufferDesc[0].punSrc = (unsigned int *) NetRxPackets[0]; + aRxBufferDesc[0].s.bits.uEnable = 1; + aRxBufferDesc[0].unLen = 1522; /* as stated in [1] p.307 */ + + *get_eth_reg_addr (NS9750_ETH_RXAPTR) = + (unsigned int) &aRxBufferDesc[0]; + + /* [1] Tab. 221 states less than 5us */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_ERXINIT; + while (! + (*get_eth_reg_addr (NS9750_ETH_EGSR) & NS9750_ETH_EGSR_RXINIT)) + /* wait for finish */ + udelay (1); + + /* @TODO do we need to clear RXINIT? */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_ERXINIT; + + *get_eth_reg_addr (NS9750_ETH_RXFREE) = 0x1; + + return 0; +} + +/*********************************************************************** + * @Function: eth_send + * @Return: -1 on timeout otherwise 1 + * @Descr: sends one frame by DMA + ***********************************************************************/ + +int eth_send (volatile void *pPacket, int nLen) +{ + ulong ulTimeout; + + DEBUG_FN (DEBUG_TX); + + /* clear old status values */ + *get_eth_reg_addr (NS9750_ETH_EINTR) &= + *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_TX_MA; + + /* prepare Tx Descriptors */ + + pTxBufferDesc->punSrc = (unsigned int *) pPacket; /* pPacket is 32bit + * aligned */ + pTxBufferDesc->unLen = nLen; + /* only 32bit accesses allowed. wrap, full, interrupt and enabled to 1 */ + pTxBufferDesc->s.unReg = 0xf0000000; + /* pTxBufferDesc is the first possible buffer descriptor */ + *get_eth_reg_addr (NS9750_ETH_TXPTR) = 0x0; + + /* enable processor for next frame */ + + *get_eth_reg_addr (NS9750_ETH_EGCR2) &= ~NS9750_ETH_EGCR2_TCLER; + *get_eth_reg_addr (NS9750_ETH_EGCR2) |= NS9750_ETH_EGCR2_TCLER; + + ulTimeout = get_timer (0); + + DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, + "Waiting for transmission to finish\n"); + while (! + (*get_eth_reg_addr (NS9750_ETH_EINTR) & + (NS9750_ETH_EINTR_TXDONE | NS9750_ETH_EINTR_TXERR))) { + /* do nothing, wait for completion */ + if (get_timer (0) - ulTimeout > TX_TIMEOUT) { + DEBUG_ARGS0 (DEBUG_TX, "Transmit Timed out\n"); + return -1; + } + } + DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, "transmitted...\n"); + + return 0; +} + +/*********************************************************************** + * @Function: eth_rx + * @Return: size of last frame in bytes or 0 if no frame available + * @Descr: gives one frame to U-Boot which has been copied by DMA engine already + * to NetRxPackets[ 0 ]. + ***********************************************************************/ + +int eth_rx (void) +{ + int nLen = 0; + unsigned int unStatus; + + unStatus = + *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_RX_MA; + + if (!unStatus) + /* no packet available, return immediately */ + return 0; + + DEBUG_FN (DEBUG_RX); + + /* unLen always < max(nLen) and discard checksum */ + nLen = (int) aRxBufferDesc[0].unLen - 4; + + /* acknowledge status register */ + *get_eth_reg_addr (NS9750_ETH_EINTR) = unStatus; + + aRxBufferDesc[0].unLen = 1522; + aRxBufferDesc[0].s.bits.uFull = 0; + + /* Buffer A descriptor available again */ + *get_eth_reg_addr (NS9750_ETH_RXFREE) |= 0x1; + + /* NetReceive may call eth_send. Due to a possible bug of the NS9750 we + * have to acknowledge the received frame before sending a new one */ + if (unStatus & NS9750_ETH_EINTR_RXDONEA) + NetReceive (NetRxPackets[0], nLen); + + return nLen; +} + +/*********************************************************************** + * @Function: eth_halt + * @Return: n/a + * @Descr: stops the ethernet engine + ***********************************************************************/ + +void eth_halt (void) +{ + DEBUG_FN (DEBUG_INIT); + + *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_RXEN; + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~(NS9750_ETH_EGCR1_ERX | + NS9750_ETH_EGCR1_ERXDMA | + NS9750_ETH_EGCR1_ETX | + NS9750_ETH_EGCR1_ETXDMA); +} + +/*********************************************************************** + * @Function: ns9750_eth_reset + * @Return: 0 on failure otherwise 1 + * @Descr: resets the ethernet interface and the PHY, + * performs auto negotiation or fixed modes + ***********************************************************************/ + +static int ns9750_eth_reset (void) +{ + DEBUG_FN (DEBUG_MINOR); + + /* Reset MAC */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_MAC_HRST; + udelay (5); /* according to [1], p.322 */ + *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_MAC_HRST; + + /* reset and initialize PHY */ + + *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_SRST; + + /* we don't support hot plugging of PHY, therefore we don't reset + phyDetected and nPhyMaxMdioClock here. The risk is if the setting is + incorrect the first open + may detect the PHY correctly but succeding will fail + For reseting the PHY and identifying we have to use the standard + MDIO CLOCK value 2.5 MHz only after hardware reset + After having identified the PHY we will do faster */ + + *get_eth_reg_addr (NS9750_ETH_MCFG) = + ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); + + /* reset PHY */ + ns9750_mii_write (PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET); + ns9750_mii_write (PHY_COMMON_CTRL, 0); + + /* @TODO check time */ + udelay (3000); /* [2] p.70 says at least 300us reset recovery time. But + go sure, it didn't worked stable at higher timer + frequencies under LxNETES-2.x */ + + /* MII clock has been setup to default, ns9750_mii_identify_phy should + work for all */ + + if (!ns9750_mii_identify_phy ()) { + printk (KERN_ERR NS9750_DRIVER_NAME + ": Unsupported PHY, aborting\n"); + return 0; + } + + /* now take the highest MDIO clock possible after detection */ + *get_eth_reg_addr (NS9750_ETH_MCFG) = + ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); + + + /* PHY has been detected, so there can be no abort reason and we can + finish initializing ethernet */ + + uiLastLinkStatus = 0xff; /* undefined */ + + if ((ucLinkMode & FS_EEPROM_AUTONEG_ENABLE_MASK) == + FS_EEPROM_AUTONEG_DISABLE) + /* use parameters defined */ + ns9750_link_force (); + else + ns9750_link_auto_negotiate (); + + if (phyDetected == PHY_LXT971A) + /* set LED2 to link mode */ + ns9750_mii_write (PHY_LXT971_LED_CFG, + PHY_LXT971_LED_CFG_LINK_ACT << + PHY_LXT971_LED_CFG_SHIFT_LED2); + + return 1; +} + +/*********************************************************************** + * @Function: ns9750_link_force + * @Return: void + * @Descr: configures eth and MII to use the link mode defined in + * ucLinkMode + ***********************************************************************/ + +static void ns9750_link_force (void) +{ + unsigned short uiControl; + + DEBUG_FN (DEBUG_LINK); + + uiControl = ns9750_mii_read (PHY_COMMON_CTRL); + uiControl &= ~(PHY_COMMON_CTRL_SPD_MA | + PHY_COMMON_CTRL_AUTO_NEG | PHY_COMMON_CTRL_DUPLEX); + + uiLastLinkStatus = 0; + + if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) == + FS_EEPROM_AUTONEG_SPEED_100) { + uiControl |= PHY_COMMON_CTRL_SPD_100; + uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX; + } else + uiControl |= PHY_COMMON_CTRL_SPD_10; + + if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) == + FS_EEPROM_AUTONEG_DUPLEX_FULL) { + uiControl |= PHY_COMMON_CTRL_DUPLEX; + uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE; + } + + ns9750_mii_write (PHY_COMMON_CTRL, uiControl); + + ns9750_link_print_changed (); + ns9750_link_update_egcr (); +} + +/*********************************************************************** + * @Function: ns9750_link_auto_negotiate + * @Return: void + * @Descr: performs auto-negotation of link. + ***********************************************************************/ + +static void ns9750_link_auto_negotiate (void) +{ + unsigned long ulStartJiffies; + unsigned short uiStatus; + + DEBUG_FN (DEBUG_LINK); + + /* run auto-negotation */ + /* define what we are capable of */ + ns9750_mii_write (PHY_COMMON_AUTO_ADV, + PHY_COMMON_AUTO_ADV_100BTXFD | + PHY_COMMON_AUTO_ADV_100BTX | + PHY_COMMON_AUTO_ADV_10BTFD | + PHY_COMMON_AUTO_ADV_10BT | + PHY_COMMON_AUTO_ADV_802_3); + /* start auto-negotiation */ + ns9750_mii_write (PHY_COMMON_CTRL, + PHY_COMMON_CTRL_AUTO_NEG | + PHY_COMMON_CTRL_RES_AUTO); + + /* wait for completion */ + + ulStartJiffies = get_ticks (); + while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) { + uiStatus = ns9750_mii_read (PHY_COMMON_STAT); + if ((uiStatus & + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) == + (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) { + /* lucky we are, auto-negotiation succeeded */ + ns9750_link_print_changed (); + ns9750_link_update_egcr (); + return; + } + } + + DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n"); + /* ignore invalid link settings */ +} + +/*********************************************************************** + * @Function: ns9750_link_update_egcr + * @Return: void + * @Descr: updates the EGCR and MAC2 link status after mode change or + * auto-negotation + ***********************************************************************/ + +static void ns9750_link_update_egcr (void) +{ + unsigned int unEGCR; + unsigned int unMAC2; + unsigned int unIPGT; + + DEBUG_FN (DEBUG_LINK); + + unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1); + unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2); + unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA; + + unMAC2 &= ~NS9750_ETH_MAC2_FULLD; + if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE) + == PHY_LXT971_STAT2_DUPLEX_MODE) { + unMAC2 |= NS9750_ETH_MAC2_FULLD; + unIPGT |= 0x15; /* see [1] p. 339 */ + } else + unIPGT |= 0x12; /* see [1] p. 339 */ + + *get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2; + *get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR; + *get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT; +} + +/*********************************************************************** + * @Function: ns9750_link_print_changed + * @Return: void + * @Descr: checks whether the link status has changed and if so prints + * the new mode + ***********************************************************************/ + +static void ns9750_link_print_changed (void) +{ + unsigned short uiStatus; + unsigned short uiControl; + + DEBUG_FN (DEBUG_LINK); + + uiControl = ns9750_mii_read (PHY_COMMON_CTRL); + + if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == + PHY_COMMON_CTRL_AUTO_NEG) { + /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */ + uiStatus = ns9750_mii_read (PHY_COMMON_STAT); + + if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) { + printk (KERN_WARNING NS9750_DRIVER_NAME + ": link down\n"); + /* @TODO Linux: carrier_off */ + } else { + /* @TODO Linux: carrier_on */ + if (phyDetected == PHY_LXT971A) { + uiStatus = ns9750_mii_read (PHY_LXT971_STAT2); + uiStatus &= (PHY_LXT971_STAT2_100BTX | + PHY_LXT971_STAT2_DUPLEX_MODE | + PHY_LXT971_STAT2_AUTO_NEG); + + /* mask out all uninteresting parts */ + } + /* other PHYs must store there link information in + uiStatus as PHY_LXT971 */ + } + } else { + /* mode has been forced, so uiStatus should be the same as the + last link status, enforce printing */ + uiStatus = uiLastLinkStatus; + uiLastLinkStatus = 0xff; + } + + if (uiStatus != uiLastLinkStatus) { + /* save current link status */ + uiLastLinkStatus = uiStatus; + + /* print new link status */ + + printk (KERN_INFO NS9750_DRIVER_NAME + ": link mode %i Mbps %s duplex %s\n", + (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10, + (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" : + "half", + (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" : + ""); + } +} + +/*********************************************************************** + * the MII low level stuff + ***********************************************************************/ + +/*********************************************************************** + * @Function: ns9750_mii_identify_phy + * @Return: 1 if supported PHY has been detected otherwise 0 + * @Descr: checks for supported PHY and prints the IDs. + ***********************************************************************/ + +static char ns9750_mii_identify_phy (void) +{ + unsigned short uiID1; + unsigned short uiID2; + unsigned char *szName; + char cRes = 0; + + DEBUG_FN (DEBUG_MII); + + phyDetected = (PhyType) uiID1 = ns9750_mii_read (PHY_COMMON_ID1); + + switch (phyDetected) { + case PHY_LXT971A: + szName = "LXT971A"; + uiID2 = ns9750_mii_read (PHY_COMMON_ID2); + nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK; + cRes = 1; + break; + case PHY_NONE: + default: + /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong + address or reset sets the wrong NS9750_ETH_MCFG_CLKS */ + + uiID2 = 0; + szName = "unknown"; + nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; + phyDetected = PHY_NONE; + } + + printk (KERN_INFO NS9750_DRIVER_NAME + ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName); + + return cRes; +} + +/*********************************************************************** + * @Function: ns9750_mii_read + * @Return: the data read from PHY register uiRegister + * @Descr: the data read may be invalid if timed out. If so, a message + * is printed but the invalid data is returned. + * The fixed device address is being used. + ***********************************************************************/ + +static unsigned short ns9750_mii_read (unsigned short uiRegister) +{ + DEBUG_FN (DEBUG_MII_LOW); + + /* write MII register to be read */ + *get_eth_reg_addr (NS9750_ETH_MADR) = + NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; + + *get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ; + + if (!ns9750_mii_poll_busy ()) + printk (KERN_WARNING NS9750_DRIVER_NAME + ": MII still busy in read\n"); + /* continue to read */ + + *get_eth_reg_addr (NS9750_ETH_MCMD) = 0; + + return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD)); +} + + +/*********************************************************************** + * @Function: ns9750_mii_write + * @Return: nothing + * @Descr: writes the data to the PHY register. In case of a timeout, + * no special handling is performed but a message printed + * The fixed device address is being used. + ***********************************************************************/ + +static void ns9750_mii_write (unsigned short uiRegister, + unsigned short uiData) +{ + DEBUG_FN (DEBUG_MII_LOW); + + /* write MII register to be written */ + *get_eth_reg_addr (NS9750_ETH_MADR) = + NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; + + *get_eth_reg_addr (NS9750_ETH_MWTD) = uiData; + + if (!ns9750_mii_poll_busy ()) { + printf (KERN_WARNING NS9750_DRIVER_NAME + ": MII still busy in write\n"); + } +} + + +/*********************************************************************** + * @Function: ns9750_mii_get_clock_divisor + * @Return: the clock divisor that should be used in NS9750_ETH_MCFG_CLKS + * @Descr: if no clock divisor can be calculated for the + * current SYSCLK and the maximum MDIO Clock, a warning is printed + * and the greatest divisor is taken + ***********************************************************************/ + +static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk) +{ + struct { + unsigned int unSysClkDivisor; + unsigned int unClks; /* field for NS9750_ETH_MCFG_CLKS */ + } PHYClockDivisors[] = { + { + 4, NS9750_ETH_MCFG_CLKS_4}, { + 6, NS9750_ETH_MCFG_CLKS_6}, { + 8, NS9750_ETH_MCFG_CLKS_8}, { + 10, NS9750_ETH_MCFG_CLKS_10}, { + 20, NS9750_ETH_MCFG_CLKS_20}, { + 30, NS9750_ETH_MCFG_CLKS_30}, { + 40, NS9750_ETH_MCFG_CLKS_40} + }; + + int nIndexSysClkDiv; + int nArraySize = + sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]); + unsigned int unClks = NS9750_ETH_MCFG_CLKS_40; /* defaults to + greatest div */ + + DEBUG_FN (DEBUG_INIT); + + for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize; + nIndexSysClkDiv++) { + /* find first sysclock divisor that isn't higher than 2.5 MHz + clock */ + if (AHB_CLK_FREQ / + PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <= + unMaxMDIOClk) { + unClks = PHYClockDivisors[nIndexSysClkDiv].unClks; + break; + } + } + + DEBUG_ARGS2 (DEBUG_INIT, + "Taking MDIO Clock bit mask 0x%0x for max clock %i\n", + unClks, unMaxMDIOClk); + + /* return greatest divisor */ + return unClks; +} + +/*********************************************************************** + * @Function: ns9750_mii_poll_busy + * @Return: 0 if timed out otherwise the remaing timeout + * @Descr: waits until the MII has completed a command or it times out + * code may be interrupted by hard interrupts. + * It is not checked what happens on multiple actions when + * the first is still being busy and we timeout. + ***********************************************************************/ + +static unsigned int ns9750_mii_poll_busy (void) +{ + unsigned int unTimeout = 10000; + + DEBUG_FN (DEBUG_MII_LOW); + + while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY) + == NS9750_ETH_MIND_BUSY) && unTimeout) + unTimeout--; + + return unTimeout; +} + +#endif /* CONFIG_DRIVER_NS9750_ETHERNET */ diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c new file mode 100644 index 0000000000..2af0e8f244 --- /dev/null +++ b/drivers/net/pcnet.c @@ -0,0 +1,526 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de. + * + * This driver for AMD PCnet network controllers is derived from the + * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#if 0 +#define PCNET_DEBUG_LEVEL 0 /* 0=off, 1=init, 2=rx/tx */ +#endif + +#if PCNET_DEBUG_LEVEL > 0 +#define PCNET_DEBUG1(fmt,args...) printf (fmt ,##args) +#if PCNET_DEBUG_LEVEL > 1 +#define PCNET_DEBUG2(fmt,args...) printf (fmt ,##args) +#else +#define PCNET_DEBUG2(fmt,args...) +#endif +#else +#define PCNET_DEBUG1(fmt,args...) +#define PCNET_DEBUG2(fmt,args...) +#endif + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_PCNET) + +#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975) +#error "Macro for PCnet chip version is not defined!" +#endif + +/* + * Set the number of Tx and Rx buffers, using Log_2(# buffers). + * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. + * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). + */ +#define PCNET_LOG_TX_BUFFERS 0 +#define PCNET_LOG_RX_BUFFERS 2 + +#define TX_RING_SIZE (1 << (PCNET_LOG_TX_BUFFERS)) +#define TX_RING_LEN_BITS ((PCNET_LOG_TX_BUFFERS) << 12) + +#define RX_RING_SIZE (1 << (PCNET_LOG_RX_BUFFERS)) +#define RX_RING_LEN_BITS ((PCNET_LOG_RX_BUFFERS) << 4) + +#define PKT_BUF_SZ 1544 + +/* The PCNET Rx and Tx ring descriptors. */ +struct pcnet_rx_head { + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; +}; + +struct pcnet_tx_head { + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; +}; + +/* The PCNET 32-Bit initialization block, described in databook. */ +struct pcnet_init_block { + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; + /* Receive and transmit ring base, along with extra bits. */ + u32 rx_ring; + u32 tx_ring; + u32 reserved2; +}; + +typedef struct pcnet_priv { + struct pcnet_rx_head rx_ring[RX_RING_SIZE]; + struct pcnet_tx_head tx_ring[TX_RING_SIZE]; + struct pcnet_init_block init_block; + /* Receive Buffer space */ + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + int cur_rx; + int cur_tx; +} pcnet_priv_t; + +static pcnet_priv_t *lp; + +/* Offsets from base I/O address for WIO mode */ +#define PCNET_RDP 0x10 +#define PCNET_RAP 0x12 +#define PCNET_RESET 0x14 +#define PCNET_BDP 0x16 + +static u16 pcnet_read_csr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_RDP); +} + +static void pcnet_write_csr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_RDP); +} + +static u16 pcnet_read_bcr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_BDP); +} + +static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_BDP); +} + +static void pcnet_reset (struct eth_device *dev) +{ + inw (dev->iobase+PCNET_RESET); +} + +static int pcnet_check (struct eth_device *dev) +{ + outw (88, dev->iobase+PCNET_RAP); + return (inw (dev->iobase+PCNET_RAP) == 88); +} + +static int pcnet_init( struct eth_device* dev, bd_t *bis); +static int pcnet_send (struct eth_device* dev, volatile void *packet, + int length); +static int pcnet_recv (struct eth_device* dev); +static void pcnet_halt (struct eth_device* dev); +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num); + +#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a)) +#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a))) + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, + { } +}; + + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device* dev; + u16 command, status; + int dev_nr = 0; + + PCNET_DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + + /* + * Find the PCnet PCI device(s). + */ + if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) { + break; + } + + /* + * Allocate and pre-fill the device structure. + */ + dev = (struct eth_device*) malloc(sizeof *dev); + dev->priv = (void *)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (unsigned int *)&dev->iobase); + dev->iobase &= ~0xf; + + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ", + dev->name, devbusfn, dev->iobase); + + command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} + +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr) +{ + int chip_version; + char *chipname; +#ifdef PCNET_HAS_PROM + int i; +#endif + + /* Reset the PCnet controller */ + pcnet_reset(dev); + + /* Check if register access is working */ + if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + printf("%s: CSR register access check failed\n", dev->name); + return -1; + } + + /* Identify the chip */ + chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16); + if ((chip_version & 0xfff) != 0x003) + return -1; + chip_version = (chip_version >> 12) & 0xffff; + switch (chip_version) { +#ifdef CONFIG_PCNET_79C973 + case 0x2625: + chipname = "PCnet/FAST III 79C973"; /* PCI */ + break; +#endif +#ifdef CONFIG_PCNET_79C975 + case 0x2627: + chipname = "PCnet/FAST III 79C975"; /* PCI */ + break; +#endif + default: + printf("%s: PCnet version %#x not supported\n", + dev->name, chip_version); + return -1; + } + + PCNET_DEBUG1("AMD %s\n", chipname); + +#ifdef PCNET_HAS_PROM + /* + * In most chips, after a chip reset, the ethernet address is read from + * the station address PROM at the base address and programmed into the + * "Physical Address Registers" CSR12-14. + */ + for (i = 0; i < 3; i++) { + unsigned int val; + val = pcnet_read_csr(dev, i+12) & 0x0ffff; + /* There may be endianness issues here. */ + dev->enetaddr[2*i ] = val & 0x0ff; + dev->enetaddr[2*i+1] = (val >> 8) & 0x0ff; + } +#endif /* PCNET_HAS_PROM */ + + return 0; +} + +static int pcnet_init(struct eth_device* dev, bd_t *bis) +{ + int i, val; + u32 addr; + + PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); + + /* Switch pcnet to 32bit mode */ + pcnet_write_bcr (dev, 20, 2); + +#ifdef CONFIG_PN62 + /* Setup LED registers */ + val = pcnet_read_bcr (dev, 2) | 0x1000; + pcnet_write_bcr (dev, 2, val); /* enable LEDPE */ + pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */ + pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */ + pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */ + pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */ +#endif + + /* Set/reset autoselect bit */ + val = pcnet_read_bcr (dev, 2) & ~2; + val |= 2; + pcnet_write_bcr (dev, 2, val); + + /* Enable auto negotiate, setup, disable fd */ + val = pcnet_read_bcr(dev, 32) & ~0x98; + val |= 0x20; + pcnet_write_bcr(dev, 32, val); + + /* + * We only maintain one structure because the drivers will never + * be used concurrently. In 32bit mode the RX and TX ring entries + * must be aligned on 16-byte boundaries. + */ + if (lp == NULL) { + addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (addr + 0xf) & ~0xf; + lp = (pcnet_priv_t *)addr; + } + + lp->init_block.mode = cpu_to_le16(0x0000); + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + + /* + * Initialize the Rx ring. + */ + lp->cur_rx = 0; + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]); + lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); + lp->rx_ring[i].status = cpu_to_le16(0x8000); + PCNET_DEBUG1("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n", + i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length, + lp->rx_ring[i].status); + } + + /* + * Initialize the Tx ring. The Tx buffer address is filled in as + * needed, but we do need to clear the upper ownership bit. + */ + lp->cur_tx = 0; + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].base = 0; + lp->tx_ring[i].status = 0; + } + + /* + * Setup Init Block. + */ + PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->init_block); + + for (i = 0; i < 6; i++) { + lp->init_block.phys_addr[i] = dev->enetaddr[i]; + PCNET_DEBUG1(" %02x", lp->init_block.phys_addr[i]); + } + + lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | + RX_RING_LEN_BITS); + lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring); + lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring); + + PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", + lp->init_block.tlen_rlen, + lp->init_block.rx_ring, lp->init_block.tx_ring); + + /* + * Tell the controller where the Init Block is located. + */ + addr = PCI_TO_MEM(dev, &lp->init_block); + pcnet_write_csr(dev, 1, addr & 0xffff); + pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + + pcnet_write_csr (dev, 4, 0x0915); + pcnet_write_csr (dev, 0, 0x0001); /* start */ + + /* Wait for Init Done bit */ + for (i = 10000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x0100) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller init failed\n", dev->name); + pcnet_reset (dev); + return 0; + } + + /* + * Finally start network controller operation. + */ + pcnet_write_csr (dev, 0, 0x0002); + + return 1; +} + +static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len) +{ + int i, status; + struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx]; + + PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet); + + /* Wait for completion by testing the OWN bit */ + for (i = 1000; i > 0; i--) { + status = le16_to_cpu(entry->status); + if ((status & 0x8000) == 0) + break; + udelay(100); + PCNET_DEBUG2("."); + } + if (i <= 0) { + printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", + dev->name, lp->cur_tx, status); + pkt_len = 0; + goto failure; + } + + /* + * Setup Tx ring. Caution: the write order is important here, + * set the status with the "ownership" bits last. + */ + status = 0x8300; + entry->length = le16_to_cpu(-pkt_len); + entry->misc = 0x00000000; + entry->base = PCI_TO_MEM_LE(dev, packet); + entry->status = le16_to_cpu(status); + + /* Trigger an immediate send poll. */ + pcnet_write_csr (dev, 0, 0x0008); + + failure: + if (++lp->cur_tx >= TX_RING_SIZE) + lp->cur_tx = 0; + + PCNET_DEBUG2("done\n"); + return pkt_len; +} + +static int pcnet_recv(struct eth_device* dev) +{ + struct pcnet_rx_head *entry; + int pkt_len = 0; + u16 status; + + while (1) { + entry = &lp->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) { + break; + } + status >>= 8; + + if (status != 0x03) { /* There was an error. */ + + printf("%s: Rx%d", dev->name, lp->cur_rx); + PCNET_DEBUG1(" (status=0x%x)", status); + if (status & 0x20) printf(" Frame"); + if (status & 0x10) printf(" Overflow"); + if (status & 0x08) printf(" CRC"); + if (status & 0x04) printf(" Fifo"); + printf(" Error\n"); + entry->status &= le16_to_cpu(0x03ff); + + } else { + + pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + dev->name, lp->cur_rx, pkt_len); + } else { + NetReceive(lp->rx_buf[lp->cur_rx], pkt_len); + PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]); + } + } + entry->status |= cpu_to_le16(0x8000); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; + } + return pkt_len; +} + +static void pcnet_halt(struct eth_device* dev) +{ + int i; + + PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); + + /* Reset the PCnet controller */ + pcnet_reset (dev); + + /* Wait for Stop bit */ + for (i = 1000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x4) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller reset failed\n", dev->name); + } +} + +#endif diff --git a/drivers/net/plb2800_eth.c b/drivers/net/plb2800_eth.c new file mode 100644 index 0000000000..0ae5d808a6 --- /dev/null +++ b/drivers/net/plb2800_eth.c @@ -0,0 +1,396 @@ +/* + * PLB2800 internal switch ethernet driver. + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#if defined(CONFIG_CMD_NET) \ + && defined(CONFIG_NET_MULTI) && defined(CONFIG_PLB2800_ETHER) + +#include +#include +#include + + +#define NUM_RX_DESC PKTBUFSRX +#define TOUT_LOOP 1000000 + +#define LONG_REF(addr) (*((volatile unsigned long*)addr)) + +#define CMAC_CRX_CTRL LONG_REF(0xb800c870) +#define CMAC_CTX_CTRL LONG_REF(0xb800c874) +#define SYS_MAC_ADDR_0 LONG_REF(0xb800c878) +#define SYS_MAC_ADDR_1 LONG_REF(0xb800c87c) +#define MIPS_H_MASK LONG_REF(0xB800C810) + +#define MA_LEARN LONG_REF(0xb8008004) +#define DA_LOOKUP LONG_REF(0xb8008008) + +#define CMAC_CRX_CTRL_PD 0x00000001 +#define CMAC_CRX_CTRL_CG 0x00000002 +#define CMAC_CRX_CTRL_PL_SHIFT 2 +#define CMAC_CRIT 0x0 +#define CMAC_NON_CRIT 0x1 +#define MBOX_STAT_ID_SHF 28 +#define MBOX_STAT_CP 0x80000000 +#define MBOX_STAT_MB 0x00000001 +#define EN_MA_LEARN 0x02000000 +#define EN_DA_LKUP 0x01000000 +#define MA_DEST_SHF 11 +#define DA_DEST_SHF 11 +#define DA_STATE_SHF 19 +#define TSTAMP_MS 0x00000000 +#define SW_H_MBOX4_MASK 0x08000000 +#define SW_H_MBOX3_MASK 0x04000000 +#define SW_H_MBOX2_MASK 0x02000000 +#define SW_H_MBOX1_MASK 0x01000000 + +typedef volatile struct { + unsigned int stat; + unsigned int cmd; + unsigned int cnt; + unsigned int adr; +} mailbox_t; + +#define MBOX_REG(mb) ((mailbox_t*)(0xb800c830+(mb<<4))) + +typedef volatile struct { + unsigned int word0; + unsigned int word1; + unsigned int word2; +} mbhdr_t; + +#define MBOX_MEM(mb) ((void*)(0xb800a000+((3-mb)<<11))) + + +static int plb2800_eth_init(struct eth_device *dev, bd_t * bis); +static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, + int length); +static int plb2800_eth_recv(struct eth_device *dev); +static void plb2800_eth_halt(struct eth_device *dev); + +static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr); +static unsigned char * plb2800_get_mac_addr(void); + +static int rx_new; +static int mac_addr_set = 0; + + +int plb2800_eth_initialize(bd_t * bis) +{ + struct eth_device *dev; + ulong temp; + +#ifdef DEBUG + printf("Entered plb2800_eth_initialize()\n"); +#endif + + if (!(dev = (struct eth_device *) malloc (sizeof *dev))) + { + printf("Failed to allocate memory\n"); + return 0; + } + memset(dev, 0, sizeof(*dev)); + + sprintf(dev->name, "PLB2800 Switch"); + dev->init = plb2800_eth_init; + dev->halt = plb2800_eth_halt; + dev->send = plb2800_eth_send; + dev->recv = plb2800_eth_recv; + + eth_register(dev); + + /* bug fix */ + *(ulong *)0xb800e800 = 0x838; + + /* Set MBOX ownership */ + temp = CMAC_CRIT << MBOX_STAT_ID_SHF; + MBOX_REG(0)->stat = temp; + MBOX_REG(1)->stat = temp; + + temp = CMAC_NON_CRIT << MBOX_STAT_ID_SHF; + MBOX_REG(2)->stat = temp; + MBOX_REG(3)->stat = temp; + + plb2800_set_mac_addr(dev, plb2800_get_mac_addr()); + + /* Disable all Mbox interrupt */ + temp = MIPS_H_MASK; + temp &= ~ (SW_H_MBOX1_MASK | SW_H_MBOX2_MASK | SW_H_MBOX3_MASK | SW_H_MBOX4_MASK) ; + MIPS_H_MASK = temp; + +#ifdef DEBUG + printf("Leaving plb2800_eth_initialize()\n"); +#endif + + return 1; +} + +static int plb2800_eth_init(struct eth_device *dev, bd_t * bis) +{ +#ifdef DEBUG + printf("Entering plb2800_eth_init()\n"); +#endif + + plb2800_set_mac_addr(dev, dev->enetaddr); + + rx_new = 0; + +#ifdef DEBUG + printf("Leaving plb2800_eth_init()\n"); +#endif + + return 0; +} + + +static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, + int length) +{ + int i; + int res = -1; + u32 temp; + mailbox_t * mb = MBOX_REG(0); + char * mem = MBOX_MEM(0); + +#ifdef DEBUG + printf("Entered plb2800_eth_send()\n"); +#endif + + if (length <= 0) + { + printf ("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + if (length < 64) + { + length = 64; + } + + temp = CMAC_CRX_CTRL_CG | ((length + 4) << CMAC_CRX_CTRL_PL_SHIFT); + +#ifdef DEBUG + printf("0 mb->stat = 0x%x\n", mb->stat); +#endif + + for(i = 0; mb->stat & (MBOX_STAT_CP | MBOX_STAT_MB); i++) + { + if (i >= TOUT_LOOP) + { + printf("%s: tx buffer not ready\n", dev->name); + printf("1 mb->stat = 0x%x\n", mb->stat); + goto Done; + } + } + + /* For some strange reason, memcpy doesn't work, here! + */ + do + { + int words = (length >> 2) + 1; + unsigned int* dst = (unsigned int*)(mem); + unsigned int* src = (unsigned int*)(packet); + for (i = 0; i < words; i++) + { + *dst = *src; + dst++; + src++; + }; + } while(0); + + CMAC_CRX_CTRL = temp; + mb->cmd = MBOX_STAT_CP; + +#ifdef DEBUG + printf("2 mb->stat = 0x%x\n", mb->stat); +#endif + + res = length; +Done: + +#ifdef DEBUG + printf("Leaving plb2800_eth_send()\n"); +#endif + + return res; +} + + +static int plb2800_eth_recv(struct eth_device *dev) +{ + int length = 0; + mailbox_t * mbox = MBOX_REG(3); + unsigned char * hdr = MBOX_MEM(3); + unsigned int stat; + +#ifdef DEBUG + printf("Entered plb2800_eth_recv()\n"); +#endif + + for (;;) + { + stat = mbox->stat; + + if (!(stat & MBOX_STAT_CP)) + { + break; + } + + length = ((*(hdr + 6) & 0x3f) << 8) + *(hdr + 7); + memcpy((void *)NetRxPackets[rx_new], hdr + 12, length); + + stat &= ~MBOX_STAT_CP; + mbox->stat = stat; +#ifdef DEBUG + { + int i; + for (i=0;i +#include +#include "rtl8019.h" +#include + +#ifdef CONFIG_DRIVER_RTL8019 + +#if defined(CONFIG_CMD_NET) + + +/* packet page register access functions */ + + +static unsigned char get_reg (unsigned int regno) +{ + return (*(unsigned char *) regno); +} + + +static void put_reg (unsigned int regno, unsigned char val) +{ + *(volatile unsigned char *) regno = val; +} + +static void eth_reset (void) +{ + unsigned char ucTemp; + + /* reset NIC */ + ucTemp = get_reg (RTL8019_RESET); + put_reg (RTL8019_RESET, ucTemp); + put_reg (RTL8019_INTERRUPTSTATUS, 0xff); + udelay (2000); /* wait for 2ms */ +} + +void rtl8019_get_enetaddr (uchar * addr) +{ + unsigned char i; + unsigned char temp; + + eth_reset (); + + put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + put_reg (RTL8019_DATACONFIGURATION, 0x48); + put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); + put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00); + put_reg (RTL8019_REMOTEBYTECOUNT0, 12); + put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + printf ("MAC: "); + for (i = 0; i < 6; i++) { + temp = get_reg (RTL8019_DMA_DATA); + *addr++ = temp; + temp = get_reg (RTL8019_DMA_DATA); + printf ("%x:", temp); + } + + while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40)); + printf ("\b \n"); + put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); + put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8019_COMMAND, RTL8019_PAGE0); +} + + +void eth_halt (void) +{ + put_reg (RTL8019_COMMAND, 0x01); +} + +int eth_init (bd_t * bd) +{ + eth_reset (); + put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); + put_reg (RTL8019_DATACONFIGURATION, 0x48); + put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); + put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8019_RECEIVECONFIGURATION, 0x00); /*00; */ + put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); + put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02); + put_reg (RTL8019_PAGESTART, RTL8019_PSTART); + put_reg (RTL8019_BOUNDARY, RTL8019_PSTART); + put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP); + put_reg (RTL8019_INTERRUPTSTATUS, 0xff); + put_reg (RTL8019_INTERRUPTMASK, 0x11); /*b; */ + put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP); + put_reg (RTL8019_PHYSICALADDRESS0, bd->bi_enetaddr[0]); + put_reg (RTL8019_PHYSICALADDRESS1, bd->bi_enetaddr[1]); + put_reg (RTL8019_PHYSICALADDRESS2, bd->bi_enetaddr[2]); + put_reg (RTL8019_PHYSICALADDRESS3, bd->bi_enetaddr[3]); + put_reg (RTL8019_PHYSICALADDRESS4, bd->bi_enetaddr[4]); + put_reg (RTL8019_PHYSICALADDRESS5, bd->bi_enetaddr[5]); + put_reg (RTL8019_MULTIADDRESS0, 0x00); + put_reg (RTL8019_MULTIADDRESS1, 0x00); + put_reg (RTL8019_MULTIADDRESS2, 0x00); + put_reg (RTL8019_MULTIADDRESS3, 0x00); + put_reg (RTL8019_MULTIADDRESS4, 0x00); + put_reg (RTL8019_MULTIADDRESS5, 0x00); + put_reg (RTL8019_MULTIADDRESS6, 0x00); + put_reg (RTL8019_MULTIADDRESS7, 0x00); + put_reg (RTL8019_CURRENT, RTL8019_PSTART); + put_reg (RTL8019_COMMAND, RTL8019_PAGE0); + put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); /*58; */ + + return 0; +} + + +static unsigned char nic_to_pc (void) +{ + unsigned char rec_head_status; + unsigned char next_packet_pointer; + unsigned char packet_length0; + unsigned char packet_length1; + unsigned short rxlen = 0; + unsigned int i = 4; + unsigned char current_point; + unsigned char *addr; + + /* + * The RTL8019's first 4B is packet status,page of next packet + * and packet length(2B).So we receive the fist 4B. + */ + put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); + put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); + put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04); + + put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + + rec_head_status = get_reg (RTL8019_DMA_DATA); + next_packet_pointer = get_reg (RTL8019_DMA_DATA); + packet_length0 = get_reg (RTL8019_DMA_DATA); + packet_length1 = get_reg (RTL8019_DMA_DATA); + + put_reg (RTL8019_COMMAND, RTL8019_PAGE0); + /*Packet length is in two 8bit registers */ + rxlen = packet_length1; + rxlen = (((rxlen << 8) & 0xff00) + packet_length0); + rxlen -= 4; + + if (rxlen > PKTSIZE_ALIGN + PKTALIGN) + printf ("packet too big!\n"); + + /*Receive the packet */ + put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04); + put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); + + put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff)); + put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff)); + + + put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + + for (addr = (unsigned char *) NetRxPackets[0], i = rxlen; i > 0; i--) + *addr++ = get_reg (RTL8019_DMA_DATA); + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], rxlen); + + while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); /* wait for the op. */ + + /* + * To test whether the packets are all received,get the + * location of current point + */ + put_reg (RTL8019_COMMAND, RTL8019_PAGE1); + current_point = get_reg (RTL8019_CURRENT); + put_reg (RTL8019_COMMAND, RTL8019_PAGE0); + put_reg (RTL8019_BOUNDARY, next_packet_pointer); + return current_point; +} + +/* Get a data block via Ethernet */ +extern int eth_rx (void) +{ + unsigned char temp, current_point; + + put_reg (RTL8019_COMMAND, RTL8019_PAGE0); + + while (1) { + temp = get_reg (RTL8019_INTERRUPTSTATUS); + + if (temp & 0x90) { + /*overflow */ + put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); + udelay (2000); + put_reg (RTL8019_REMOTEBYTECOUNT0, 0); + put_reg (RTL8019_REMOTEBYTECOUNT1, 0); + put_reg (RTL8019_TRANSMITCONFIGURATION, 2); + do { + current_point = nic_to_pc (); + } while (get_reg (RTL8019_BOUNDARY) != current_point); + + put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); + } + + if (temp & 0x1) { + /*packet received */ + do { + put_reg (RTL8019_INTERRUPTSTATUS, 0x01); + current_point = nic_to_pc (); + } while (get_reg (RTL8019_BOUNDARY) != current_point); + } + + if (!(temp & 0x1)) + return 0; + /* done and exit. */ + } +} + +/* Send a data block via Ethernet. */ +extern int eth_send (volatile void *packet, int length) +{ + volatile unsigned char *p; + unsigned int pn; + + pn = length; + p = (volatile unsigned char *) packet; + + while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT); + + put_reg (RTL8019_REMOTESTARTADDRESS0, 0); + put_reg (RTL8019_REMOTESTARTADDRESS1, RTL8019_TPSTART); + put_reg (RTL8019_REMOTEBYTECOUNT0, (pn & 0xff)); + put_reg (RTL8019_REMOTEBYTECOUNT1, ((pn >> 8) & 0xff)); + + put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR); + while (pn > 0) { + put_reg (RTL8019_DMA_DATA, *p++); + pn--; + } + + pn = length; + + while (pn < 60) { /*Padding */ + put_reg (RTL8019_DMA_DATA, 0); + pn++; + } + + while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); + + put_reg (RTL8019_INTERRUPTSTATUS, 0x40); + put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); + put_reg (RTL8019_TRANSMITBYTECOUNT0, (pn & 0xff)); + put_reg (RTL8019_TRANSMITBYTECOUNT1, ((pn >> 8 & 0xff))); + put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT); + + return 0; +} + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_RTL8019 */ diff --git a/drivers/net/rtl8019.h b/drivers/net/rtl8019.h new file mode 100644 index 0000000000..38116ad845 --- /dev/null +++ b/drivers/net/rtl8019.h @@ -0,0 +1,117 @@ +/* + * Realtek 8019AS Ethernet + * (C) Copyright 2002-2003 + * Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * This code works in 8bit mode. + * If you need to work in 16bit mode, PLS change it! + */ + +#include +#include + + +#ifdef CONFIG_DRIVER_RTL8019 + +#define RTL8019_REG_00 (RTL8019_BASE + 0x00) +#define RTL8019_REG_01 (RTL8019_BASE + 0x01) +#define RTL8019_REG_02 (RTL8019_BASE + 0x02) +#define RTL8019_REG_03 (RTL8019_BASE + 0x03) +#define RTL8019_REG_04 (RTL8019_BASE + 0x04) +#define RTL8019_REG_05 (RTL8019_BASE + 0x05) +#define RTL8019_REG_06 (RTL8019_BASE + 0x06) +#define RTL8019_REG_07 (RTL8019_BASE + 0x07) +#define RTL8019_REG_08 (RTL8019_BASE + 0x08) +#define RTL8019_REG_09 (RTL8019_BASE + 0x09) +#define RTL8019_REG_0a (RTL8019_BASE + 0x0a) +#define RTL8019_REG_0b (RTL8019_BASE + 0x0b) +#define RTL8019_REG_0c (RTL8019_BASE + 0x0c) +#define RTL8019_REG_0d (RTL8019_BASE + 0x0d) +#define RTL8019_REG_0e (RTL8019_BASE + 0x0e) +#define RTL8019_REG_0f (RTL8019_BASE + 0x0f) +#define RTL8019_REG_10 (RTL8019_BASE + 0x10) +#define RTL8019_REG_1f (RTL8019_BASE + 0x1f) + +#define RTL8019_COMMAND RTL8019_REG_00 +#define RTL8019_PAGESTART RTL8019_REG_01 +#define RTL8019_PAGESTOP RTL8019_REG_02 +#define RTL8019_BOUNDARY RTL8019_REG_03 +#define RTL8019_TRANSMITSTATUS RTL8019_REG_04 +#define RTL8019_TRANSMITPAGE RTL8019_REG_04 +#define RTL8019_TRANSMITBYTECOUNT0 RTL8019_REG_05 +#define RTL8019_NCR RTL8019_REG_05 +#define RTL8019_TRANSMITBYTECOUNT1 RTL8019_REG_06 +#define RTL8019_INTERRUPTSTATUS RTL8019_REG_07 +#define RTL8019_CURRENT RTL8019_REG_07 +#define RTL8019_REMOTESTARTADDRESS0 RTL8019_REG_08 +#define RTL8019_CRDMA0 RTL8019_REG_08 +#define RTL8019_REMOTESTARTADDRESS1 RTL8019_REG_09 +#define RTL8019_CRDMA1 RTL8019_REG_09 +#define RTL8019_REMOTEBYTECOUNT0 RTL8019_REG_0a +#define RTL8019_REMOTEBYTECOUNT1 RTL8019_REG_0b +#define RTL8019_RECEIVESTATUS RTL8019_REG_0c +#define RTL8019_RECEIVECONFIGURATION RTL8019_REG_0c +#define RTL8019_TRANSMITCONFIGURATION RTL8019_REG_0d +#define RTL8019_FAE_TALLY RTL8019_REG_0d +#define RTL8019_DATACONFIGURATION RTL8019_REG_0e +#define RTL8019_CRC_TALLY RTL8019_REG_0e +#define RTL8019_INTERRUPTMASK RTL8019_REG_0f +#define RTL8019_MISS_PKT_TALLY RTL8019_REG_0f +#define RTL8019_PHYSICALADDRESS0 RTL8019_REG_01 +#define RTL8019_PHYSICALADDRESS1 RTL8019_REG_02 +#define RTL8019_PHYSICALADDRESS2 RTL8019_REG_03 +#define RTL8019_PHYSICALADDRESS3 RTL8019_REG_04 +#define RTL8019_PHYSICALADDRESS4 RTL8019_REG_05 +#define RTL8019_PHYSICALADDRESS5 RTL8019_REG_06 +#define RTL8019_MULTIADDRESS0 RTL8019_REG_08 +#define RTL8019_MULTIADDRESS1 RTL8019_REG_09 +#define RTL8019_MULTIADDRESS2 RTL8019_REG_0a +#define RTL8019_MULTIADDRESS3 RTL8019_REG_0b +#define RTL8019_MULTIADDRESS4 RTL8019_REG_0c +#define RTL8019_MULTIADDRESS5 RTL8019_REG_0d +#define RTL8019_MULTIADDRESS6 RTL8019_REG_0e +#define RTL8019_MULTIADDRESS7 RTL8019_REG_0f +#define RTL8019_DMA_DATA RTL8019_REG_10 +#define RTL8019_RESET RTL8019_REG_1f + + +#define RTL8019_PAGE0 0x22 +#define RTL8019_PAGE1 0x62 +#define RTL8019_PAGE0DMAWRITE 0x12 +#define RTL8019_PAGE2DMAWRITE 0x92 +#define RTL8019_REMOTEDMAWR 0x12 +#define RTL8019_REMOTEDMARD 0x0A +#define RTL8019_ABORTDMAWR 0x32 +#define RTL8019_ABORTDMARD 0x2A +#define RTL8019_PAGE0STOP 0x21 +#define RTL8019_PAGE1STOP 0x61 +#define RTL8019_TRANSMIT 0x26 +#define RTL8019_TXINPROGRESS 0x04 +#define RTL8019_SEND 0x1A + +#define RTL8019_PSTART 0x4c +#define RTL8019_PSTOP 0x80 +#define RTL8019_TPSTART 0x40 + + +#endif /*end of CONFIG_DRIVER_RTL8019*/ diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c new file mode 100644 index 0000000000..2367180057 --- /dev/null +++ b/drivers/net/rtl8139.c @@ -0,0 +1,547 @@ +/* + * rtl8139.c : U-Boot driver for the RealTek RTL8139 + * + * Masami Komiya (mkomiya@sonare.it) + * + * Most part is taken from rtl8139.c of etherboot + * + */ + +/* rtl8139.c - etherboot driver for the Realtek 8139 chipset + + ported from the linux driver written by Donald Becker + by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + changes to the original driver: + - removed support for interrupts, switching to polling mode (yuck!) + - removed support for the 8129 chip (external MII) + +*/ + +/*********************************************************************/ +/* Revision History */ +/*********************************************************************/ + +/* + 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap) + Put in virt_to_bus calls to allow Etherboot relocation. + + 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap) + Following email from Hyun-Joon Cha, added a disable routine, otherwise + NIC remains live and can crash the kernel later. + + 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub) + Shuffled things around, removed the leftovers from the 8129 support + that was in the Linux driver and added a bit more 8139 definitions. + Moved the 8K receive buffer to a fixed, available address outside the + 0x98000-0x9ffff range. This is a bit of a hack, but currently the only + way to make room for the Etherboot features that need substantial amounts + of code like the ANSI console support. Currently the buffer is just below + 0x10000, so this even conforms to the tagged boot image specification, + which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My + interpretation of this "reserved" is that Etherboot may do whatever it + likes, as long as its environment is kept intact (like the BIOS + variables). Hopefully fixed rtl_poll() once and for all. The symptoms + were that if Etherboot was left at the boot menu for several minutes, the + first eth_poll failed. Seems like I am the only person who does this. + First of all I fixed the debugging code and then set out for a long bug + hunting session. It took me about a week full time work - poking around + various places in the driver, reading Don Becker's and Jeff Garzik's Linux + driver and even the FreeBSD driver (what a piece of crap!) - and + eventually spotted the nasty thing: the transmit routine was acknowledging + each and every interrupt pending, including the RxOverrun and RxFIFIOver + interrupts. This confused the RTL8139 thoroughly. It destroyed the + Rx ring contents by dumping the 2K FIFO contents right where we wanted to + get the next packet. Oh well, what fun. + + 18 Jan 2000 mdc@thinguin.org (Marty Connor) + Drastically simplified error handling. Basically, if any error + in transmission or reception occurs, the card is reset. + Also, pointed all transmit descriptors to the same buffer to + save buffer space. This should decrease driver size and avoid + corruption because of exceeding 32K during runtime. + + 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) + rtl_poll was quite broken: it used the RxOK interrupt flag instead + of the RxBufferEmpty flag which often resulted in very bad + transmission performace - below 1kBytes/s. + +*/ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_RTL8139) + +#define TICKS_PER_SEC CFG_HZ +#define TICKS_PER_MS (TICKS_PER_SEC/1000) + +#define RTL_TIMEOUT (1*TICKS_PER_SEC) + +#define ETH_FRAME_LEN 1514 +#define ETH_ALEN 6 +#define ETH_ZLEN 60 + +/* PCI Tuning Parameters + Threshold is bytes transferred to chip before transmission starts. */ +#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ +#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ +#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ +#define TX_DMA_BURST 4 /* Calculate as 16<priv, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) + +/* Symbolic offsets to registers. */ +enum RTL8139_registers { + MAC0=0, /* Ethernet hardware address. */ + MAR0=8, /* Multicast filter. */ + TxStatus0=0x10, /* Transmit status (four 32bit registers). */ + TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ + RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, + ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, + IntrMask=0x3C, IntrStatus=0x3E, + TxConfig=0x40, RxConfig=0x44, + Timer=0x48, /* general-purpose counter. */ + RxMissed=0x4C, /* 24 bits valid, write clears. */ + Cfg9346=0x50, Config0=0x51, Config1=0x52, + TimerIntrReg=0x54, /* intr if gp counter reaches this value */ + MediaStatus=0x58, + Config3=0x59, + MultiIntr=0x5C, + RevisionID=0x5E, /* revision of the RTL8139 chip */ + TxSummary=0x60, + MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, + NWayExpansion=0x6A, + DisconnectCnt=0x6C, FalseCarrierCnt=0x6E, + NWayTestReg=0x70, + RxCnt=0x72, /* packet received counter */ + CSCR=0x74, /* chip status and configuration register */ + PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80, /* undocumented */ + /* from 0x84 onwards are a number of power management/wakeup frame + * definitions we will probably never need to know about. */ +}; + +enum ChipCmdBits { + CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, }; + +/* Interrupt register bits, using my own meaningful names. */ +enum IntrStatusBits { + PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000, + RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10, + TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01, +}; +enum TxStatusBits { + TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000, + TxOutOfWindow=0x20000000, TxAborted=0x40000000, + TxCarrierLost=0x80000000, +}; +enum RxStatusBits { + RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000, + RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004, + RxBadAlign=0x0002, RxStatusOK=0x0001, +}; + +enum MediaStatusBits { + MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08, + MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01, +}; + +enum MIIBMCRBits { + BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000, + BMCRRestartNWay=0x0200, BMCRDuplex=0x0100, +}; + +enum CSCRBits { + CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, + CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, + CSCR_LinkDownCmd=0x0f3c0, +}; + +/* Bits in RxConfig. */ +enum rx_mode_bits { + RxCfgWrap=0x80, + AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, + AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, +}; + +static int ioaddr; +static unsigned int cur_rx,cur_tx; + +/* The RTL8139 can only transmit from a contiguous, aligned memory block. */ +static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); +static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); + +static int rtl8139_probe(struct eth_device *dev, bd_t *bis); +static int read_eeprom(int location, int addr_len); +static void rtl_reset(struct eth_device *dev); +static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length); +static int rtl_poll(struct eth_device *dev); +static void rtl_disable(struct eth_device *dev); +#ifdef CONFIG_MCAST_TFTP/* This driver already accepts all b/mcast */ +static int rtl_bcast_addr (struct eth_device *dev, u8 bcast_mac, u8 set) +{ + return (0); +} +#endif + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139}, + {PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139}, + {} +}; + +int rtl8139_initialize(bd_t *bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase; + int idx=0; + + while(1){ + /* Find RTL8139 */ + if ((devno = pci_find_devices(supported, idx++)) < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug ("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + + dev = (struct eth_device *)malloc(sizeof *dev); + + sprintf (dev->name, "RTL8139#%d", card_number); + + dev->priv = (void *) devno; + dev->iobase = (int)bus_to_phys(iobase); + dev->init = rtl8139_probe; + dev->halt = rtl_disable; + dev->send = rtl_transmit; + dev->recv = rtl_poll; +#ifdef CONFIG_MCAST_TFTP + dev->mcast = rtl_bcast_addr; +#endif + + eth_register (dev); + + card_number++; + + pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); + + udelay (10 * 1000); + } + + return card_number; +} + +static int rtl8139_probe(struct eth_device *dev, bd_t *bis) +{ + int i; + int speed10, fullduplex; + int addr_len; + unsigned short *ap = (unsigned short *)dev->enetaddr; + + ioaddr = dev->iobase; + + /* Bring the chip out of low-power mode. */ + outb(0x00, ioaddr + Config1); + + addr_len = read_eeprom(0,8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + *ap++ = le16_to_cpu (read_eeprom(i + 7, addr_len)); + + speed10 = inb(ioaddr + MediaStatus) & MSRSpeed10; + fullduplex = inw(ioaddr + MII_BMCR) & BMCRDuplex; + + rtl_reset(dev); + + if (inb(ioaddr + MediaStatus) & MSRLinkFail) { + printf("Cable not connected or other link failure\n"); + return(0); + } + + return 1; +} + +/* Serial EEPROM section. */ + +/* EEPROM_Ctrl bits. */ +#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ +#define EE_CS 0x08 /* EEPROM chip select. */ +#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x00 +#define EE_WRITE_1 0x02 +#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ +#define EE_ENB (0x80 | EE_CS) + +/* + Delay between EEPROM clock transitions. + No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. +*/ + +#define eeprom_delay() inl(ee_addr) + +/* The EEPROM commands include the alway-set leading bit. */ +#define EE_WRITE_CMD (5) +#define EE_READ_CMD (6) +#define EE_ERASE_CMD (7) + +static int read_eeprom(int location, int addr_len) +{ + int i; + unsigned int retval = 0; + long ee_addr = ioaddr + Cfg9346; + int read_cmd = location | (EE_READ_CMD << addr_len); + + outb(EE_ENB & ~EE_CS, ee_addr); + outb(EE_ENB, ee_addr); + eeprom_delay(); + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + outb(EE_ENB | dataval, ee_addr); + eeprom_delay(); + outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + } + outb(EE_ENB, ee_addr); + eeprom_delay(); + + for (i = 16; i > 0; i--) { + outb(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); + outb(EE_ENB, ee_addr); + eeprom_delay(); + } + + /* Terminate the EEPROM access. */ + outb(~EE_CS, ee_addr); + eeprom_delay(); + return retval; +} + +static const unsigned int rtl8139_rx_config = + (RX_BUF_LEN_IDX << 11) | + (RX_FIFO_THRESH << 13) | + (RX_DMA_BURST << 8); + +static void set_rx_mode(struct eth_device *dev) { + unsigned int mc_filter[2]; + int rx_mode; + /* !IFF_PROMISC */ + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + + outl(rtl8139_rx_config | rx_mode, ioaddr + RxConfig); + + outl(mc_filter[0], ioaddr + MAR0 + 0); + outl(mc_filter[1], ioaddr + MAR0 + 4); +} + +static void rtl_reset(struct eth_device *dev) +{ + int i; + + outb(CmdReset, ioaddr + ChipCmd); + + cur_rx = 0; + cur_tx = 0; + + /* Give the chip 10ms to finish the reset. */ + for (i=0; i<100; ++i){ + if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; + udelay (100); /* wait 100us */ + } + + + for (i = 0; i < ETH_ALEN; i++) + outb(dev->enetaddr[i], ioaddr + MAC0 + i); + + /* Must enable Tx/Rx before setting transfer thresholds! */ + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8), + ioaddr + RxConfig); /* accept no frames yet! */ + outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); + + /* The Linux driver changes Config1 here to use a different LED pattern + * for half duplex or full/autodetect duplex (for full/autodetect, the + * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses + * TX/RX, Link100, Link10). This is messy, because it doesn't match + * the inscription on the mounting bracket. It should not be changed + * from the configuration EEPROM default, because the card manufacturer + * should have set that to match the card. */ + +#ifdef DEBUG_RX + printf("rx ring address is %X\n",(unsigned long)rx_ring); +#endif + outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf); + + /* If we add multicast support, the MAR0 register would have to be + * initialized to 0xffffffffffffffff (two 32 bit accesses). Etherboot + * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast. */ + + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + + outl(rtl8139_rx_config, ioaddr + RxConfig); + + /* Start the chip's Tx and Rx process. */ + outl(0, ioaddr + RxMissed); + + /* set_rx_mode */ + set_rx_mode(dev); + + /* Disable all known interrupts by setting the interrupt mask. */ + outw(0, ioaddr + IntrMask); +} + +static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length) +{ + unsigned int status, to; + unsigned long txstatus; + unsigned int len = length; + + ioaddr = dev->iobase; + + memcpy((char *)tx_buffer, (char *)packet, (int)length); + +#ifdef DEBUG_TX + printf("sending %d bytes\n", len); +#endif + + /* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 + * bytes are sent automatically for the FCS, totalling to 64 bytes). */ + while (len < ETH_ZLEN) { + tx_buffer[len++] = '\0'; + } + + outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); + outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, + ioaddr + TxStatus0 + cur_tx*4); + + to = currticks() + RTL_TIMEOUT; + + do { + status = inw(ioaddr + IntrStatus); + /* Only acknlowledge interrupt sources we can properly handle + * here - the RxOverflow/RxFIFOOver MUST be handled in the + * rtl_poll() function. */ + outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); + if ((status & (TxOK | TxErr | PCIErr)) != 0) break; + } while (currticks() < to); + + txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); + + if (status & TxOK) { + cur_tx = (cur_tx + 1) % NUM_TX_DESC; +#ifdef DEBUG_TX + printf("tx done (%d ticks), status %hX txstatus %X\n", + to-currticks(), status, txstatus); +#endif + return length; + } else { +#ifdef DEBUG_TX + printf("tx timeout/error (%d ticks), status %hX txstatus %X\n", + currticks()-to, status, txstatus); +#endif + rtl_reset(dev); + + return 0; + } +} + +static int rtl_poll(struct eth_device *dev) +{ + unsigned int status; + unsigned int ring_offs; + unsigned int rx_size, rx_status; + int length=0; + + ioaddr = dev->iobase; + + if (inb(ioaddr + ChipCmd) & RxBufEmpty) { + return 0; + } + + status = inw(ioaddr + IntrStatus); + /* See below for the rest of the interrupt acknowledges. */ + outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); + +#ifdef DEBUG_RX + printf("rtl_poll: int %hX ", status); +#endif + + ring_offs = cur_rx % RX_BUF_LEN; + rx_status = *(unsigned int*)KSEG1ADDR((rx_ring + ring_offs)); + rx_size = rx_status >> 16; + rx_status &= 0xffff; + + if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) || + (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { + printf("rx error %hX\n", rx_status); + rtl_reset(dev); /* this clears all interrupts still pending */ + return 0; + } + + /* Received a good packet */ + length = rx_size - 4; /* no one cares about the FCS */ + if (ring_offs+4+rx_size-4 > RX_BUF_LEN) { + int semi_count = RX_BUF_LEN - ring_offs - 4; + unsigned char rxdata[RX_BUF_LEN]; + + memcpy(rxdata, rx_ring + ring_offs + 4, semi_count); + memcpy(&(rxdata[semi_count]), rx_ring, rx_size-4-semi_count); + + NetReceive(rxdata, length); +#ifdef DEBUG_RX + printf("rx packet %d+%d bytes", semi_count,rx_size-4-semi_count); +#endif + } else { + NetReceive(rx_ring + ring_offs + 4, length); +#ifdef DEBUG_RX + printf("rx packet %d bytes", rx_size-4); +#endif + } + + cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; + outw(cur_rx - 16, ioaddr + RxBufPtr); + /* See RTL8139 Programming Guide V0.1 for the official handling of + * Rx overflow situations. The document itself contains basically no + * usable information, except for a few exception handling rules. */ + outw(status & (RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); + return length; +} + +static void rtl_disable(struct eth_device *dev) +{ + int i; + + ioaddr = dev->iobase; + + /* reset the chip */ + outb(CmdReset, ioaddr + ChipCmd); + + /* Give the chip 10ms to finish the reset. */ + for (i=0; i<100; ++i){ + if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; + udelay (100); /* wait 100us */ + } +} +#endif diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c new file mode 100644 index 0000000000..63ea2cca9b --- /dev/null +++ b/drivers/net/rtl8169.c @@ -0,0 +1,888 @@ +/* + * rtl8169.c : U-Boot driver for the RealTek RTL8169 + * + * Masami Komiya (mkomiya@sonare.it) + * + * Most part is taken from r8169.c of etherboot + * + */ + +/************************************************************************** +* r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit +* Written 2003 by Timothy Legge +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Portions of this code based on: +* r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver +* for Linux kernel 2.4.x. +* +* Written 2002 ShuChen +* See Linux Driver for full information +* +* Linux Driver Version 1.27a, 10.02.2002 +* +* Thanks to: +* Jean Chen of RealTek Semiconductor Corp. for +* providing the evaluation NIC used to develop +* this driver. RealTek's support for Etherboot +* is appreciated. +* +* REVISION HISTORY: +* ================ +* +* v1.0 11-26-2003 timlegge Initial port of Linux driver +* v1.5 01-17-2004 timlegge Initial driver output cleanup +* +* Indent Options: indent -kr -i8 +***************************************************************************/ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_RTL8169) + +#undef DEBUG_RTL8169 +#undef DEBUG_RTL8169_TX +#undef DEBUG_RTL8169_RX + +#define drv_version "v1.5" +#define drv_date "01-17-2004" + +static u32 ioaddr; + +/* Condensed operations for readability. */ +#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) +#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) + +#define currticks() get_timer(0) +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) + +/* media options */ +#define MAX_UNITS 8 +static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + +/* MAC address length*/ +#define MAC_ADDR_LEN 6 + +/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ +#define MAX_ETH_FRAME_SIZE 1536 + +#define TX_FIFO_THRESH 256 /* In bytes */ + +#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ +#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ +#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ +#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ + +#define NUM_TX_DESC 1 /* Number of Tx descriptor registers */ +#define NUM_RX_DESC 4 /* Number of Rx descriptor registers */ +#define RX_BUF_SIZE 1536 /* Rx Buffer size */ +#define RX_BUF_LEN 8192 + +#define RTL_MIN_IO_SIZE 0x80 +#define TX_TIMEOUT (6*HZ) + +/* write/read MMIO register */ +#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) +#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) +#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) +#define RTL_R8(reg) readb (ioaddr + (reg)) +#define RTL_R16(reg) readw (ioaddr + (reg)) +#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) + +#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE +#define ETH_ALEN MAC_ADDR_LEN +#define ETH_ZLEN 60 + +enum RTL8169_registers { + MAC0 = 0, /* Ethernet hardware address. */ + MAR0 = 8, /* Multicast filter. */ + TxDescStartAddr = 0x20, + TxHDescStartAddr = 0x28, + FLASH = 0x30, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + RxMissed = 0x4C, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + MultiIntr = 0x5C, + PHYAR = 0x60, + TBICSR = 0x64, + TBI_ANAR = 0x68, + TBI_LPAR = 0x6A, + PHYstatus = 0x6C, + RxMaxSize = 0xDA, + CPlusCmd = 0xE0, + RxDescStartAddr = 0xE4, + EarlyTxThres = 0xEC, + FuncEvent = 0xF0, + FuncEventMask = 0xF4, + FuncPresetState = 0xF8, + FuncForceEvent = 0xFC, +}; + +enum RTL8169_register_content { + /*InterruptStatusBits */ + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x80, + RxFIFOOver = 0x40, + RxUnderrun = 0x20, + RxOverflow = 0x10, + TxErr = 0x08, + TxOK = 0x04, + RxErr = 0x02, + RxOK = 0x01, + + /*RxStatusDesc */ + RxRES = 0x00200000, + RxCRC = 0x00080000, + RxRUNT = 0x00100000, + RxRWT = 0x00400000, + + /*ChipCmdBits */ + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /*Cfg9346Bits */ + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xC0, + + /*rx_mode_bits */ + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, + + /*RxConfigBits */ + RxCfgFIFOShift = 13, + RxCfgDMAShift = 8, + + /*TxConfigBits */ + TxInterFrameGapShift = 24, + TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + + /*rtl8169_PHYstatus */ + TBI_Enable = 0x80, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, + + /*GIGABIT_PHY_registers */ + PHY_CTRL_REG = 0, + PHY_STAT_REG = 1, + PHY_AUTO_NEGO_REG = 4, + PHY_1000_CTRL_REG = 9, + + /*GIGABIT_PHY_REG_BIT */ + PHY_Restart_Auto_Nego = 0x0200, + PHY_Enable_Auto_Nego = 0x1000, + + /* PHY_STAT_REG = 1; */ + PHY_Auto_Neco_Comp = 0x0020, + + /* PHY_AUTO_NEGO_REG = 4; */ + PHY_Cap_10_Half = 0x0020, + PHY_Cap_10_Full = 0x0040, + PHY_Cap_100_Half = 0x0080, + PHY_Cap_100_Full = 0x0100, + + /* PHY_1000_CTRL_REG = 9; */ + PHY_Cap_1000_Full = 0x0200, + + PHY_Cap_Null = 0x0, + + /*_MediaType*/ + _10_Half = 0x01, + _10_Full = 0x02, + _100_Half = 0x04, + _100_Full = 0x08, + _1000_Full = 0x10, + + /*_TBICSRBit*/ + TBILinkOK = 0x02000000, +}; + +static struct { + const char *name; + u8 version; /* depend on RTL8169 docs */ + u32 RxConfigMask; /* should clear the bits supported by this chip */ +} rtl_chip_info[] = { + {"RTL-8169", 0x00, 0xff7e1880,}, + {"RTL-8169", 0x04, 0xff7e1880,}, +}; + +enum _DescStatusBit { + OWNbit = 0x80000000, + EORbit = 0x40000000, + FSbit = 0x20000000, + LSbit = 0x10000000, +}; + +struct TxDesc { + u32 status; + u32 vlan_tag; + u32 buf_addr; + u32 buf_Haddr; +}; + +struct RxDesc { + u32 status; + u32 vlan_tag; + u32 buf_addr; + u32 buf_Haddr; +}; + +/* Define the TX Descriptor */ +static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256]; +/* __attribute__ ((aligned(256))); */ + +/* Create a static buffer of size RX_BUF_SZ for each +TX Descriptor. All descriptors point to a +part of this buffer */ +static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE]; + +/* Define the RX Descriptor */ +static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256]; + /* __attribute__ ((aligned(256))); */ + +/* Create a static buffer of size RX_BUF_SZ for each +RX Descriptor All descriptors point to a +part of this buffer */ +static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; + +struct rtl8169_private { + void *mmio_addr; /* memory map physical address */ + int chipset; + unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ + unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ + unsigned long dirty_tx; + unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */ + unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ + struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + unsigned char *RxBufferRings; /* Index of Rx Buffer */ + unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */ + unsigned char *Tx_skbuff[NUM_TX_DESC]; +} tpx; + +static struct rtl8169_private *tpc; + +static const u16 rtl8169_intr_mask = + SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | + TxOK | RxErr | RxOK; +static const unsigned int rtl8169_rx_config = + (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_REALTEK, 0x8169}, + {} +}; + +void mdio_write(int RegAddr, int value) +{ + int i; + + RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); + udelay(1000); + + for (i = 2000; i > 0; i--) { + /* Check if the RTL8169 has completed writing to the specified MII register */ + if (!(RTL_R32(PHYAR) & 0x80000000)) { + break; + } else { + udelay(100); + } + } +} + +int mdio_read(int RegAddr) +{ + int i, value = -1; + + RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); + udelay(1000); + + for (i = 2000; i > 0; i--) { + /* Check if the RTL8169 has completed retrieving data from the specified MII register */ + if (RTL_R32(PHYAR) & 0x80000000) { + value = (int) (RTL_R32(PHYAR) & 0xFFFF); + break; + } else { + udelay(100); + } + } + return value; +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static int rtl8169_init_board(struct eth_device *dev) +{ + int i; + u32 tmp; + +#ifdef DEBUG_RTL8169 + printf ("%s\n", __FUNCTION__); +#endif + ioaddr = dev->iobase; + + /* Soft reset the chip. */ + RTL_W8(ChipCmd, CmdReset); + + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) + if ((RTL_R8(ChipCmd) & CmdReset) == 0) + break; + else + udelay(10); + + /* identify chip attached to board */ + tmp = RTL_R32(TxConfig); + tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24; + + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--){ + if (tmp == rtl_chip_info[i].version) { + tpc->chipset = i; + goto match; + } + } + + /* if unknown chip, assume array element #0, original RTL-8169 in this case */ + printf("PCI device %s: unknown chip version, assuming RTL-8169\n", dev->name); + printf("PCI device: TxConfig = 0x%hX\n", (unsigned long) RTL_R32(TxConfig)); + tpc->chipset = 0; + +match: + return 0; +} + +/************************************************************************** +RECV - Receive a frame +***************************************************************************/ +static int rtl_recv(struct eth_device *dev) +{ + /* return true if there's an ethernet packet ready to read */ + /* nic->packet should contain data on return */ + /* nic->packetlen should contain length of data */ + int cur_rx; + int length = 0; + +#ifdef DEBUG_RTL8169_RX + printf ("%s\n", __FUNCTION__); +#endif + ioaddr = dev->iobase; + + cur_rx = tpc->cur_rx; + if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { + if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { + unsigned char rxdata[RX_BUF_LEN]; + length = (int) (tpc->RxDescArray[cur_rx]. + status & 0x00001FFF) - 4; + + memcpy(rxdata, tpc->RxBufferRing[cur_rx], length); + NetReceive(rxdata, length); + + if (cur_rx == NUM_RX_DESC - 1) + tpc->RxDescArray[cur_rx].status = + (OWNbit | EORbit) + RX_BUF_SIZE; + else + tpc->RxDescArray[cur_rx].status = + OWNbit + RX_BUF_SIZE; + tpc->RxDescArray[cur_rx].buf_addr = + virt_to_bus(tpc->RxBufferRing[cur_rx]); + } else { + puts("Error Rx"); + } + cur_rx = (cur_rx + 1) % NUM_RX_DESC; + tpc->cur_rx = cur_rx; + return 1; + + } + tpc->cur_rx = cur_rx; + return (0); /* initially as this is called to flush the input */ +} + +#define HZ 1000 +/************************************************************************** +SEND - Transmit a frame +***************************************************************************/ +static int rtl_send(struct eth_device *dev, volatile void *packet, int length) +{ + /* send the packet to destination */ + + u32 to; + u8 *ptxb; + int entry = tpc->cur_tx % NUM_TX_DESC; + u32 len = length; + +#ifdef DEBUG_RTL8169_TX + int stime = currticks(); + printf ("%s\n", __FUNCTION__); + printf("sending %d bytes\n", len); +#endif + + ioaddr = dev->iobase; + + /* point to the current txb incase multiple tx_rings are used */ + ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; + memcpy(ptxb, (char *)packet, (int)length); + + while (len < ETH_ZLEN) + ptxb[len++] = '\0'; + + tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb); + if (entry != (NUM_TX_DESC - 1)) { + tpc->TxDescArray[entry].status = + (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? + len : ETH_ZLEN); + } else { + tpc->TxDescArray[entry].status = + (OWNbit | EORbit | FSbit | LSbit) | + ((len > ETH_ZLEN) ? length : ETH_ZLEN); + } + RTL_W8(TxPoll, 0x40); /* set polling bit */ + + tpc->cur_tx++; + to = currticks() + TX_TIMEOUT; + while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ + + if (currticks() >= to) { +#ifdef DEBUG_RTL8169_TX + puts ("tx timeout/error\n"); + printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); +#endif + return 0; + } else { +#ifdef DEBUG_RTL8169_TX + puts("tx done\n"); +#endif + return length; + } +} + +static void rtl8169_set_rx_mode(struct eth_device *dev) +{ + u32 mc_filter[2]; /* Multicast hash filter */ + int rx_mode; + u32 tmp = 0; + +#ifdef DEBUG_RTL8169 + printf ("%s\n", __FUNCTION__); +#endif + + /* IFF_ALLMULTI */ + /* Too many to filter perfectly -- accept all multicasts. */ + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + + tmp = rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & + rtl_chip_info[tpc->chipset].RxConfigMask); + + RTL_W32(RxConfig, tmp); + RTL_W32(MAR0 + 0, mc_filter[0]); + RTL_W32(MAR0 + 4, mc_filter[1]); +} + +static void rtl8169_hw_start(struct eth_device *dev) +{ + u32 i; + +#ifdef DEBUG_RTL8169 + int stime = currticks(); + printf ("%s\n", __FUNCTION__); +#endif + +#if 0 + /* Soft reset the chip. */ + RTL_W8(ChipCmd, CmdReset); + + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) { + if ((RTL_R8(ChipCmd) & CmdReset) == 0) + break; + else + udelay(10); + } +#endif + + RTL_W8(Cfg9346, Cfg9346_Unlock); + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8(EarlyTxThres, EarlyTxThld); + + /* For gigabit rtl8169 */ + RTL_W16(RxMaxSize, RxPacketMaxSize); + + /* Set Rx Config register */ + i = rtl8169_rx_config | (RTL_R32(RxConfig) & + rtl_chip_info[tpc->chipset].RxConfigMask); + RTL_W32(RxConfig, i); + + /* Set DMA burst size and Interframe Gap Time */ + RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | + (InterFrameGap << TxInterFrameGapShift)); + + + tpc->cur_rx = 0; + + RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); + RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray)); + RTL_W8(Cfg9346, Cfg9346_Lock); + udelay(10); + + RTL_W32(RxMissed, 0); + + rtl8169_set_rx_mode(dev); + + /* no early-rx interrupts */ + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); + +#ifdef DEBUG_RTL8169 + printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); +#endif +} + +static void rtl8169_init_ring(struct eth_device *dev) +{ + int i; + +#ifdef DEBUG_RTL8169 + int stime = currticks(); + printf ("%s\n", __FUNCTION__); +#endif + + tpc->cur_rx = 0; + tpc->cur_tx = 0; + tpc->dirty_tx = 0; + memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); + memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); + + for (i = 0; i < NUM_TX_DESC; i++) { + tpc->Tx_skbuff[i] = &txb[i]; + } + + for (i = 0; i < NUM_RX_DESC; i++) { + if (i == (NUM_RX_DESC - 1)) + tpc->RxDescArray[i].status = + (OWNbit | EORbit) + RX_BUF_SIZE; + else + tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; + + tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; + tpc->RxDescArray[i].buf_addr = + virt_to_bus(tpc->RxBufferRing[i]); + } + +#ifdef DEBUG_RTL8169 + printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); +#endif +} + +/************************************************************************** +RESET - Finish setting up the ethernet interface +***************************************************************************/ +static void rtl_reset(struct eth_device *dev, bd_t *bis) +{ + int i; + u8 diff; + u32 TxPhyAddr, RxPhyAddr; + +#ifdef DEBUG_RTL8169 + int stime = currticks(); + printf ("%s\n", __FUNCTION__); +#endif + + tpc->TxDescArrays = tx_ring; + if (tpc->TxDescArrays == 0) + puts("Allot Error"); + /* Tx Desscriptor needs 256 bytes alignment; */ + TxPhyAddr = virt_to_bus(tpc->TxDescArrays); + diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); + TxPhyAddr += diff; + tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff); + + tpc->RxDescArrays = rx_ring; + /* Rx Desscriptor needs 256 bytes alignment; */ + RxPhyAddr = virt_to_bus(tpc->RxDescArrays); + diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); + RxPhyAddr += diff; + tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff); + + if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) { + puts("Allocate RxDescArray or TxDescArray failed\n"); + return; + } + + rtl8169_init_ring(dev); + rtl8169_hw_start(dev); + /* Construct a perfect filter frame with the mac address as first match + * and broadcast for all others */ + for (i = 0; i < 192; i++) + txb[i] = 0xFF; + + txb[0] = dev->enetaddr[0]; + txb[1] = dev->enetaddr[1]; + txb[2] = dev->enetaddr[2]; + txb[3] = dev->enetaddr[3]; + txb[4] = dev->enetaddr[4]; + txb[5] = dev->enetaddr[5]; + +#ifdef DEBUG_RTL8169 + printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); +#endif +} + +/************************************************************************** +HALT - Turn off ethernet interface +***************************************************************************/ +static void rtl_halt(struct eth_device *dev) +{ + int i; + +#ifdef DEBUG_RTL8169 + printf ("%s\n", __FUNCTION__); +#endif + + ioaddr = dev->iobase; + + /* Stop the chip's Tx and Rx DMA processes. */ + RTL_W8(ChipCmd, 0x00); + + /* Disable interrupts by clearing the interrupt mask. */ + RTL_W16(IntrMask, 0x0000); + + RTL_W32(RxMissed, 0); + + tpc->TxDescArrays = NULL; + tpc->RxDescArrays = NULL; + tpc->TxDescArray = NULL; + tpc->RxDescArray = NULL; + for (i = 0; i < NUM_RX_DESC; i++) { + tpc->RxBufferRing[i] = NULL; + } +} + +/************************************************************************** +INIT - Look for an adapter, this routine's visible to the outside +***************************************************************************/ + +#define board_found 1 +#define valid_link 0 +static int rtl_init(struct eth_device *dev, bd_t *bis) +{ + static int board_idx = -1; + static int printed_version = 0; + int i, rc; + int option = -1, Cap10_100 = 0, Cap1000 = 0; + +#ifdef DEBUG_RTL8169 + printf ("%s\n", __FUNCTION__); +#endif + + ioaddr = dev->iobase; + + board_idx++; + + printed_version = 1; + + /* point to private storage */ + tpc = &tpx; + + rc = rtl8169_init_board(dev); + if (rc) + return rc; + + /* Get MAC address. FIXME: read EEPROM */ + for (i = 0; i < MAC_ADDR_LEN; i++) + dev->enetaddr[i] = RTL_R8(MAC0 + i); + +#ifdef DEBUG_RTL8169 + printf("MAC Address"); + for (i = 0; i < MAC_ADDR_LEN; i++) + printf(":%02x", dev->enetaddr[i]); + putc('\n'); +#endif + +#ifdef DEBUG_RTL8169 + /* Print out some hardware info */ + printf("%s: at ioaddr 0x%x\n", dev->name, ioaddr); +#endif + + /* if TBI is not endbled */ + if (!(RTL_R8(PHYstatus) & TBI_Enable)) { + int val = mdio_read(PHY_AUTO_NEGO_REG); + + option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; + /* Force RTL8169 in 10/100/1000 Full/Half mode. */ + if (option > 0) { +#ifdef DEBUG_RTL8169 + printf("%s: Force-mode Enabled.\n", dev->name); +#endif + Cap10_100 = 0, Cap1000 = 0; + switch (option) { + case _10_Half: + Cap10_100 = PHY_Cap_10_Half; + Cap1000 = PHY_Cap_Null; + break; + case _10_Full: + Cap10_100 = PHY_Cap_10_Full; + Cap1000 = PHY_Cap_Null; + break; + case _100_Half: + Cap10_100 = PHY_Cap_100_Half; + Cap1000 = PHY_Cap_Null; + break; + case _100_Full: + Cap10_100 = PHY_Cap_100_Full; + Cap1000 = PHY_Cap_Null; + break; + case _1000_Full: + Cap10_100 = PHY_Cap_Null; + Cap1000 = PHY_Cap_1000_Full; + break; + default: + break; + } + mdio_write(PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); /* leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ + mdio_write(PHY_1000_CTRL_REG, Cap1000); + } else { +#ifdef DEBUG_RTL8169 + printf("%s: Auto-negotiation Enabled.\n", + dev->name); +#endif + /* enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ + mdio_write(PHY_AUTO_NEGO_REG, + PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full | + (val & 0x1F)); + + /* enable 1000 Full Mode */ + mdio_write(PHY_1000_CTRL_REG, PHY_Cap_1000_Full); + + } + + /* Enable auto-negotiation and restart auto-nigotiation */ + mdio_write(PHY_CTRL_REG, + PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); + udelay(100); + + /* wait for auto-negotiation process */ + for (i = 10000; i > 0; i--) { + /* check if auto-negotiation complete */ + if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) { + udelay(100); + option = RTL_R8(PHYstatus); + if (option & _1000bpsF) { +#ifdef DEBUG_RTL8169 + printf("%s: 1000Mbps Full-duplex operation.\n", + dev->name); +#endif + } else { +#ifdef DEBUG_RTL8169 + printf + ("%s: %sMbps %s-duplex operation.\n", + dev->name, + (option & _100bps) ? "100" : + "10", + (option & FullDup) ? "Full" : + "Half"); +#endif + } + break; + } else { + udelay(100); + } + } /* end for-loop to wait for auto-negotiation process */ + + } else { + udelay(100); +#ifdef DEBUG_RTL8169 + printf + ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", + dev->name, + (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); +#endif + } + + return 1; +} + +int rtl8169_initialize(bd_t *bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + u32 iobase; + int idx=0; + + while(1){ + /* Find RTL8169 */ + if ((devno = pci_find_devices(supported, idx++)) < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase); + + dev = (struct eth_device *)malloc(sizeof *dev); + + sprintf (dev->name, "RTL8169#%d", card_number); + + dev->priv = (void *) devno; + dev->iobase = (int)bus_to_phys(iobase); + + dev->init = rtl_reset; + dev->halt = rtl_halt; + dev->send = rtl_send; + dev->recv = rtl_recv; + + eth_register (dev); + + rtl_init(dev, bis); + + card_number++; + } + return card_number; +} + +#endif diff --git a/drivers/net/s3c4510b_eth.c b/drivers/net/s3c4510b_eth.c new file mode 100644 index 0000000000..3d9066abea --- /dev/null +++ b/drivers/net/s3c4510b_eth.c @@ -0,0 +1,246 @@ +/*********************************************************************** + * + * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) + * Curt Brune + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Description: Ethernet interface for Samsung S3C4510B SoC + */ + +#include + +#ifdef CONFIG_DRIVER_S3C4510_ETH + +#include +#include +#include +#include "s3c4510b_eth.h" + +static TX_FrameDescriptor txFDbase[ETH_MaxTxFrames]; +static MACFrame txFrameBase[ETH_MaxTxFrames]; +static RX_FrameDescriptor rxFDbase[PKTBUFSRX]; +static ETH m_eth; + +static s32 TxFDinit( ETH *eth) { + + s32 i; + MACFrame *txFrmBase; + + /* disable cache for access to the TX buffers */ + txFrmBase = (MACFrame *)( (u32)txFrameBase | CACHE_DISABLE_MASK); + + /* store start of Tx descriptors and set current */ + eth->m_curTX_FD = (TX_FrameDescriptor *) ((u32)txFDbase | CACHE_DISABLE_MASK); + eth->m_baseTX_FD = eth->m_curTX_FD; + + for ( i = 0; i < ETH_MaxTxFrames; i++) { + eth->m_baseTX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)&txFrmBase[i]; + eth->m_baseTX_FD[i].m_frameDataPtr.bf.owner = 0x0; /* CPU owner */ + eth->m_baseTX_FD[i].m_opt.ui = 0x0; + eth->m_baseTX_FD[i].m_status.ui = 0x0; + eth->m_baseTX_FD[i].m_nextFD = ð->m_baseTX_FD[i+1]; + } + + /* make the list circular */ + eth->m_baseTX_FD[i-1].m_nextFD = ð->m_baseTX_FD[0]; + + PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD); + + return 0; +} + +static s32 RxFDinit( ETH *eth) { + + s32 i; + /* MACFrame *rxFrmBase; */ + + /* disable cache for access to the RX buffers */ + /* rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */ + + /* store start of Rx descriptors and set current */ + eth->m_curRX_FD = (RX_FrameDescriptor *)((u32)rxFDbase | CACHE_DISABLE_MASK); + eth->m_baseRX_FD = eth->m_curRX_FD; + for ( i = 0; i < PKTBUFSRX; i++) { + eth->m_baseRX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)NetRxPackets[i] | CACHE_DISABLE_MASK; + eth->m_baseRX_FD[i].m_frameDataPtr.bf.owner = 0x1; /* BDMA owner */ + eth->m_baseRX_FD[i].m_reserved = 0x0; + eth->m_baseRX_FD[i].m_status.ui = 0x0; + eth->m_baseRX_FD[i].m_nextFD = ð->m_baseRX_FD[i+1]; + } + + /* make the list circular */ + eth->m_baseRX_FD[i-1].m_nextFD = ð->m_baseRX_FD[0]; + + PUT_REG( REG_BDMARXPTR, (u32)eth->m_curRX_FD); + + return 0; +} + +/* + * Public u-boot interface functions below + */ + +int eth_init(bd_t *bis) +{ + + ETH *eth = &m_eth; + + /* store our MAC address */ + eth->m_mac = bis->bi_enetaddr; + + /* setup DBMA and MAC */ + PUT_REG( REG_BDMARXCON, ETH_BRxRS); /* reset BDMA RX machine */ + PUT_REG( REG_BDMATXCON, ETH_BTxRS); /* reset BDMA TX machine */ + PUT_REG( REG_MACCON , ETH_SwReset); /* reset MAC machine */ + PUT_REG( REG_BDMARXLSZ, sizeof(MACFrame)); + PUT_REG( REG_MACCON , 0); /* reset MAC machine */ + + /* init frame descriptors */ + TxFDinit( eth); + RxFDinit( eth); + + /* init the CAM with our MAC address */ + PUT_REG( REG_CAM_BASE, (eth->m_mac[0] << 24) | + (eth->m_mac[1] << 16) | + (eth->m_mac[2] << 8) | + (eth->m_mac[3])); + PUT_REG( REG_CAM_BASE + 0x4, (eth->m_mac[4] << 24) | + (eth->m_mac[5] << 16)); + + /* enable CAM address 1 -- the MAC we just loaded */ + PUT_REG( REG_CAMEN, 0x1); + + PUT_REG( REG_CAMCON, + ETH_BroadAcc | /* accept broadcast packetes */ + ETH_CompEn); /* enable compare mode (check against the CAM) */ + + /* configure the BDMA Transmitter control */ + PUT_REG( REG_BDMATXCON, + ETH_BTxBRST | /* BDMA Tx burst size 16 words */ + ETH_BTxMSL110 | /* BDMA Tx wait to fill 6/8 of the BDMA */ + ETH_BTxSTSKO | /* BDMA Tx interrupt(Stop) on non-owner TX FD */ + ETH_BTxEn); /* BDMA Tx Enable */ + + /* configure the MAC Transmitter control */ + PUT_REG( REG_MACTXCON, + ETH_EnComp | /* interrupt when the MAC transmits or discards packet */ + ETH_TxEn); /* MAC transmit enable */ + + /* configure the BDMA Receiver control */ + PUT_REG( REG_BDMARXCON, + ETH_BRxBRST | /* BDMA Rx Burst Size 16 words */ + ETH_BRxSTSKO | /* BDMA Rx interrupt(Stop) on non-owner RX FD */ + ETH_BRxMAINC | /* BDMA Rx Memory Address increment */ + ETH_BRxDIE | /* BDMA Rx Every Received Frame Interrupt Enable */ + ETH_BRxNLIE | /* BDMA Rx NULL List Interrupt Enable */ + ETH_BRxNOIE | /* BDMA Rx Not Owner Interrupt Enable */ + ETH_BRxLittle | /* BDMA Rx Little endian */ + ETH_BRxEn); /* BDMA Rx Enable */ + + /* configure the MAC Receiver control */ + PUT_REG( REG_MACRXCON, + ETH_RxEn); /* MAC ETH_RxEn */ + + return 0; + +} + +/* Send a packet */ +s32 eth_send(volatile void *packet, s32 length) +{ + + u32 i; + ETH *eth = &m_eth; + + if ( eth->m_curTX_FD->m_frameDataPtr.bf.owner) { + printf("eth_send(): TX Frame. CPU not owner.\n"); + return -1; + } + + /* copy user data into frame data pointer */ + memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)), + (void *)packet, + length); + + /* Set TX Frame flags */ + eth->m_curTX_FD->m_opt.bf.widgetAlign = 0; + eth->m_curTX_FD->m_opt.bf.frameDataDir = 1; + eth->m_curTX_FD->m_opt.bf.littleEndian = 1; + eth->m_curTX_FD->m_opt.bf.macTxIrqEnbl = 1; + eth->m_curTX_FD->m_opt.bf.no_crc = 0; + eth->m_curTX_FD->m_opt.bf.no_padding = 0; + + /* Set TX Frame length */ + eth->m_curTX_FD->m_status.bf.len = length; + + /* Change ownership to BDMA */ + eth->m_curTX_FD->m_frameDataPtr.bf.owner = 1; + + /* Enable MAC and BDMA Tx control register */ + SET_REG( REG_BDMATXCON, ETH_BTxEn); + SET_REG( REG_MACTXCON, ETH_TxEn); + + /* poll on TX completion status */ + while ( !eth->m_curTX_FD->m_status.bf.complete) { + /* sleep */ + for ( i = 0; i < 0x10000; i ++); + } + + /* Change the Tx frame descriptor for next use */ + eth->m_curTX_FD = eth->m_curTX_FD->m_nextFD; + + return 0; +} + +/* Check for received packets */ +s32 eth_rx (void) +{ + s32 nLen = 0; + ETH *eth = &m_eth; + + /* check if packet ready */ + if ( (GET_REG( REG_BDMASTAT)) & ETH_S_BRxRDF) { + /* process all waiting packets */ + while ( !eth->m_curRX_FD->m_frameDataPtr.bf.owner) { + nLen = eth->m_curRX_FD->m_status.bf.len; + /* call back u-boot -- may call eth_send() */ + NetReceive ((u8 *)eth->m_curRX_FD->m_frameDataPtr.ui, nLen); + /* set owner back to CPU */ + eth->m_curRX_FD->m_frameDataPtr.bf.owner = 1; + /* clear status */ + eth->m_curRX_FD->m_status.ui = 0x0; + /* advance to next descriptor */ + eth->m_curRX_FD = eth->m_curRX_FD->m_nextFD; + /* clear received frame bit */ + PUT_REG( REG_BDMASTAT, ETH_S_BRxRDF); + } + } + + return nLen; +} + +/* Halt ethernet engine */ +void eth_halt(void) +{ + /* disable MAC */ + PUT_REG( REG_MACCON, ETH_HaltReg); +} + +#endif diff --git a/drivers/net/s3c4510b_eth.h b/drivers/net/s3c4510b_eth.h new file mode 100644 index 0000000000..cbddba71a4 --- /dev/null +++ b/drivers/net/s3c4510b_eth.h @@ -0,0 +1,302 @@ +#ifndef __S3C4510B_ETH_H +#define __S3C4510B_ETH_H +/* + * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) + * Curt Brune + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * MODULE: $Id:$ + * Description: Ethernet interface + * Runtime Env: ARM7TDMI + * Change History: + * 03-02-04 Create (Curt Brune) curt@cucy.com + * + */ + +#define __packed __attribute__ ((packed)) + +#define ETH_MAC_ADDR_SIZE (6) /* dst,src addr is 6bytes each */ +#define ETH_MaxTxFrames (16) /* Max number of Tx Frames */ + +/* Buffered DMA Receiver Control Register */ +#define ETH_BRxBRST 0x0000F /* BDMA Rx Burst Size * BRxBRST */ + /* = Burst Data Size 16 */ +#define ETH_BRxSTSKO 0x00020 /* BDMA Rx Stop/Skip Frame or Interrupt(=1) */ + /* case of not OWNER the current Frame */ +#define ETH_BRxMAINC 0x00040 /* BDMA Rx Memory Address Inc/Dec */ +#define ETH_BRxDIE 0x00080 /* BDMA Rx Every Received Frame Interrupt Enable */ +#define ETH_BRxNLIE 0x00100 /* BDMA Rx NULL List Interrupt Enable */ +#define ETH_BRxNOIE 0x00200 /* BDMA Rx Not Owner Interrupt Enable */ +#define ETH_BRxMSOIE 0x00400 /* BDMA Rx Maximum Size over Interrupr Enable */ +#define ETH_BRxLittle 0x00800 /* BDMA Rx Big/Little Endian */ +#define ETH_BRxBig 0x00000 /* BDMA Rx Big/Little Endian */ +#define ETH_BRxWA01 0x01000 /* BDMA Rx Word Alignment- one invalid byte */ +#define ETH_BRxWA10 0x02000 /* BDMA Rx Word Alignment- two invalid byte */ +#define ETH_BRxWA11 0x03000 /* BDMA Rx Word Alignment- three invalid byte */ +#define ETH_BRxEn 0x04000 /* BDMA Rx Enable */ +#define ETH_BRxRS 0x08000 /* BDMA Rx Reset */ +#define ETH_RxEmpty 0x10000 /* BDMA Rx Buffer empty interrupt */ +#define ETH_BRxEarly 0x20000 /* BDMA Rx Early notify Interrupt */ + +/* Buffered DMA Trasmit Control Register(BDMATXCON) */ +#define ETH_BTxBRST 0x0000F /* BDMA Tx Burst Size = 16 */ +#define ETH_BTxSTSKO 0x00020 /* BDMA Tx Stop/Skip Frame or Interrupt in case */ + /* of not Owner the current frame */ +#define ETH_BTxCPIE 0x00080 /* BDMA Tx Complete to send control */ + /* packet Enable */ +#define ETH_BTxNOIE 0x00200 /* BDMA Tx Buffer Not Owner */ +#define ETH_BTxEmpty 0x00400 /* BDMA Tx Buffer Empty Interrupt */ + +/* BDMA Tx buffer can be moved to the MAC Tx IO when the new frame comes in. */ +#define ETH_BTxMSL000 0x00000 /* No wait to fill the BDMA */ +#define ETH_BTxMSL001 0x00800 /* wait to fill 1/8 of the BDMA */ +#define ETH_BTxMSL010 0x01000 /* wait to fill 2/8 of the BDMA */ +#define ETH_BTxMSL011 0x01800 /* wait to fill 3/8 of the BDMA */ +#define ETH_BTxMSL100 0x02000 /* wait to fill 4/8 of the BDMA */ +#define ETH_BTxMSL101 0x02800 /* wait to fill 5/8 of the BDMA */ +#define ETH_BTxMSL110 0x03000 /* wait to fill 6/8 of the BDMA */ +#define ETH_BTxMSL111 0x03800 /* wait to fill 7/8 of the BDMA */ +#define ETH_BTxEn 0x04000 /* BDMA Tx Enable */ +#define ETH_BTxRS 0x08000 /* BDMA Tx Reset */ + +/* BDMA Status Register */ +#define ETH_S_BRxRDF 0x00001 /* BDMA Rx Done Every Received Frame */ +#define ETH_S_BRxNL 0x00002 /* BDMA Rx NULL List */ +#define ETH_S_BRxNO 0x00004 /* BDMA Rx Not Owner */ +#define ETH_S_BRxMSO 0x00008 /* BDMA Rx Maximum Size Over */ +#define ETH_S_BRxEmpty 0x00010 /* BDMA Rx Buffer Empty */ +#define ETH_S_BRxSEarly 0x00020 /* Early Notify */ +#define ETH_S_BRxFRF 0x00080 /* One more frame data in BDMA receive buffer */ +#define ETH_S_BTxCCP 0x10000 /* BDMA Tx Complete to send Control Packet */ +#define ETH_S_BTxNL 0x20000 /* BDMA Tx Null List */ +#define ETH_S_BTxNO 0x40000 /* BDMA Tx Not Owner */ +#define ETH_S_BTxEmpty 0x100000 /* BDMA Tx Buffer Empty */ + +/* MAC Control Register */ +#define ETH_HaltReg 0x0001 /* stop transmission and reception */ + /* after completion of any current packets */ +#define ETH_HaltImm 0x0002 /* Stop transmission and reception immediately */ +#define ETH_SwReset 0x0004 /* reset all Ethernet controller state machines */ + /* and FIFOs */ +#define ETH_FullDup 0x0008 /* allow transmission to begin while reception */ + /* is occurring */ +#define ETH_MACLoop 0x0010 /* MAC loopback */ +#define ETH_ConnM00 0x0000 /* Automatic-default */ +#define ETH_ConnM01 0x0020 /* Force 10Mbits endec */ +#define ETH_ConnM10 0x0040 /* Force MII (rate determined by MII clock */ +#define ETH_MIIOFF 0x0040 /* Force MII (rate determined by MII clock */ +#define ETH_Loop10 0x0080 /* Loop 10Mbps */ +#define ETH_MissRoll 0x0400 /* Missed error counter rolled over */ +#define ETH_MDCOFF 0x1000 /* MII Station Management Clock Off */ +#define ETH_EnMissRoll 0x2000 /* Interrupt when missed error counter rolls */ + /* over */ +#define ETH_Link10 0x8000 /* Link status 10Mbps */ + +/* CAM control register(CAMCON) */ +#define ETH_StationAcc 0x0001 /* Accept any packet with a unicast station */ + /* address */ +#define ETH_GroupAcc 0x0002 /* Accept any packet with multicast-group */ + /* station address */ +#define ETH_BroadAcc 0x0004 /* Accept any packet with a broadcast station */ + /* address */ +#define ETH_NegCAM 0x0008 /* 0: Accept packets CAM recognizes, */ + /* reject others */ + /* 1: reject packets CAM recognizes, */ + /* accept others */ +#define ETH_CompEn 0x0010 /* Compare Enable mode */ + +/* Transmit Control Register(MACTXCON) */ +#define ETH_TxEn 0x0001 /* transmit Enable */ +#define ETH_TxHalt 0x0002 /* Transmit Halt Request */ +#define ETH_NoPad 0x0004 /* suppress Padding */ +#define ETH_NoCRC 0x0008 /* Suppress CRC */ +#define ETH_FBack 0x0010 /* Fast Back-off */ +#define ETH_NoDef 0x0020 /* Disable the defer counter */ +#define ETH_SdPause 0x0040 /* Send Pause */ +#define ETH_MII10En 0x0080 /* MII 10Mbps mode enable */ +#define ETH_EnUnder 0x0100 /* Enable Underrun */ +#define ETH_EnDefer 0x0200 /* Enable Deferral */ +#define ETH_EnNCarr 0x0400 /* Enable No Carrier */ +#define ETH_EnExColl 0x0800 /* interrupt if 16 collision occur */ + /* in the same packet */ +#define ETH_EnLateColl 0x1000 /* interrupt if collision occurs after */ + /* 512 bit times(64 bytes times) */ +#define ETH_EnTxPar 0x2000 /* interrupt if the MAC transmit FIFO */ + /* has a parity error */ +#define ETH_EnComp 0x4000 /* interrupt when the MAC transmits or */ + /* discards one packet */ + +/* Transmit Status Register(MACTXSTAT) */ +#define ETH_ExColl 0x0010 /* Excessive collision */ +#define ETH_TxDeffered 0x0020 /* set if 16 collisions occur for same packet */ +#define ETH_Paused 0x0040 /* packet waited because of pause during */ + /* transmission */ +#define ETH_IntTx 0x0080 /* set if transmission of packet causes an */ + /* interrupt condiftion */ +#define ETH_Under 0x0100 /* MAC transmit FIFO becomes empty during */ + /* transmission */ +#define ETH_Defer 0x0200 /* MAC defers for MAC deferral */ +#define ETH_NCarr 0x0400 /* No carrier sense detected during the */ + /* transmission of a packet */ +#define ETH_SQE 0x0800 /* Signal Quality Error */ +#define ETH_LateColl 0x1000 /* a collision occures after 512 bit times */ +#define ETH_TxPar 0x2000 /* MAC transmit FIFO has detected a parity error */ +#define ETH_Comp 0x4000 /* MAC transmit or discards one packet */ +#define ETH_TxHalted 0x8000 /* Transmission was halted by clearing */ + /* TxEn or Halt immedite */ + +/* Receive Control Register (MACRXCON) */ +#define ETH_RxEn 0x0001 +#define ETH_RxHalt 0x0002 +#define ETH_LongEn 0x0004 +#define ETH_ShortEn 0x0008 +#define ETH_StripCRC 0x0010 +#define ETH_PassCtl 0x0020 +#define ETH_IgnoreCRC 0x0040 +#define ETH_EnAlign 0x0100 +#define ETH_EnCRCErr 0x0200 +#define ETH_EnOver 0x0400 +#define ETH_EnLongErr 0x0800 +#define ETH_EnRxPar 0x2000 +#define ETH_EnGood 0x4000 + +/* Receive Status Register(MACRXSTAT) */ +#define ETH_MCtlRecd 0x0020 +#define ETH_MIntRx 0x0040 +#define ETH_MRx10Stat 0x0080 +#define ETH_MAllignErr 0x0100 +#define ETH_MCRCErr 0x0200 +#define ETH_MOverflow 0x0400 +#define ETH_MLongErr 0x0800 +#define ETH_MRxPar 0x2000 +#define ETH_MRxGood 0x4000 +#define ETH_MRxHalted 0x8000 + +/* type of ethernet packets */ +#define ETH_TYPE_ARP (0x0806) +#define ETH_TYPE_IP (0x0800) + +#define ETH_HDR_SIZE (14) + +/* bit field for frame data pointer word */ +typedef struct __BF_FrameDataPtr { + u32 dataPtr:31; + u32 owner: 1; +} BF_FrameDataPtr; + +typedef union _FrameDataPtr { + u32 ui; + BF_FrameDataPtr bf; +} FrameDataPtr; + +typedef struct __BF_TX_Options { + u32 no_padding: 1; + u32 no_crc: 1; + u32 macTxIrqEnbl: 1; + u32 littleEndian: 1; + u32 frameDataDir: 1; + u32 widgetAlign: 2; + u32 reserved:25; +} BF_TX_Options; + +typedef union _TX_Options { + u32 ui; + BF_TX_Options bf; +} TX_Options; + +typedef struct __BF_RX_Status { + u32 len:16; /* frame length */ + u32 reserved1: 3; + u32 overMax: 1; + u32 reserved2: 1; + u32 ctrlRcv: 1; + u32 intRx: 1; + u32 rx10stat: 1; + u32 alignErr: 1; + u32 crcErr: 1; + u32 overFlow: 1; + u32 longErr: 1; + u32 reserved3: 1; + u32 parityErr: 1; + u32 good: 1; + u32 halted: 1; +} BF_RX_Status; + +typedef union _RX_Status { + u32 ui; + BF_RX_Status bf; +} RX_Status; + +typedef struct __BF_TX_Status { + u32 len:16; /* frame length */ + u32 txCollCnt: 4; + u32 exColl: 1; + u32 txDefer: 1; + u32 paused: 1; + u32 intTx: 1; + u32 underRun: 1; + u32 defer: 1; + u32 noCarrier: 1; + u32 SQErr: 1; + u32 lateColl: 1; + u32 parityErr: 1; + u32 complete: 1; + u32 halted: 1; +} BF_TX_Status; + +typedef union _TX_Status { + u32 ui; + BF_TX_Status bf; +} TX_Status; + +/* TX descriptor structure */ +typedef struct __TX_FrameDescriptor { + volatile FrameDataPtr m_frameDataPtr; + TX_Options m_opt; + volatile TX_Status m_status; + struct __TX_FrameDescriptor *m_nextFD; +} TX_FrameDescriptor; + +/* RX descriptor structure */ +typedef struct __RX_FrameDescriptor { + volatile FrameDataPtr m_frameDataPtr; + u32 m_reserved; + volatile RX_Status m_status; + struct __RX_FrameDescriptor *m_nextFD; +} RX_FrameDescriptor; + +/* MAC Frame Structure */ +typedef struct __MACFrame { + u8 m_dstAddr[6] __packed; + u8 m_srcAddr[6] __packed; + u16 m_lengthOrType __packed; + u8 m_payload[1506] __packed; +} MACFrame; + +/* Ethernet Control block */ +typedef struct __ETH { + TX_FrameDescriptor *m_curTX_FD; /* pointer to current TX frame descriptor */ + TX_FrameDescriptor *m_baseTX_FD; /* pointer to base TX frame descriptor */ + RX_FrameDescriptor *m_curRX_FD; /* pointer to current RX frame descriptor */ + RX_FrameDescriptor *m_baseRX_FD; /* pointer to base RX frame descriptor */ + u8 *m_mac; /* pointer to our MAC address */ +} ETH; + +#endif diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile new file mode 100644 index 0000000000..a7d4a3b7a7 --- /dev/null +++ b/drivers/net/sk98lin/Makefile @@ -0,0 +1,120 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# File: drivers/sk98lin/Makefile +# +# Makefile for the SysKonnect SK-98xx device driver. +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libsk98lin.a + +COBJS-y += skge.o +COBJS-y += skaddr.o +COBJS-y += skgehwt.o +COBJS-y += skgeinit.o +COBJS-y += skgepnmi.o +COBJS-y += skgesirq.o +COBJS-y += ski2c.o +COBJS-y += sklm80.o +COBJS-y += skqueue.o +COBJS-y += skrlmt.o +COBJS-y += sktimer.o +COBJS-y += skvpd.o +COBJS-y += skxmac2.o +COBJS-y += skcsum.o +#COBJS-y += skproc.o + +COBJS-y += uboot_skb.o +COBJS-y += uboot_drv.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +# DBGDEF = \ +# -DDEBUG + +ifdef DEBUG +DBGDEF += \ +-DSK_DEBUG_CHKMOD=0x00000000L \ +-DSK_DEBUG_CHKCAT=0x00000000L +endif + + +# **** possible debug modules for SK_DEBUG_CHKMOD ***************** +# SK_DBGMOD_MERR 0x00000001L /* general module error indication */ +# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ +# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ +# SK_DBGMOD_VPD 0x00000008L /* VPD module */ +# SK_DBGMOD_I2C 0x00000010L /* I2C module */ +# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ +# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ +# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ +# SK_DBGMOD_DRV 0x00010000L /* DRV module */ + +# **** possible debug categories for SK_DEBUG_CHKCAT ************** +# *** common modules *** +# SK_DBGCAT_INIT 0x00000001L module/driver initialization +# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL) +# SK_DBGCAT_ERR 0x00000004L error handling paths +# SK_DBGCAT_TX 0x00000008L transmit path +# SK_DBGCAT_RX 0x00000010L receive path +# SK_DBGCAT_IRQ 0x00000020L general IRQ handling +# SK_DBGCAT_QUEUE 0x00000040L any queue management +# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump +# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump + +# *** driver (file skge.c) *** +# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points +# SK_DBGCAT_DRV_??? 0x00020000 not used +# SK_DBGCAT_DRV_MCA 0x00040000 multicast +# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path +# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path +# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime +# SK_DBGCAT_DRV_??? 0x00400000 not used +# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode +# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames +# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions +# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources +# SK_DBGCAT_DRV_EVENT 0x08000000 driver events + +EXTRA_CFLAGS += -I. -DSK_USE_CSUM $(DBGDEF) + +CFLAGS += $(EXTRA_CFLAGS) +HOST_CFLAGS += $(EXTRA_CFLAGS) + + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h new file mode 100644 index 0000000000..981a4cab02 --- /dev/null +++ b/drivers/net/sk98lin/h/lm80.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * + * Name: lm80.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.4 $ + * Date: $Date: 2002/04/25 11:04:10 $ + * Purpose: Contains all defines for the LM80 Chip + * (National Semiconductor). + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: lm80.h,v $ + * Revision 1.4 2002/04/25 11:04:10 rschmidt + * Editorial changes + * + * Revision 1.3 1999/11/22 13:41:19 cgoos + * Changed license header to GPL. + * + * Revision 1.2 1999/03/12 13:26:51 malthoff + * remove __STDC__. + * + * Revision 1.1 1998/06/19 09:28:31 malthoff + * created. + * + * + ******************************************************************************/ + +#ifndef __INC_LM80_H +#define __INC_LM80_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines ********************************************************************/ + +/* + * LM80 register definition + * + * All registers are 8 bit wide + */ +#define LM80_CFG 0x00 /* Configuration Register */ +#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ +#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */ +#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */ +#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */ +#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */ +#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */ + /* 0x07 - 0x1f reserved */ + /* current values */ +#define LM80_VT0_IN 0x20 /* current Voltage 0 value */ +#define LM80_VT1_IN 0x21 /* current Voltage 1 value */ +#define LM80_VT2_IN 0x22 /* current Voltage 2 value */ +#define LM80_VT3_IN 0x23 /* current Voltage 3 value */ +#define LM80_VT4_IN 0x24 /* current Voltage 4 value */ +#define LM80_VT5_IN 0x25 /* current Voltage 5 value */ +#define LM80_VT6_IN 0x26 /* current Voltage 6 value */ +#define LM80_TEMP_IN 0x27 /* current Temperature value */ +#define LM80_FAN1_IN 0x28 /* current Fan 1 count */ +#define LM80_FAN2_IN 0x29 /* current Fan 2 count */ + /* limit values */ +#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */ +#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */ +#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */ +#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */ +#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */ +#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */ +#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */ +#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */ +#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */ +#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */ +#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */ +#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */ +#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */ +#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */ +#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */ +#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */ +#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */ +#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */ +#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ +#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ + /* 0x3e - 0x3f reserved */ + +/* + * LM80 bit definitions + */ + +/* LM80_CFG Configuration Register */ +#define LM80_CFG_START (1<<0) /* start monitoring operation */ +#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */ +#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */ +#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */ +#define LM80_CFG_RESET (1<<4) /* signals a reset */ +#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */ +#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */ +#define LM80_CFG_INIT (1<<7) /* restore power on defaults */ + +/* LM80_ISRC_1 Interrupt Status Register 1 */ +/* LM80_IMSK_1 Interrupt Mask Register 1 */ +#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */ +#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */ +#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */ +#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */ +#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */ +#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */ +#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */ +#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */ + +/* LM80_ISRC_2 Interrupt Status Register 2 */ +/* LM80_IMSK_2 Interrupt Mask Register 2 */ +#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ +#define LM80_IS_BTI (1<<1) /* state of BTI# pin */ +#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */ +#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */ +#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */ +#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */ + /* bit 6 and 7 are reserved in LM80_ISRC_2 */ +#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */ +#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */ + +/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */ +#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */ +#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */ +#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */ +#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */ +#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/ +#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */ + +/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */ +#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ +#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */ +#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */ +#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/ +#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */ +#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */ + + /* 0x07 - 0x1f reserved */ +/* LM80_VT0_IN current Voltage 0 value */ +/* LM80_VT1_IN current Voltage 1 value */ +/* LM80_VT2_IN current Voltage 2 value */ +/* LM80_VT3_IN current Voltage 3 value */ +/* LM80_VT4_IN current Voltage 4 value */ +/* LM80_VT5_IN current Voltage 5 value */ +/* LM80_VT6_IN current Voltage 6 value */ +/* LM80_TEMP_IN current temperature value */ +/* LM80_FAN1_IN current Fan 1 count */ +/* LM80_FAN2_IN current Fan 2 count */ +/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */ +/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */ +/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */ +/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */ +/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */ +/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */ +/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */ +/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */ +/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */ +/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */ +/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */ +/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */ +/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */ +/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */ +/* LM80_THOT_LIM_UP hot temperature limit (high) */ +/* LM80_THOT_LIM_LO hot temperature limit (low) */ +/* LM80_TOS_LIM_UP OS temperature limit (high) */ +/* LM80_TOS_LIM_LO OS temperature limit (low) */ +/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */ +/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */ + /* 0x3e - 0x3f reserved */ + +#define LM80_ADDR 0x28 /* LM80 default addr */ + +/* typedefs *******************************************************************/ + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_LM80_H */ diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h new file mode 100644 index 0000000000..711f873e7f --- /dev/null +++ b/drivers/net/sk98lin/h/skaddr.h @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * Name: skaddr.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.26 $ + * Date: $Date: 2002/11/15 07:24:42 $ + * Purpose: Header file for Address Management (MC, UC, Prom). + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skaddr.h,v $ + * Revision 1.26 2002/11/15 07:24:42 tschilli + * SK_ADDR_EQUAL macro fixed. + * + * Revision 1.25 2002/06/10 13:55:18 tschilli + * Changes for handling YUKON. + * All changes are internally and not visible to the programmer + * using this module. + * + * Revision 1.24 2001/01/22 13:41:34 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.23 2000/08/10 11:27:50 rassmann + * Editorial changes. + * Preserving 32-bit alignment in structs for the adapter context. + * + * Revision 1.22 2000/08/07 11:10:40 rassmann + * Editorial changes. + * + * Revision 1.21 2000/05/04 09:39:59 rassmann + * Editorial changes. + * Corrected multicast address hashing. + * + * Revision 1.20 1999/11/22 13:46:14 cgoos + * Changed license header to GPL. + * Allowing overwrite for SK_ADDR_EQUAL. + * + * Revision 1.19 1999/05/28 10:56:07 rassmann + * Editorial changes. + * + * Revision 1.18 1999/04/06 17:22:04 rassmann + * Added private "ActivePort". + * + * Revision 1.17 1999/01/14 16:18:19 rassmann + * Corrected multicast initialization. + * + * Revision 1.16 1999/01/04 10:30:36 rassmann + * SkAddrOverride only possible after SK_INIT_IO phase. + * + * Revision 1.15 1998/12/29 13:13:11 rassmann + * An address override is now preserved in the SK_INIT_IO phase. + * All functions return an int now. + * Extended parameter checking. + * + * Revision 1.14 1998/11/24 12:39:45 rassmann + * Reserved multicast entry for BPDU address. + * 13 multicast entries left for protocol. + * + * Revision 1.13 1998/11/13 17:24:32 rassmann + * Changed return value of SkAddrOverride to int. + * + * Revision 1.12 1998/11/13 16:56:19 rassmann + * Added macro SK_ADDR_COMPARE. + * Changed return type of SkAddrOverride to SK_BOOL. + * + * Revision 1.11 1998/10/28 18:16:35 rassmann + * Avoiding I/Os before SK_INIT_RUN level. + * Aligning InexactFilter. + * + * Revision 1.10 1998/10/22 11:39:10 rassmann + * Corrected signed/unsigned mismatches. + * + * Revision 1.9 1998/10/15 15:15:49 rassmann + * Changed Flags Parameters from SK_U8 to int. + * Checked with lint. + * + * Revision 1.8 1998/09/24 19:15:12 rassmann + * Code cleanup. + * + * Revision 1.7 1998/09/18 20:22:13 rassmann + * Added HW access. + * + * Revision 1.6 1998/09/04 19:40:20 rassmann + * Interface enhancements. + * + * Revision 1.5 1998/09/04 12:40:57 rassmann + * Interface cleanup. + * + * Revision 1.4 1998/09/04 12:14:13 rassmann + * Interface cleanup. + * + * Revision 1.3 1998/09/02 16:56:40 rassmann + * Updated interface. + * + * Revision 1.2 1998/08/27 14:26:09 rassmann + * Updated interface. + * + * Revision 1.1 1998/08/21 08:31:08 rassmann + * First public version. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This module is intended to manage multicast addresses and promiscuous mode + * on GEnesis adapters. + * + * Include File Hierarchy: + * + * "skdrv1st.h" + * ... + * "sktypes.h" + * "skqueue.h" + * "skaddr.h" + * ... + * "skdrv2nd.h" + * + ******************************************************************************/ + +#ifndef __INC_SKADDR_H +#define __INC_SKADDR_H + +#ifdef __cplusplus +#error C++ is not yet supported. +extern "C" { +#endif /* cplusplus */ + +/* defines ********************************************************************/ + +#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */ +#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */ + +/* ----- Common return values ----- */ + +#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */ +#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */ +#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */ + +/* ----- Clear/Add flag bits ----- */ + +#define SK_ADDR_PERMANENT 1 /* RLMT Address */ + +/* ----- Additional Clear flag bits ----- */ + +#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */ + +/* ----- Override flag bits ----- */ + +#define SK_ADDR_LOGICAL_ADDRESS 0 +#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */ +#define SK_ADDR_PHYSICAL_ADDRESS 1 +#define SK_ADDR_CLEAR_LOGICAL 2 +#define SK_ADDR_SET_LOGICAL 4 + +/* ----- Override return values ----- */ + +#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS) +#define SK_ADDR_DUPLICATE_ADDRESS 1 +#define SK_ADDR_MULTICAST_ADDRESS 2 + +/* ----- Partitioning of excact match table ----- */ + +#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */ + +#define SK_ADDR_FIRST_MATCH_RLMT 1 +#define SK_ADDR_LAST_MATCH_RLMT 2 +#define SK_ADDR_FIRST_MATCH_DRV 3 +#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1) + +/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */ + +#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */ +#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */ + +/* ----- Additional SkAddrMcAdd return values ----- */ + +#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */ +#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */ +#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */ + +/* Promiscuous mode bits ----- */ + +#define SK_PROM_MODE_NONE 0 /* Normal receive. */ +#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */ +#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */ +/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */ + +/* Macros */ + +#if 0 +#ifndef SK_ADDR_EQUAL +/* + * "&" instead of "&&" allows better optimization on IA-64. + * The replacement is safe here, as all bytes exist. + */ +#ifndef SK_ADDR_DWORD_COMPARE +#define SK_ADDR_EQUAL(A1,A2) ( \ + (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ + (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ + (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ + (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ + (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ + (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) +#else /* SK_ADDR_DWORD_COMPARE */ +#define SK_ADDR_EQUAL(A1,A2) ( \ + (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \ + (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) +#endif /* SK_ADDR_DWORD_COMPARE */ +#endif /* SK_ADDR_EQUAL */ +#endif /* 0 */ + +#ifndef SK_ADDR_EQUAL +#ifndef SK_ADDR_DWORD_COMPARE +#define SK_ADDR_EQUAL(A1,A2) ( \ + (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ + (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ + (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ + (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ + (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ + (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) +#else /* SK_ADDR_DWORD_COMPARE */ +#define SK_ADDR_EQUAL(A1,A2) ( \ + (*(SK_U16 *)&(((SK_U8 *)(A1))[4]) == *(SK_U16 *)&(((SK_U8 *)(A2))[4])) && \ + (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) +#endif /* SK_ADDR_DWORD_COMPARE */ +#endif /* SK_ADDR_EQUAL */ + +/* typedefs *******************************************************************/ + +typedef struct s_MacAddr { + SK_U8 a[SK_MAC_ADDR_LEN]; +} SK_MAC_ADDR; + + +/* SK_FILTER is used to ensure alignment of the filter. */ +typedef union s_InexactFilter { + SK_U8 Bytes[8]; + SK_U64 Val; /* Dummy entry for alignment only. */ +} SK_FILTER64; + + +typedef struct s_AddrNet SK_ADDR_NET; + + +typedef struct s_AddrPort { + +/* ----- Public part (read-only) ----- */ + + SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */ + SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */ + int PromMode; /* Promiscuous Mode. */ + +/* ----- Private part ----- */ + + SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */ + SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ + SK_U8 Align01; + + SK_U32 FirstExactMatchRlmt; + SK_U32 NextExactMatchRlmt; + SK_U32 FirstExactMatchDrv; + SK_U32 NextExactMatchDrv; + SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES]; + SK_FILTER64 InexactFilter; /* For 64-bit hash register. */ + SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */ + SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */ +} SK_ADDR_PORT; + + +struct s_AddrNet { +/* ----- Public part (read-only) ----- */ + + SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */ + SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */ + +/* ----- Private part ----- */ + + SK_U32 ActivePort; /* View of module ADDR. */ + SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ + SK_U8 Align01; + SK_U16 Align02; +}; + + +typedef struct s_Addr { + +/* ----- Public part (read-only) ----- */ + + SK_ADDR_NET Net[SK_MAX_NETS]; + SK_ADDR_PORT Port[SK_MAX_MACS]; + +/* ----- Private part ----- */ +} SK_ADDR; + +/* function prototypes ********************************************************/ + +#ifndef SK_KR_PROTO + +/* Functions provided by SkAddr */ + +/* ANSI/C++ compliant function prototypes */ + +extern int SkAddrInit( + SK_AC *pAC, + SK_IOC IoC, + int Level); + +extern int SkAddrMcClear( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int Flags); + +extern int SkAddrXmacMcClear( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int Flags); + +extern int SkAddrGmacMcClear( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int Flags); + +extern int SkAddrMcAdd( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + SK_MAC_ADDR *pMc, + int Flags); + +extern int SkAddrXmacMcAdd( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + SK_MAC_ADDR *pMc, + int Flags); + +extern int SkAddrGmacMcAdd( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + SK_MAC_ADDR *pMc, + int Flags); + +extern int SkAddrMcUpdate( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber); + +extern int SkAddrXmacMcUpdate( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber); + +extern int SkAddrGmacMcUpdate( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber); + +extern int SkAddrOverride( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + SK_MAC_ADDR *pNewAddr, + int Flags); + +extern int SkAddrPromiscuousChange( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int NewPromMode); + +extern int SkAddrXmacPromiscuousChange( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int NewPromMode); + +extern int SkAddrGmacPromiscuousChange( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 PortNumber, + int NewPromMode); + +extern int SkAddrSwap( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 FromPortNumber, + SK_U32 ToPortNumber); + +#else /* defined(SK_KR_PROTO)) */ + +/* Non-ANSI/C++ compliant function prototypes */ + +#error KR-style prototypes are not yet provided. + +#endif /* defined(SK_KR_PROTO)) */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_SKADDR_H */ diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h new file mode 100644 index 0000000000..2acae329e3 --- /dev/null +++ b/drivers/net/sk98lin/h/skcsum.h @@ -0,0 +1,261 @@ +/****************************************************************************** + * + * Name: skcsum.h + * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) + * Version: $Revision: 1.9 $ + * Date: $Date: 2001/02/06 11:21:39 $ + * Purpose: Store/verify Internet checksum in send/receive packets. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skcsum.h,v $ + * Revision 1.9 2001/02/06 11:21:39 rassmann + * Editorial changes. + * + * Revision 1.8 2001/02/06 11:15:36 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.7 2000/06/29 13:17:05 rassmann + * Corrected reception of a packet with UDP checksum == 0 (which means there + * is no UDP checksum). + * + * Revision 1.6 2000/02/28 12:33:44 cgoos + * Changed C++ style comments to C style. + * + * Revision 1.5 2000/02/21 12:10:05 cgoos + * Fixed license comment. + * + * Revision 1.4 2000/02/21 11:08:37 cgoos + * Merged changes back into common source. + * + * Revision 1.1 1999/07/26 14:47:49 mkarl + * changed from common source to windows specific source + * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and + * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester + * changes for Tx csum offload + * + * Revision 1.2 1998/09/04 12:16:34 mhaveman + * Checked in for Stephan to allow compilation. + * -Added definition SK_CSUM_EVENT_CLEAR_PROTO_STATS to clear statistic + * -Added prototype for SkCsEvent() + * + * Revision 1.1 1998/09/01 15:36:53 swolf + * initial revision + * + * 01-Sep-1998 sw Created. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * Public header file for the "GEnesis" common module "CSUM". + * + * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" + * and is the code name of this SysKonnect project. + * + * Compilation Options: + * + * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an + * empty module. + * + * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id + * definitions. In this case, all SKCS_PROTO_xxx definitions must be made + * external. + * + * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status + * definitions. In this case, all SKCS_STATUS_xxx definitions must be made + * external. + * + * Include File Hierarchy: + * + * "h/skcsum.h" + * "h/sktypes.h" + * "h/skqueue.h" + * + ******************************************************************************/ + +#ifndef __INC_SKCSUM_H +#define __INC_SKCSUM_H + +#include "h/sktypes.h" +#include "h/skqueue.h" + +/* defines ********************************************************************/ + +/* + * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user + * overwrite. + */ +#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */ +#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */ +#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */ +#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */ + +/* Indices for protocol statistics. */ +#define SKCS_PROTO_STATS_IP 0 +#define SKCS_PROTO_STATS_UDP 1 +#define SKCS_PROTO_STATS_TCP 2 +#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */ +#endif /* !SKCS_OVERWRITE_PROTO */ + +/* + * Define the default SKCS_STATUS type and values if no user overwrite. + * + * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. + * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. + * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. + * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame + * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). + * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). + * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). + * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). + * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. + * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. + * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. + */ +#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */ +#define SKCS_STATUS int /* Define status type. */ + +#define SKCS_STATUS_UNKNOWN_IP_VERSION 1 +#define SKCS_STATUS_IP_CSUM_ERROR 2 +#define SKCS_STATUS_IP_FRAGMENT 3 +#define SKCS_STATUS_IP_CSUM_OK 4 +#define SKCS_STATUS_TCP_CSUM_ERROR 5 +#define SKCS_STATUS_UDP_CSUM_ERROR 6 +#define SKCS_STATUS_TCP_CSUM_OK 7 +#define SKCS_STATUS_UDP_CSUM_OK 8 +/* needed for Microsoft */ +#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9 +#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10 +/* UDP checksum may be omitted */ +#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11 +#endif /* !SKCS_OVERWRITE_STATUS */ + +/* Clear protocol statistics event. */ +#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1 + +/* + * Add two values in one's complement. + * + * Note: One of the two input values may be "longer" than 16-bit, but then the + * resulting sum may be 17 bits long. In this case, add zero to the result using + * SKCS_OC_ADD() again. + * + * Result = Value1 + Value2 + */ +#define SKCS_OC_ADD(Result, Value1, Value2) { \ + unsigned long Sum; \ + \ + Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \ + /* Add-in any carry. */ \ + (Result) = (Sum & 0xffff) + (Sum >> 16); \ +} + +/* + * Subtract two values in one's complement. + * + * Result = Value1 - Value2 + */ +#define SKCS_OC_SUB(Result, Value1, Value2) \ + SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff) + +/* typedefs *******************************************************************/ + +/* + * SKCS_PROTO_STATS - The CSUM protocol statistics structure. + * + * There is one instance of this structure for each protocol supported. + */ +typedef struct s_CsProtocolStatistics { + SK_U64 RxOkCts; /* Receive checksum ok. */ + SK_U64 RxUnableCts; /* Unable to verify receive checksum. */ + SK_U64 RxErrCts; /* Receive checksum error. */ + SK_U64 TxOkCts; /* Transmit checksum ok. */ + SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */ +} SKCS_PROTO_STATS; + +/* + * s_Csum - The CSUM module context structure. + */ +typedef struct s_Csum { + /* Enabled receive SK_PROTO_XXX bit flags. */ + unsigned ReceiveFlags[SK_MAX_NETS]; +#ifdef TX_CSUM + unsigned TransmitFlags[SK_MAX_NETS]; +#endif /* TX_CSUM */ + + /* The protocol statistics structure; one per supported protocol. */ + SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS]; +} SK_CSUM; + +/* + * SKCS_PACKET_INFO - The packet information structure. + */ +typedef struct s_CsPacketInfo { + /* Bit field specifiying the desired/found protocols. */ + unsigned ProtocolFlags; + + /* Length of complete IP header, including any option fields. */ + unsigned IpHeaderLength; + + /* IP header checksum. */ + unsigned IpHeaderChecksum; + + /* TCP/UDP pseudo header checksum. */ + unsigned PseudoHeaderChecksum; +} SKCS_PACKET_INFO; + +/* function prototypes ********************************************************/ + +#ifndef SkCsCalculateChecksum +extern unsigned SkCsCalculateChecksum( + void *pData, + unsigned Length); +#endif + +extern int SkCsEvent( + SK_AC *pAc, + SK_IOC Ioc, + SK_U32 Event, + SK_EVPARA Param); + +extern SKCS_STATUS SkCsGetReceiveInfo( + SK_AC *pAc, + void *pIpHeader, + unsigned Checksum1, + unsigned Checksum2, + int NetNumber); + +extern void SkCsGetSendInfo( + SK_AC *pAc, + void *pIpHeader, + SKCS_PACKET_INFO *pPacketInfo, + int NetNumber); + +extern void SkCsSetReceiveFlags( + SK_AC *pAc, + unsigned ReceiveFlags, + unsigned *pChecksum1Offset, + unsigned *pChecksum2Offset, + int NetNumber); + +#endif /* __INC_SKCSUM_H */ diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h new file mode 100644 index 0000000000..cf5b5ad332 --- /dev/null +++ b/drivers/net/sk98lin/h/skdebug.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Name: skdebug.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.12 $ + * Date: $Date: 2002/07/15 15:37:13 $ + * Purpose: SK specific DEBUG support + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skdebug.h,v $ + * Revision 1.12 2002/07/15 15:37:13 rschmidt + * Power Management support + * Editorial changes + * + * Revision 1.11 2002/04/25 11:04:39 rschmidt + * Editorial changes + * + * Revision 1.10 1999/11/22 13:47:40 cgoos + * Changed license header to GPL. + * + * Revision 1.9 1999/09/14 14:02:43 rwahl + * Added SK_DBGMOD_PECP. + * + * Revision 1.8 1998/11/25 08:31:54 gklug + * fix: no C++ comments allowed in common sources + * + * Revision 1.7 1998/11/24 16:47:24 swolf + * Driver may now define its own SK_DBG_MSG() (eg. in "h/skdrv1st.h"). + * + * Revision 1.6 1998/10/28 10:23:55 rassmann + * ADDED SK_DBGMOD_ADDR. + * + * Revision 1.5 1998/10/22 09:43:55 gklug + * add: CSUM module + * + * Revision 1.4 1998/10/01 07:54:44 gklug + * add: PNMI debug module + * + * Revision 1.3 1998/09/18 08:32:34 afischer + * Macros changed according ssr-spec.: + * SK_DBG_MODCHK -> SK_DBG_CHKMOD + * SK_DBG_CATCHK -> SK_DBG_CHKCAT + * + * Revision 1.2 1998/07/03 14:38:25 malthoff + * Add category SK_DBGCAT_FATAL. + * + * Revision 1.1 1998/06/19 13:39:01 malthoff + * created. + * + * + ******************************************************************************/ + +#ifndef __INC_SKDEBUG_H +#define __INC_SKDEBUG_H + +#ifdef DEBUG +#ifndef SK_DBG_MSG +#define SK_DBG_MSG(pAC,comp,cat,arg) \ + if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ + ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ + SK_DBG_PRINTF arg ; \ + } +#endif +#else +#define SK_DBG_MSG(pAC,comp,lev,arg) +#endif + +/* PLS NOTE: + * ========= + * Due to any restrictions of kernel printf routines do not use other + * format identifiers as: %x %d %c %s . + * Never use any combined format identifiers such as: %lx %ld in your + * printf - argument (arg) because some OS specific kernel printfs may + * only support some basic identifiers. + */ + +/* Debug modules */ + +#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */ +#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ +#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ +#define SK_DBGMOD_VPD 0x00000008L /* VPD module */ +#define SK_DBGMOD_I2C 0x00000010L /* I2C module */ +#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ +#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ +#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ +#define SK_DBGMOD_PECP 0x00000100L /* PECP module */ +#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */ + +/* Debug events */ + +#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */ +#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */ +#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */ +#define SK_DBGCAT_TX 0x00000008L /* transmit path */ +#define SK_DBGCAT_RX 0x00000010L /* receive path */ +#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */ +#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */ +#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */ +#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */ + +#endif /* __INC_SKDEBUG_H */ diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h new file mode 100644 index 0000000000..af34d7b96f --- /dev/null +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -0,0 +1,264 @@ +/****************************************************************************** + * + * Name: skdrv1st.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/02/25 14:16:40 $ + * Purpose: First header file for driver and all other modules + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skdrv1st.h,v $ + * Revision 1.11 2003/02/25 14:16:40 mlindner + * Fix: Copyright statement + * + * Revision 1.10 2002/10/02 12:46:02 mlindner + * Add: Support for Yukon + * + * Revision 1.9.2.2 2001/12/07 12:06:42 mlindner + * Fix: malloc -> slab changes + * + * Revision 1.9.2.1 2001/03/12 16:50:59 mlindner + * chg: kernel 2.4 adaption + * + * Revision 1.9 2001/01/22 14:16:04 mlindner + * added ProcFs functionality + * Dual Net functionality integrated + * Rlmt networks added + * + * Revision 1.8 2000/02/21 12:19:18 cgoos + * Added default for SK_DEBUG_CHKMOD/_CHKCAT + * + * Revision 1.7 1999/11/22 13:50:00 cgoos + * Changed license header to GPL. + * Added overwrite for several functions. + * Removed linux 2.0.x definitions. + * Removed PCI vendor ID definition (now in kernel). + * + * Revision 1.6 1999/07/27 08:03:33 cgoos + * Changed SK_IN/OUT macros to readX/writeX instead of memory + * accesses (necessary for ALPHA). + * + * Revision 1.5 1999/07/23 12:10:21 cgoos + * Removed SK_RLMT_SLOW_LOOKAHEAD define. + * + * Revision 1.4 1999/07/14 12:31:13 cgoos + * Added SK_RLMT_SLOW_LOOKAHEAD define. + * + * Revision 1.3 1999/04/07 10:12:54 cgoos + * Added check for KERNEL and OPTIMIZATION defines. + * + * Revision 1.2 1999/03/01 08:51:47 cgoos + * Fixed pcibios_read/write definitions. + * + * Revision 1.1 1999/02/16 07:40:49 cgoos + * First version. + * + * + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This is the first include file of the driver, which includes all + * neccessary system header files and some of the GEnesis header files. + * It also defines some basic items. + * + * Include File Hierarchy: + * + * see skge.c + * + ******************************************************************************/ + +#ifndef __INC_SKDRV1ST_H +#define __INC_SKDRV1ST_H + +#if 0 +/* Check kernel version */ +#include +#if (LINUX_VERSION_CODE > 0x020300) +#endif +#endif + +typedef struct s_AC SK_AC; + +/* override some default functions with optimized linux functions */ + +#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2) +#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4) +#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8) +#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2) +#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),2) +#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),2) + +#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) + +#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) + + +#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + +#if 0 +#include +#endif +#include +#if 0 +#include +#endif +#include +#if 0 +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#if 0 +#include +#include +#include + +#include +#include +#include +#endif + +#include "h/sktypes.h" +#include "h/skerror.h" +#include "h/skdebug.h" +#include "h/lm80.h" +#include "h/xmac_ii.h" + +#include "u-boot_compat.h" + +#ifdef __LITTLE_ENDIAN +#define SK_LITTLE_ENDIAN +#else +#define SK_BIG_ENDIAN +#endif + +#if 0 +#define SK_NET_DEVICE net_device +#else +#define SK_NET_DEVICE eth_device +#endif + + +/* we use gethrtime(), return unit: nanoseconds */ +#if 0 +#define SK_TICKS_PER_SEC HZ +#else +#define SK_TICKS_PER_SEC CFG_HZ +#endif + +#define SK_MEM_MAPPED_IO + +/* #define SK_RLMT_SLOW_LOOKAHEAD */ + +#define SK_MAX_MACS 2 +#define SK_MAX_NETS 2 + +#define SK_IOC char* + +typedef struct s_DrvRlmtMbuf SK_MBUF; + +#define SK_CONST64 INT64_C +#define SK_CONSTU64 UINT64_C + +#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size) +#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size) +#define SK_MEMSET(dest,val,size) memset(dest,val,size) +#define SK_STRLEN(pStr) strlen((char*)(pStr)) +#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size) +#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2)) + +/* macros to access the adapter */ +#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) +#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) +#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) +#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a))) +#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a))) +#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a))) + +#define int8_t char +#define int16_t short +#define int32_t long +#define int64_t long long +#define uint8_t u_char +#define uint16_t u_short +#define uint32_t u_long +#define uint64_t unsigned long long +#define t_scalar_t int +#define t_uscalar_t unsigned int +#define uintptr_t unsigned long + +#define __CONCAT__(A,B) A##B + +#define INT32_C(a) __CONCAT__(a,L) +#define INT64_C(a) __CONCAT__(a,LL) +#define UINT32_C(a) __CONCAT__(a,UL) +#define UINT64_C(a) __CONCAT__(a,ULL) + +#ifdef DEBUG +#define SK_DBG_PRINTF printk +#ifndef SK_DEBUG_CHKMOD +#define SK_DEBUG_CHKMOD 0 +#endif +#ifndef SK_DEBUG_CHKCAT +#define SK_DEBUG_CHKCAT 0 +#endif +/* those come from the makefile */ +#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD) +#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT) + +extern void SkDbgPrintf(const char *format,...); + +#define SK_DBGMOD_DRV 0x00010000 + +/**** possible driver debug categories ********************************/ +#define SK_DBGCAT_DRV_ENTRY 0x00010000 +#define SK_DBGCAT_DRV_SAP 0x00020000 +#define SK_DBGCAT_DRV_MCA 0x00040000 +#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 +#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 +#define SK_DBGCAT_DRV_PROGRESS 0x00200000 +#define SK_DBGCAT_DRV_MSG 0x00400000 +#define SK_DBGCAT_DRV_PROM 0x00800000 +#define SK_DBGCAT_DRV_TX_FRAME 0x01000000 +#define SK_DBGCAT_DRV_ERROR 0x02000000 +#define SK_DBGCAT_DRV_INT_SRC 0x04000000 +#define SK_DBGCAT_DRV_EVENT 0x08000000 + +#endif + +#define SK_ERR_LOG SkErrorLog + +extern void SkErrorLog(SK_AC*, int, int, char*); + +#endif diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h new file mode 100644 index 0000000000..a311827aa7 --- /dev/null +++ b/drivers/net/sk98lin/h/skdrv2nd.h @@ -0,0 +1,561 @@ +/****************************************************************************** + * + * Name: skdrv2nd.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.15 $ + * Date: $Date: 2003/02/25 14:16:40 $ + * Purpose: Second header file for driver and all other modules + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skdrv2nd.h,v $ + * Revision 1.15 2003/02/25 14:16:40 mlindner + * Fix: Copyright statement + * + * Revision 1.14 2003/02/25 13:26:26 mlindner + * Add: Support for various vendors + * + * Revision 1.13 2002/10/02 12:46:02 mlindner + * Add: Support for Yukon + * + * Revision 1.12.2.2 2001/09/05 12:14:50 mlindner + * add: New hardware revision int + * + * Revision 1.12.2.1 2001/03/12 16:50:59 mlindner + * chg: kernel 2.4 adaption + * + * Revision 1.12 2001/03/01 12:52:15 mlindner + * Fixed ring size + * + * Revision 1.11 2001/02/19 13:28:02 mlindner + * Changed PNMI parameter values + * + * Revision 1.10 2001/01/22 14:16:04 mlindner + * added ProcFs functionality + * Dual Net functionality integrated + * Rlmt networks added + * + * Revision 1.1 2000/10/05 19:46:50 phargrov + * Add directory src/vipk_devs_nonlbl/vipk_sk98lin/ + * This is the SysKonnect SK-98xx Gigabit Ethernet driver, + * contributed by SysKonnect. + * + * Revision 1.9 2000/02/21 10:39:55 cgoos + * Added flag for jumbo support usage. + * + * Revision 1.8 1999/11/22 13:50:44 cgoos + * Changed license header to GPL. + * Fixed two comments. + * + * Revision 1.7 1999/09/28 12:38:21 cgoos + * Added CheckQueue to SK_AC. + * + * Revision 1.6 1999/07/27 08:04:05 cgoos + * Added checksumming variables to SK_AC. + * + * Revision 1.5 1999/03/29 12:33:26 cgoos + * Rreversed to fine lock granularity. + * + * Revision 1.4 1999/03/15 12:14:02 cgoos + * Added DriverLock to SK_AC. + * Removed other locks. + * + * Revision 1.3 1999/03/01 08:52:27 cgoos + * Changed pAC->PciDev declaration. + * + * Revision 1.2 1999/02/18 10:57:14 cgoos + * Removed SkDrvTimeStamp prototype. + * Fixed SkGeOsGetTime prototype. + * + * Revision 1.1 1999/02/16 07:41:01 cgoos + * First version. + * + * + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This is the second include file of the driver, which includes all other + * neccessary files and defines all structures and constants used by the + * driver and the common modules. + * + * Include File Hierarchy: + * + * see skge.c + * + ******************************************************************************/ + +#ifndef __INC_SKDRV2ND_H +#define __INC_SKDRV2ND_H + +#include "h/skqueue.h" +#include "h/skgehwt.h" +#include "h/sktimer.h" +#include "h/ski2c.h" +#include "h/skgepnmi.h" +#include "h/skvpd.h" +#include "h/skgehw.h" +#include "h/skgeinit.h" +#include "h/skaddr.h" +#include "h/skgesirq.h" +#include "h/skcsum.h" +#include "h/skrlmt.h" +#include "h/skgedrv.h" + +#define SK_PCI_ISCOMPLIANT(result, pdev) { \ + result = SK_FALSE; /* default */ \ + /* 3Com (0x10b7) */ \ + if (pdev->vendor == 0x10b7) { \ + /* Gigabit Ethernet Adapter (0x1700) */ \ + if ((pdev->device == 0x1700)) { \ + result = SK_TRUE; \ + } \ + /* SysKonnect (0x1148) */ \ + } else if (pdev->vendor == 0x1148) { \ + /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */ \ + /* SK-98xx V2 Gigabit Ethernet Adapter (0x4320) */ \ + if ((pdev->device == 0x4300) || \ + (pdev->device == 0x4320)) { \ + result = SK_TRUE; \ + } \ + /* D-Link (0x1186) */ \ + } else if (pdev->vendor == 0x1186) { \ + /* Gigabit Ethernet Adapter (0x4c00) */ \ + if ((pdev->device == 0x4c00)) { \ + result = SK_TRUE; \ + } \ + /* CNet (0x1371) */ \ + } else if (pdev->vendor == 0x1371) { \ + /* GigaCard Network Adapter (0x434e) */ \ + if ((pdev->device == 0x434e)) { \ + result = SK_TRUE; \ + } \ + /* Linksys (0x1737) */ \ + } else if (pdev->vendor == 0x1737) { \ + /* Gigabit Network Adapter (0x1032) */ \ + /* Gigabit Network Adapter (0x1064) */ \ + if ((pdev->device == 0x1032) || \ + (pdev->device == 0x1064)) { \ + result = SK_TRUE; \ + } \ + } else { \ + result = SK_FALSE; \ + } \ +} + + +extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); +extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); +extern SK_U64 SkOsGetTime(SK_AC*); +extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); +extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); +extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); +extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32); +extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); +extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); +extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); + +struct s_DrvRlmtMbuf { + SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ + SK_U8 *pData; /* Data buffer (virtually contig.). */ + unsigned Size; /* Data buffer size. */ + unsigned Length; /* Length of packet (<= Size). */ + SK_U32 PortIdx; /* Receiving/transmitting port. */ +#ifdef SK_RLMT_MBUF_PRIVATE + SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ +#endif /* SK_RLMT_MBUF_PRIVATE */ + struct sk_buff *pOs; /* Pointer to message block */ +}; + + +/* + * ioctl definitions + */ +#define SK_IOCTL_BASE (SIOCDEVPRIVATE) +#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) +#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) +#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) + +typedef struct s_IOCTL SK_GE_IOCTL; + +struct s_IOCTL { + char* pData; + unsigned int Len; +}; + + +/* + * define sizes of descriptor rings in bytes + */ + +#if 0 +#define TX_RING_SIZE (8*1024) +#define RX_RING_SIZE (24*1024) +#else +#define TX_RING_SIZE (10 * 40) +#define RX_RING_SIZE (10 * 40) +#endif + +/* + * Buffer size for ethernet packets + */ +#define ETH_BUF_SIZE 1540 +#define ETH_MAX_MTU 1514 +#define ETH_MIN_MTU 60 +#define ETH_MULTICAST_BIT 0x01 +#define SK_JUMBO_MTU 9000 + +/* + * transmit priority selects the queue: LOW=asynchron, HIGH=synchron + */ +#define TX_PRIO_LOW 0 +#define TX_PRIO_HIGH 1 + +/* + * alignment of rx/tx descriptors + */ +#define DESCR_ALIGN 8 + +/* + * definitions for pnmi. TODO + */ +#define SK_DRIVER_RESET(pAC, IoC) 0 +#define SK_DRIVER_SENDEVENT(pAC, IoC) 0 +#define SK_DRIVER_SELFTEST(pAC, IoC) 0 +/* For get mtu you must add an own function */ +#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0 +#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0 +#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0 + + +/* TX and RX descriptors *****************************************************/ + +typedef struct s_RxD RXD; /* the receive descriptor */ + +struct s_RxD { + volatile SK_U32 RBControl; /* Receive Buffer Control */ + SK_U32 VNextRxd; /* Next receive descriptor,low dword */ + SK_U32 VDataLow; /* Receive buffer Addr, low dword */ + SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ + SK_U32 FrameStat; /* Receive Frame Status word */ + SK_U32 TimeStamp; /* Time stamp from XMAC */ + SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ + SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ + RXD *pNextRxd; /* Pointer to next Rxd */ + struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ +}; + +typedef struct s_TxD TXD; /* the transmit descriptor */ + +struct s_TxD { + volatile SK_U32 TBControl; /* Transmit Buffer Control */ + SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ + SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ + SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ + SK_U32 FrameStat; /* Transmit Frame Status Word */ + SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ + SK_U16 TcpSumSt; /* TCP Sum Start */ + SK_U16 TcpSumWr; /* TCP Sum Write */ + SK_U32 TcpReserved; /* not used */ + TXD *pNextTxd; /* Pointer to next Txd */ + struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ +}; + + +/* definition of flags in descriptor control field */ +#define RX_CTRL_OWN_BMU UINT32_C(0x80000000) +#define RX_CTRL_STF UINT32_C(0x40000000) +#define RX_CTRL_EOF UINT32_C(0x20000000) +#define RX_CTRL_EOB_IRQ UINT32_C(0x10000000) +#define RX_CTRL_EOF_IRQ UINT32_C(0x08000000) +#define RX_CTRL_DEV_NULL UINT32_C(0x04000000) +#define RX_CTRL_STAT_VALID UINT32_C(0x02000000) +#define RX_CTRL_TIME_VALID UINT32_C(0x01000000) +#define RX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) +#define RX_CTRL_CHECK_CSUM UINT32_C(0x00560000) +#define RX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) + +#define TX_CTRL_OWN_BMU UINT32_C(0x80000000) +#define TX_CTRL_STF UINT32_C(0x40000000) +#define TX_CTRL_EOF UINT32_C(0x20000000) +#define TX_CTRL_EOB_IRQ UINT32_C(0x10000000) +#define TX_CTRL_EOF_IRQ UINT32_C(0x08000000) +#define TX_CTRL_ST_FWD UINT32_C(0x04000000) +#define TX_CTRL_DISAB_CRC UINT32_C(0x02000000) +#define TX_CTRL_SOFTWARE UINT32_C(0x01000000) +#define TX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) +#define TX_CTRL_CHECK_CSUM UINT32_C(0x00560000) +#define TX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) + + +/* The offsets of registers in the TX and RX queue control io area ***********/ + +#define RX_Q_BUF_CTRL_CNT 0x00 +#define RX_Q_NEXT_DESCR_LOW 0x04 +#define RX_Q_BUF_ADDR_LOW 0x08 +#define RX_Q_BUF_ADDR_HIGH 0x0c +#define RX_Q_FRAME_STAT 0x10 +#define RX_Q_TIME_STAMP 0x14 +#define RX_Q_CSUM_1_2 0x18 +#define RX_Q_CSUM_START_1_2 0x1c +#define RX_Q_CUR_DESCR_LOW 0x20 +#define RX_Q_DESCR_HIGH 0x24 +#define RX_Q_CUR_ADDR_LOW 0x28 +#define RX_Q_CUR_ADDR_HIGH 0x2c +#define RX_Q_CUR_BYTE_CNT 0x30 +#define RX_Q_CTRL 0x34 +#define RX_Q_FLAG 0x38 +#define RX_Q_TEST1 0x3c +#define RX_Q_TEST2 0x40 +#define RX_Q_TEST3 0x44 + +#define TX_Q_BUF_CTRL_CNT 0x00 +#define TX_Q_NEXT_DESCR_LOW 0x04 +#define TX_Q_BUF_ADDR_LOW 0x08 +#define TX_Q_BUF_ADDR_HIGH 0x0c +#define TX_Q_FRAME_STAT 0x10 +#define TX_Q_CSUM_START 0x14 +#define TX_Q_CSUM_START_POS 0x18 +#define TX_Q_RESERVED 0x1c +#define TX_Q_CUR_DESCR_LOW 0x20 +#define TX_Q_DESCR_HIGH 0x24 +#define TX_Q_CUR_ADDR_LOW 0x28 +#define TX_Q_CUR_ADDR_HIGH 0x2c +#define TX_Q_CUR_BYTE_CNT 0x30 +#define TX_Q_CTRL 0x34 +#define TX_Q_FLAG 0x38 +#define TX_Q_TEST1 0x3c +#define TX_Q_TEST2 0x40 +#define TX_Q_TEST3 0x44 + +/* definition of flags in the queue control field */ +#define RX_Q_CTRL_POLL_ON 0x00000080 +#define RX_Q_CTRL_POLL_OFF 0x00000040 +#define RX_Q_CTRL_STOP 0x00000020 +#define RX_Q_CTRL_START 0x00000010 +#define RX_Q_CTRL_CLR_I_PAR 0x00000008 +#define RX_Q_CTRL_CLR_I_EOB 0x00000004 +#define RX_Q_CTRL_CLR_I_EOF 0x00000002 +#define RX_Q_CTRL_CLR_I_ERR 0x00000001 + +#define TX_Q_CTRL_POLL_ON 0x00000080 +#define TX_Q_CTRL_POLL_OFF 0x00000040 +#define TX_Q_CTRL_STOP 0x00000020 +#define TX_Q_CTRL_START 0x00000010 +#define TX_Q_CTRL_CLR_I_EOB 0x00000004 +#define TX_Q_CTRL_CLR_I_EOF 0x00000002 +#define TX_Q_CTRL_CLR_I_ERR 0x00000001 + + +/* Interrupt bits in the interrupts source register **************************/ +#define IRQ_HW_ERROR 0x80000000 +#define IRQ_RESERVED 0x40000000 +#define IRQ_PKT_TOUT_RX1 0x20000000 +#define IRQ_PKT_TOUT_RX2 0x10000000 +#define IRQ_PKT_TOUT_TX1 0x08000000 +#define IRQ_PKT_TOUT_TX2 0x04000000 +#define IRQ_I2C_READY 0x02000000 +#define IRQ_SW 0x01000000 +#define IRQ_EXTERNAL_REG 0x00800000 +#define IRQ_TIMER 0x00400000 +#define IRQ_MAC1 0x00200000 +#define IRQ_LINK_SYNC_C_M1 0x00100000 +#define IRQ_MAC2 0x00080000 +#define IRQ_LINK_SYNC_C_M2 0x00040000 +#define IRQ_EOB_RX1 0x00020000 +#define IRQ_EOF_RX1 0x00010000 +#define IRQ_CHK_RX1 0x00008000 +#define IRQ_EOB_RX2 0x00004000 +#define IRQ_EOF_RX2 0x00002000 +#define IRQ_CHK_RX2 0x00001000 +#define IRQ_EOB_SY_TX1 0x00000800 +#define IRQ_EOF_SY_TX1 0x00000400 +#define IRQ_CHK_SY_TX1 0x00000200 +#define IRQ_EOB_AS_TX1 0x00000100 +#define IRQ_EOF_AS_TX1 0x00000080 +#define IRQ_CHK_AS_TX1 0x00000040 +#define IRQ_EOB_SY_TX2 0x00000020 +#define IRQ_EOF_SY_TX2 0x00000010 +#define IRQ_CHK_SY_TX2 0x00000008 +#define IRQ_EOB_AS_TX2 0x00000004 +#define IRQ_EOF_AS_TX2 0x00000002 +#define IRQ_CHK_AS_TX2 0x00000001 + +#define DRIVER_IRQS (IRQ_SW | IRQ_EOF_RX1 | IRQ_EOF_RX2 | \ + IRQ_EOF_SY_TX1 | IRQ_EOF_AS_TX1 | \ + IRQ_EOF_SY_TX2 | IRQ_EOF_AS_TX2) + +#define SPECIAL_IRQS (IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ + IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ + IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ + IRQ_MAC1 | IRQ_LINK_SYNC_C_M1 | \ + IRQ_MAC2 | IRQ_LINK_SYNC_C_M2 | \ + IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ + IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ + IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) + +#define IRQ_MASK (IRQ_SW | IRQ_EOB_RX1 | IRQ_EOF_RX1 | \ + IRQ_EOB_RX2 | IRQ_EOF_RX2 | \ + IRQ_EOB_SY_TX1 | IRQ_EOF_SY_TX1 | \ + IRQ_EOB_AS_TX1 | IRQ_EOF_AS_TX1 | \ + IRQ_EOB_SY_TX2 | IRQ_EOF_SY_TX2 | \ + IRQ_EOB_AS_TX2 | IRQ_EOF_AS_TX2 | \ + IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ + IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ + IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ + IRQ_MAC1 | \ + IRQ_MAC2 | \ + IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ + IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ + IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) + +#define IRQ_HWE_MASK 0x00000FFF /* enable all HW irqs */ + +typedef struct s_DevNet DEV_NET; + +struct s_DevNet { + int PortNr; + int NetNr; + int Mtu; + int Up; + SK_AC *pAC; +}; + +typedef struct s_TxPort TX_PORT; + +struct s_TxPort { + /* the transmit descriptor rings */ + caddr_t pTxDescrRing; /* descriptor area memory */ + SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ + TXD *pTxdRingHead; /* Head of Tx rings */ + TXD *pTxdRingTail; /* Tail of Tx rings */ + TXD *pTxdRingPrev; /* descriptor sent previously */ + int TxdRingFree; /* # of free entrys */ +#if 0 + spinlock_t TxDesRingLock; /* serialize descriptor accesses */ +#endif + caddr_t HwAddr; /* bmu registers address */ + int PortIndex; /* index number of port (0 or 1) */ +}; + +typedef struct s_RxPort RX_PORT; + +struct s_RxPort { + /* the receive descriptor rings */ + caddr_t pRxDescrRing; /* descriptor area memory */ + SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ + RXD *pRxdRingHead; /* Head of Rx rings */ + RXD *pRxdRingTail; /* Tail of Rx rings */ + RXD *pRxdRingPrev; /* descriptor given to BMU previously */ + int RxdRingFree; /* # of free entrys */ +#if 0 + spinlock_t RxDesRingLock; /* serialize descriptor accesses */ +#endif + int RxFillLimit; /* limit for buffers in ring */ + caddr_t HwAddr; /* bmu registers address */ + int PortIndex; /* index number of port (0 or 1) */ +}; + +typedef struct s_PerStrm PER_STRM; + +#define SK_ALLOC_IRQ 0x00000001 + +/**************************************************************************** + * Per board structure / Adapter Context structure: + * Allocated within attach(9e) and freed within detach(9e). + * Contains all 'per device' necessary handles, flags, locks etc.: + */ +struct s_AC { + SK_GEINIT GIni; /* GE init struct */ + SK_PNMI Pnmi; /* PNMI data struct */ + SK_VPD vpd; /* vpd data struct */ + SK_QUEUE Event; /* Event queue */ + SK_HWT Hwt; /* Hardware Timer control struct */ + SK_TIMCTRL Tim; /* Software Timer control struct */ + SK_I2C I2c; /* I2C relevant data structure */ + SK_ADDR Addr; /* for Address module */ + SK_CSUM Csum; /* for checksum module */ + SK_RLMT Rlmt; /* for rlmt module */ +#if 0 + spinlock_t SlowPathLock; /* Normal IRQ lock */ +#endif + SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */ + int RlmtMode; /* link check mode to set */ + int RlmtNets; /* Number of nets */ + + SK_IOC IoBase; /* register set of adapter */ + int BoardLevel; /* level of active hw init (0-2) */ + char DeviceStr[80]; /* adapter string from vpd */ + SK_U32 AllocFlag; /* flag allocation of resources */ +#if 0 + struct pci_dev *PciDev; /* for access to pci config space */ + SK_U32 PciDevId; /* pci device id */ +#else + int PciDev; +#endif + struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ + char Name[30]; /* driver name */ + struct SK_NET_DEVICE *Next; /* link all devices (for clearing) */ + int RxBufSize; /* length of receive buffers */ +#if 0 + struct net_device_stats stats; /* linux 'netstat -i' statistics */ +#endif + int Index; /* internal board index number */ + + /* adapter RAM sizes for queues of active port */ + int RxQueueSize; /* memory used for receive queue */ + int TxSQueueSize; /* memory used for sync. tx queue */ + int TxAQueueSize; /* memory used for async. tx queue */ + + int PromiscCount; /* promiscuous mode counter */ + int AllMultiCount; /* allmulticast mode counter */ + int MulticCount; /* number of different MC */ + /* addresses for this board */ + /* (may be more than HW can)*/ + + int HWRevision; /* Hardware revision */ + int ActivePort; /* the active XMAC port */ + int MaxPorts; /* number of activated ports */ + int TxDescrPerRing; /* # of descriptors per tx ring */ + int RxDescrPerRing; /* # of descriptors per rx ring */ + + caddr_t pDescrMem; /* Pointer to the descriptor area */ + dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ + + /* the port structures with descriptor rings */ + TX_PORT TxPort[SK_MAX_MACS][2]; + RX_PORT RxPort[SK_MAX_MACS]; + + unsigned int CsOfs1; /* for checksum calculation */ + unsigned int CsOfs2; /* for checksum calculation */ + SK_U32 CsOfs; /* for checksum calculation */ + + SK_BOOL CheckQueue; /* check event queue soon */ + + /* Only for tests */ + int PortUp; + int PortDown; + +}; + +#endif /* __INC_SKDRV2ND_H */ diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h new file mode 100644 index 0000000000..a454d9daa9 --- /dev/null +++ b/drivers/net/sk98lin/h/skerror.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Name: skerror.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.5 $ + * Date: $Date: 2002/04/25 11:05:10 $ + * Purpose: SK specific Error log support + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skerror.h,v $ + * Revision 1.5 2002/04/25 11:05:10 rschmidt + * Editorial changes + * + * Revision 1.4 1999/11/22 13:51:59 cgoos + * Changed license header to GPL. + * + * Revision 1.3 1999/09/14 14:04:42 rwahl + * Added error base SK_ERRBASE_PECP. + * Changed error base for driver. + * + * Revision 1.2 1998/08/11 11:15:41 gklug + * chg: comments + * + * Revision 1.1 1998/08/11 11:09:38 gklug + * add: error bases + * add: error Classes + * first version + * + * + * + ******************************************************************************/ + +#ifndef _INC_SKERROR_H_ +#define _INC_SKERROR_H_ + +/* + * Define Error Classes + */ +#define SK_ERRCL_OTHER (0) /* Other error */ +#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */ +#define SK_ERRCL_INIT (1L<<1) /* Initialization error */ +#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */ +#define SK_ERRCL_SW (1L<<3) /* Internal Software error */ +#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */ +#define SK_ERRCL_COMM (1L<<5) /* Communication error */ + + +/* + * Define Error Code Bases + */ +#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */ +#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */ +#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */ +#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */ +#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */ +#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */ +#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */ +#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */ +#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */ +#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ +#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */ + +#endif /* _INC_SKERROR_H_ */ diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h new file mode 100644 index 0000000000..72ba9ce198 --- /dev/null +++ b/drivers/net/sk98lin/h/skgedrv.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * Name: skgedrv.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.6 $ + * Date: $Date: 2002/07/15 15:38:01 $ + * Purpose: Interface with the driver + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgedrv.h,v $ + * Revision 1.6 2002/07/15 15:38:01 rschmidt + * Power Management support + * Editorial changes + * + * Revision 1.5 2002/04/25 11:05:47 rschmidt + * Editorial changes + * + * Revision 1.4 1999/11/22 13:52:46 cgoos + * Changed license header to GPL. + * + * Revision 1.3 1998/12/01 13:31:39 cgoos + * SWITCH INTERN Event added. + * + * Revision 1.2 1998/11/25 08:28:38 gklug + * rmv: PORT SWITCH Event + * + * Revision 1.1 1998/09/29 06:14:07 gklug + * add: driver events (initial version) + * + * + ******************************************************************************/ + +#ifndef __INC_SKGEDRV_H_ +#define __INC_SKGEDRV_H_ + +/* defines ********************************************************************/ + +/* + * Define the driver events. + * Usually the events are defined by the destination module. + * In case of the driver we put the definition of the events here. + */ +#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */ +#define SK_DRV_NET_UP 2 /* The net is operational */ +#define SK_DRV_NET_DOWN 3 /* The net is down */ +#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */ +#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */ +#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */ +#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */ +#define SK_DRV_PORT_FAIL 8 /* One port fails */ +#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */ +#define SK_DRV_POWER_DOWN 10 /* Power down mode */ + +#endif /* __INC_SKGEDRV_H_ */ diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h new file mode 100644 index 0000000000..2c98427675 --- /dev/null +++ b/drivers/net/sk98lin/h/skgehw.h @@ -0,0 +1,2336 @@ +/****************************************************************************** + * + * Name: skgehw.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.49 $ + * Date: $Date: 2003/01/28 09:43:49 $ + * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skgehw.h,v $ + * Revision 1.49 2003/01/28 09:43:49 rschmidt + * Added defines for PCI-Spec. 2.3 IRQ + * Added defines for CLK_RUN (YUKON-Lite) + * Editorial changes + * + * Revision 1.48 2002/12/05 10:25:11 rschmidt + * Added defines for Half Duplex Burst Mode On/Off + * Added defines for Rx GMAC FIFO Flush feature + * Editorial changes + * + * Revision 1.47 2002/11/12 17:01:31 rschmidt + * Added defines for WOL_CTL_DEFAULT + * Editorial changes + * + * Revision 1.46 2002/10/14 14:47:57 rschmidt + * Corrected bit mask for HW self test results + * Added defines for WOL Registers + * Editorial changes + * + * Revision 1.45 2002/10/11 09:25:22 mkarl + * Added bit mask for HW self test results. + * + * Revision 1.44 2002/08/16 14:44:36 rschmidt + * Added define GPC_HWCFG_GMII_FIB for YUKON Fiber + * + * Revision 1.43 2002/08/12 13:31:50 rschmidt + * Corrected macros for GMAC Address Registers: GM_INADDR(), + * GM_OUTADDR(), GM_INHASH, GM_OUTHASH. + * Editorial changes + * + * Revision 1.42 2002/08/08 15:37:56 rschmidt + * Added defines for Power Management Capabilities + * Editorial changes + * + * Revision 1.41 2002/07/23 16:02:25 rschmidt + * Added macro WOL_REG() to access WOL reg. (HW-Bug in YUKON 1st rev.) + * + * Revision 1.40 2002/07/15 15:41:37 rschmidt + * Added new defines for Power Management Cap. & Control + * Editorial changes + * + * Revision 1.39 2002/06/10 09:37:07 rschmidt + * Added macros for the ADDR-Modul + * + * Revision 1.38 2002/06/05 08:15:19 rschmidt + * Added defines for WOL Registers + * Editorial changes + * + * Revision 1.37 2002/04/25 11:39:23 rschmidt + * Added new defines for PCI Our Register 1 + * Added new registers and defines for YUKON (Rx FIFO, Tx FIFO, + * Time Stamp Timer, GMAC Control, GPHY Control,Link Control, + * GMAC IRQ Source and Mask, Wake-up Frame Pattern Match); + * Added new defines for Control/Status (VAUX available) + * Added Chip ID for YUKON + * Added define for descriptors with UDP ext. for YUKON + * Added macros to access the GMAC + * Added new Phy Type for Marvell 88E1011S (GPHY) + * Editorial changes + * + * Revision 1.36 2000/11/09 12:32:49 rassmann + * Renamed variables. + * + * Revision 1.35 2000/05/19 10:17:13 cgoos + * Added inactivity check in PHY_READ (in DEBUG mode only). + * + * Revision 1.34 1999/11/22 13:53:40 cgoos + * Changed license header to GPL. + * + * Revision 1.33 1999/08/27 11:17:10 malthoff + * It's more savely to put brackets around macro parameters. + * Brackets added for PHY_READ and PHY_WRITE. + * + * Revision 1.32 1999/05/19 07:31:01 cgoos + * Changes for 1000Base-T. + * Added HWAC_LINK_LED macro. + * + * Revision 1.31 1999/03/12 13:27:40 malthoff + * Remove __STDC__. + * + * Revision 1.30 1999/02/09 09:28:20 malthoff + * Add PCI_ERRBITS. + * + * Revision 1.29 1999/01/26 08:55:48 malthoff + * Bugfix: The 16 bit field relations inside the descriptor are + * endianess dependend if the descriptor reversal feature + * (PCI_REV_DESC bit in PCI_OUR_REG_2) is enabled. + * Drivers which use this feature has to set the define + * SK_USE_REV_DESC. + * + * Revision 1.28 1998/12/10 11:10:22 malthoff + * bug fix: IS_IRQ_STAT and IS_IRQ_MST_ERR has been twisted. + * + * Revision 1.27 1998/11/13 14:19:21 malthoff + * Bug Fix: The bit definition of B3_PA_CTRL has completely + * changed from HW Spec v1.3 to v1.5. + * + * Revision 1.26 1998/11/04 08:31:48 cgoos + * Fixed byte ordering in XM_OUTADDR/XM_OUTHASH macros. + * + * Revision 1.25 1998/11/04 07:16:25 cgoos + * Changed byte ordering in XM_INADDR/XM_INHASH again. + * + * Revision 1.24 1998/11/02 11:08:43 malthoff + * RxCtrl and TxCtrl must be volatile. + * + * Revision 1.23 1998/10/28 13:50:45 malthoff + * Fix: Endian support missing in XM_IN/OUT-ADDR/HASH macros. + * + * Revision 1.22 1998/10/26 08:01:36 malthoff + * RX_MFF_CTRL1 is split up into RX_MFF_CTRL1, + * RX_MFF_STAT_TO, and RX_MFF_TIST_TO. + * TX_MFF_CTRL1 is split up TX_MFF_CTRL1 and TX_MFF_WAF. + * + * Revision 1.21 1998/10/20 07:43:10 malthoff + * Fix: XM_IN/OUT/ADDR/HASH macros: + * The pointer must be casted. + * + * Revision 1.20 1998/10/19 15:53:59 malthoff + * Remove ML proto definitions. + * + * Revision 1.19 1998/10/16 14:40:17 gklug + * fix: typo B0_XM_IMSK regs + * + * Revision 1.18 1998/10/16 09:46:54 malthoff + * Remove temp defines for ML diag prototype. + * Fix register definition for B0_XM1_PHY_DATA, B0_XM1_PHY_DATA + * B0_XM2_PHY_DATA, B0_XM2_PHY_ADDR, B0_XA1_CSR, B0_XS1_CSR, + * B0_XS2_CSR, and B0_XA2_CSR. + * + * Revision 1.17 1998/10/14 06:03:14 cgoos + * Changed shifted constant to ULONG. + * + * Revision 1.16 1998/10/09 07:05:41 malthoff + * Rename ALL_PA_ENA_TO to PA_ENA_TO_ALL. + * + * Revision 1.15 1998/10/05 07:54:23 malthoff + * Split up RB_CTRL and it's bit definition into + * RB_CTRL, RB_TST1, and RB_TST2. + * Rename RB_RX_HTPP to RB_RX_LTPP. + * Add ALL_PA_ENA_TO. Modify F_WATER_MARK + * according to HW Spec. v1.5. + * Add MFF_TX_CTRL_DEF. + * + * Revision 1.14 1998/09/28 13:31:16 malthoff + * bug fix: B2_MAC_3 is 0x110 not 0x114 + * + * Revision 1.13 1998/09/24 14:42:56 malthoff + * Split the RX_MFF_TST into RX_MFF_CTRL2, + * RX_MFF_TST1, and RX_MFF_TST2. + * Rename RX_MFF_CTRL to RX_MFF_CTRL1. + * Add BMU bit CSR_SV_IDLE. + * Add macros PHY_READ() and PHY_WRITE(). + * Rename macro SK_ADDR() to SK_HW_ADDR() + * because of conflicts with the Address Module. + * + * Revision 1.12 1998/09/16 07:25:33 malthoff + * Change the parameter order in the XM_INxx and XM_OUTxx macros, + * to have the IoC as first parameter. + * + * Revision 1.11 1998/09/03 09:58:41 malthoff + * Rework the XM_xxx macros. Use {} instead of () to + * be compatible with SK_xxx macros which are defined + * with {}. + * + * Revision 1.10 1998/09/02 11:16:39 malthoff + * Temporary modify B2_I2C_SW to make tests with + * the GE/ML prototype. + * + * Revision 1.9 1998/08/19 09:11:49 gklug + * fix: struct are removed from c-source (see CCC) + * add: typedefs for all structs + * + * Revision 1.8 1998/08/18 08:27:27 malthoff + * Add some temporary workarounds to test GE + * sources with the ML. + * + * Revision 1.7 1998/07/03 14:42:26 malthoff + * bug fix: Correct macro XMA(). + * Add temporary workaround to access the PCI config space over I/O + * + * Revision 1.6 1998/06/23 11:30:36 malthoff + * Remove ';' with ',' in macors. + * + * Revision 1.5 1998/06/22 14:20:57 malthoff + * Add macro SK_ADDR(Base,Addr). + * + * Revision 1.4 1998/06/19 13:35:43 malthoff + * change 'pGec' with 'pAC' + * + * Revision 1.3 1998/06/17 14:58:16 cvs + * Lost keywords reinserted. + * + * Revision 1.1 1998/06/17 14:16:36 cvs + * created + * + * + ******************************************************************************/ + +#ifndef __INC_SKGEHW_H +#define __INC_SKGEHW_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines ********************************************************************/ + +#define BIT_31 (1UL << 31) +#define BIT_30 (1L << 30) +#define BIT_29 (1L << 29) +#define BIT_28 (1L << 28) +#define BIT_27 (1L << 27) +#define BIT_26 (1L << 26) +#define BIT_25 (1L << 25) +#define BIT_24 (1L << 24) +#define BIT_23 (1L << 23) +#define BIT_22 (1L << 22) +#define BIT_21 (1L << 21) +#define BIT_20 (1L << 20) +#define BIT_19 (1L << 19) +#define BIT_18 (1L << 18) +#define BIT_17 (1L << 17) +#define BIT_16 (1L << 16) +#define BIT_15 (1L << 15) +#define BIT_14 (1L << 14) +#define BIT_13 (1L << 13) +#define BIT_12 (1L << 12) +#define BIT_11 (1L << 11) +#define BIT_10 (1L << 10) +#define BIT_9 (1L << 9) +#define BIT_8 (1L << 8) +#define BIT_7 (1L << 7) +#define BIT_6 (1L << 6) +#define BIT_5 (1L << 5) +#define BIT_4 (1L << 4) +#define BIT_3 (1L << 3) +#define BIT_2 (1L << 2) +#define BIT_1 (1L << 1) +#define BIT_0 1L + +#define BIT_15S (1U << 15) +#define BIT_14S (1 << 14) +#define BIT_13S (1 << 13) +#define BIT_12S (1 << 12) +#define BIT_11S (1 << 11) +#define BIT_10S (1 << 10) +#define BIT_9S (1 << 9) +#define BIT_8S (1 << 8) +#define BIT_7S (1 << 7) +#define BIT_6S (1 << 6) +#define BIT_5S (1 << 5) +#define BIT_4S (1 << 4) +#define BIT_3S (1 << 3) +#define BIT_2S (1 << 2) +#define BIT_1S (1 << 1) +#define BIT_0S 1 + +#define SHIFT31(x) ((x) << 31) +#define SHIFT30(x) ((x) << 30) +#define SHIFT29(x) ((x) << 29) +#define SHIFT28(x) ((x) << 28) +#define SHIFT27(x) ((x) << 27) +#define SHIFT26(x) ((x) << 26) +#define SHIFT25(x) ((x) << 25) +#define SHIFT24(x) ((x) << 24) +#define SHIFT23(x) ((x) << 23) +#define SHIFT22(x) ((x) << 22) +#define SHIFT21(x) ((x) << 21) +#define SHIFT20(x) ((x) << 20) +#define SHIFT19(x) ((x) << 19) +#define SHIFT18(x) ((x) << 18) +#define SHIFT17(x) ((x) << 17) +#define SHIFT16(x) ((x) << 16) +#define SHIFT15(x) ((x) << 15) +#define SHIFT14(x) ((x) << 14) +#define SHIFT13(x) ((x) << 13) +#define SHIFT12(x) ((x) << 12) +#define SHIFT11(x) ((x) << 11) +#define SHIFT10(x) ((x) << 10) +#define SHIFT9(x) ((x) << 9) +#define SHIFT8(x) ((x) << 8) +#define SHIFT7(x) ((x) << 7) +#define SHIFT6(x) ((x) << 6) +#define SHIFT5(x) ((x) << 5) +#define SHIFT4(x) ((x) << 4) +#define SHIFT3(x) ((x) << 3) +#define SHIFT2(x) ((x) << 2) +#define SHIFT1(x) ((x) << 1) +#define SHIFT0(x) ((x) << 0) + +/* + * Configuration Space header + * Since this module is used for different OS', those may be + * duplicate on some of them (e.g. Linux). But to keep the + * common source, we have to live with this... + */ +#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */ +#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */ +#define PCI_COMMAND 0x04 /* 16 bit Command */ +#define PCI_STATUS 0x06 /* 16 bit Status */ +#define PCI_REV_ID 0x08 /* 8 bit Revision ID */ +#if 0 +#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */ +#endif +#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */ +#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */ +#define PCI_HEADER_T 0x0e /* 8 bit Header Type */ +#define PCI_BIST 0x0f /* 8 bit Built-in selftest */ +#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */ +#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */ + /* Byte 0x18..0x2b: reserved */ +#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */ +#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */ +#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */ +#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */ + /* Byte 35..3b: reserved */ +#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */ +#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */ +#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */ +#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */ + /* Device Dependent Region */ +#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ +#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ + /* Power Management Region */ +#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ +#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */ +#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ +#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ + /* Byte 0x4e: reserved */ +#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ + /* VPD Region */ +#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ +#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */ +#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ +#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ + /* Byte 0x58..0xff: reserved */ + +/* + * I2C Address (PCI Config) + * + * Note: The temperature and voltage sensors are relocated on a different + * I2C bus. + */ +#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */ + +/* + * Define Bits and Values of the registers + */ +/* PCI_COMMAND 16 bit Command */ + /* Bit 15..11: reserved */ +#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */ +#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */ +#define PCI_SERREN BIT_8S /* SERR enable */ +#define PCI_ADSTEP BIT_7S /* Address Stepping */ +#define PCI_PERREN BIT_6S /* Parity Report Response enable */ +#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */ +#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */ +#define PCI_SCYCEN BIT_3S /* Special Cycle enable */ +#define PCI_BMEN BIT_2S /* Bus Master enable */ +#define PCI_MEMEN BIT_1S /* Memory Space Access enable */ +#define PCI_IOEN BIT_0S /* I/O Space Access enable */ + +#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\ + PCI_BMEN | PCI_MEMEN | PCI_IOEN) + +/* PCI_STATUS 16 bit Status */ +#define PCI_PERR BIT_15S /* Parity Error */ +#define PCI_SERR BIT_14S /* Signaled SERR */ +#define PCI_RMABORT BIT_13S /* Received Master Abort */ +#define PCI_RTABORT BIT_12S /* Received Target Abort */ + /* Bit 11: reserved */ +#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */ +#define PCI_DEV_FAST (0<<9) /* fast */ +#define PCI_DEV_MEDIUM (1<<9) /* medium */ +#define PCI_DEV_SLOW (2<<9) /* slow */ +#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */ +#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */ +#define PCI_UDF BIT_6S /* User Defined Features */ +#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */ +#define PCI_NEWCAP BIT_4S /* New cap. list implemented */ +#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */ + /* Bit 2.. 0: reserved */ + +#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\ + PCI_DATAPERR) + +/* PCI_CLASS_CODE 24 bit Class Code */ +/* Byte 2: Base Class (02) */ +/* Byte 1: SubClass (00) */ +/* Byte 0: Programming Interface (00) */ + +/* PCI_CACHE_LSZ 8 bit Cache Line Size */ +/* Possible values: 0,2,4,8,16,32,64,128 */ + +/* PCI_HEADER_T 8 bit Header Type */ +#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */ +#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */ + +/* PCI_BIST 8 bit Built-in selftest */ +/* Built-in Self test not supported (optional) */ + +/* PCI_BASE_1ST 32 bit 1st Base address */ +#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */ +#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */ +#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */ +#define PCI_PREFEN BIT_3 /* Prefetchable */ +#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */ +#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */ +#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */ +#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */ +#define PCI_MEMSPACE BIT_0 /* Memory Space Indic. */ + +/* PCI_BASE_2ND 32 bit 2nd Base address */ +#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */ +#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */ + /* Bit 1: reserved */ +#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */ + +/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */ +#define PCI_ROMBASE 0xfffe0000L /* Bit 31..17: ROM BASE address (1st)*/ +#define PCI_ROMBASZ (0x1cL<<14) /* Bit 16..14: Treat as BASE or SIZE */ +#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */ + /* Bit 10.. 1: reserved */ +#define PCI_ROMEN BIT_0 /* Address Decode enable */ + +/* Device Dependent Region */ +/* PCI_OUR_REG_1 32 bit Our Register 1 */ + /* Bit 31..29: reserved */ +#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode */ +#define PCI_EN_CAL BIT_27 /* Enable PCI buffer strength calibr. */ +#define PCI_DIS_CAL BIT_26 /* Disable PCI buffer strength calibr. */ +#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */ +#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */ +#define PCI_EN_IO BIT_23 /* Mapping to I/O space */ +#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */ + /* 1 = Map Flash to memory */ + /* 0 = Disable addr. dec */ +#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */ +#define PCI_PAGE_16 (0L<<20) /* 16 k pages */ +#define PCI_PAGE_32K (1L<<20) /* 32 k pages */ +#define PCI_PAGE_64K (2L<<20) /* 64 k pages */ +#define PCI_PAGE_128K (3L<<20) /* 128 k pages */ + /* Bit 19: reserved */ +#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ +#define PCI_NOTAR BIT_15 /* No turnaround cycle */ +#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */ +#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */ +#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */ +#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */ +#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */ +#define PCI_BURST_DIS BIT_9 /* Burst Disable */ +#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */ +#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */ +#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */ + + +/* PCI_OUR_REG_2 32 bit Our Register 2 */ +#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */ +#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */ +#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */ + /* Bit 13..12: reserved */ +#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */ +#define PCI_PATCH_DIR_3 BIT_11 +#define PCI_PATCH_DIR_2 BIT_10 +#define PCI_PATCH_DIR_1 BIT_9 +#define PCI_PATCH_DIR_0 BIT_8 +#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */ +#define PCI_EXT_PATCH_3 BIT_7 +#define PCI_EXT_PATCH_2 BIT_6 +#define PCI_EXT_PATCH_1 BIT_5 +#define PCI_EXT_PATCH_0 BIT_4 +#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */ +#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */ + /* Bit 1: reserved */ +#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */ + + +/* Power Management Region */ +/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */ +#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */ +#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */ +#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */ +#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */ +#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */ +#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */ +#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */ +#define PCI_PM_D1_SUP BIT_9S /* D1 Support */ + /* Bit 8.. 6: reserved */ +#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */ +#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */ +#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */ +#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */ + +/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */ +#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */ +#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */ +#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */ +#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */ + /* Bit 7.. 2: reserved */ +#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */ + +#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */ +#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */ +#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */ +#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */ + +/* VPD Region */ +/* PCI_VPD_ADR_REG 16 bit VPD Address Register */ +#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */ +#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */ + +/* Control Register File (Address Map) */ + +/* + * Bank 0 + */ +#define B0_RAP 0x0000 /* 8 bit Register Address Port */ + /* 0x0001 - 0x0003: reserved */ +#define B0_CTST 0x0004 /* 16 bit Control/Status register */ +#define B0_LED 0x0006 /* 8 Bit LED register */ +#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */ +#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */ +#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */ +#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */ +#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */ +#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */ + /* 0x001c: reserved */ + +/* B0 XMAC 1 registers (GENESIS only) */ +#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/ + /* 0x0022 - 0x0027: reserved */ +#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */ + /* 0x002a - 0x002f: reserved */ +#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */ + /* 0x0032 - 0x0033: reserved */ +#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */ + /* 0x0036 - 0x003f: reserved */ + +/* B0 XMAC 2 registers (GENESIS only) */ +#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/ + /* 0x0042 - 0x0047: reserved */ +#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */ + /* 0x004a - 0x004f: reserved */ +#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */ + /* 0x0052 - 0x0053: reserved */ +#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */ + /* 0x0056 - 0x005f: reserved */ + +/* BMU Control Status Registers */ +#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */ +#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */ +#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ +#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/ +#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ +#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/ + /* 0x0078 - 0x007f: reserved */ + +/* + * Bank 1 + * - completely empty (this is the RAP Block window) + * Note: if RAP = 1 this page is reserved + */ + +/* + * Bank 2 + */ +/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */ +#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */ + /* 0x0106 - 0x0107: reserved */ +#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */ + /* 0x010e - 0x010f: reserved */ +#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */ + /* 0x0116 - 0x0117: reserved */ +#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */ +#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */ +#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */ +#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ + /* Eprom registers are currently of no use */ +#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */ +#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */ +#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */ +#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */ +#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ +#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ + /* 0x0125 - 0x0127: reserved */ +#define B2_LD_CRTL 0x0128 /* 8 bit EPROM loader control register */ +#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ + /* 0x012a - 0x012f: reserved */ +#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ +#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ +#define B2_TI_CRTL 0x0138 /* 8 bit Timer Control */ +#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ + /* 0x013a - 0x013f: reserved */ +#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ +#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */ +#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */ +#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */ +#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */ +#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */ + /* 0x0154 - 0x0157: reserved */ +#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */ +#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */ + /* 0x015a - 0x015b: reserved */ +#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */ +#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */ +#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */ +#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */ +#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */ + +/* Blink Source Counter (GENESIS only) */ +#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */ +#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */ +#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */ +#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */ +#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */ + /* 0x017c - 0x017f: reserved */ + +/* + * Bank 3 + */ +/* RAM Random Registers */ +#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */ +#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */ +#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */ + /* 0x018c - 0x018f: reserved */ + +/* RAM Interface Registers */ +/* + * The HW-Spec. calls this registers Timeout Value 0..11. But this names are + * not usable in SW. Please notice these are NOT real timeouts, these are + * the number of qWords transferred continuously. + */ +#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */ +#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */ +#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */ +#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */ +#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */ +#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */ +#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */ +#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */ +#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */ +#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */ +#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/ +#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/ +#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */ + /* 0x019d - 0x019f: reserved */ +#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */ +#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */ + /* 0x01a3 - 0x01af: reserved */ + +/* MAC Arbiter Registers (GENESIS only) */ +/* these are the no. of qWord transferred continuously and NOT real timeouts */ +#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */ +#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */ +#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */ +#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */ +#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */ +#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */ +#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */ +#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */ +#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */ +#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */ + /* 0x01bc - 0x01bf: reserved */ +#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */ +#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */ +#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */ +#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */ +#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */ +#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */ +#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */ +#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */ +#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */ +#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */ + /* 0x01cc - 0x01cf: reserved */ + +/* Packet Arbiter Registers (GENESIS only) */ +/* these are real timeouts */ +#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */ + /* 0x01d2 - 0x01d3: reserved */ +#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */ + /* 0x01d6 - 0x01d7: reserved */ +#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */ + /* 0x01da - 0x01db: reserved */ +#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */ + /* 0x01de - 0x01df: reserved */ +#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */ + /* 0x01e2 - 0x01e3: reserved */ +#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */ + /* 0x01e6 - 0x01e7: reserved */ +#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */ + /* 0x01ea - 0x01eb: reserved */ +#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */ + /* 0x01ee - 0x01ef: reserved */ +#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ +#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ + /* 0x01f4 - 0x01ff: reserved */ + +/* + * Bank 4 - 5 + */ +/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ +#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/ +#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */ +#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */ +#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */ +#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */ +#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */ +#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */ + /* 0x0213 - 0x027f: reserved */ + /* 0x0280 - 0x0292: MAC 2 */ + /* 0x0213 - 0x027f: reserved */ + +/* + * Bank 6 + */ +/* External registers (GENESIS only) */ +#define B6_EXT_REG 0x0300 + +/* + * Bank 7 + */ +/* This is a copy of the Configuration register file (lower half) */ +#define B7_CFG_SPC 0x0380 + +/* + * Bank 8 - 15 + */ +/* Receive and Transmit Queue Registers, use Q_ADDR() to access */ +#define B8_Q_REGS 0x0400 + +/* Queue Register Offsets, use Q_ADDR() to access */ +#define Q_D 0x00 /* 8*32 bit Current Descriptor */ +#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */ +#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */ +#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */ +#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */ +#define Q_BC 0x30 /* 32 bit Current Byte Counter */ +#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */ +#define Q_F 0x38 /* 32 bit Flag Register */ +#define Q_T1 0x3c /* 32 bit Test Register 1 */ +#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */ +#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */ +#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */ +#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */ +#define Q_T2 0x40 /* 32 bit Test Register 2 */ +#define Q_T3 0x44 /* 32 bit Test Register 3 */ + /* 0x48 - 0x7f: reserved */ + +/* + * Bank 16 - 23 + */ +/* RAM Buffer Registers */ +#define B16_RAM_REGS 0x0800 + +/* RAM Buffer Register Offsets, use RB_ADDR() to access */ +#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */ +#define RB_END 0x04 /* 32 bit RAM Buffer End Address */ +#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */ +#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */ +#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */ +#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */ +#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */ +#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */ + /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ +#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */ +#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */ +#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */ +#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */ +#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */ + /* 0x2c - 0x7f: reserved */ + +/* + * Bank 24 + */ +/* + * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) + * use MR_ADDR() to access + */ +#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */ +#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ + /* 0x0c08 - 0x0c0b: reserved */ +#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */ +#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */ +#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */ +#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/ +#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */ +#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */ +#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/ +#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */ +#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */ + /* 0x0c1f: reserved */ +#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */ +#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */ +#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */ +#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */ + /* 0x0c2a - 0x0c2f: reserved */ +#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */ +#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */ +#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */ +#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */ + /* 0x0c3a - 0x0c3b: reserved */ +#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */ + /* 0x0c3d - 0x0c3f: reserved */ + +/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */ +#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */ +#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */ +#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */ +#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ +#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ + /* 0x0c54 - 0x0c5f: reserved */ +#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ + /* 0x0c64 - 0x0c67: reserved */ +#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ + /* 0x0c6c - 0x0c6f: reserved */ +#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ + /* 0x0c74 - 0x0c77: reserved */ +#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ + /* 0x0c7c - 0x0c7f: reserved */ + +/* + * Bank 25 + */ + /* 0x0c80 - 0x0cbf: MAC 2 */ + /* 0x0cc0 - 0x0cff: reserved */ + +/* + * Bank 26 + */ +/* + * Transmit MAC FIFO and Transmit LED Registers (GENESIS only), + * use MR_ADDR() to access + */ +#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */ +#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ +#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */ +#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */ +#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */ +#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */ +#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ +#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */ + /* 0x0c1b: reserved */ +#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ +#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */ +#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */ + /* 0x0d1f: reserved */ +#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */ +#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */ +#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */ +#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */ + /* 0x0d2a - 0x0d3f: reserved */ + +/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */ +#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */ +#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ +#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */ + /* 0x0d4c - 0x0d5f: reserved */ +#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ +#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ +#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ + /* 0x0d6c - 0x0d6f: reserved */ +#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ +#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ +#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ + /* 0x0d7c - 0x0d7f: reserved */ + +/* + * Bank 27 + */ + /* 0x0d80 - 0x0dbf: MAC 2 */ + /* 0x0daa - 0x0dff: reserved */ + +/* + * Bank 28 + */ +/* Descriptor Poll Timer Registers */ +#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */ +#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */ +#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */ + /* 0x0e09: reserved */ +#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */ + /* 0x0e0b: reserved */ + +/* Time Stamp Timer Registers (YUKON only) */ + /* 0x0e10: reserved */ +#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */ +#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */ + /* 0x0e19: reserved */ +#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */ + /* 0x0e1b - 0x0e7f: reserved */ + +/* + * Bank 29 + */ + /* 0x0e80 - 0x0efc: reserved */ + +/* + * Bank 30 + */ +/* GMAC and GPHY Control Registers (YUKON only) */ +#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */ +#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */ +#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */ + /* 0x0f09 - 0x0f0b: reserved */ +#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */ + /* 0x0f0d - 0x0f0f: reserved */ +#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */ + /* 0x0f14 - 0x0f1f: reserved */ + +/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ + +#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */ + +#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */ +#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */ +#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */ +#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */ +#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */ +#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */ + +/* use this macro to access above registers */ +#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs)) + + +/* WOL Pattern Length Registers (YUKON only) */ + +#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */ +#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */ + +/* WOL Pattern Counter Registers (YUKON only) */ + +#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */ +#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */ + /* 0x0f40 - 0x0f7f: reserved */ + +/* + * Bank 31 + */ +/* 0x0f80 - 0x0fff: reserved */ + +/* + * Bank 32 - 33 + */ +#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */ + +/* + * Bank 0x22 - 0x3f + */ +/* 0x1100 - 0x1fff: reserved */ + +/* + * Bank 0x40 - 0x4f + */ +#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */ + +/* + * Bank 0x50 - 0x5f + */ + +#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */ + +/* + * Bank 0x60 - 0x6f + */ +#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */ + +/* + * Bank 0x70 - 0x7f + */ +#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */ + +/* + * Control Register Bit Definitions: + */ +/* B0_RAP 8 bit Register Address Port */ + /* Bit 7: reserved */ +#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ + +/* B0_CTST 16 bit Control/Status register */ + /* Bit 15..14: reserved */ +#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ +#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ +#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */ +#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */ +#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */ +#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */ +#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */ +#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */ +#define CS_STOP_DONE BIT_5S /* Stop Master is finished */ +#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */ +#define CS_MRST_CLR BIT_3S /* Clear Master reset */ +#define CS_MRST_SET BIT_2S /* Set Master reset */ +#define CS_RST_CLR BIT_1S /* Clear Software reset */ +#define CS_RST_SET BIT_0S /* Set Software reset */ + +/* B0_LED 8 Bit LED register */ + /* Bit 7.. 2: reserved */ +#define LED_STAT_ON BIT_1S /* Status LED on */ +#define LED_STAT_OFF BIT_0S /* Status LED off */ + +/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ +#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */ +#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ +#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ +#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ +#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ +#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ +#define PC_VCC_ON BIT_1 /* Switch VCC On */ +#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ + +/* B0_ISRC 32 bit Interrupt Source Register */ +/* B0_IMSK 32 bit Interrupt Mask Register */ +/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ +/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ +#define IS_ALL_MSK 0xbfffffffL /* All Interrupt bits */ +#define IS_HW_ERR BIT_31 /* Interrupt HW Error */ + /* Bit 30: reserved */ +#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */ +#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */ +#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */ +#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */ +#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */ +#define IS_IRQ_SW BIT_24 /* SW forced IRQ */ +#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */ + /* IRQ from PHY (YUKON only) */ +#define IS_TIMINT BIT_22 /* IRQ from Timer */ +#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */ +#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */ +#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */ +#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */ +/* Receive Queue 1 */ +#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */ +#define IS_R1_F BIT_16 /* Q_R1 End of Frame */ +#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */ +/* Receive Queue 2 */ +#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */ +#define IS_R2_F BIT_13 /* Q_R2 End of Frame */ +#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */ +/* Synchronous Transmit Queue 1 */ +#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */ +#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */ +#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */ +/* Asynchronous Transmit Queue 1 */ +#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */ +#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */ +#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */ +/* Synchronous Transmit Queue 2 */ +#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */ +#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */ +#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */ +/* Asynchronous Transmit Queue 2 */ +#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */ +#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */ +#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ + + +/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ +/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ +/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ +#define IS_ERR_MSK 0x00000fffL /* All Error bits */ + /* Bit 31..14: reserved */ +#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ +#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */ +#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */ +#define IS_IRQ_STAT BIT_10 /* IRQ status exception */ +#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */ +#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */ +#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */ +#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */ +#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */ +#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */ +#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */ +#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */ +#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ +#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ + +/* B2_CONN_TYP 8 bit Connector type */ +/* B2_PMD_TYP 8 bit PMD type */ +/* Values of connector and PMD type comply to SysKonnect internal std */ + +/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ +#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ + /* Bit 3.. 2: reserved */ +#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ +#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ + +/* B2_CHIP_ID 8 bit Chip Identification Number */ +#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ +#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ + +/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ +#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ + +/* B2_LD_CRTL 8 bit EPROM loader control register */ +/* Bits are currently reserved */ + +/* B2_LD_TEST 8 bit EPROM loader test register */ + /* Bit 7.. 4: reserved */ +#define LD_T_ON BIT_3S /* Loader Test mode on */ +#define LD_T_OFF BIT_2S /* Loader Test mode off */ +#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */ +#define LD_START BIT_0S /* Start loading FPROM */ + +/* + * Timer Section + */ +/* B2_TI_CRTL 8 bit Timer control */ +/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ + /* Bit 7.. 3: reserved */ +#define TIM_START BIT_2S /* Start Timer */ +#define TIM_STOP BIT_1S /* Stop Timer */ +#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ + +/* B2_TI_TEST 8 Bit Timer Test */ +/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ +/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ + /* Bit 7.. 3: reserved */ +#define TIM_T_ON BIT_2S /* Test mode on */ +#define TIM_T_OFF BIT_1S /* Test mode off */ +#define TIM_T_STEP BIT_0S /* Test step */ + +/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */ +/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */ + /* Bit 31..24: reserved */ +#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */ + +/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ + /* Bit 7.. 2: reserved */ +#define DPT_START BIT_1S /* Start Descriptor Poll Timer */ +#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */ + +/* B2_E_3 8 bit lower 4 bits used for HW self test result */ +#define B2_E3_RES_MASK 0x0f + +/* B2_TST_CTRL1 8 bit Test Control Register 1 */ +#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */ +#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */ +#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */ +#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */ +#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */ +#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */ +#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */ +#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */ + +/* B2_TST_CTRL2 8 bit Test Control Register 2 */ + /* Bit 7.. 4: reserved */ + /* force the following error on the next master read/write */ +#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */ +#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */ +#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ +#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ + +/* B2_GP_IO 32 bit General Purpose I/O Register */ + /* Bit 31..26: reserved */ +#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=I/1=O */ +#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=I/1=O */ +#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=I/1=O */ +#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=I/1=O */ +#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=I/1=O */ +#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=I/1=O */ +#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=I/1=O */ +#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=I/1=O */ +#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=I/1=O */ +#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=I/1=O */ + /* Bit 15..10: reserved */ +#define GP_IO_9 BIT_9 /* IO_9 pin */ +#define GP_IO_8 BIT_8 /* IO_8 pin */ +#define GP_IO_7 BIT_7 /* IO_7 pin */ +#define GP_IO_6 BIT_6 /* IO_6 pin */ +#define GP_IO_5 BIT_5 /* IO_5 pin */ +#define GP_IO_4 BIT_4 /* IO_4 pin */ +#define GP_IO_3 BIT_3 /* IO_3 pin */ +#define GP_IO_2 BIT_2 /* IO_2 pin */ +#define GP_IO_1 BIT_1 /* IO_1 pin */ +#define GP_IO_0 BIT_0 /* IO_0 pin */ + +/* B2_I2C_CTRL 32 bit I2C HW Control Register */ +#define I2C_FLAG BIT_31 /* Start read/write if WR */ +#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ +#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ + /* Bit 8.. 5: reserved */ +#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ +#define I2C_DEV_SIZE (7L<<1) /* Bit 3.. 1: I2C Device Size */ +#define I2C_025K_DEV (0L<<1) /* 0: 256 Bytes or smal. */ +#define I2C_05K_DEV (1L<<1) /* 1: 512 Bytes */ +#define I2C_1K_DEV (2L<<1) /* 2: 1024 Bytes */ +#define I2C_2K_DEV (3L<<1) /* 3: 2048 Bytes */ +#define I2C_4K_DEV (4L<<1) /* 4: 4096 Bytes */ +#define I2C_8K_DEV (5L<<1) /* 5: 8192 Bytes */ +#define I2C_16K_DEV (6L<<1) /* 6: 16384 Bytes */ +#define I2C_32K_DEV (7L<<1) /* 7: 32768 Bytes */ +#define I2C_STOP BIT_0 /* Interrupt I2C transfer */ + +/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ + /* Bit 31.. 1 reserved */ +#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ + +/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ + /* Bit 7.. 3: reserved */ +#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ +#define I2C_DATA BIT_1S /* I2C Data Port */ +#define I2C_CLK BIT_0S /* I2C Clock Port */ + +/* + * I2C Address + */ +#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ + + +/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ + /* Bit 7.. 2: reserved */ +#define BSC_START BIT_1S /* Start Blink Source Counter */ +#define BSC_STOP BIT_0S /* Stop Blink Source Counter */ + +/* B2_BSC_STAT 8 bit Blink Source Counter Status */ + /* Bit 7.. 1: reserved */ +#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ + +/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ +#define BSC_T_ON BIT_2S /* Test mode on */ +#define BSC_T_OFF BIT_1S /* Test mode off */ +#define BSC_T_STEP BIT_0S /* Test step */ + + +/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ + /* Bit 31..19: reserved */ +#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ + +/* RAM Interface Registers */ +/* B3_RI_CTRL 16 bit RAM Iface Control Register */ + /* Bit 15..10: reserved */ +#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ +#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ + /* Bit 7.. 2: reserved */ +#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ +#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ + +/* B3_RI_TEST 8 bit RAM Iface Test Register */ + /* Bit 15.. 4: reserved */ +#define RI_T_EV BIT_3S /* Timeout Event occured */ +#define RI_T_ON BIT_2S /* Timeout Timer Test On */ +#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */ +#define RI_T_STEP BIT_0S /* Timeout Timer Step */ + +/* MAC Arbiter Registers */ +/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ + /* Bit 15.. 4: reserved */ +#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */ +#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */ +#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ +#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ + +/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */ + /* Bit 15.. 8: reserved */ +#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */ +#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */ +#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */ +#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */ +#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */ +#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */ +#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */ +#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ + +/* Packet Arbiter Registers */ +/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ + /* Bit 15..14: reserved */ +#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ +#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ +#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */ +#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */ +#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */ +#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */ +#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */ +#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */ +#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */ +#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */ +#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */ +#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */ +#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ +#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ + +#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ + PA_ENA_TO_TX1 | PA_ENA_TO_TX2) + +/* Rx/Tx Path related Arbiter Test Registers */ +/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ +/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ +/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ +/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ +#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ +#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ +#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */ +#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */ +#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */ +#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */ +#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */ +#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */ +#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */ +#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */ +#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */ +#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */ +#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */ +#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */ +#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */ +#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */ + + +/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ +/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ +/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ +/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ +/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ + /* Bit 31..24: reserved */ +#define TXA_MAX_VAL 0x00ffffffL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ + +/* TXA_CTRL 8 bit Tx Arbiter Control Register */ +#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ +#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ +#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ +#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */ +#define TXA_START_RC BIT_3S /* Start sync Rate Control */ +#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */ +#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ +#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ + +/* TXA_TEST 8 bit Tx Arbiter Test Register */ + /* Bit 7.. 6: reserved */ +#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ +#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ +#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */ +#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */ +#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ +#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ + +/* TXA_STAT 8 bit Tx Arbiter Status Register */ + /* Bit 7.. 1: reserved */ +#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ + +/* Q_BC 32 bit Current Byte Counter */ + /* Bit 31..16: reserved */ +#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ + +/* BMU Control Status Registers */ +/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ +/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ +/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ +/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ +/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ +/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ +/* Q_CSR 32 bit BMU Control/Status Register */ + /* Bit 31..25: reserved */ +#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ + /* Bit 23..22: reserved */ +#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */ +#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */ +#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */ +#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */ +#define CSR_HPI_RUN BIT_17 /* Release HPI SM */ +#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */ +#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */ +#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */ +#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */ +#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */ +#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */ +#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */ +#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */ +#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */ +#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */ +#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */ +#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */ +#define CSR_START BIT_4 /* Start Rx/Tx Queue */ +#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */ +#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */ +#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */ +#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */ + +#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ + CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ + CSR_TRANS_RST) +#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ + CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ + CSR_TRANS_RUN) + +/* Q_F 32 bit Flag Register */ + /* Bit 31..28: reserved */ +#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ +#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ +#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ +#define F_WM_REACHED BIT_25 /* Watermark reached */ + /* reserved */ +#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */ + /* Bit 15..11: reserved */ +#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ + +/* Q_T1 32 bit Test Register 1 */ +/* Holds four State Machine control Bytes */ +#define SM_CRTL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ +#define SM_CRTL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ +#define SM_CRTL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ +#define SM_CRTL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ + +/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ +/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ +/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ +/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ + +/* The control status byte of each machine looks like ... */ +#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ +#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */ +#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */ +#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */ +#define SM_STEP BIT_0S /* Step the State Machine */ +/* The encoding of the states is not supported by the Diagnostics Tool */ + +/* Q_T2 32 bit Test Register 2 */ + /* Bit 31.. 8: reserved */ +#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ +#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ +#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */ +#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */ +#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */ +#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */ +#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ +#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ + +/* Q_T3 32 bit Test Register 3 */ + /* Bit 31.. 7: reserved */ +#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ + /* Bit 3: reserved */ +#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ + +/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ +/* RB_START 32 bit RAM Buffer Start Address */ +/* RB_END 32 bit RAM Buffer End Address */ +/* RB_WP 32 bit RAM Buffer Write Pointer */ +/* RB_RP 32 bit RAM Buffer Read Pointer */ +/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ +/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ +/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ +/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ +/* RB_PC 32 bit RAM Buffer Packet Counter */ +/* RB_LEV 32 bit RAM Buffer Level Register */ + /* Bit 31..19: reserved */ +#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ + +/* RB_TST2 8 bit RAM Buffer Test Register 2 */ + /* Bit 7.. 4: reserved */ +#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */ +#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */ +#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */ +#define RB_PC_INC BIT_0S /* Packet Counter Increm */ + +/* RB_TST1 8 bit RAM Buffer Test Register 1 */ + /* Bit 7: reserved */ +#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */ +#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */ +#define RB_WP_INC BIT_4S /* Write Pointer Increm */ + /* Bit 3: reserved */ +#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */ +#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */ +#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */ + +/* RB_CTRL 8 bit RAM Buffer Control Register */ + /* Bit 7.. 6: reserved */ +#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */ +#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */ +#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */ +#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */ +#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */ +#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */ + + +/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ + +/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ +/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ +/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ +/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ +/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ +/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ +/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ +/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ +/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ +/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ +/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ + /* Bit 31.. 6: reserved */ +#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ + +/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ + /* Bit 15..14: reserved */ +#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */ +#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */ +#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */ +#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */ +#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */ +#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */ +#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */ +#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */ +#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */ +#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */ +#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */ +#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */ +#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */ +#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */ + +#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT + +/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ +#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */ + /* Bit 14: reserved */ +#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */ +#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */ +/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */ +/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */ +/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */ +/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */ +#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */ +#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */ +/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */ +/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */ +#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */ +#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */ +#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */ +#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */ + +#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) + +/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ +/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ + /* Bit 7: reserved */ +#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */ +#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */ +#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */ +#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */ +#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */ +#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */ +#define MFF_PC_INC BIT_0S /* Packet Counter Increment */ + +/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ +/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ + /* Bit 7: reserved */ +#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */ +#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */ +#define MFF_WP_INC BIT_4S /* Write Pointer Increm */ + /* Bit 3: reserved */ +#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */ +#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */ +#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */ + +/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ +/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ + /* Bit 7..4: reserved */ +#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */ +#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */ +#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */ +#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */ + + +/* Link LED Counter Registers (GENESIS only) */ + +/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ +/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ +/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ + /* Bit 7.. 3: reserved */ +#define LED_START BIT_2S /* Start Timer */ +#define LED_STOP BIT_1S /* Stop Timer */ +#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */ +#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */ + +/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ +/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ +/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ + /* Bit 7.. 3: reserved */ +#define LED_T_ON BIT_2S /* LED Counter Test mode On */ +#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */ +#define LED_T_STEP BIT_0S /* LED Counter Step */ + +/* LNK_LED_REG 8 bit Link LED Register */ + /* Bit 7.. 6: reserved */ +#define LED_BLK_ON BIT_5S /* Link LED Blinking On */ +#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */ +#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */ +#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */ +#define LED_ON BIT_1S /* switch LED on */ +#define LED_OFF BIT_0S /* switch LED off */ + +/* Receive and Transmit GMAC FIFO Registers (YUKON only) */ + +/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */ +/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */ +/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ +/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ +/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ +/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ +/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ +/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ +/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ +/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */ +/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ +/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ +/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ +/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ + +/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ + /* Bits 31..15: reserved */ +#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ +#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ +#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ + /* Bit 11: reserved */ +#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ +#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ +#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ +#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ +#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ +#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ +#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ +#define GMF_OPER_ON BIT_3 /* Operational Mode On */ +#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ +#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ +#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ + +/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ + /* Bits 31..19: reserved */ +#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ +#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ +#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ + /* Bits 15..7: same as for RX_GMF_CTRL_T */ +#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ +#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ +#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ + /* Bits 3..0: same as for RX_GMF_CTRL_T */ + +#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON) +#define GMF_TX_CTRL_DEF GMF_OPER_ON + +#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ + +/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ + /* Bit 7.. 3: reserved */ +#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ +#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ +#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ + +/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ + /* Bits 31.. 8: reserved */ +#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ +#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ +#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ +#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ +#define GMC_PAUSE_ON BIT_3 /* Pause On */ +#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ +#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ +#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ + +/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ + /* Bits 31..29: reserved */ +#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */ +#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */ +#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */ +#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */ +#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */ +#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */ +#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */ +#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */ +#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */ +#define GPC_ANEG_0 BIT_19 /* ANEG[0] */ +#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */ +#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */ +#define GPC_ANEG_3 BIT_16 /* ANEG[3] */ +#define GPC_ANEG_2 BIT_15 /* ANEG[2] */ +#define GPC_ANEG_1 BIT_14 /* ANEG[1] */ +#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */ +#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */ +#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */ +#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */ +#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */ +#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */ + /* Bits 7..2: reserved */ +#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */ +#define GPC_RST_SET BIT_0 /* Set GPHY Reset */ + +#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \ + GPC_HWCFG_M_1 | GPC_HWCFG_M_0) + +#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \ + GPC_HWCFG_M_1 | GPC_HWCFG_M_0) + +#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \ + GPC_ANEG_1 | GPC_ANEG_0) + +/* forced speed and duplex mode (don't mix with other ANEG bits) */ +#define GPC_FRC10MBIT_HALF 0 +#define GPC_FRC10MBIT_FULL GPC_ANEG_0 +#define GPC_FRC100MBIT_HALF GPC_ANEG_1 +#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) + +/* auto-negotiation with limited advertised speeds */ +/* mix only with master/slave settings (for copper) */ +#define GPC_ADV_1000_HALF GPC_ANEG_2 +#define GPC_ADV_1000_FULL GPC_ANEG_3 +#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) + +/* master/slave settings */ +/* only for copper with 1000 Mbps */ +#define GPC_FORCE_MASTER 0 +#define GPC_FORCE_SLAVE GPC_ANEG_0 +#define GPC_PREF_MASTER GPC_ANEG_1 +#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) + +/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ +/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ +#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */ +#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */ +#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */ +#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */ +#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */ +#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */ + +#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ + GM_IS_TX_FF_UR) + +/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ + /* Bits 15.. 2: reserved */ +#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ +#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ + + +/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ +#define WOL_CTL_LINK_CHG_OCC BIT_15S +#define WOL_CTL_MAGIC_PKT_OCC BIT_14S +#define WOL_CTL_PATTERN_OCC BIT_13S + +#define WOL_CTL_CLEAR_RESULT BIT_12S + +#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S +#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S +#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S +#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S +#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S +#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S + +#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S +#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S +#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S +#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S +#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S +#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S + +#define WOL_CTL_DEFAULT \ + (WOL_CTL_DIS_PME_ON_LINK_CHG | \ + WOL_CTL_DIS_PME_ON_PATTERN | \ + WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ + WOL_CTL_DIS_LINK_CHG_UNIT | \ + WOL_CTL_DIS_PATTERN_UNIT | \ + WOL_CTL_DIS_MAGIC_PKT_UNIT) + +/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ +#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) + +#define SK_NUM_WOL_PATTERN 7 +#define SK_PATTERN_PER_WORD 4 +#define SK_BITMASK_PATTERN 7 +#define SK_POW_PATTERN_LENGTH 128 + +#define WOL_LENGTH_MSK 0x7f +#define WOL_LENGTH_SHIFT 8 + + +/* Receive and Transmit Descriptors ******************************************/ + +/* Transmit Descriptor struct */ +typedef struct s_HwTxd { + SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */ + SK_U32 TxNext; /* Physical Address Pointer to the next TxD */ + SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */ + SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */ + SK_U32 TxStat; /* Transmit Frame Status Word */ +#ifndef SK_USE_REV_DESC + SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ + SK_U16 TxRes1; /* 16 bit reserved field */ + SK_U16 TxTcpWp; /* TCP Checksum Write Position */ + SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ +#else /* SK_USE_REV_DESC */ + SK_U16 TxRes1; /* 16 bit reserved field */ + SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ + SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ + SK_U16 TxTcpWp; /* TCP Checksum Write Position */ +#endif /* SK_USE_REV_DESC */ + SK_U32 TxRes2; /* 32 bit reserved field */ +} SK_HWTXD; + +/* Receive Descriptor struct */ +typedef struct s_HwRxd { + SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */ + SK_U32 RxNext; /* Physical Address Pointer to the next RxD */ + SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */ + SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */ + SK_U32 RxStat; /* Receive Frame Status Word */ + SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */ +#ifndef SK_USE_REV_DESC + SK_U16 RxTcpSum1; /* TCP Checksum 1 */ + SK_U16 RxTcpSum2; /* TCP Checksum 2 */ + SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ + SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ +#else /* SK_USE_REV_DESC */ + SK_U16 RxTcpSum2; /* TCP Checksum 2 */ + SK_U16 RxTcpSum1; /* TCP Checksum 1 */ + SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ + SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ +#endif /* SK_USE_REV_DESC */ +} SK_HWRXD; + +/* + * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2) + * should set the define SK_USE_REV_DESC. + * Structures are 'normaly' not endianess dependent. But in + * this case the SK_U16 fields are bound to bit positions inside the + * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord. + * The bit positions inside a DWord are of course endianess dependent and + * swaps if the DWord is swapped by the hardware. + */ + + +/* Descriptor Bit Definition */ +/* TxCtrl Transmit Buffer Control Field */ +/* RxCtrl Receive Buffer Control Field */ +#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */ +#define BMU_STF BIT_30 /* Start of Frame */ +#define BMU_EOF BIT_29 /* End of Frame */ +#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */ +#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */ +/* TxCtrl specific bits */ +#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */ +#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */ +#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */ +/* RxCtrl specific bits */ +#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */ +#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */ +#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */ + /* Bit 23..16: BMU Check Opcodes */ +#define BMU_CHECK (0x55L<<16) /* Default BMU check */ +#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */ +#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */ +#define BMU_BBC 0xFFFFL /* Bit 15.. 0: Buffer Byte Counter */ + +/* TxStat Transmit Frame Status Word */ +/* RxStat Receive Frame Status Word */ +/* + *Note: TxStat is reserved for ASIC loopback mode only + * + * The Bits of the Status words are defined in xmac_ii.h + * (see XMR_FS bits) + */ + +/* other defines *************************************************************/ + +/* + * FlashProm specification + */ +#define MAX_PAGES 0x20000L /* Every byte has a single page */ +#define MAX_FADDR 1 /* 1 byte per page */ +#define SKFDDI_PSZ 8 /* address PROM size */ + +/* macros ********************************************************************/ + +/* + * Receive and Transmit Queues + */ +#define Q_R1 0x0000 /* Receive Queue 1 */ +#define Q_R2 0x0080 /* Receive Queue 2 */ +#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */ +#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */ +#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */ +#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */ + +/* + * Macro Q_ADDR() + * + * Use this macro to access the Receive and Transmit Queue Registers. + * + * para: + * Queue Queue to access. + * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 + * Offs Queue register offset. + * Values: Q_D, Q_DA_L ... Q_T2, Q_T3 + * + * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal) + */ +#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs)) + +/* + * Macro RB_ADDR() + * + * Use this macro to access the RAM Buffer Registers. + * + * para: + * Queue Queue to access. + * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 + * Offs Queue register offset. + * Values: RB_START, RB_END ... RB_LEV, RB_CTRL + * + * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal) + */ +#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs)) + + +/* + * MAC Related Registers + */ +#define MAC_1 0 /* belongs to the port near the slot */ +#define MAC_2 1 /* belongs to the port far away from the slot */ + +/* + * Macro MR_ADDR() + * + * Use this macro to access a MAC Related Registers inside the ASIC. + * + * para: + * Mac MAC to access. + * Values: MAC_1, MAC_2 + * Offs MAC register offset. + * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG, + * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST + * + * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) + */ +#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs)) + +#ifdef SK_LITTLE_ENDIAN +#define XM_WORD_LO 0 +#define XM_WORD_HI 1 +#else /* !SK_LITTLE_ENDIAN */ +#define XM_WORD_LO 1 +#define XM_WORD_HI 0 +#endif /* !SK_LITTLE_ENDIAN */ + + +/* + * macros to access the XMAC (GENESIS only) + * + * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD) + * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD) + * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT) + * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT) + * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK) + * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK) + * XM_INHASH(), to read the XM_HSM_CHK register + * XM_OUTHASH() to write the XM_HSM_CHK register + * + * para: + * Mac XMAC to access values: MAC_1 or MAC_2 + * IoC I/O context needed for SK I/O macros + * Reg XMAC Register to read or write + * (p)Val Value or pointer to the value which should be read or written + * + * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value); + */ + +#define XMA(Mac, Reg) \ + ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1)) + +#define XM_IN16(IoC, Mac, Reg, pVal) \ + SK_IN16((IoC), XMA((Mac), (Reg)), (pVal)) + +#define XM_OUT16(IoC, Mac, Reg, Val) \ + SK_OUT16((IoC), XMA((Mac), (Reg)), (Val)) + +#define XM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16((IoC), XMA((Mac), (Reg)), \ + (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ + SK_IN16((IoC), XMA((Mac), (Reg+2)), \ + (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ +} + +#define XM_OUT32(IoC, Mac, Reg, Val) { \ + SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ + SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\ +} + +/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */ + +#define XM_INADDR(IoC, Mac, Reg, pVal) { \ + SK_U16 Word; \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ + pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ + pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ +} + +#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ + (((SK_U16)(pByte[0]) & 0x00ff) | \ + (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ + SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ + (((SK_U16)(pByte[2]) & 0x00ff) | \ + (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ + SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ + (((SK_U16)(pByte[4]) & 0x00ff) | \ + (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ +} + +#define XM_INHASH(IoC, Mac, Reg, pVal) { \ + SK_U16 Word; \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ + pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ + pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \ + pByte[6] = (SK_U8)(Word & 0x00ff); \ + pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ +} + +#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ + (((SK_U16)(pByte[0]) & 0x00ff)| \ + (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ + SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ + (((SK_U16)(pByte[2]) & 0x00ff)| \ + (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ + SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ + (((SK_U16)(pByte[4]) & 0x00ff)| \ + (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ + SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \ + (((SK_U16)(pByte[6]) & 0x00ff)| \ + (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ +} + +/* + * macros to access the GMAC (YUKON only) + * + * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT) + * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL) + * GM_IN32(), to read a 32 bit register (e.g. GM_) + * GM_OUT32(), to write a 32 bit register (e.g. GM_) + * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L) + * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L) + * GM_INHASH(), to read the GM_MC_ADDR_H1 register + * GM_OUTHASH() to write the GM_MC_ADDR_H1 register + * + * para: + * Mac GMAC to access values: MAC_1 or MAC_2 + * IoC I/O context needed for SK I/O macros + * Reg GMAC Register to read or write + * (p)Val Value or pointer to the value which should be read or written + * + * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value); + */ + +#define GMA(Mac, Reg) \ + ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg)) + +#define GM_IN16(IoC, Mac, Reg, pVal) \ + SK_IN16((IoC), GMA((Mac), (Reg)), (pVal)) + +#define GM_OUT16(IoC, Mac, Reg, Val) \ + SK_OUT16((IoC), GMA((Mac), (Reg)), (Val)) + +#define GM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16((IoC), GMA((Mac), (Reg)), \ + (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ + SK_IN16((IoC), GMA((Mac), (Reg+4)), \ + (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ +} + +#define GM_OUT32(IoC, Mac, Reg, Val) { \ + SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ + SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\ +} + +#define GM_INADDR(IoC, Mac, Reg, pVal) { \ + SK_U16 Word; \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ + pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ + pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ +} + +#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ + (((SK_U16)(pByte[0]) & 0x00ff) | \ + (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ + SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ + (((SK_U16)(pByte[2]) & 0x00ff) | \ + (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ + SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ + (((SK_U16)(pByte[4]) & 0x00ff) | \ + (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ +} + +#define GM_INHASH(IoC, Mac, Reg, pVal) { \ + SK_U16 Word; \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ + pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ + pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \ + pByte[6] = (SK_U8)(Word & 0x00ff); \ + pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ +} + +#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \ + SK_U8 *pByte; \ + pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ + (((SK_U16)(pByte[0]) & 0x00ff)| \ + (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ + SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ + (((SK_U16)(pByte[2]) & 0x00ff)| \ + (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ + SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ + (((SK_U16)(pByte[4]) & 0x00ff)| \ + (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ + SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \ + (((SK_U16)(pByte[6]) & 0x00ff)| \ + (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ +} + +/* + * Different MAC Types + */ +#define SK_MAC_XMAC 0 /* Xaqti XMAC II */ +#define SK_MAC_GMAC 1 /* Marvell GMAC */ + +/* + * Different PHY Types + */ +#define SK_PHY_XMAC 0 /* integrated in XMAC II */ +#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */ +#define SK_PHY_LONE 2 /* Level One LXT1000 */ +#define SK_PHY_NAT 3 /* National DP83891 */ +#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */ +#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */ + +/* + * PHY addresses (bits 12..8 of PHY address reg) + */ +#define PHY_ADDR_XMAC (0<<8) +#define PHY_ADDR_BCOM (1<<8) +#define PHY_ADDR_LONE (3<<8) +#define PHY_ADDR_NAT (0<<8) + +/* GPHY address (bits 15..11 of SMI control reg) */ +#define PHY_ADDR_MARV 0 + +/* + * macros to access the PHY + * + * PHY_READ() read a 16 bit value from the PHY + * PHY_WRITE() write a 16 bit value to the PHY + * + * para: + * IoC I/O context needed for SK I/O macros + * pPort Pointer to port struct for PhyAddr + * Mac XMAC to access values: MAC_1 or MAC_2 + * PhyReg PHY Register to read or write + * (p)Val Value or pointer to the value which should be read or + * written. + * + * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value); + * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never + * comes back. This is checked in DEBUG mode. + */ +#ifndef DEBUG +#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ + SK_U16 Mmu; \ + \ + XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ + XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ + if ((pPort)->PhyType != SK_PHY_XMAC) { \ + do { \ + XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ + } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ + XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ + } \ +} +#else +#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ + SK_U16 Mmu; \ + int __i = 0; \ + \ + XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ + XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ + if ((pPort)->PhyType != SK_PHY_XMAC) { \ + do { \ + XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ + __i++; \ + if (__i > 100000) { \ + SK_DBG_PRINTF("*****************************\n"); \ + SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \ + SK_DBG_PRINTF("*****************************\n"); \ + break; \ + } \ + } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ + XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ + } \ +} +#endif /* DEBUG */ + +#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \ + SK_U16 Mmu; \ + \ + if ((pPort)->PhyType != SK_PHY_XMAC) { \ + do { \ + XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ + } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ + } \ + XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ + XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \ + if ((pPort)->PhyType != SK_PHY_XMAC) { \ + do { \ + XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ + } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ + } \ +} + +/* + * Macro PCI_C() + * + * Use this macro to access PCI config register from the I/O space. + * + * para: + * Addr PCI configuration register to access. + * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG, + * + * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal); + */ +#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */ + +/* + * Macro SK_HW_ADDR(Base, Addr) + * + * Calculates the effective HW address + * + * para: + * Base I/O or memory base address + * Addr Address offset + * + * usage: May be used in SK_INxx and SK_OUTxx macros + * #define SK_IN8(pAC, Addr, pVal) ...\ + * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr))) + */ +#ifdef SK_MEM_MAPPED_IO +#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr)) +#else /* SK_MEM_MAPPED_IO */ +#define SK_HW_ADDR(Base, Addr) \ + ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0))) +#endif /* SK_MEM_MAPPED_IO */ + +#define SZ_LONG (sizeof(SK_U32)) + +/* + * Macro SK_HWAC_LINK_LED() + * + * Use this macro to set the link LED mode. + * para: + * pAC Pointer to adapter context struct + * IoC I/O context needed for SK I/O macros + * Port Port number + * Mode Mode to set for this LED + */ +#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \ + SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode); + + +/* typedefs *******************************************************************/ + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_SKGEHW_H */ diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h new file mode 100644 index 0000000000..8aa9edd71c --- /dev/null +++ b/drivers/net/sk98lin/h/skgehwt.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Name: skhwt.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.5 $ + * Date: $Date: 1999/11/22 13:54:24 $ + * Purpose: Defines for the hardware timer functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgehwt.h,v $ + * Revision 1.5 1999/11/22 13:54:24 cgoos + * Changed license header to GPL. + * + * Revision 1.4 1998/08/19 09:50:58 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.3 1998/08/14 07:09:29 gklug + * fix: chg pAc -> pAC + * + * Revision 1.2 1998/08/07 12:54:21 gklug + * fix: first compiled version + * + * Revision 1.1 1998/08/07 09:32:58 gklug + * first version + * + * + * + * + * + ******************************************************************************/ + +/* + * SKGEHWT.H contains all defines and types for the timer functions + */ + +#ifndef _SKGEHWT_H_ +#define _SKGEHWT_H_ + +/* + * SK Hardware Timer + * - needed wherever the HWT module is used + * - use in Adapters context name pAC->Hwt + */ +typedef struct s_Hwt { + SK_U32 TStart ; /* HWT start */ + SK_U32 TStop ; /* HWT stop */ + int TActive ; /* HWT: flag : active/inactive */ +} SK_HWT; + +extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); +extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); +extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); +extern SK_U32 SkHwtRead(SK_AC *pAC,SK_IOC Ioc); +extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); +#endif /* _SKGEHWT_H_ */ diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h new file mode 100644 index 0000000000..e639f733c6 --- /dev/null +++ b/drivers/net/sk98lin/h/skgei2c.h @@ -0,0 +1,299 @@ +/****************************************************************************** + * + * Name: skgei2c.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.23 $ + * Date: $Date: 2002/12/19 14:34:27 $ + * Purpose: Special GEnesis defines for TWSI + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgei2c.h,v $ + * Revision 1.23 2002/12/19 14:34:27 rschmidt + * Added cast in macros SK_I2C_SET_BIT() and SK_I2C_CLR_BIT() + * Editorial changes (TWSI) + * + * Revision 1.22 2002/10/14 16:45:56 rschmidt + * Editorial changes (TWSI) + * + * Revision 1.21 2002/08/13 08:42:24 rschmidt + * Changed define for SK_MIN_SENSORS back to 5 + * Merged defines for PHY PLL 3V3 voltage (A and B) + * Editorial changes + * + * Revision 1.20 2002/08/06 09:43:56 jschmalz + * Extensions and changes for Yukon + * + * Revision 1.19 2002/08/02 12:00:08 rschmidt + * Added defines for YUKON sensors + * Editorial changes + * + * Revision 1.18 2001/08/16 12:44:33 afischer + * LM80 sensor init values corrected + * + * Revision 1.17 1999/11/22 13:55:25 cgoos + * Changed license header to GPL. + * + * Revision 1.16 1999/11/12 08:24:10 malthoff + * Change voltage warning and error limits + * (warning +-5%, error +-10%). + * + * Revision 1.15 1999/09/14 14:14:43 malthoff + * The 1000BT Dual Link adapter has got only one Fan. + * The second Fan has been removed. + * + * Revision 1.14 1999/05/27 13:40:50 malthoff + * Fan Divisor = 1. Assuming fan with 6500 rpm. + * + * Revision 1.13 1999/05/20 14:56:55 malthoff + * Bug Fix: Missing brace in SK_LM80_FAN_FAKTOR. + * + * Revision 1.12 1999/05/20 09:22:00 cgoos + * Changes for 1000Base-T (Fan sensors). + * + * Revision 1.11 1998/10/14 05:57:22 cgoos + * Fixed compilation warnings. + * + * Revision 1.10 1998/09/04 08:37:00 malthoff + * bugfix: correct the SK_I2C_GET_CTL() macro. + * + * Revision 1.9 1998/08/25 06:10:03 gklug + * add: thresholds for all sensors + * + * Revision 1.8 1998/08/20 11:37:42 gklug + * chg: change Ioc to IoC + * + * Revision 1.7 1998/08/20 08:53:11 gklug + * fix: compiler errors + * add: Threshold values + * + * Revision 1.6 1998/08/17 11:37:09 malthoff + * Bugfix in SK_I2C_CTL macro. The parameter 'dev' + * has to be shifted 9 bits. + * + * Revision 1.5 1998/08/17 06:52:21 malthoff + * Remove unrequired macros. + * Add macros for accessing TWSI SW register. + * + * Revision 1.4 1998/08/13 08:30:18 gklug + * add: conversion factors for read values + * add: new state SEN_VALEXT to read extension value of temperature sensor + * + * Revision 1.3 1998/08/12 13:37:56 gklug + * rmv: error numbers and messages + * + * Revision 1.2 1998/08/11 07:54:38 gklug + * add: sensor states for GE sensors + * add: Macro to access TWSI hardware register + * chg: Error messages for TWSI errors + * + * Revision 1.1 1998/07/17 11:27:56 gklug + * Created. + * + * + * + ******************************************************************************/ + +/* + * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling + */ + +#ifndef _INC_SKGEI2C_H_ +#define _INC_SKGEI2C_H_ + +/* + * Macros to access the B2_I2C_CTRL + */ +#define SK_I2C_CTL(IoC, flag, dev, reg, burst) \ + SK_OUT32(IoC, B2_I2C_CTRL,\ + (flag ? 0x80000000UL : 0x0L) | \ + (((SK_U32) reg << 16) & I2C_ADDR) | \ + (((SK_U32) dev << 9) & I2C_DEV_SEL) | \ + (( burst << 4) & I2C_BURST_LEN)) + +#define SK_I2C_STOP(IoC) { \ + SK_U32 I2cCtrl; \ + SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \ + SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \ +} + +#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl) + +/* + * Macros to access the TWSI SW Registers + */ +#define SK_I2C_SET_BIT(IoC, SetBits) { \ + SK_U8 OrgBits; \ + SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ + SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \ +} + +#define SK_I2C_CLR_BIT(IoC, ClrBits) { \ + SK_U8 OrgBits; \ + SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ + SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \ +} + +#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw) + +/* + * define the possible sensor states + */ +#define SK_SEN_IDLE 0 /* Idle: sensor not read */ +#define SK_SEN_VALUE 1 /* Value Read cycle */ +#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */ + +/* + * Conversion factor to convert read Voltage sensor to milli Volt + * Conversion factor to convert read Temperature sensor to 10th degree Celsius + */ +#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ +#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ +#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for the + * extension value + */ +#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) +/* formula: counter = (22500*60)/(rpm * divisor * pulses/2) + * assuming: 6500rpm, 4 pulses, divisor 1 + */ + +/* + * Define sensor management data + * Maximum is reached on copperfield with dual Broadcom. + * Board specific maximum is in pAC->I2c.MaxSens + */ +#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ +#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ + +/* + * To watch the statemachine (JS) use the timer in two ways instead of one as hitherto + */ +#define SK_TIMER_WATCH_STATEMACHINE 0 /* Watch the statemachine to finish in a specific time */ +#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ + + +/* + * Defines for the individual Thresholds + */ + +/* Temperature sensor */ +#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ +#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ +#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ +#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ + +/* VCC which should be 5 V */ +#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ +#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ +#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ +#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ + +/* + * VIO may be 5 V or 3.3 V. Initialization takes two parts: + * 1. Initialize lowest lower limit and highest higher limit. + * 2. After the first value is read correct the upper or the lower limit to + * the appropriate C constant. + * + * Warning limits are +-5% of the exepected voltage. + * Error limits are +-10% of the expected voltage. + */ + +/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ + +#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */ +#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */ + /* 5000 mVolt */ +#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */ +#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */ + +#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */ + +/* correction values for the second pass */ +#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ +#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ + /* 3300 mVolt */ +#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ +#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ + + +/* + * VDD voltage + */ +#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ +#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ +#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ +#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ + +/* + * PHY PLL 3V3 voltage + */ +#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */ +#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */ +#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */ +#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */ + +/* + * VAUX (YUKON only) + */ +#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */ +#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */ +#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */ +#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ +#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ +#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ + +/* + * PHY 2V5 voltage + */ +#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */ +#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */ +#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */ +#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */ + +/* + * ASIC Core 1V5 voltage (YUKON only) + */ +#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ +#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */ +#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */ +#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */ + +/* + * FAN 1 speed + */ +/* assuming: 6500rpm +-15%, 4 pulses, + * warning at: 80 % + * error at: 70 % + * no upper limit + */ +#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ +#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ +#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ +#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ + +/* + * Some Voltages need dynamic thresholds + */ +#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */ +#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */ +#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */ + +extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); +#endif /* n_INC_SKGEI2C_H */ diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h new file mode 100644 index 0000000000..cdddef92b3 --- /dev/null +++ b/drivers/net/sk98lin/h/skgeinit.h @@ -0,0 +1,1113 @@ +/****************************************************************************** + * + * Name: skgeinit.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.75 $ + * Date: $Date: 2003/02/05 13:36:39 $ + * Purpose: Structures and prototypes for the GE Init Module + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgeinit.h,v $ + * Revision 1.75 2003/02/05 13:36:39 rschmidt + * Added define SK_FACT_78 for YUKON's Host Clock of 78.12 MHz + * Editorial changes + * + * Revision 1.74 2003/01/28 09:39:16 rschmidt + * Added entry GIYukonLite in s_GeInit structure + * Editorial changes + * + * Revision 1.73 2002/11/15 12:47:25 rschmidt + * Replaced error message SKERR_HWI_E024 for Cable Diagnostic with + * Rx queue error in SkGeStopPort(). + * + * Revision 1.72 2002/11/12 17:08:35 rschmidt + * Added entries for Cable Diagnostic to Port structure + * Added entries GIPciSlot64 and GIPciClock66 in s_GeInit structure + * Added error message for Cable Diagnostic + * Added prototypes for SkGmCableDiagStatus() + * Editorial changes + * + * Revision 1.71 2002/10/21 11:26:10 mkarl + * Changed interface of SkGeInitAssignRamToQueues(). + * + * Revision 1.70 2002/10/14 08:21:32 rschmidt + * Changed type of GICopperType, GIVauxAvail to SK_BOOL + * Added entry PRxOverCnt to Port structure + * Added entry GIYukon32Bit in s_GeInit structure + * Editorial changes + * + * Revision 1.69 2002/10/09 16:57:15 mkarl + * Added some constants and macros for SkGeInitAssignRamToQueues(). + * + * Revision 1.68 2002/09/12 08:58:51 rwahl + * Retrieve counters needed for XMAC errata workarounds directly because + * PNMI returns corrected counter values (e.g. #10620). + * + * Revision 1.67 2002/08/16 14:40:30 rschmidt + * Added entries GIGenesis and GICopperType in s_GeInit structure + * Added prototypes for SkMacHashing() + * Editorial changes + * + * Revision 1.66 2002/08/12 13:27:21 rschmidt + * Added defines for Link speed capabilities + * Added entry PLinkSpeedCap to Port structure + * Added entry GIVauxAvail in s_GeInit structure + * Added prototypes for SkMacPromiscMode() + * Editorial changes + * + * Revision 1.65 2002/08/08 15:46:18 rschmidt + * Added define SK_PHY_ACC_TO for PHY access timeout + * Added define SK_XM_RX_HI_WM for XMAC Rx High Watermark + * Added define SK_MIN_TXQ_SIZE for Min RAM Buffer Tx Queue Size + * Added entry PhyId1 to Port structure + * + * Revision 1.64 2002/07/23 16:02:56 rschmidt + * Added entry GIWolOffs in s_GeInit struct (HW-Bug in YUKON 1st rev.) + * Added prototypes for: SkGePhyRead(), SkGePhyWrite() + * + * Revision 1.63 2002/07/18 08:17:38 rwahl + * Corrected definitions for SK_LSPEED_xxx & SK_LSPEED_STAT_xxx. + * + * Revision 1.62 2002/07/17 18:21:55 rwahl + * Added SK_LSPEED_INDETERMINATED define. + * + * Revision 1.61 2002/07/17 17:16:03 rwahl + * - MacType now member of GIni struct. + * - Struct alignment to 32bit. + * - Editorial change. + * + * Revision 1.60 2002/07/15 18:23:39 rwahl + * Added GeMacFunc to GE Init structure. + * Added prototypes for SkXmUpdateStats(), SkGmUpdateStats(), + * SkXmMacStatistic(), SkGmMacStatistic(), SkXmResetCounter(), + * SkGmResetCounter(), SkXmOverflowStatus(), SkGmOverflowStatus(). + * Added defines for current link speed state. + * Added ERRMSG defintions for MacUpdateStat() & MacStatistics(). + * + * Revision 1.59 2002/07/15 15:40:22 rschmidt + * Added entry PLinkSpeedUsed to Port structure + * Editorial changes + * + * Revision 1.58 2002/06/10 09:36:30 rschmidt + * Editorial changes. + * + * Revision 1.57 2002/06/05 08:18:00 rschmidt + * Corrected alignment in Port Structure + * Added new prototypes for GMAC + * Editorial changes + * + * Revision 1.56 2002/04/25 11:38:12 rschmidt + * Added defines for Link speed values + * Added defines for Loopback parameters for MAC and PHY + * Removed entry PRxCmd from Port structure + * Added entry PLinkSpeed to Port structure + * Added entries GIChipId and GIChipRev to GE Init structure + * Removed entry GIAnyPortAct from GE Init structure + * Added prototypes for: SkMacInit(), SkMacInitPhy(), + * SkMacRxTxDisable(), SkMacSoftRst(), SkMacHardRst(), SkMacIrq(), + * SkMacIrqDisable(), SkMacFlushTxFifo(), SkMacFlushRxFifo(), + * SkMacAutoNegDone(), SkMacAutoNegLipaPhy(), SkMacSetRxTxEn(), + * SkXmPhyRead(), SkXmPhyRead(), SkGmPhyWrite(), SkGmPhyWrite(); + * Removed prototypes for static functions in SkXmac2.c + * Editorial changes + * + * Revision 1.55 2002/02/26 15:24:53 rwahl + * Fix: no link with manual configuration (#10673). The previous fix for + * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to + * misconfigured port. It should not occur for the other RLMT modes. + * + * Revision 1.54 2002/01/18 16:52:52 rwahl + * Editorial corrections. + * + * Revision 1.53 2001/11/20 09:19:58 rwahl + * Reworked bugfix #10639 (no dependency to RLMT mode). + * + * Revision 1.52 2001/10/26 07:52:23 afischer + * Port switching bug in `check local link` mode + * + * Revision 1.51 2001/02/09 12:26:38 cgoos + * Inserted #ifdef DIAG for half duplex workaround timer. + * + * Revision 1.50 2001/02/07 07:56:40 rassmann + * Corrected copyright. + * + * Revision 1.49 2001/01/31 15:32:18 gklug + * fix: problem with autosensing an SR8800 switch + * add: counter for autoneg timeouts + * + * Revision 1.48 2000/11/09 11:30:10 rassmann + * WA: Waiting after releasing reset until BCom chip is accessible. + * + * Revision 1.47 2000/10/18 12:22:40 cgoos + * Added workaround for half duplex hangup. + * + * Revision 1.46 2000/08/10 11:28:00 rassmann + * Editorial changes. + * Preserving 32-bit alignment in structs for the adapter context. + * + * Revision 1.45 1999/11/22 13:56:19 cgoos + * Changed license header to GPL. + * + * Revision 1.44 1999/10/26 07:34:15 malthoff + * The define SK_LNK_ON has been lost in v1.41. + * + * Revision 1.43 1999/10/06 09:30:16 cgoos + * Changed SK_XM_THR_JUMBO. + * + * Revision 1.42 1999/09/16 12:58:26 cgoos + * Changed SK_LED_STANDY macro to be independent of HW link sync. + * + * Revision 1.41 1999/07/30 06:56:14 malthoff + * Correct comment for SK_MS_STAT_UNSET. + * + * Revision 1.40 1999/05/27 13:38:46 cgoos + * Added SK_BMU_TX_WM. + * Made SK_BMU_TX_WM and SK_BMU_RX_WM user-definable. + * Changed XMAC Tx treshold to max. values. + * + * Revision 1.39 1999/05/20 14:35:26 malthoff + * Remove prototypes for SkGeLinkLED(). + * + * Revision 1.38 1999/05/19 11:59:12 cgoos + * Added SK_MS_CAP_INDETERMINATED define. + * + * Revision 1.37 1999/05/19 07:32:33 cgoos + * Changes for 1000Base-T. + * LED-defines for HWAC_LINK_LED macro. + * + * Revision 1.36 1999/04/08 14:00:24 gklug + * add:Port struct field PLinkResCt + * + * Revision 1.35 1999/03/25 07:43:07 malthoff + * Add error string for SKERR_HWI_E018MSG. + * + * Revision 1.34 1999/03/12 16:25:57 malthoff + * Remove PPollRxD and PPollTxD. + * Add SKERR_HWI_E017MSG. and SK_DPOLL_MAX. + * + * Revision 1.33 1999/03/12 13:34:41 malthoff + * Add Autonegotiation error codes. + * Change defines for parameter Mode in SkXmSetRxCmd(). + * Replace __STDC__ by SK_KR_PROTO. + * + * Revision 1.32 1999/01/25 14:40:20 mhaveman + * Added new return states for the virtual management port if multiple + * ports are active but differently configured. + * + * Revision 1.31 1998/12/11 15:17:02 gklug + * add: Link partnet autoneg states : Unknown Manual and Auto-negotiation + * + * Revision 1.30 1998/12/07 12:17:04 gklug + * add: Link Partner auto-negotiation flag + * + * Revision 1.29 1998/12/01 10:54:42 gklug + * add: variables for XMAC Errata + * + * Revision 1.28 1998/12/01 10:14:15 gklug + * add: PIsave saves the Interrupt status word + * + * Revision 1.27 1998/11/26 15:24:52 mhaveman + * Added link status states SK_LMODE_STAT_AUTOHALF and + * SK_LMODE_STAT_AUTOFULL which are used by PNMI. + * + * Revision 1.26 1998/11/26 14:53:01 gklug + * add:autoNeg Timeout variable + * + * Revision 1.25 1998/11/26 08:58:50 gklug + * add: Link Mode configuration (AUTO Sense mode) + * + * Revision 1.24 1998/11/24 13:30:27 gklug + * add: PCheckPar to port struct + * + * Revision 1.23 1998/11/18 13:23:26 malthoff + * Add SK_PKT_TO_MAX. + * + * Revision 1.22 1998/11/18 13:19:54 gklug + * add: PPrevShorts and PLinkBroken to port struct for WA XMAC Errata #C1 + * + * Revision 1.21 1998/10/26 08:02:57 malthoff + * Add GIRamOffs. + * + * Revision 1.20 1998/10/19 07:28:37 malthoff + * Add prototype for SkGeInitRamIface(). + * + * Revision 1.19 1998/10/14 14:47:48 malthoff + * SK_TIMER should not be defined for Diagnostics. + * Add SKERR_HWI_E015MSG and SKERR_HWI_E016MSG. + * + * Revision 1.18 1998/10/14 14:00:03 gklug + * add: timer to port struct for workaround of Errata #2 + * + * Revision 1.17 1998/10/14 11:23:09 malthoff + * Add prototype for SkXmAutoNegDone(). + * Fix SkXmSetRxCmd() prototype statement. + * + * Revision 1.16 1998/10/14 05:42:29 gklug + * add: HWLinkUp flag to Port struct + * + * Revision 1.15 1998/10/09 08:26:33 malthoff + * Rename SK_RB_ULPP_B to SK_RB_LLPP_B. + * + * Revision 1.14 1998/10/09 07:11:13 malthoff + * bug fix: SK_FACT_53 is 85 not 117. + * Rework time out init values. + * Add GIPortUsage and corresponding defines. + * Add some error log messages. + * + * Revision 1.13 1998/10/06 14:13:14 malthoff + * Add prototype for SkGeLoadLnkSyncCnt(). + * + * Revision 1.12 1998/10/05 11:29:53 malthoff + * bug fix: A comment was not closed. + * + * Revision 1.11 1998/10/05 08:01:59 malthoff + * Add default Timeout- Threshold- and + * Watermark constants. Add QRam start and end + * variables. Also add vars to store the polling + * mode and receive command. Add new Error Log + * Messages and function prototypes. + * + * Revision 1.10 1998/09/28 13:34:48 malthoff + * Add mode bits for LED functions. + * Move Autoneg and Flow Ctrl bits from shgesirq.h + * Add the required Error Log Entries + * and Function Prototypes. + * + * Revision 1.9 1998/09/16 14:38:41 malthoff + * Rework the SK_LNK_xxx defines. + * Add error log message defines. + * Add prototypes for skxmac2.c + * + * Revision 1.8 1998/09/11 05:29:18 gklug + * add: init state of a port + * + * Revision 1.7 1998/09/08 08:35:52 gklug + * add: defines of the Init Levels + * + * Revision 1.6 1998/09/03 13:48:42 gklug + * add: Link strati, capabilities to Port struct + * + * Revision 1.5 1998/09/03 13:30:59 malthoff + * Add SK_LNK_BLINK and SK_LNK_PERM. + * + * Revision 1.4 1998/09/03 09:55:31 malthoff + * Add constants for parameters Dir and RstMode + * when calling SkGeStopPort(). + * Rework the prototype section. + * Add Queue Address offsets PRxQOff, PXsQOff, and PXaQOff. + * Remove Ioc with IoC. + * + * Revision 1.3 1998/08/19 09:11:54 gklug + * fix: struct are removed from c-source (see CCC) + * add: typedefs for all structs + * + * Revision 1.2 1998/07/28 12:38:26 malthoff + * The prototypes got the parameter 'IoC'. + * + * Revision 1.1 1998/07/23 09:50:24 malthoff + * Created. + * + ******************************************************************************/ + +#ifndef __INC_SKGEINIT_H_ +#define __INC_SKGEINIT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines ********************************************************************/ + +/* modifying Link LED behaviour (used with SkGeLinkLED()) */ +#define SK_LNK_OFF LED_OFF +#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) +#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON) +#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON) +#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF) + +/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */ +#define SK_LED_OFF LED_OFF +#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) +#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF) + +/* addressing LED Registers in SkGeXmitLED() */ +#define XMIT_LED_INI 0 +#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI) +#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI) +#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI) + +/* parameter 'Mode' when calling SkGeXmitLED() */ +#define SK_LED_DIS 0 +#define SK_LED_ENA 1 +#define SK_LED_TST 2 + +/* Counter and Timer constants, for a host clock of 62.5 MHz */ +#define SK_XMIT_DUR 0x002faf08L /* 50 ms */ +#define SK_BLK_DUR 0x01dcd650L /* 500 ms */ + +#define SK_DPOLL_DEF 0x00ee6b28L /* 250 ms at 62.5 MHz */ + +#define SK_DPOLL_MAX 0x00ffffffL /* 268 ms at 62.5 MHz */ + /* 215 ms at 78.12 MHz */ + +#define SK_FACT_62 100 /* is given in percent */ +#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ +#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ + +/* Timeout values */ +#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ +#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ +#define SK_PKT_TO_MAX 0xffff /* Maximum value */ +#define SK_RI_TO_53 36 /* RAM interface timeout */ + +#define SK_PHY_ACC_TO 600000 /* PHY access timeout */ + +/* RAM Buffer High Pause Threshold values */ +#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */ +#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */ +#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */ + +#ifndef SK_BMU_RX_WM +#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ +#endif +#ifndef SK_BMU_TX_WM +#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ +#endif + +/* XMAC II Rx High Watermark */ +#define SK_XM_RX_HI_WM 0x05aa /* 1450 */ + +/* XMAC II Tx Threshold */ +#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */ +#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */ +#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */ +#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */ + +/* values for GIPortUsage */ +#define SK_RED_LINK 1 /* redundant link usage */ +#define SK_MUL_LINK 2 /* multiple link usage */ +#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */ + +/* Minimum RAM Buffer Rx Queue Size */ +#define SK_MIN_RXQ_SIZE 16 /* 16 kB */ + +/* Minimum RAM Buffer Tx Queue Size */ +#define SK_MIN_TXQ_SIZE 16 /* 16 kB */ + +/* Queue Size units */ +#define QZ_UNITS 0x7 +#define QZ_STEP 8 + +/* Percentage of queue size from whole memory */ +/* 80 % for receive */ +#define RAM_QUOTA_RX 80L +/* 0% for sync transfer */ +#define RAM_QUOTA_SYNC 0L +/* the rest (20%) is taken for async transfer */ + +/* Get the rounded queue size in Bytes in 8k steps */ +#define ROUND_QUEUE_SIZE(SizeInBytes) \ + ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \ + ~(QZ_STEP-1)) + +/* Get the rounded queue size in KBytes in 8k steps */ +#define ROUND_QUEUE_SIZE_KB(Kilobytes) \ + ROUND_QUEUE_SIZE((Kilobytes) * 1024L) + +/* Types of RAM Buffer Queues */ +#define SK_RX_SRAM_Q 1 /* small receive queue */ +#define SK_RX_BRAM_Q 2 /* big receive queue */ +#define SK_TX_RAM_Q 3 /* small or big transmit queue */ + +/* parameter 'Dir' when calling SkGeStopPort() */ +#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */ +#define SK_STOP_RX 2 /* Stops the receive path */ +#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */ + +/* parameter 'RstMode' when calling SkGeStopPort() */ +#define SK_SOFT_RST 1 /* perform a software reset */ +#define SK_HARD_RST 2 /* perform a hardware reset */ + +/* Init Levels */ +#define SK_INIT_DATA 0 /* Init level 0: init data structures */ +#define SK_INIT_IO 1 /* Init level 1: init with IOs */ +#define SK_INIT_RUN 2 /* Init level 2: init for run time */ + +/* Link Mode Parameter */ +#define SK_LMODE_HALF 1 /* Half Duplex Mode */ +#define SK_LMODE_FULL 2 /* Full Duplex Mode */ +#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */ +#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */ +#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */ +#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */ +#define SK_LMODE_INDETERMINATED 7 /* indeterminated */ + +/* Auto-negotiation timeout in 100ms granularity */ +#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */ + +/* Auto-negotiation error codes */ +#define SK_AND_OK 0 /* no error */ +#define SK_AND_OTHER 1 /* other error than below */ +#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */ + + +/* Link Speed Capabilities */ +#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */ +#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */ +#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */ +#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */ +#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */ + +/* Link Speed Parameter */ +#define SK_LSPEED_AUTO 1 /* Automatic resolution */ +#define SK_LSPEED_10MBPS 2 /* 10 Mbps */ +#define SK_LSPEED_100MBPS 3 /* 100 Mbps */ +#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */ +#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */ + +/* Link Speed Current State */ +#define SK_LSPEED_STAT_UNKNOWN 1 +#define SK_LSPEED_STAT_10MBPS 2 +#define SK_LSPEED_STAT_100MBPS 3 +#define SK_LSPEED_STAT_1000MBPS 4 +#define SK_LSPEED_STAT_INDETERMINATED 5 + + +/* Link Capability Parameter */ +#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */ +#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */ +#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */ +#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */ +#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */ + +/* Link Mode Current State */ +#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */ +#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */ +#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */ +#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */ +#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */ +#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */ + +/* Flow Control Mode Parameter (and capabilities) */ +#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */ +#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */ +#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */ +#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or + * just the remote station may send PAUSE + */ +#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */ + +/* Flow Control Status Parameter */ +#define SK_FLOW_STAT_NONE 1 /* No Flow Control */ +#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */ +#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */ +#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */ +#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */ + +/* Master/Slave Mode Capabilities */ +#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */ +#define SK_MS_CAP_MASTER (1<<1) /* This station is master */ +#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */ +#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */ + +/* Set Master/Slave Mode Parameter (and capabilities) */ +#define SK_MS_MODE_AUTO 1 /* Automatic resolution */ +#define SK_MS_MODE_MASTER 2 /* This station is master */ +#define SK_MS_MODE_SLAVE 3 /* This station is slave */ +#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */ + +/* Master/Slave Status Parameter */ +#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */ +#define SK_MS_STAT_MASTER 2 /* This station is Master */ +#define SK_MS_STAT_SLAVE 3 /* This station is Dlave */ +#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */ +#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */ + +/* parameter 'Mode' when calling SkXmSetRxCmd() */ +#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */ +#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */ +#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */ +#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */ +#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */ +#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */ +#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */ +#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */ +#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */ +#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */ + +/* parameter 'Para' when calling SkMacSetRxTxEn() */ +#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */ +#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */ +#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */ +#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */ +#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */ +#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */ + +/* States of PState */ +#define SK_PRT_RESET 0 /* the port is reset */ +#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */ +#define SK_PRT_INIT 2 /* the port is initialized */ +#define SK_PRT_RUN 3 /* the port has an active link */ + +/* Default receive frame limit for Workaround of XMAC Errata */ +#define SK_DEF_RX_WA_LIM SK_CONSTU64(100) + +/* Link Partner Status */ +#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */ +#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */ +#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */ + +/* Maximum Restarts before restart is ignored (3Com WA) */ +#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */ + +/* Max. Auto-neg. timeouts before link detection in sense mode is reset */ +#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */ + +/* structures *****************************************************************/ + +/* + * MAC specific functions + */ +typedef struct s_GeMacFunc { + int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); + int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, + SK_U16 StatAddr, SK_U32 *pVal); + int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); + int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, + SK_U16 IStatus, SK_U64 *pVal); +} SK_GEMACFUNC; + +/* + * Port Structure + */ +typedef struct s_GePort { +#ifndef SK_DIAG + SK_TIMER PWaTimer; /* Workaround Timer */ + SK_TIMER HalfDupChkTimer; +#endif /* SK_DIAG */ + SK_U32 PPrevShorts; /* Previous short Counter checking */ + SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */ + SK_U64 PPrevRx; /* Previous RxOk Counter checking */ + SK_U64 PRxLim; /* Previous RxOk Counter checking */ + SK_U64 LastOctets; /* For half duplex hang check */ + int PLinkResCt; /* Link Restart Counter */ + int PAutoNegTimeOut;/* Auto-negotiation timeout current value */ + int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */ + int PRxQSize; /* Port Rx Queue Size in kB */ + int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */ + int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */ + SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */ + SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */ + SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */ + SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */ + SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */ + SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */ + SK_U32 PRxOverCnt; /* Receive Overflow Counter */ + int PRxQOff; /* Rx Queue Address Offset */ + int PXsQOff; /* Synchronous Tx Queue Address Offset */ + int PXaQOff; /* Asynchronous Tx Queue Address Offset */ + int PhyType; /* PHY used on this port */ + SK_U16 PhyId1; /* PHY Id1 on this port */ + SK_U16 PhyAddr; /* MDIO/MDC PHY address */ + SK_U16 PIsave; /* Saved Interrupt status word */ + SK_U16 PSsave; /* Saved PHY status word */ + SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */ + SK_BOOL PState; /* Is port initialized ? */ + SK_BOOL PLinkBroken; /* Is Link broken ? */ + SK_BOOL PCheckPar; /* Do we check for parity errors ? */ + SK_BOOL HalfDupTimerActive; + SK_U8 PLinkCap; /* Link Capabilities */ + SK_U8 PLinkModeConf; /* Link Mode configured */ + SK_U8 PLinkMode; /* Link Mode currently used */ + SK_U8 PLinkModeStatus;/* Link Mode Status */ + SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */ + SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */ + SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */ + SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */ + SK_U8 PFlowCtrlMode; /* Flow Control Mode */ + SK_U8 PFlowCtrlStatus;/* Flow Control Status */ + SK_U8 PMSCap; /* Master/Slave Capabilities */ + SK_U8 PMSMode; /* Master/Slave Mode */ + SK_U8 PMSStatus; /* Master/Slave Status */ + SK_U8 PAutoNegFail; /* Auto-negotiation fail flag */ + SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */ + SK_U8 PCableLen; /* Cable Length */ + SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ + SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ +} SK_GEPORT; + +/* + * Gigabit Ethernet Initialization Struct + * (has to be included in the adapter context) + */ +typedef struct s_GeInit { + SK_U8 GIPciHwRev; /* PCI HW Revision Number */ + SK_U8 GIChipId; /* Chip Identification Number */ + SK_U8 GIChipRev; /* Chip Revision Number */ + SK_BOOL GIGenesis; /* Genesis adapter ? */ + SK_BOOL GICopperType; /* Copper Type adapter ? */ + SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */ + SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */ + SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */ + SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */ + SK_BOOL GIYukonLite; /* YUKON-Lite chip */ + int GIMacsFound; /* Number of MACs found on this adapter */ + int GIMacType; /* MAC Type used on this adapter */ + int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */ + int GIPortUsage; /* Driver Port Usage */ + int GILevel; /* Initialization Level completed */ + int GIRamSize; /* The RAM size of the adapter in kB */ + int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */ + SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */ + SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */ + SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */ + SK_GEMACFUNC GIFunc; /* MAC depedent functions */ +} SK_GEINIT; + +/* + * Error numbers and messages for skxmac2.c and skgeinit.c + */ +#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT) +#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters" +#define SKERR_HWI_E002 (SKERR_HWI_E001+1) +#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing" +#define SKERR_HWI_E003 (SKERR_HWI_E002+1) +#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level" +#define SKERR_HWI_E004 (SKERR_HWI_E003+1) +#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured" +#define SKERR_HWI_E005 (SKERR_HWI_E004+1) +#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports" +#define SKERR_HWI_E006 (SKERR_HWI_E005+1) +#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state" +#define SKERR_HWI_E007 (SKERR_HWI_E006+1) +#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode" +#define SKERR_HWI_E008 (SKERR_HWI_E007+1) +#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode" +#define SKERR_HWI_E009 (SKERR_HWI_E008+1) +#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero" +#define SKERR_HWI_E010 (SKERR_HWI_E009+1) +#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters" +#define SKERR_HWI_E011 (SKERR_HWI_E010+1) +#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small" +#define SKERR_HWI_E012 (SKERR_HWI_E011+1) +#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified" +#define SKERR_HWI_E013 (SKERR_HWI_E012+1) +#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue" +#define SKERR_HWI_E014 (SKERR_HWI_E013+1) +#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified" +#define SKERR_HWI_E015 (SKERR_HWI_E014+1) +#define SKERR_HWI_E015MSG "Illegal Link mode parameter" +#define SKERR_HWI_E016 (SKERR_HWI_E015+1) +#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter" +#define SKERR_HWI_E017 (SKERR_HWI_E016+1) +#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal" +#define SKERR_HWI_E018 (SKERR_HWI_E017+1) +#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)" +#define SKERR_HWI_E019 (SKERR_HWI_E018+1) +#define SKERR_HWI_E019MSG "Illegal Speed parameter" +#define SKERR_HWI_E020 (SKERR_HWI_E019+1) +#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter" +#define SKERR_HWI_E021 (SKERR_HWI_E020+1) +#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" +#define SKERR_HWI_E022 (SKERR_HWI_E021+1) +#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" +#define SKERR_HWI_E023 (SKERR_HWI_E022+1) +#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small" +#define SKERR_HWI_E024 (SKERR_HWI_E023+1) +#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)" +#define SKERR_HWI_E025 (SKERR_HWI_E024+1) +#define SKERR_HWI_E025MSG "" + +/* function prototypes ********************************************************/ + +#ifndef SK_KR_PROTO + +/* + * public functions in skgeinit.c + */ +extern void SkGePollRxD( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL PollRxD); + +extern void SkGePollTxD( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL PollTxD); + +extern void SkGeYellowLED( + SK_AC *pAC, + SK_IOC IoC, + int State); + +extern int SkGeCfgSync( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U32 IntTime, + SK_U32 LimCount, + int SyncMode); + +extern void SkGeLoadLnkSyncCnt( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U32 CntVal); + +extern void SkGeStopPort( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Dir, + int RstMode); + +extern int SkGeInit( + SK_AC *pAC, + SK_IOC IoC, + int Level); + +extern void SkGeDeInit( + SK_AC *pAC, + SK_IOC IoC); + +extern int SkGeInitPort( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkGeXmitLED( + SK_AC *pAC, + SK_IOC IoC, + int Led, + int Mode); + +extern void SkGeInitRamIface( + SK_AC *pAC, + SK_IOC IoC); + +extern int SkGeInitAssignRamToQueues( + SK_AC *pAC, + int ActivePort, + SK_BOOL DualNet); + +/* + * public functions in skxmac2.c + */ +extern void SkMacRxTxDisable( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacSoftRst( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacHardRst( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkXmInitMac( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkGmInitMac( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacInitPhy( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL DoLoop); + +extern void SkMacIrqDisable( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacFlushTxFifo( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacFlushRxFifo( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacIrq( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern int SkMacAutoNegDone( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacAutoNegLipaPhy( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U16 IStatus); + +extern void SkMacSetRxTxEn( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Para); + +extern int SkMacRxTxEnable( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkMacPromiscMode( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); + +extern void SkMacHashing( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); + +extern void SkXmPhyRead( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 *pVal); + +extern void SkXmPhyWrite( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 Val); + +extern void SkGmPhyRead( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 *pVal); + +extern void SkGmPhyWrite( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 Val); + +extern void SkGePhyRead( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 *pVal); + +extern void SkGePhyWrite( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 Val); + +extern void SkXmClrExactAddr( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int StartNum, + int StopNum); + +extern void SkXmInitDupMd( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkXmInitPauseMd( + SK_AC *pAC, + SK_IOC IoC, + int Port); + +extern void SkXmAutoNegLipaXmac( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U16 IStatus); + +extern int SkXmUpdateStats( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port); + +extern int SkGmUpdateStats( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port); + +extern int SkXmMacStatistic( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port, + SK_U16 StatAddr, + SK_U32 *pVal); + +extern int SkGmMacStatistic( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port, + SK_U16 StatAddr, + SK_U32 *pVal); + +extern int SkXmResetCounter( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port); + +extern int SkGmResetCounter( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port); + +extern int SkXmOverflowStatus( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port, + SK_U16 IStatus, + SK_U64 *pStatus); + +extern int SkGmOverflowStatus( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Port, + SK_U16 MacStatus, + SK_U64 *pStatus); + +extern int SkGmCableDiagStatus( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL StartTest); + +#ifdef SK_DIAG +extern void SkMacSetRxCmd( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Mode); +extern void SkMacCrcGener( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); +extern void SkMacTimeStamp( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); +extern void SkXmSendCont( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); +#endif /* SK_DIAG */ + +#else /* SK_KR_PROTO */ + +/* + * public functions in skgeinit.c + */ +extern void SkGePollRxD(); +extern void SkGePollTxD(); +extern void SkGeYellowLED(); +extern int SkGeCfgSync(); +extern void SkGeLoadLnkSyncCnt(); +extern void SkGeStopPort(); +extern int SkGeInit(); +extern void SkGeDeInit(); +extern int SkGeInitPort(); +extern void SkGeXmitLED(); +extern void SkGeInitRamIface(); +extern int SkGeInitAssignRamToQueues(); + +/* + * public functions in skxmac2.c + */ +extern void SkMacRxTxDisable(); +extern void SkMacSoftRst(); +extern void SkMacHardRst(); +extern void SkMacInitPhy(); +extern int SkMacRxTxEnable(); +extern void SkMacPromiscMode(); +extern void SkMacHashing(); +extern void SkMacIrqDisable(); +extern void SkMacFlushTxFifo(); +extern void SkMacFlushRxFifo(); +extern void SkMacIrq(); +extern int SkMacAutoNegDone(); +extern void SkMacAutoNegLipaPhy(); +extern void SkMacSetRxTxEn(); +extern void SkGePhyRead(); +extern void SkGePhyWrite(); +extern void SkXmInitMac(); +extern void SkXmPhyRead(); +extern void SkXmPhyWrite(); +extern void SkGmInitMac(); +extern void SkGmPhyRead(); +extern void SkGmPhyWrite(); +extern void SkXmClrExactAddr(); +extern void SkXmInitDupMd(); +extern void SkXmInitPauseMd(); +extern void SkXmAutoNegLipaXmac(); +extern int SkXmUpdateStats(); +extern int SkGmUpdateStats(); +extern int SkXmMacStatistic(); +extern int SkGmMacStatistic(); +extern int SkXmResetCounter(); +extern int SkGmResetCounter(); +extern int SkXmOverflowStatus(); +extern int SkGmOverflowStatus(); +extern int SkGmCableDiagStatus(); + +#ifdef SK_DIAG +extern void SkMacSetRxCmd(); +extern void SkMacCrcGener(); +extern void SkMacTimeStamp(); +extern void SkXmSendCont(); +#endif /* SK_DIAG */ + +#endif /* SK_KR_PROTO */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_SKGEINIT_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h new file mode 100644 index 0000000000..5c44f47719 --- /dev/null +++ b/drivers/net/sk98lin/h/skgepnm2.h @@ -0,0 +1,462 @@ +/***************************************************************************** + * + * Name: skgepnm2.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.34 $ + * Date: $Date: 2002/12/16 09:05:18 $ + * Purpose: Defines for Private Network Management Interface + * + ****************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/***************************************************************************** + * + * History: + * + * $Log: skgepnm2.h,v $ + * Revision 1.34 2002/12/16 09:05:18 tschilli + * Code for VCT handling added. + * + * Revision 1.33 2002/09/10 09:00:03 rwahl + * Adapted boolean definitions according sktypes. + * + * Revision 1.32 2002/08/09 09:47:01 rwahl + * Added write-only flag to oid access defines. + * Editorial changes. + * + * Revision 1.31 2002/07/17 19:23:18 rwahl + * - Replaced MAC counter definitions by enumeration. + * - Added definition SK_PNMI_MAC_TYPES. + * - Added chipset defnition for Yukon. + * + * Revision 1.30 2001/02/06 10:03:41 mkunz + * - Pnmi V4 dual net support added. Interface functions and macros extended + * - Vpd bug fixed + * - OID_SKGE_MTU added + * + * Revision 1.29 2001/01/22 13:41:37 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.28 2000/08/03 15:12:48 rwahl + * - Additional comment for MAC statistic data structure. + * + * Revision 1.27 2000/08/01 16:10:18 rwahl + * - Added mac statistic data structure for StatRxLongFrame counter. + * + * Revision 1.26 2000/03/31 13:51:34 rwahl + * Added SK_UPTR cast to offset calculation for PNMI struct fields; + * missing cast caused compiler warnings by Win64 compiler. + * + * Revision 1.25 1999/11/22 13:57:41 cgoos + * Changed license header to GPL. + * Allowing overwrite for SK_PNMI_STORE/_READ defines. + * + * Revision 1.24 1999/04/13 15:11:11 mhaveman + * Changed copyright. + * + * Revision 1.23 1999/01/28 15:07:12 mhaveman + * Changed default threshold for port switches per hour from 10 + * to 240 which means 4 switches per minute. This fits better + * the granularity of 32 for the port switch estimate + * counter. + * + * Revision 1.22 1999/01/05 12:52:30 mhaveman + * Removed macro SK_PNMI_MICRO_SEC. + * + * Revision 1.21 1999/01/05 12:50:34 mhaveman + * Enlarged macro definition SK_PNMI_HUNDREDS_SEC() so that no 64-bit + * arithmetic is necessary if SK_TICKS_PER_SEC is 100. + * + * Revision 1.20 1998/12/09 14:02:53 mhaveman + * Defined macro SK_PNMI_DEF_RLMT_CHG_THRES for default port switch + * threshold. + * + * Revision 1.19 1998/12/03 11:28:41 mhaveman + * Removed SK_PNMI_CHECKPTR macro. + * + * Revision 1.18 1998/12/03 11:21:00 mhaveman + * -Added pointer check macro SK_PNMI_CHECKPTR + * -Added macros SK_PNMI_VPD_ARR_SIZE and SK_PNMI_VPD_STR_SIZE for + * VPD key evaluation. + * + * Revision 1.17 1998/11/20 13:20:33 mhaveman + * Fixed bug in SK_PNMI_SET_STAT macro. ErrorStatus was not correctly set. + * + * Revision 1.16 1998/11/20 08:08:49 mhaveman + * Macro SK_PNMI_CHECKFLAGS has got a if clause. + * + * Revision 1.15 1998/11/03 13:53:40 mhaveman + * Fixed alignment problem in macor SK_PNMI_SET_STAT macro. + * + * Revision 1.14 1998/10/30 15:50:13 mhaveman + * Added macro SK_PNMI_MICRO_SEC() + * + * Revision 1.13 1998/10/30 12:32:20 mhaveman + * Added forgotten cast in SK_PNMI_READ_U32 macro. + * + * Revision 1.12 1998/10/29 15:40:26 mhaveman + * -Changed SK_PNMI_TRAP_SENSOR_LEN because SensorDescr has now + * variable string length. + * -Defined SK_PNMI_CHECKFLAGS macro + * + * Revision 1.11 1998/10/29 08:53:34 mhaveman + * Removed SK_PNMI_RLM_XXX table indexed because these counters need + * not been saved over XMAC resets. + * + * Revision 1.10 1998/10/28 08:48:20 mhaveman + * -Added macros for storage according to alignment + * -Changed type of Instance to SK_U32 because of VPD + * -Removed trap structures. Not needed because of alignment problem + * -Changed type of Action form SK_U8 to int + * + * Revision 1.9 1998/10/21 13:34:45 mhaveman + * Shit, mismatched calculation of SK_PNMI_HUNDREDS_SEC. Corrected. + * + * Revision 1.8 1998/10/21 13:24:58 mhaveman + * Changed calculation of hundreds of seconds. + * + * Revision 1.7 1998/10/20 07:31:41 mhaveman + * Made type changes to unsigned int where possible. + * + * Revision 1.6 1998/09/04 17:04:05 mhaveman + * Added Sync counters to offset storage to provided settled values on + * port switch. + * + * Revision 1.5 1998/09/04 12:45:35 mhaveman + * Removed dummies for SK_DRIVER_ macros. They should be added by driver + * writer in skdrv2nd.h. + * + * Revision 1.4 1998/09/04 11:59:50 mhaveman + * Everything compiles now. Driver Macros for counting still missing. + * + * Revision 1.3 1998/08/24 12:01:35 mhaveman + * Intermediate state. + * + * Revision 1.2 1998/08/17 07:51:40 mhaveman + * Intermediate state. + * + * Revision 1.1 1998/08/11 09:08:40 mhaveman + * Intermediate state. + * + ****************************************************************************/ + +#ifndef _SKGEPNM2_H_ +#define _SKGEPNM2_H_ + +/* + * General definitions + */ +#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ +#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ + +#define SK_PNMI_BUS_PCI 1 /* PCI bus*/ + +/* + * Actions + */ +#define SK_PNMI_ACT_IDLE 1 +#define SK_PNMI_ACT_RESET 2 +#define SK_PNMI_ACT_SELFTEST 3 +#define SK_PNMI_ACT_RESETCNT 4 + +/* + * VPD releated defines + */ + +#define SK_PNMI_VPD_RW 1 +#define SK_PNMI_VPD_RO 2 + +#define SK_PNMI_VPD_OK 0 +#define SK_PNMI_VPD_NOTFOUND 1 +#define SK_PNMI_VPD_CUT 2 +#define SK_PNMI_VPD_TIMEOUT 3 +#define SK_PNMI_VPD_FULL 4 +#define SK_PNMI_VPD_NOWRITE 5 +#define SK_PNMI_VPD_FATAL 6 + +#define SK_PNMI_VPD_IGNORE 0 +#define SK_PNMI_VPD_CREATE 1 +#define SK_PNMI_VPD_DELETE 2 + + +/* + * RLMT related defines + */ +#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */ + + +/* + * VCT internal status values + */ +#define SK_PNMI_VCT_PENDING 32 +#define SK_PNMI_VCT_TEST_DONE 64 +#define SK_PNMI_VCT_LINK 128 + +/* + * Internal table definitions + */ +#define SK_PNMI_GET 0 +#define SK_PNMI_PRESET 1 +#define SK_PNMI_SET 2 + +#define SK_PNMI_RO 0 +#define SK_PNMI_RW 1 +#define SK_PNMI_WO 2 + +typedef struct s_OidTabEntry { + SK_U32 Id; + SK_U32 InstanceNo; + unsigned int StructSize; + unsigned int Offset; + int Access; + int (* Func)(SK_AC *pAc, SK_IOC pIo, int action, + SK_U32 Id, char* pBuf, unsigned int* pLen, + SK_U32 Instance, unsigned int TableIndex, + SK_U32 NetNumber); + SK_U16 Param; +} SK_PNMI_TAB_ENTRY; + + +/* + * Trap lengths + */ +#define SK_PNMI_TRAP_SIMPLE_LEN 17 +#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46 +#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23 +#define SK_PNMI_TRAP_RLMT_PORT_LEN 23 + +/* + * Number of MAC types supported + */ +#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1) + +/* + * MAC statistic data list (overall set for MAC types used) + */ +enum SK_MACSTATS { + SK_PNMI_HTX = 0, + SK_PNMI_HTX_OCTET, + SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET, + SK_PNMI_HTX_OCTETLOW, + SK_PNMI_HTX_BROADCAST, + SK_PNMI_HTX_MULTICAST, + SK_PNMI_HTX_UNICAST, + SK_PNMI_HTX_BURST, + SK_PNMI_HTX_PMACC, + SK_PNMI_HTX_MACC, + SK_PNMI_HTX_COL, + SK_PNMI_HTX_SINGLE_COL, + SK_PNMI_HTX_MULTI_COL, + SK_PNMI_HTX_EXCESS_COL, + SK_PNMI_HTX_LATE_COL, + SK_PNMI_HTX_DEFFERAL, + SK_PNMI_HTX_EXCESS_DEF, + SK_PNMI_HTX_UNDERRUN, + SK_PNMI_HTX_CARRIER, + SK_PNMI_HTX_UTILUNDER, + SK_PNMI_HTX_UTILOVER, + SK_PNMI_HTX_64, + SK_PNMI_HTX_127, + SK_PNMI_HTX_255, + SK_PNMI_HTX_511, + SK_PNMI_HTX_1023, + SK_PNMI_HTX_MAX, + SK_PNMI_HTX_LONGFRAMES, + SK_PNMI_HTX_SYNC, + SK_PNMI_HTX_SYNC_OCTET, + SK_PNMI_HTX_RESERVED, + + SK_PNMI_HRX, + SK_PNMI_HRX_OCTET, + SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET, + SK_PNMI_HRX_OCTETLOW, + SK_PNMI_HRX_BADOCTET, + SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET, + SK_PNMI_HRX_BADOCTETLOW, + SK_PNMI_HRX_BROADCAST, + SK_PNMI_HRX_MULTICAST, + SK_PNMI_HRX_UNICAST, + SK_PNMI_HRX_PMACC, + SK_PNMI_HRX_MACC, + SK_PNMI_HRX_PMACC_ERR, + SK_PNMI_HRX_MACC_UNKWN, + SK_PNMI_HRX_BURST, + SK_PNMI_HRX_MISSED, + SK_PNMI_HRX_FRAMING, + SK_PNMI_HRX_UNDERSIZE, + SK_PNMI_HRX_OVERFLOW, + SK_PNMI_HRX_JABBER, + SK_PNMI_HRX_CARRIER, + SK_PNMI_HRX_IRLENGTH, + SK_PNMI_HRX_SYMBOL, + SK_PNMI_HRX_SHORTS, + SK_PNMI_HRX_RUNT, + SK_PNMI_HRX_TOO_LONG, + SK_PNMI_HRX_FCS, + SK_PNMI_HRX_CEXT, + SK_PNMI_HRX_UTILUNDER, + SK_PNMI_HRX_UTILOVER, + SK_PNMI_HRX_64, + SK_PNMI_HRX_127, + SK_PNMI_HRX_255, + SK_PNMI_HRX_511, + SK_PNMI_HRX_1023, + SK_PNMI_HRX_MAX, + SK_PNMI_HRX_LONGFRAMES, + + SK_PNMI_HRX_RESERVED, + + SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */ +}; + +/* + * MAC specific data + */ +typedef struct s_PnmiStatAddr { + SK_U16 Reg; /* MAC register containing the value */ + SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/ +} SK_PNMI_STATADDR; + + +/* + * SK_PNMI_STRUCT_DATA copy offset evaluation macros + */ +#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) +#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) +#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e)) +#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e)) +#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e)) +#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e)) +#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e)) +#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e)) +#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e)) +#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e)) + +#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \ + Val32 = (s); \ + pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ + &(((SK_PNMI_STRUCT_DATA *)0)-> \ + ReturnStatus.ErrorStatus)); \ + SK_PNMI_STORE_U32(pVal, Val32); \ + Val32 = (o); \ + pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ + &(((SK_PNMI_STRUCT_DATA *)0)-> \ + ReturnStatus.ErrorOffset)); \ + SK_PNMI_STORE_U32(pVal, Val32);} + +/* + * Time macros + */ +#if SK_TICKS_PER_SEC == 100 +#define SK_PNMI_HUNDREDS_SEC(t) (t) +#else +#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) +#endif + +/* + * Macros to work around alignment problems + */ +#ifndef SK_PNMI_STORE_U16 +#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \ + *((char *)(p) + 1) = \ + *(((char *)&(v)) + 1);} +#endif + +#ifndef SK_PNMI_STORE_U32 +#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \ + *((char *)(p) + 1) = \ + *(((char *)&(v)) + 1); \ + *((char *)(p) + 2) = \ + *(((char *)&(v)) + 2); \ + *((char *)(p) + 3) = \ + *(((char *)&(v)) + 3);} +#endif + +#ifndef SK_PNMI_STORE_U64 +#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \ + *((char *)(p) + 1) = \ + *(((char *)&(v)) + 1); \ + *((char *)(p) + 2) = \ + *(((char *)&(v)) + 2); \ + *((char *)(p) + 3) = \ + *(((char *)&(v)) + 3); \ + *((char *)(p) + 4) = \ + *(((char *)&(v)) + 4); \ + *((char *)(p) + 5) = \ + *(((char *)&(v)) + 5); \ + *((char *)(p) + 6) = \ + *(((char *)&(v)) + 6); \ + *((char *)(p) + 7) = \ + *(((char *)&(v)) + 7);} +#endif + +#ifndef SK_PNMI_READ_U16 +#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \ + *(((char *)&(v)) + 1) = \ + *((char *)(p) + 1);} +#endif + +#ifndef SK_PNMI_READ_U32 +#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \ + *(((char *)&(v)) + 1) = \ + *((char *)(p) + 1); \ + *(((char *)&(v)) + 2) = \ + *((char *)(p) + 2); \ + *(((char *)&(v)) + 3) = \ + *((char *)(p) + 3);} +#endif + +#ifndef SK_PNMI_READ_U64 +#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \ + *(((char *)&(v)) + 1) = \ + *((char *)(p) + 1); \ + *(((char *)&(v)) + 2) = \ + *((char *)(p) + 2); \ + *(((char *)&(v)) + 3) = \ + *((char *)(p) + 3); \ + *(((char *)&(v)) + 4) = \ + *((char *)(p) + 4); \ + *(((char *)&(v)) + 5) = \ + *((char *)(p) + 5); \ + *(((char *)&(v)) + 6) = \ + *((char *)(p) + 6); \ + *(((char *)&(v)) + 7) = \ + *((char *)(p) + 7);} +#endif + +/* + * Macros for Debug + */ +#ifdef DEBUG + +#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \ + pAC->Pnmi.RlmtUpdatedFlag > 0 || \ + pAC->Pnmi.SirqUpdatedFlag > 0) { \ + SK_DBG_MSG(pAC, \ + SK_DBGMOD_PNMI, \ + SK_DBGCAT_CTRL, \ + ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \ + vSt, \ + pAC->Pnmi.MacUpdatedFlag, \ + pAC->Pnmi.RlmtUpdatedFlag, \ + pAC->Pnmi.SirqUpdatedFlag))}} + +#else /* !DEBUG */ + +#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */ + +#endif /* !DEBUG */ + +#endif /* _SKGEPNM2_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h new file mode 100644 index 0000000000..7532313ba8 --- /dev/null +++ b/drivers/net/sk98lin/h/skgepnmi.h @@ -0,0 +1,1114 @@ +/***************************************************************************** + * + * Name: skgepnmi.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.59 $ + * Date: $Date: 2002/12/16 14:03:50 $ + * Purpose: Defines for Private Network Management Interface + * + ****************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/***************************************************************************** + * + * History: + * + * $Log: skgepnmi.h,v $ + * Revision 1.59 2002/12/16 14:03:50 tschilli + * New defines for VCT added. + * + * Revision 1.58 2002/12/16 09:04:59 tschilli + * Code for VCT handling added. + * + * Revision 1.57 2002/09/26 12:41:05 tschilli + * SK_PNMI_PORT BufPort entry in struct SK_PNMI added. + * + * Revision 1.56 2002/08/16 11:10:41 rwahl + * - Replaced c++ comment. + * + * Revision 1.55 2002/08/09 15:40:21 rwahl + * Editorial change (renamed ConfSpeedCap). + * + * Revision 1.54 2002/08/09 11:06:07 rwahl + * Added OID_SKGE_SPEED_CAP. + * + * Revision 1.53 2002/08/09 09:45:28 rwahl + * Added support for NDIS OID_PNP_xxx. + * Editorial changes. + * + * Revision 1.52 2002/08/06 17:54:07 rwahl + * - Added speed cap to PNMI config struct. + * + * Revision 1.51 2002/07/17 19:19:26 rwahl + * - Added OID_SKGE_SPEED_MODE and OID_SKGE_SPEED_STATUS. + * - Added SK_PNMI_CNT_RX_PMACC_ERR() & SK_PNMI_CNT_RX_LONGFRAMES(). + * - Added speed mode & status to PNMI config struct. + * - Editorial changes. + * + * Revision 1.50 2002/05/22 08:59:37 rwahl + * Added string definitions for error msgs. + * + * Revision 1.49 2001/11/20 09:23:50 rwahl + * - pnmi struct: reordered and aligned to 32bit. + * + * Revision 1.48 2001/02/23 14:34:24 mkunz + * Changed macro PHYS2INST. Added pAC to Interface + * + * Revision 1.47 2001/02/07 08:28:23 mkunz + * - Added Oids: OID_SKGE_DIAG_ACTION + * OID_SKGE_DIAG_RESULT + * OID_SKGE_MULTICAST_LIST + * OID_SKGE_CURRENT_PACKET_FILTER + * OID_SKGE_INTERMEDIATE_SUPPORT + * - Changed value of OID_SKGE_MTU + * + * Revision 1.46 2001/02/06 10:01:41 mkunz + * - Pnmi V4 dual net support added. Interface functions and macros extended + * - Vpd bug fixed + * - OID_SKGE_MTU added + * + * Revision 1.45 2001/01/22 13:41:37 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.44 2000/09/07 07:35:27 rwahl + * - removed NDIS counter specific data type. + * - fixed spelling for OID_SKGE_RLMT_PORT_PREFERRED. + * + * Revision 1.43 2000/08/04 11:41:08 rwahl + * - Fixed compiler warning (port is always >= 0) for macros + * SK_PNMI_CNT_RX_LONGFRAMES & SK_PNMI_CNT_SYNC_OCTETS + * + * Revision 1.42 2000/08/03 15:14:07 rwahl + * - Corrected error in driver macros addressing a physical port. + * + * Revision 1.41 2000/08/01 16:22:29 rwahl + * - Changed MDB version to 3.1. + * - Added definitions for StatRxLongFrames counter. + * - Added macro to be used by driver to count long frames received. + * - Added directive to control width (default = 32bit) of NDIS statistic + * counters (SK_NDIS_64BIT_CTR). + * + * Revision 1.40 2000/03/31 13:51:34 rwahl + * Added SK_UPTR cast to offset calculation for PNMI struct fields; + * missing cast caused compiler warnings by Win64 compiler. + * + * Revision 1.39 1999/12/06 10:09:47 rwahl + * Added new error log message. + * + * Revision 1.38 1999/11/22 13:57:55 cgoos + * Changed license header to GPL. + * + * Revision 1.37 1999/09/14 14:25:32 rwahl + * Set MDB version for 1000Base-T (sensors, Master/Slave) changes. + * + * Revision 1.36 1999/05/20 09:24:56 cgoos + * Changes for 1000Base-T (sensors, Master/Slave). + * + * Revision 1.35 1999/04/13 15:10:51 mhaveman + * Replaced RLMT macros SK_RLMT_CHECK_xxx again by those of PNMI to + * grant unified interface. But PNMI macros will store the same + * value as RLMT macros. + * + * Revision 1.34 1999/04/13 15:03:49 mhaveman + * -Changed copyright + * -Removed SK_PNMI_RLMT_MODE_CHK_xxx macros. Those of RLMT should be + * used. + * + * Revision 1.33 1999/03/23 10:41:02 mhaveman + * Changed comments. + * + * Revision 1.32 1999/01/25 15:01:33 mhaveman + * Added support for multiple simultaniously active ports. + * + * Revision 1.31 1999/01/19 10:06:26 mhaveman + * Added new error log message. + * + * Revision 1.30 1999/01/05 10:34:49 mhaveman + * Fixed little error in RlmtChangeEstimate calculation. + * + * Revision 1.29 1999/01/05 09:59:41 mhaveman + * Redesigned port switch average calculation to avoid 64bit + * arithmetic. + * + * Revision 1.28 1998/12/08 10:05:48 mhaveman + * Defined macro SK_PNMI_MIN_STRUCT_SIZE. + * + * Revision 1.27 1998/12/03 14:39:35 mhaveman + * Fixed problem that LSTAT was enumerated wrong. + * + * Revision 1.26 1998/12/03 11:19:51 mhaveman + * Changed contents of errlog message SK_PNMI_ERR016MSG + * + * Revision 1.25 1998/12/01 10:40:04 mhaveman + * Changed size of SensorNumber, ChecksumNumber and RlmtPortNumber in + * SK_PNMI_STRUCT_DATA to be conform with OID definition. + * + * Revision 1.24 1998/11/20 08:09:27 mhaveman + * Added macros to convert between logical, physical port indexes and + * instances. + * + * Revision 1.23 1998/11/10 13:41:13 mhaveman + * Needed to change interface, because NT driver needs a return value + * of needed buffer space on TOO_SHORT errors. Therefore all + * SkPnmiGet/Preset/Set functions now have a pointer to the length + * parameter, where the needed space on error is returned. + * + * Revision 1.22 1998/11/03 12:05:51 mhaveman + * Added pAC parameter to counter macors. + * + * Revision 1.21 1998/11/02 10:47:36 mhaveman + * Added syslog messages for internal errors. + * + * Revision 1.20 1998/10/30 15:49:36 mhaveman + * -Removed unused SK_PNMI_UTILIZATION_BASE and EstOldCnt. + * -Redefined SK_PNMI_CHG_EST_BASE to hundreds of seconds. + * + * Revision 1.19 1998/10/29 15:38:44 mhaveman + * Changed string lengths of PNMI_STRUCT_DATA structure because + * string OIDs are now encoded with leading length ocetet. + * + * Revision 1.18 1998/10/29 08:52:27 mhaveman + * -Added byte to strings in PNMI_STRUCT_DATA structure. + * -Shortened SK_PNMI_RLMT structure to SK_MAX_MACS elements. + * + * Revision 1.17 1998/10/28 08:49:50 mhaveman + * -Changed type of Instance back to SK_U32 because of VPD + * -Changed type from SK_U8 to char of PciBusSpeed, PciBusWidth, PMD, + * and Connector. + * + * Revision 1.16 1998/10/22 10:42:31 mhaveman + * -Removed (SK_U32) casts for OIDs + * -excluded NDIS OIDs when they are already defined with ifndef _NDIS_ + * + * Revision 1.15 1998/10/20 13:56:28 mhaveman + * Headerfile includes now directly other header files to comile correctly. + * + * Revision 1.14 1998/10/20 07:31:09 mhaveman + * Made type changes to unsigned int where possible. + * + * Revision 1.13 1998/10/19 10:53:13 mhaveman + * -Casted OID definitions to SK_U32 + * -Renamed RlmtMAC... to RlmtPort... + * -Changed wrong type of VpdEntriesList from SK_U32 to char * + * + * Revision 1.12 1998/10/13 07:42:27 mhaveman + * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA + * -Removed old cvs history entries + * -Renamed MacNumber to PortNumber + * + * Revision 1.11 1998/10/07 10:55:24 mhaveman + * -Added OID_MDB_VERSION. Therefore was a renumbering of the VPD OIDs + * necessary. + * -Added OID_GEN_ Ids to support the windows driver. + * + * Revision 1.10 1998/09/30 13:41:10 mhaveman + * Renamed some OIDs to reduce usage of 'MAC' which is replaced by 'PORT'. + * + * Revision 1.9 1998/09/04 17:06:17 mhaveman + * -Added SyncCounter as macro. + * -Renamed OID_SKGE_.._NO_DESCR_CTS to OID_SKGE_.._NO_BUF_CTS. + * -Added macros for driver description and version strings. + * + * Revision 1.8 1998/09/04 14:36:52 mhaveman + * Added OIDs and Structure to access value of macro counters which are + * counted by the driver. + * + * Revision 1.7 1998/09/04 11:59:36 mhaveman + * Everything compiles now. Driver Macros for counting still missing. + * + ****************************************************************************/ + +#ifndef _SKGEPNMI_H_ +#define _SKGEPNMI_H_ + +/* + * Include dependencies + */ +#include "h/sktypes.h" +#include "h/skerror.h" +#include "h/sktimer.h" +#include "h/ski2c.h" +#include "h/skaddr.h" +#include "h/skrlmt.h" +#include "h/skvpd.h" + +/* + * Management Database Version + */ +#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */ + + +/* + * Event definitions + */ +#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */ +#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */ +#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */ +#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */ +#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */ +#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */ +#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */ +#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */ +#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */ + +#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */ +#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */ +#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */ +#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */ +#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */ +#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets + 1 = single net; 2 = dual net */ +#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ + + +/* + * Return values + */ +#define SK_PNMI_ERR_OK 0 +#define SK_PNMI_ERR_GENERAL 1 +#define SK_PNMI_ERR_TOO_SHORT 2 +#define SK_PNMI_ERR_BAD_VALUE 3 +#define SK_PNMI_ERR_READ_ONLY 4 +#define SK_PNMI_ERR_UNKNOWN_OID 5 +#define SK_PNMI_ERR_UNKNOWN_INST 6 +#define SK_PNMI_ERR_UNKNOWN_NET 7 + + +/* + * Return values of driver reset function SK_DRIVER_RESET() and + * driver event function SK_DRIVER_EVENT() + */ +#define SK_PNMI_ERR_OK 0 +#define SK_PNMI_ERR_FAIL 1 + + +/* + * Return values of driver test function SK_DRIVER_SELFTEST() + */ +#define SK_PNMI_TST_UNKNOWN (1 << 0) +#define SK_PNMI_TST_TRANCEIVER (1 << 1) +#define SK_PNMI_TST_ASIC (1 << 2) +#define SK_PNMI_TST_SENSOR (1 << 3) +#define SK_PNMI_TST_POWERMGMT (1 << 4) +#define SK_PNMI_TST_PCI (1 << 5) +#define SK_PNMI_TST_MAC (1 << 6) + + +/* + * RLMT specific definitions + */ +#define SK_PNMI_RLMT_STATUS_STANDBY 1 +#define SK_PNMI_RLMT_STATUS_ACTIVE 2 +#define SK_PNMI_RLMT_STATUS_ERROR 3 + +#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1 +#define SK_PNMI_RLMT_LSTAT_AUTONEG 2 +#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3 +#define SK_PNMI_RLMT_LSTAT_LOG_UP 4 +#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5 + +#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK) +#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK) +#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG) +/* #define SK_PNMI_RLMT_MODE_CHK_EX */ + +/* + * OID definition + */ +#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */ + +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */ +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */ +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */ +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */ +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */ +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */ +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +/* #define OID_802_3_MULTICAST_LIST 0x01010103 */ +/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */ +/* #define OID_802_3_MAC_OPTIONS 0x01010105 */ + +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* + * PnP and PM OIDs + */ +#ifdef SK_POWER_MGMT +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 +#endif /* SK_POWER_MGMT */ + +#endif /* _NDIS_ */ + +#define OID_SKGE_MDB_VERSION 0xFF010100 +#define OID_SKGE_SUPPORTED_LIST 0xFF010101 +#define OID_SKGE_VPD_FREE_BYTES 0xFF010102 +#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103 +#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104 +#define OID_SKGE_VPD_KEY 0xFF010105 +#define OID_SKGE_VPD_VALUE 0xFF010106 +#define OID_SKGE_VPD_ACCESS 0xFF010107 +#define OID_SKGE_VPD_ACTION 0xFF010108 + +#define OID_SKGE_PORT_NUMBER 0xFF010110 +#define OID_SKGE_DEVICE_TYPE 0xFF010111 +#define OID_SKGE_DRIVER_DESCR 0xFF010112 +#define OID_SKGE_DRIVER_VERSION 0xFF010113 +#define OID_SKGE_HW_DESCR 0xFF010114 +#define OID_SKGE_HW_VERSION 0xFF010115 +#define OID_SKGE_CHIPSET 0xFF010116 +#define OID_SKGE_ACTION 0xFF010117 +#define OID_SKGE_RESULT 0xFF010118 +#define OID_SKGE_BUS_TYPE 0xFF010119 +#define OID_SKGE_BUS_SPEED 0xFF01011A +#define OID_SKGE_BUS_WIDTH 0xFF01011B +/* 0xFF01011C unused */ +#define OID_SKGE_DIAG_ACTION 0xFF01011D +#define OID_SKGE_DIAG_RESULT 0xFF01011E +#define OID_SKGE_MTU 0xFF01011F +#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120 +#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121 +#define OID_SKGE_PMD 0xFF010122 +#define OID_SKGE_CONNECTOR 0xFF010123 +#define OID_SKGE_LINK_CAP 0xFF010124 +#define OID_SKGE_LINK_MODE 0xFF010125 +#define OID_SKGE_LINK_MODE_STATUS 0xFF010126 +#define OID_SKGE_LINK_STATUS 0xFF010127 +#define OID_SKGE_FLOWCTRL_CAP 0xFF010128 +#define OID_SKGE_FLOWCTRL_MODE 0xFF010129 +#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A +#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B +#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C +#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D +#define OID_SKGE_MULTICAST_LIST 0xFF01012E +#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F + +#define OID_SKGE_TRAP 0xFF010130 +#define OID_SKGE_TRAP_NUMBER 0xFF010131 + +#define OID_SKGE_RLMT_MODE 0xFF010140 +#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141 +#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142 +#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143 +#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 + +#define OID_SKGE_SPEED_CAP 0xFF010170 +#define OID_SKGE_SPEED_MODE 0xFF010171 +#define OID_SKGE_SPEED_STATUS 0xFF010172 + +#define OID_SKGE_SENSOR_NUMBER 0xFF020100 +#define OID_SKGE_SENSOR_INDEX 0xFF020101 +#define OID_SKGE_SENSOR_DESCR 0xFF020102 +#define OID_SKGE_SENSOR_TYPE 0xFF020103 +#define OID_SKGE_SENSOR_VALUE 0xFF020104 +#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105 +#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106 +#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107 +#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108 +#define OID_SKGE_SENSOR_STATUS 0xFF020109 +#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A +#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B +#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C +#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D + +#define OID_SKGE_CHKSM_NUMBER 0xFF020110 +#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111 +#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112 +#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113 +#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114 +#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115 + +#define OID_SKGE_STAT_TX 0xFF020120 +#define OID_SKGE_STAT_TX_OCTETS 0xFF020121 +#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122 +#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123 +#define OID_SKGE_STAT_TX_UNICAST 0xFF020124 +#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125 +#define OID_SKGE_STAT_TX_BURST 0xFF020126 +#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127 +#define OID_SKGE_STAT_TX_FLOWC 0xFF020128 +#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129 +#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A +#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B +#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C +#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D +#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E +#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F +#define OID_SKGE_STAT_TX_CARRIER 0xFF020130 +/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */ +#define OID_SKGE_STAT_TX_64 0xFF020132 +#define OID_SKGE_STAT_TX_127 0xFF020133 +#define OID_SKGE_STAT_TX_255 0xFF020134 +#define OID_SKGE_STAT_TX_511 0xFF020135 +#define OID_SKGE_STAT_TX_1023 0xFF020136 +#define OID_SKGE_STAT_TX_MAX 0xFF020137 +#define OID_SKGE_STAT_TX_SYNC 0xFF020138 +#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139 +#define OID_SKGE_STAT_RX 0xFF02013A +#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B +#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C +#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D +#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E +#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F +#define OID_SKGE_STAT_RX_FLOWC 0xFF020140 +#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141 +#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142 +#define OID_SKGE_STAT_RX_BURST 0xFF020143 +#define OID_SKGE_STAT_RX_MISSED 0xFF020144 +#define OID_SKGE_STAT_RX_FRAMING 0xFF020145 +#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146 +#define OID_SKGE_STAT_RX_JABBER 0xFF020147 +#define OID_SKGE_STAT_RX_CARRIER 0xFF020148 +#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149 +#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A +#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B +#define OID_SKGE_STAT_RX_RUNT 0xFF02014C +#define OID_SKGE_STAT_RX_CEXT 0xFF02014D +#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E +#define OID_SKGE_STAT_RX_FCS 0xFF02014F +/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */ +#define OID_SKGE_STAT_RX_64 0xFF020151 +#define OID_SKGE_STAT_RX_127 0xFF020152 +#define OID_SKGE_STAT_RX_255 0xFF020153 +#define OID_SKGE_STAT_RX_511 0xFF020154 +#define OID_SKGE_STAT_RX_1023 0xFF020155 +#define OID_SKGE_STAT_RX_MAX 0xFF020156 +#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157 + +#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160 +#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161 +#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162 +#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163 + +#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164 +#define OID_SKGE_RLMT_STATUS 0xFF020165 +#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166 +#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167 +#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168 +#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169 + +#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 +#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 +#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 +#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 +#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 +#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 + +#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170 +#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171 +#define OID_SKGE_TX_RETRY 0xFF020172 +#define OID_SKGE_RX_INTR_CTS 0xFF020173 +#define OID_SKGE_TX_INTR_CTS 0xFF020174 +#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175 +#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176 +#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177 +#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178 +#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179 +#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A +#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B +#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C +#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D +#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E +#define OID_SKGE_SYSUPTIME 0xFF02017F + +#define OID_SKGE_ALL_DATA 0xFF020190 + +/* Defines for VCT. */ +#define OID_SKGE_VCT_GET 0xFF020200 +#define OID_SKGE_VCT_SET 0xFF020201 +#define OID_SKGE_VCT_STATUS 0xFF020202 + + +/* VCT struct to store a backup copy of VCT data after a port reset. */ +typedef struct s_PnmiVct { + SK_U8 VctStatus; + SK_U8 PCableLen; + SK_U32 PMdiPairLen[4]; + SK_U8 PMdiPairSts[4]; +} SK_PNMI_VCT; + + +/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */ +#define SK_PNMI_VCT_NONE 0 +#define SK_PNMI_VCT_OLD_VCT_DATA 1 +#define SK_PNMI_VCT_NEW_VCT_DATA 2 +#define SK_PNMI_VCT_OLD_DSP_DATA 4 +#define SK_PNMI_VCT_NEW_DSP_DATA 8 +#define SK_PNMI_VCT_RUNNING 16 + + +/* VCT cable test status. */ +#define SK_PNMI_VCT_NORMAL_CABLE 0 +#define SK_PNMI_VCT_SHORT_CABLE 1 +#define SK_PNMI_VCT_OPEN_CABLE 2 +#define SK_PNMI_VCT_TEST_FAIL 3 +#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 + +#define OID_SKGE_TRAP_SEN_WAR_LOW 500 +#define OID_SKGE_TRAP_SEN_WAR_UPP 501 +#define OID_SKGE_TRAP_SEN_ERR_LOW 502 +#define OID_SKGE_TRAP_SEN_ERR_UPP 503 +#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520 +#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521 +#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522 +#define OID_SKGE_TRAP_RLMT_PORT_UP 523 +#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 + + +/* + * Define error numbers and messages for syslog + */ +#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1) +#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID" +#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2) +#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys" +#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3) +#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID" +#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4) +#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action" +#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5) +#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver" +#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6) +#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command" +#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7) +#define SK_PNMI_ERR007MSG "General: Driver description not initialized" +#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8) +#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID" +#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9) +#define SK_PNMI_ERR009MSG "Addr: Unknown OID" +#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10) +#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID" +#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11) +#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long" +#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12) +#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID" +#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13) +#define SK_PNMI_ERR013MSG "" +#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14) +#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys" +#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15) +#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small" +#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16) +#define SK_PNMI_ERR016MSG "Vpd: Key string too long" +#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17) +#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer" +#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18) +#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid" +#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19) +#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long" +#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21) +#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long" +#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22) +#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before" +#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23) +#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action" +#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24) +#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action" +#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25) +#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry" +#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26) +#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD" +#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27) +#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry" +#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28) +#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry" +#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29) +#define SK_PNMI_ERR029MSG "General: Driver description string too long" +#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30) +#define SK_PNMI_ERR030MSG "General: Driver version not initialized" +#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31) +#define SK_PNMI_ERR031MSG "General: Driver version string too long" +#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32) +#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr" +#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33) +#define SK_PNMI_ERR033MSG "General: HW description string too long" +#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34) +#define SK_PNMI_ERR034MSG "General: Unknown OID" +#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35) +#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID" +#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36) +#define SK_PNMI_ERR036MSG "" +#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37) +#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0" +#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38) +#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0" +#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39) +#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID" +#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40) +#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID" +#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41) +#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID" +#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42) +#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0" +#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43) +#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0" +#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44) +#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0" +#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45) +#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0" +#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46) +#define SK_PNMI_ERR046MSG "Monitor: Unknown OID" +#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47) +#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0" +#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48) +#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0" +#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49) +#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!" +#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50) +#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!" +#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51) +#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" +#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) +#define SK_PNMI_ERR052MSG "" + +/* + * Management counter macros called by the driver + */ +#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \ + (char *)(v)) + +#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ + (char *)(v)) + + +#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ + { \ + (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \ + if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \ + (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \ + } \ + } +#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++) +#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++) +#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++) +#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++) +#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++) +#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \ + ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v)); +#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \ + { \ + ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \ + (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \ + } +#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++); + +#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \ + { \ + if ((p) < SK_MAX_MACS) { \ + ((pAC)->Pnmi.Port[p].StatSyncCts)++; \ + (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \ + } \ + } + +#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \ + { \ + if ((p) < SK_MAX_MACS) { \ + ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \ + } \ + } + +#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \ + { \ + if ((p) < SK_MAX_MACS) { \ + ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \ + } \ + } + +#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \ + { \ + if ((p) < SK_MAX_MACS) { \ + ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \ + } \ + } + +/* + * Conversion Macros + */ +#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1) +#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1) +#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1) +#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1) +#define SK_PNMI_PORT_PHYS2INST(pAC,p) \ + (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2)) +#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2) + +/* + * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct + */ +#define SK_PNMI_VPD_KEY_SIZE 5 +#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE) +#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4) +#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */ + +#define SK_PNMI_MULTICAST_LISTLEN 64 +#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS) +#define SK_PNMI_CHECKSUM_ENTRIES 3 +#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1) +#define SK_PNMI_MONITOR_ENTRIES 20 +#define SK_PNMI_TRAP_ENTRIES 10 +#define SK_PNMI_TRAPLEN 128 +#define SK_PNMI_STRINGLEN1 80 +#define SK_PNMI_STRINGLEN2 25 +#define SK_PNMI_TRAP_QUEUE_LEN 512 + +typedef struct s_PnmiVpd { + char VpdKey[SK_PNMI_VPD_KEY_SIZE]; + char VpdValue[SK_PNMI_VPD_DATALEN]; + SK_U8 VpdAccess; + SK_U8 VpdAction; +} SK_PNMI_VPD; + +typedef struct s_PnmiSensor { + SK_U8 SensorIndex; + char SensorDescr[SK_PNMI_STRINGLEN2]; + SK_U8 SensorType; + SK_U32 SensorValue; + SK_U32 SensorWarningThresholdLow; + SK_U32 SensorWarningThresholdHigh; + SK_U32 SensorErrorThresholdLow; + SK_U32 SensorErrorThresholdHigh; + SK_U8 SensorStatus; + SK_U64 SensorWarningCts; + SK_U64 SensorErrorCts; + SK_U64 SensorWarningTimestamp; + SK_U64 SensorErrorTimestamp; +} SK_PNMI_SENSOR; + +typedef struct s_PnmiChecksum { + SK_U64 ChecksumRxOkCts; + SK_U64 ChecksumRxUnableCts; + SK_U64 ChecksumRxErrCts; + SK_U64 ChecksumTxOkCts; + SK_U64 ChecksumTxUnableCts; +} SK_PNMI_CHECKSUM; + +typedef struct s_PnmiStat { + SK_U64 StatTxOkCts; + SK_U64 StatTxOctetsOkCts; + SK_U64 StatTxBroadcastOkCts; + SK_U64 StatTxMulticastOkCts; + SK_U64 StatTxUnicastOkCts; + SK_U64 StatTxLongFramesCts; + SK_U64 StatTxBurstCts; + SK_U64 StatTxPauseMacCtrlCts; + SK_U64 StatTxMacCtrlCts; + SK_U64 StatTxSingleCollisionCts; + SK_U64 StatTxMultipleCollisionCts; + SK_U64 StatTxExcessiveCollisionCts; + SK_U64 StatTxLateCollisionCts; + SK_U64 StatTxDeferralCts; + SK_U64 StatTxExcessiveDeferralCts; + SK_U64 StatTxFifoUnderrunCts; + SK_U64 StatTxCarrierCts; + SK_U64 Dummy1; /* StatTxUtilization */ + SK_U64 StatTx64Cts; + SK_U64 StatTx127Cts; + SK_U64 StatTx255Cts; + SK_U64 StatTx511Cts; + SK_U64 StatTx1023Cts; + SK_U64 StatTxMaxCts; + SK_U64 StatTxSyncCts; + SK_U64 StatTxSyncOctetsCts; + SK_U64 StatRxOkCts; + SK_U64 StatRxOctetsOkCts; + SK_U64 StatRxBroadcastOkCts; + SK_U64 StatRxMulticastOkCts; + SK_U64 StatRxUnicastOkCts; + SK_U64 StatRxLongFramesCts; + SK_U64 StatRxPauseMacCtrlCts; + SK_U64 StatRxMacCtrlCts; + SK_U64 StatRxPauseMacCtrlErrorCts; + SK_U64 StatRxMacCtrlUnknownCts; + SK_U64 StatRxBurstCts; + SK_U64 StatRxMissedCts; + SK_U64 StatRxFramingCts; + SK_U64 StatRxFifoOverflowCts; + SK_U64 StatRxJabberCts; + SK_U64 StatRxCarrierCts; + SK_U64 StatRxIRLengthCts; + SK_U64 StatRxSymbolCts; + SK_U64 StatRxShortsCts; + SK_U64 StatRxRuntCts; + SK_U64 StatRxCextCts; + SK_U64 StatRxTooLongCts; + SK_U64 StatRxFcsCts; + SK_U64 Dummy2; /* StatRxUtilization */ + SK_U64 StatRx64Cts; + SK_U64 StatRx127Cts; + SK_U64 StatRx255Cts; + SK_U64 StatRx511Cts; + SK_U64 StatRx1023Cts; + SK_U64 StatRxMaxCts; +} SK_PNMI_STAT; + +typedef struct s_PnmiConf { + char ConfMacCurrentAddr[6]; + char ConfMacFactoryAddr[6]; + SK_U8 ConfPMD; + SK_U8 ConfConnector; + SK_U8 ConfLinkCapability; + SK_U8 ConfLinkMode; + SK_U8 ConfLinkModeStatus; + SK_U8 ConfLinkStatus; + SK_U8 ConfFlowCtrlCapability; + SK_U8 ConfFlowCtrlMode; + SK_U8 ConfFlowCtrlStatus; + SK_U8 ConfPhyOperationCapability; + SK_U8 ConfPhyOperationMode; + SK_U8 ConfPhyOperationStatus; + SK_U8 ConfSpeedCapability; + SK_U8 ConfSpeedMode; + SK_U8 ConfSpeedStatus; +} SK_PNMI_CONF; + +typedef struct s_PnmiRlmt { + SK_U32 RlmtIndex; + SK_U32 RlmtStatus; + SK_U64 RlmtTxHelloCts; + SK_U64 RlmtRxHelloCts; + SK_U64 RlmtTxSpHelloReqCts; + SK_U64 RlmtRxSpHelloCts; +} SK_PNMI_RLMT; + +typedef struct s_PnmiRlmtMonitor { + SK_U32 RlmtMonitorIndex; + char RlmtMonitorAddr[6]; + SK_U64 RlmtMonitorErrorCts; + SK_U64 RlmtMonitorTimestamp; + SK_U8 RlmtMonitorAdmin; +} SK_PNMI_RLMT_MONITOR; + +typedef struct s_PnmiRequestStatus { + SK_U32 ErrorStatus; + SK_U32 ErrorOffset; +} SK_PNMI_REQUEST_STATUS; + +typedef struct s_PnmiStrucData { + SK_U32 MgmtDBVersion; + SK_PNMI_REQUEST_STATUS ReturnStatus; + SK_U32 VpdFreeBytes; + char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE]; + SK_U32 VpdEntriesNumber; + SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES]; + SK_U32 PortNumber; + SK_U32 DeviceType; + char DriverDescr[SK_PNMI_STRINGLEN1]; + char DriverVersion[SK_PNMI_STRINGLEN2]; + char HwDescr[SK_PNMI_STRINGLEN1]; + char HwVersion[SK_PNMI_STRINGLEN2]; + SK_U16 Chipset; + SK_U32 MtuSize; + SK_U32 Action; + SK_U32 TestResult; + SK_U8 BusType; + SK_U8 BusSpeed; + SK_U8 BusWidth; + SK_U8 SensorNumber; + SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES]; + SK_U8 ChecksumNumber; + SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES]; + SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES]; + SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES]; + SK_U8 RlmtMode; + SK_U32 RlmtPortNumber; + SK_U8 RlmtPortActive; + SK_U8 RlmtPortPreferred; + SK_U64 RlmtChangeCts; + SK_U64 RlmtChangeTime; + SK_U64 RlmtChangeEstimate; + SK_U64 RlmtChangeThreshold; + SK_PNMI_RLMT Rlmt[SK_MAX_MACS]; + SK_U32 RlmtMonitorNumber; + SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES]; + SK_U32 TrapNumber; + SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN]; + SK_U64 TxSwQueueLen; + SK_U64 TxSwQueueMax; + SK_U64 TxRetryCts; + SK_U64 RxIntrCts; + SK_U64 TxIntrCts; + SK_U64 RxNoBufCts; + SK_U64 TxNoBufCts; + SK_U64 TxUsedDescrNo; + SK_U64 RxDeliveredCts; + SK_U64 RxOctetsDeliveredCts; + SK_U64 RxHwErrorsCts; + SK_U64 TxHwErrorsCts; + SK_U64 InErrorsCts; + SK_U64 OutErrorsCts; + SK_U64 ErrRecoveryCts; + SK_U64 SysUpTime; +} SK_PNMI_STRUCT_DATA; + +#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA)) +#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\ + &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes)) + /* + * ReturnStatus field + * must be located + * before VpdFreeBytes + */ + +/* + * Various definitions + */ +#define SK_PNMI_MAX_PROTOS 3 + +#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum + * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK + * for check while init phase 1 + */ + +/* + * Estimate data structure + */ +typedef struct s_PnmiEstimate { + unsigned int EstValueIndex; + SK_U64 EstValue[7]; + SK_U64 Estimate; + SK_TIMER EstTimer; +} SK_PNMI_ESTIMATE; + + +/* + * VCT timer data structure + */ +typedef struct s_VctTimer { + SK_TIMER VctTimer; +} SK_PNMI_VCT_TIMER; + + +/* + * PNMI specific adapter context structure + */ +typedef struct s_PnmiPort { + SK_U64 StatSyncCts; + SK_U64 StatSyncOctetsCts; + SK_U64 StatRxLongFrameCts; + SK_U64 StatRxFrameTooLongCts; + SK_U64 StatRxPMaccErr; + SK_U64 TxSwQueueLen; + SK_U64 TxSwQueueMax; + SK_U64 TxRetryCts; + SK_U64 RxIntrCts; + SK_U64 TxIntrCts; + SK_U64 RxNoBufCts; + SK_U64 TxNoBufCts; + SK_U64 TxUsedDescrNo; + SK_U64 RxDeliveredCts; + SK_U64 RxOctetsDeliveredCts; + SK_U64 RxHwErrorsCts; + SK_U64 TxHwErrorsCts; + SK_U64 InErrorsCts; + SK_U64 OutErrorsCts; + SK_U64 ErrRecoveryCts; + SK_U64 RxShortZeroMark; + SK_U64 CounterOffset[SK_PNMI_CNT_NO]; + SK_U32 CounterHigh[SK_PNMI_CNT_NO]; + SK_BOOL ActiveFlag; + SK_U8 Align[3]; +} SK_PNMI_PORT; + + +typedef struct s_PnmiData { + SK_PNMI_PORT Port [SK_MAX_MACS]; + SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */ + SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO]; + SK_U32 TestResult; + char HwVersion[10]; + SK_U16 Align01; + + char *pDriverDescription; + char *pDriverVersion; + + int MacUpdatedFlag; + int RlmtUpdatedFlag; + int SirqUpdatedFlag; + + SK_U64 RlmtChangeCts; + SK_U64 RlmtChangeTime; + SK_PNMI_ESTIMATE RlmtChangeEstimate; + SK_U64 RlmtChangeThreshold; + + SK_U64 StartUpTime; + SK_U32 DeviceType; + char PciBusSpeed; + char PciBusWidth; + char Chipset; + char PMD; + char Connector; + SK_BOOL DualNetActiveFlag; + SK_U16 Align02; + + char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN]; + unsigned int TrapBufFree; + unsigned int TrapQueueBeg; + unsigned int TrapQueueEnd; + unsigned int TrapBufPad; + unsigned int TrapUnique; + SK_U8 VctStatus[SK_MAX_MACS]; + SK_PNMI_VCT VctBackup[SK_MAX_MACS]; + SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; +} SK_PNMI; + + +/* + * Function prototypes + */ +extern int SkPnmiInit(SK_AC *pAc, SK_IOC IoC, int level); +extern int SkPnmiGetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, + unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex); +extern int SkPnmiPreSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, + void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +extern int SkPnmiSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, + unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +extern int SkPnmiGetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, + unsigned int *pLen, SK_U32 NetIndex); +extern int SkPnmiPreSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, + unsigned int *pLen, SK_U32 NetIndex); +extern int SkPnmiSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, + unsigned int *pLen, SK_U32 NetIndex); +extern int SkPnmiEvent(SK_AC *pAc, SK_IOC IoC, SK_U32 Event, + SK_EVPARA Param); + +#endif diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h new file mode 100644 index 0000000000..fc001b2376 --- /dev/null +++ b/drivers/net/sk98lin/h/skgesirq.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * Name: skgesirq.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.26 $ + * Date: $Date: 2002/10/14 09:52:36 $ + * Purpose: SK specific Gigabit Ethernet special IRQ functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skgesirq.h,v $ + * Revision 1.26 2002/10/14 09:52:36 rschmidt + * Added SKERR_SIRQ_E023 and SKERR_SIRQ_E023 for GPHY (Yukon) + * Editorial changes + * + * Revision 1.25 2002/07/15 18:15:52 rwahl + * Editorial changes. + * + * Revision 1.24 2002/07/15 15:39:21 rschmidt + * Corrected define for SKERR_SIRQ_E022 + * Editorial changes + * + * Revision 1.23 2002/04/25 11:09:45 rschmidt + * Removed declarations for SkXmInitPhy(), SkXmRxTxEnable() + * Editorial changes + * + * Revision 1.22 2000/11/09 11:30:10 rassmann + * WA: Waiting after releasing reset until BCom chip is accessible. + * + * Revision 1.21 2000/10/18 12:22:40 cgoos + * Added workaround for half duplex hangup. + * + * Revision 1.20 1999/12/06 10:00:44 cgoos + * Added SET event for role. + * + * Revision 1.19 1999/11/22 13:58:26 cgoos + * Changed license header to GPL. + * + * Revision 1.18 1999/05/19 07:32:59 cgoos + * Changes for 1000Base-T. + * + * Revision 1.17 1999/03/12 13:29:31 malthoff + * Move Autonegotiation Error Codes to skgeinit.h. + * + * Revision 1.16 1999/03/08 10:11:28 gklug + * add: AutoNegDone return codes + * + * Revision 1.15 1998/11/18 13:20:53 gklug + * add: different timeouts for active and non-active links + * + * Revision 1.14 1998/11/04 07:18:14 cgoos + * Added prototype for SkXmRxTxEnable. + * + * Revision 1.13 1998/10/21 05:52:23 gklug + * add: parameter DoLoop to InitPhy function + * + * Revision 1.12 1998/10/19 06:45:03 cgoos + * Added prototype for SkXmInitPhy. + * + * Revision 1.11 1998/10/15 14:34:10 gklug + * add: WA_TIME is 500 msec + * + * Revision 1.10 1998/10/14 14:49:41 malthoff + * Remove err log defines E021 and E022. They are + * defined in skgeinit.h now. + * + * Revision 1.9 1998/10/14 14:00:39 gklug + * add: error logs for init phys + * + * Revision 1.8 1998/10/14 05:44:05 gklug + * add: E020 + * + * Revision 1.7 1998/10/02 06:24:58 gklug + * add: error messages + * + * Revision 1.6 1998/10/01 07:54:45 gklug + * add: PNMI debug module + * + * Revision 1.5 1998/09/28 13:36:31 malthoff + * Move the bit definitions for Autonegotiation + * and Flow Control to skgeinit.h. + * + * Revision 1.4 1998/09/15 12:29:34 gklug + * add: error logs + * + * Revision 1.3 1998/09/03 13:54:02 gklug + * add: function prototypes + * + * Revision 1.2 1998/09/03 10:24:36 gklug + * add: Events send by PNMI + * add: parameter definition for Flow Control etc. + * + * Revision 1.1 1998/08/27 11:50:27 gklug + * initial revision + * + * + ******************************************************************************/ + +#ifndef _INC_SKGESIRQ_H_ +#define _INC_SKGESIRQ_H_ + +/* + * Define the Event the special IRQ/INI module can handle + */ +#define SK_HWEV_WATIM 1 /* Timeout for WA errata #2 XMAC */ +#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */ +#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */ +#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */ +#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */ +#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */ +#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */ +#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */ +#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */ +#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */ + +#define SK_WA_ACT_TIME (5000000L) /* 5 sec */ +#define SK_WA_INA_TIME (100000L) /* 100 msec */ + +#define SK_HALFDUP_CHK_TIME (10000L) /* 10 msec */ + +/* + * Define the error numbers and messages + */ +#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0) +#define SKERR_SIRQ_E001MSG "Unknown event" +#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1) +#define SKERR_SIRQ_E002MSG "Packet timeout RX1" +#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1) +#define SKERR_SIRQ_E003MSG "Packet timeout RX2" +#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1) +#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized" +#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1) +#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized" +#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1) +#define SKERR_SIRQ_E006MSG "CHECK failure R1" +#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1) +#define SKERR_SIRQ_E007MSG "CHECK failure R2" +#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1) +#define SKERR_SIRQ_E008MSG "CHECK failure XS1" +#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1) +#define SKERR_SIRQ_E009MSG "CHECK failure XA1" +#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1) +#define SKERR_SIRQ_E010MSG "CHECK failure XS2" +#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1) +#define SKERR_SIRQ_E011MSG "CHECK failure XA2" +#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1) +#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error" +#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1) +#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error" +#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1) +#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)" +#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1) +#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)" +#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1) +#define SKERR_SIRQ_E016MSG "Parity error MAC 1" +#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1) +#define SKERR_SIRQ_E017MSG "Parity error MAC 2" +#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1) +#define SKERR_SIRQ_E018MSG "Parity error RX 1" +#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1) +#define SKERR_SIRQ_E019MSG "Parity error RX 2" +#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1) +#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun" +#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1) +#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt" +#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1) +#define SKERR_SIRQ_E022MSG "Cable pair swap error" +#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1) +#define SKERR_SIRQ_E023MSG "Auto-negotiation error" +#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1) +#define SKERR_SIRQ_E024MSG "FIFO overflow error" + +extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); +extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); +extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port); +extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); + +#endif /* _INC_SKGESIRQ_H_ */ diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h new file mode 100644 index 0000000000..5ffaf6ede1 --- /dev/null +++ b/drivers/net/sk98lin/h/ski2c.h @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * Name: ski2c.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.34 $ + * Date: $Date: 2003/01/28 09:11:21 $ + * Purpose: Defines to access Voltage and Temperature Sensor + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: ski2c.h,v $ + * Revision 1.34 2003/01/28 09:11:21 rschmidt + * Editorial changes + * + * Revision 1.33 2002/10/14 16:40:50 rschmidt + * Editorial changes (TWSI) + * + * Revision 1.32 2002/08/13 08:55:07 rschmidt + * Editorial changes + * + * Revision 1.31 2002/08/06 09:44:22 jschmalz + * Extensions and changes for Yukon + * + * Revision 1.30 2001/04/05 11:38:09 rassmann + * Set SenState to idle in SkI2cWaitIrq(). + * Changed error message in SkI2cWaitIrq(). + * + * Revision 1.29 2000/08/03 14:28:17 rassmann + * - Added function to wait for I2C being ready before resetting the board. + * - Replaced one duplicate "out of range" message with correct one. + * + * Revision 1.28 1999/11/22 13:55:46 cgoos + * Changed license header to GPL. + * + * Revision 1.27 1999/05/20 09:23:10 cgoos + * Changes for 1000Base-T (Fan sensors). + * + * Revision 1.26 1998/12/01 13:45:47 gklug + * add: InitLevel to I2c struct + * + * Revision 1.25 1998/11/03 06:55:16 gklug + * add: Dummy Reads to I2c struct + * + * Revision 1.24 1998/10/02 14:28:59 cgoos + * Added prototype for SkI2cIsr. + * + * Revision 1.23 1998/09/08 12:20:11 gklug + * add: prototypes for init and read functions + * + * Revision 1.22 1998/09/08 07:37:56 gklug + * add: log error if PCI_IO voltage sensor could not be initialized + * + * Revision 1.21 1998/09/04 08:38:05 malthoff + * Change the values for I2C_READ and I2C_WRITE + * + * Revision 1.20 1998/08/25 07:52:22 gklug + * chg: Timestamps (last) added for logging + * + * Revision 1.19 1998/08/25 06:09:00 gklug + * rmv: warning and error levels of the individual sensors. + * add: timing definitions for sending traps and logging errors + * + * Revision 1.18 1998/08/20 11:41:15 gklug + * chg: omit STRCPY macro by using char * as Sensor Description + * + * Revision 1.17 1998/08/20 11:37:43 gklug + * chg: change Ioc to IoC + * + * Revision 1.16 1998/08/20 11:30:38 gklug + * fix: SenRead declaration + * + * Revision 1.15 1998/08/20 11:27:53 gklug + * fix: Compile bugs with new awrning constants + * + * Revision 1.14 1998/08/20 08:53:12 gklug + * fix: compiler errors + * add: Threshold values + * + * Revision 1.13 1998/08/19 12:21:16 gklug + * fix: remove struct from C files (see CCC) + * add: typedefs for all structs + * + * Revision 1.12 1998/08/19 10:57:41 gklug + * add: Warning levels + * + * Revision 1.11 1998/08/18 08:37:02 malthoff + * Prototypes not required for SK_DIAG. + * + * Revision 1.10 1998/08/17 13:54:00 gklug + * fix: declaration of event function + * + * Revision 1.9 1998/08/17 06:48:39 malthoff + * Remove some unrequired macros. + * Fix the compiler errors. + * + * Revision 1.8 1998/08/14 06:47:19 gklug + * fix: Values are intergers + * + * Revision 1.7 1998/08/14 06:26:05 gklug + * add: Init error message + * + * Revision 1.6 1998/08/13 08:31:08 gklug + * add: Error message + * + * Revision 1.5 1998/08/12 14:32:04 gklug + * add: new error code/message + * + * Revision 1.4 1998/08/12 13:39:08 gklug + * chg: names of error messages + * add: defines for Sensor type and thresholds + * + * Revision 1.3 1998/08/11 07:57:16 gklug + * add: sensor struct + * add: Timeout defines + * add: I2C control struct for pAC + * + * Revision 1.2 1998/07/17 11:29:02 gklug + * rmv: Microwire and SMTPANIC + * + * Revision 1.1 1998/06/19 14:30:10 malthoff + * Created. Sources taken from ML Project. + * + * + ******************************************************************************/ + +/* + * SKI2C.H contains all I2C specific defines + */ + +#ifndef _SKI2C_H_ +#define _SKI2C_H_ + +typedef struct s_Sensor SK_SENSOR; + +#include "h/skgei2c.h" + +/* + * Define the I2C events. + */ +#define SK_I2CEV_IRQ 1 /* IRQ happened Event */ +#define SK_I2CEV_TIM 2 /* Timeout event */ +#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */ + +/* + * Define READ and WRITE Constants. + */ +#undef I2C_READ /* just in case */ +#undef I2C_WRITE /* just in case */ +#define I2C_READ 0 +#define I2C_WRITE 1 +#define I2C_BURST 1 +#define I2C_SINGLE 0 + +#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0) +#define SKERR_I2C_E001MSG "Sensor index unknown" +#define SKERR_I2C_E002 (SKERR_I2C_E001+1) +#define SKERR_I2C_E002MSG "TWSI: transfer does not complete" +#define SKERR_I2C_E003 (SKERR_I2C_E002+1) +#define SKERR_I2C_E003MSG "LM80: NAK on device send" +#define SKERR_I2C_E004 (SKERR_I2C_E003+1) +#define SKERR_I2C_E004MSG "LM80: NAK on register send" +#define SKERR_I2C_E005 (SKERR_I2C_E004+1) +#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send" +#define SKERR_I2C_E006 (SKERR_I2C_E005+1) +#define SKERR_I2C_E006MSG "Unknown event" +#define SKERR_I2C_E007 (SKERR_I2C_E006+1) +#define SKERR_I2C_E007MSG "LM80 read out of state" +#define SKERR_I2C_E008 (SKERR_I2C_E007+1) +#define SKERR_I2C_E008MSG "Unexpected sensor read completed" +#define SKERR_I2C_E009 (SKERR_I2C_E008+1) +#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range" +#define SKERR_I2C_E010 (SKERR_I2C_E009+1) +#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range" +#define SKERR_I2C_E011 (SKERR_I2C_E010+1) +#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range" +#define SKERR_I2C_E012 (SKERR_I2C_E011+1) +#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range" +#define SKERR_I2C_E013 (SKERR_I2C_E012+1) +#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor" +#define SKERR_I2C_E014 (SKERR_I2C_E013+1) +#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range" +#define SKERR_I2C_E015 (SKERR_I2C_E014+1) +#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range" +#define SKERR_I2C_E016 (SKERR_I2C_E015+1) +#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete" + +/* + * Define Timeout values + */ +#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */ +#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */ +#define SK_I2C_TIM_WATCH 1000000L /* 1 second */ + +/* + * Define trap and error log hold times + */ +#ifndef SK_SEN_ERR_TR_HOLD +#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_ERR_LOG_HOLD +#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_WARN_TR_HOLD +#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_WARN_LOG_HOLD +#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC) +#endif + +/* + * Defines for SenType + */ +#define SK_SEN_UNKNOWN 0 +#define SK_SEN_TEMP 1 +#define SK_SEN_VOLT 2 +#define SK_SEN_FAN 3 + +/* + * Define for the SenErrorFlag + */ +#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */ +#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */ +#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */ +#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */ +#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */ + +/* + * Define the Sensor struct + */ +struct s_Sensor { + char *SenDesc; /* Description */ + int SenType; /* Voltage or Temperature */ + SK_I32 SenValue; /* Current value of the sensor */ + SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */ + SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */ + SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */ + SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ + int SenErrFlag; /* Sensor indicated an error */ + SK_BOOL SenInit; /* Is sensor initialized ? */ + SK_U64 SenErrCts; /* Error trap counter */ + SK_U64 SenWarnCts; /* Warning trap counter */ + SK_U64 SenBegErrTS; /* Begin error timestamp */ + SK_U64 SenBegWarnTS; /* Begin warning timestamp */ + SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */ + SK_U64 SenLastErrLogTS; /* Last error log timestamp */ + SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */ + SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */ + int SenState; /* Sensor State (see HW specific include) */ + int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen); + /* Sensors read function */ + SK_U16 SenReg; /* Register Address for this sensor */ + SK_U8 SenDev; /* Device Selection for this sensor */ +}; + +typedef struct s_I2c { + SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */ + int CurrSens; /* Which sensor is currently queried */ + int MaxSens; /* Max. number of sensors */ + int TimerMode; /* Use the timer also to watch the state machine */ + int InitLevel; /* Initialized Level */ +#ifndef SK_DIAG + int DummyReads; /* Number of non-checked dummy reads */ + SK_TIMER SenTimer; /* Sensors timer */ +#endif /* !SK_DIAG */ +} SK_I2C; + +extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); +#ifndef SK_DIAG +extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); +extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); +extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); +extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); + +#endif +#endif /* n_SKI2C_H */ diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h new file mode 100644 index 0000000000..bce20a75b6 --- /dev/null +++ b/drivers/net/sk98lin/h/skqueue.h @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Name: skqueue.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.14 $ + * Date: $Date: 2002/03/15 10:52:13 $ + * Purpose: Defines for the Event queue + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skqueue.h,v $ + * Revision 1.14 2002/03/15 10:52:13 mkunz + * Added event classes for link aggregation + * + * Revision 1.13 1999/11/22 13:59:05 cgoos + * Changed license header to GPL. + * + * Revision 1.12 1998/09/08 08:48:01 gklug + * add: init level handling + * + * Revision 1.11 1998/09/03 14:15:11 gklug + * add: CSUM and HWAC Eventclass and function. + * fix: pParaPtr according to CCC + * + * Revision 1.10 1998/08/20 12:43:03 gklug + * add: typedef SK_QUEUE + * + * Revision 1.9 1998/08/19 09:50:59 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.8 1998/08/18 07:00:01 gklug + * fix: SK_PTR not defined use void * instead. + * + * Revision 1.7 1998/08/17 13:43:19 gklug + * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR + * + * Revision 1.6 1998/08/14 07:09:30 gklug + * fix: chg pAc -> pAC + * + * Revision 1.5 1998/08/11 14:26:44 gklug + * chg: Event Dispatcher returns now int. + * + * Revision 1.4 1998/08/11 12:15:21 gklug + * add: Error numbers of skqueue module + * + * Revision 1.3 1998/08/07 12:54:23 gklug + * fix: first compiled version + * + * Revision 1.2 1998/08/07 09:34:00 gklug + * adapt structure defs to CCC + * add: prototypes for functions + * + * Revision 1.1 1998/07/30 14:52:12 gklug + * Initial version. + * Defines Event Classes, Event structs and queue management variables. + * + * + * + ******************************************************************************/ + +/* + * SKQUEUE.H contains all defines and types for the event queue + */ + +#ifndef _SKQUEUE_H_ +#define _SKQUEUE_H_ + + +/* + * define the event classes to be served + */ +#define SKGE_DRV 1 /* Driver Event Class */ +#define SKGE_RLMT 2 /* RLMT Event Class */ +#define SKGE_I2C 3 /* i2C Event Class */ +#define SKGE_PNMI 4 /* PNMI Event Class */ +#define SKGE_CSUM 5 /* Checksum Event Class */ +#define SKGE_HWAC 6 /* Hardware Access Event Class */ + +#define SKGE_SWT 9 /* Software Timer Event Class */ +#define SKGE_LACP 10 /* LACP Aggregation Event Class */ +#define SKGE_RSF 11 /* RSF Aggregation Event Class */ +#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */ +#define SKGE_FD 13 /* FD Distributor Event Class */ + +/* + * define event queue as circular buffer + */ +#define SK_MAX_EVENT 64 + +/* + * Parameter union for the Para stuff + */ +typedef union u_EvPara { + void *pParaPtr; /* Parameter Pointer */ + SK_U64 Para64; /* Parameter 64bit version */ + SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */ +} SK_EVPARA; + +/* + * Event Queue + * skqueue.c + * events are class/value pairs + * class is addressee, e.g. RMT, PCM etc. + * value is command, e.g. line state change, ring op change etc. + */ +typedef struct s_EventElem { + SK_U32 Class ; /* Event class */ + SK_U32 Event ; /* Event value */ + SK_EVPARA Para ; /* Event parameter */ +} SK_EVENTELEM; + +typedef struct s_Queue { + SK_EVENTELEM EvQueue[SK_MAX_EVENT]; + SK_EVENTELEM *EvPut ; + SK_EVENTELEM *EvGet ; +} SK_QUEUE; + +extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); +extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, + SK_EVPARA Para); +extern int SkEventDispatcher(SK_AC *pAC,SK_IOC Ioc); + + +/* Define Error Numbers and messages */ +#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0) +#define SKERR_Q_E001MSG "Event queue overflow" +#define SKERR_Q_E002 (SKERR_Q_E001+1) +#define SKERR_Q_E002MSG "Undefined event class" +#endif /* _SKQUEUE_H_ */ diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h new file mode 100644 index 0000000000..04d025b009 --- /dev/null +++ b/drivers/net/sk98lin/h/skrlmt.h @@ -0,0 +1,563 @@ +/****************************************************************************** + * + * Name: skrlmt.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.35 $ + * Date: $Date: 2003/01/31 14:12:41 $ + * Purpose: Header file for Redundant Link ManagemenT. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skrlmt.h,v $ + * Revision 1.35 2003/01/31 14:12:41 mkunz + * single port adapter runs now with two identical MAC addresses + * + * Revision 1.34 2002/09/23 15:13:41 rwahl + * Editorial changes. + * + * Revision 1.33 2001/07/03 12:16:48 mkunz + * New Flag ChgBcPrio (Change priority of last broadcast received) + * + * Revision 1.32 2001/02/14 14:06:31 rassmann + * Editorial changes. + * + * Revision 1.31 2001/02/05 14:25:26 rassmann + * Prepared RLMT for transparent operation. + * + * Revision 1.30 2001/01/22 13:41:39 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.29 2000/11/17 08:58:00 rassmann + * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. + * + * Revision 1.28 2000/11/09 12:24:34 rassmann + * Editorial changes. + * + * Revision 1.27 1999/11/22 13:59:56 cgoos + * Changed license header to GPL. + * + * Revision 1.26 1999/10/04 14:01:19 rassmann + * Corrected reaction to reception of BPDU frames (#10441). + * + * Revision 1.25 1999/07/20 12:53:39 rassmann + * Fixed documentation errors for lookahead macros. + * + * Revision 1.24 1999/05/28 11:15:56 rassmann + * Changed behaviour to reflect Design Spec v1.2. + * Controlling Link LED(s). + * Introduced RLMT Packet Version field in RLMT Packet. + * Newstyle lookahead macros (checking meta-information before looking at + * the packet). + * + * Revision 1.23 1999/01/28 12:50:42 rassmann + * Not using broadcast time stamps in CheckLinkState mode. + * + * Revision 1.22 1999/01/27 14:13:04 rassmann + * Monitoring broadcast traffic. + * Switching more reliably and not too early if switch is + * configured for spanning tree. + * + * Revision 1.21 1998/12/08 13:11:25 rassmann + * Stopping SegTimer at RlmtStop. + * + * Revision 1.20 1998/11/24 12:37:33 rassmann + * Implemented segmentation check. + * + * Revision 1.19 1998/11/17 13:43:06 rassmann + * Handling (logical) tx failure. + * Sending packet on logical address after PORT_SWITCH. + * + * Revision 1.18 1998/11/13 16:56:56 rassmann + * Added macro version of SkRlmtLookaheadPacket. + * + * Revision 1.17 1998/11/06 18:06:05 rassmann + * Corrected timing when RLMT checks fail. + * Clearing tx counter earlier in periodical checks. + * + * Revision 1.16 1998/11/03 13:53:50 rassmann + * RLMT should switch now (at least in mode 3). + * + * Revision 1.15 1998/10/22 11:39:52 rassmann + * Corrected signed/unsigned mismatches. + * Corrected receive list handling and address recognition. + * + * Revision 1.14 1998/10/15 15:16:36 rassmann + * Finished Spanning Tree checking. + * Checked with lint. + * + * Revision 1.13 1998/09/24 19:16:08 rassmann + * Code cleanup. + * Introduced Timer for PORT_DOWN due to no RX. + * + * Revision 1.12 1998/09/16 11:09:52 rassmann + * Syntax corrections. + * + * Revision 1.11 1998/09/15 11:28:50 rassmann + * Syntax corrections. + * + * Revision 1.10 1998/09/14 17:07:38 rassmann + * Added code for port checking via LAN. + * Changed Mbuf definition. + * + * Revision 1.9 1998/09/07 11:14:15 rassmann + * Syntax corrections. + * + * Revision 1.8 1998/09/07 09:06:08 rassmann + * Syntax corrections. + * + * Revision 1.7 1998/09/04 19:41:34 rassmann + * Syntax corrections. + * Started entering code for checking local links. + * + * Revision 1.6 1998/09/04 12:14:28 rassmann + * Interface cleanup. + * + * Revision 1.5 1998/09/02 16:55:29 rassmann + * Updated to reflect new DRV/HWAC/RLMT interface. + * + * Revision 1.4 1998/09/02 07:26:02 afischer + * typedef for SK_RLMT_PORT + * + * Revision 1.3 1998/08/27 14:29:03 rassmann + * Code cleanup. + * + * Revision 1.2 1998/08/27 14:26:25 rassmann + * Updated interface. + * + * Revision 1.1 1998/08/21 08:29:10 rassmann + * First public version. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This is the header file for Redundant Link ManagemenT. + * + * Include File Hierarchy: + * + * "skdrv1st.h" + * ... + * "sktypes.h" + * "skqueue.h" + * "skaddr.h" + * "skrlmt.h" + * ... + * "skdrv2nd.h" + * + ******************************************************************************/ + +#ifndef __INC_SKRLMT_H +#define __INC_SKRLMT_H + +#ifdef __cplusplus +#error C++ is not yet supported. +extern "C" { +#endif /* cplusplus */ + +/* defines ********************************************************************/ + +#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */ +#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */ + +/* ----- Default queue sizes - must be multiples of 8 KB ----- */ + +/* Less than 8 KB free in RX queue => pause frames. */ +#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */ +#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */ +#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */ + +#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */ + +/* ----- PORT states ----- */ + +#define SK_RLMT_PS_INIT 0 /* Port state: Init. */ +#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */ +#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */ +#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */ +#define SK_RLMT_PS_UP 4 /* Port state: Up. */ + +/* ----- RLMT states ----- */ + +#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */ +#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */ +#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */ + +/* ----- PORT events ----- */ + +#define SK_RLMT_LINK_UP 1001 /* Link came up. */ +#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */ +#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */ + +/* ----- RLMT events ----- */ + +#define SK_RLMT_START 2001 /* Start RLMT. */ +#define SK_RLMT_STOP 2002 /* Stop RLMT. */ +#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */ +#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */ +#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */ +#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */ +#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */ +#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */ + +/* ----- RLMT mode bits ----- */ + +/* + * CAUTION: These defines are private to RLMT. + * Please use the RLMT mode defines below. + */ + +#define SK_RLMT_CHECK_LINK 1 /* Check Link. */ +#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */ +#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */ + +#ifndef RLMT_CHECK_REMOTE +#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK +#else /* RLMT_CHECK_REMOTE */ +#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */ +#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3 +#define SK_RLMT_CHECK_OTHERS \ + (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) +#endif /* RLMT_CHECK_REMOTE */ + +#ifndef SK_RLMT_ENABLE_TRANSPARENT +#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */ +#else /* SK_RLMT_ENABLE_TRANSPARENT */ +#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */ +#endif /* SK_RLMT_ENABLE_TRANSPARENT */ + +/* ----- RLMT modes ----- */ + +/* Check Link State. */ +#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK) + +/* Check Local Ports: check other links on the same adapter. */ +#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK) + +/* Check Local Ports and Segmentation Status. */ +#define SK_RLMT_MODE_CLPSS \ + (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG) + +#ifdef RLMT_CHECK_REMOTE +/* Check Local and Remote Ports: check links (local or remote). */ + Name of define TBD! +#define SK_RLMT_MODE_CRP \ + (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) + +/* Check Local and Remote Ports and Segmentation Status. */ + Name of define TBD! +#define SK_RLMT_MODE_CRPSS \ + (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \ + SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG) +#endif /* RLMT_CHECK_REMOTE */ + +/* ----- RLMT lookahead result bits ----- */ + +#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */ +#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */ + +/* Macros */ + +#if 0 +SK_AC *pAC /* adapter context */ +SK_U32 PortNum /* receiving port */ +unsigned PktLen /* received packet's length */ +SK_BOOL IsBc /* Flag: packet is broadcast */ +unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */ +unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */ +#endif /* 0 */ + +#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \ + SK_AC *_pAC; \ + SK_U32 _PortNum; \ + _pAC = (pAC); \ + _PortNum = (SK_U32)(PortNum); \ + /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \ + _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \ + if (_pAC->Rlmt.RlmtOff) { \ + *(pNumBytes) = 0; \ + } \ + else {\ + if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ + *(pNumBytes) = 0; \ + } \ + else if (IsBc) { \ + if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ + *(pNumBytes) = 6; \ + *(pOffset) = 6; \ + } \ + else { \ + *(pNumBytes) = 0; \ + } \ + } \ + else { \ + if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ + /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ + *(pNumBytes) = 0; \ + } \ + else { \ + *(pNumBytes) = 6; \ + *(pOffset) = 0; \ + } \ + } \ + } \ +} + +#if 0 +SK_AC *pAC /* adapter context */ +SK_U32 PortNum /* receiving port */ +SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */ +SK_BOOL IsBc /* Flag: packet is broadcast */ +SK_BOOL IsMc /* Flag: packet is multicast */ +unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */ +SK_RLMT_LOOKAHEAD() expects *pNumBytes from +packet offset *pOffset (s.a.) at *pLaPacket. + +If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is +BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler +can trash unneeded parts of the if construction. +#endif /* 0 */ + +#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \ + SK_AC *_pAC; \ + SK_U32 _PortNum; \ + SK_U8 *_pLaPacket; \ + _pAC = (pAC); \ + _PortNum = (SK_U32)(PortNum); \ + _pLaPacket = (SK_U8 *)(pLaPacket); \ + if (IsBc) {\ + if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \ + _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \ + _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \ + _pAC->Rlmt.CheckSwitch = SK_TRUE; \ + } \ + /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ + *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ + } \ + else if (IsMc) { \ + if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \ + _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \ + if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \ + *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \ + } \ + else { \ + *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ + } \ + } \ + else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \ + *(pForRlmt) = SK_RLMT_RX_RLMT; \ + } \ + else { \ + /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ + *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ + } \ + } \ + else { \ + if (SK_ADDR_EQUAL( \ + _pLaPacket, \ + _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \ + *(pForRlmt) = SK_RLMT_RX_RLMT; \ + } \ + else { \ + /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ + *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ + } \ + } \ +} + +#ifdef SK_RLMT_FAST_LOOKAHEAD +Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead. +#endif /* SK_RLMT_FAST_LOOKAHEAD */ +#ifdef SK_RLMT_SLOW_LOOKAHEAD +Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead. +#endif /* SK_RLMT_SLOW_LOOKAHEAD */ + +/* typedefs *******************************************************************/ + +#ifdef SK_RLMT_MBUF_PRIVATE +typedef struct s_RlmtMbuf { + some content +} SK_RLMT_MBUF; +#endif /* SK_RLMT_MBUF_PRIVATE */ + + +#ifdef SK_LA_INFO +typedef struct s_Rlmt_PacketInfo { + unsigned PacketLength; /* Length of packet. */ + unsigned PacketType; /* Directed/Multicast/Broadcast. */ +} SK_RLMT_PINFO; +#endif /* SK_LA_INFO */ + + +typedef struct s_RootId { + SK_U8 Id[8]; /* Root Bridge Id. */ +} SK_RLMT_ROOT_ID; + + +typedef struct s_port { + SK_MAC_ADDR CheckAddr; + SK_BOOL SuspectTx; +} SK_PORT_CHECK; + + +typedef struct s_RlmtNet SK_RLMT_NET; + + +typedef struct s_RlmtPort { + +/* ----- Public part (read-only) ----- */ + + SK_U8 PortState; /* Current state of this port. */ + + /* For PNMI */ + SK_BOOL LinkDown; + SK_BOOL PortDown; + SK_U8 Align01; + + SK_U32 PortNumber; /* Number of port on adapter. */ + SK_RLMT_NET * Net; /* Net port belongs to. */ + + SK_U64 TxHelloCts; + SK_U64 RxHelloCts; + SK_U64 TxSpHelloReqCts; + SK_U64 RxSpHelloCts; + +/* ----- Private part ----- */ + +/* SK_U64 PacketsRx; */ /* Total packets received. */ + SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */ +/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */ + SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */ + SK_U64 BcTimeStamp; /* Time of last BC receive. */ + SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */ + + SK_TIMER UpTimer; /* Timer struct Link/Port up. */ + SK_TIMER DownRxTimer; /* Timer struct down rx. */ + SK_TIMER DownTxTimer; /* Timer struct down tx. */ + + SK_U32 CheckingState; /* Checking State. */ + + SK_ADDR_PORT * AddrPort; + + SK_U8 Random[4]; /* Random value. */ + unsigned PortsChecked; /* #ports checked. */ + unsigned PortsSuspect; /* #ports checked that are s. */ + SK_PORT_CHECK PortCheck[1]; +/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */ + + SK_BOOL PortStarted; /* Port is started. */ + SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */ + SK_BOOL RootIdSet; + SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ +} SK_RLMT_PORT; + + +struct s_RlmtNet { + +/* ----- Public part (read-only) ----- */ + + SK_U32 NetNumber; /* Number of net. */ + + SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */ + SK_U32 NumPorts; /* Number of ports. */ + SK_U32 PrefPort; /* Preferred port. */ + + /* For PNMI */ + + SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */ + SK_U32 RlmtMode; /* Check ... */ + SK_U32 ActivePort; /* Active port. */ + SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */ + + SK_U8 RlmtState; /* Current RLMT state. */ + +/* ----- Private part ----- */ + SK_BOOL RootIdSet; + SK_U16 Align01; + + int LinksUp; /* #Links up. */ + int PortsUp; /* #Ports up. */ + SK_U32 TimeoutValue; /* RLMT timeout value. */ + + SK_U32 CheckingState; /* Checking State. */ + SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ + + SK_TIMER LocTimer; /* Timer struct. */ + SK_TIMER SegTimer; /* Timer struct. */ +}; + + +typedef struct s_Rlmt { + +/* ----- Public part (read-only) ----- */ + + SK_U32 NumNets; /* Number of nets. */ + SK_U32 NetsStarted; /* Number of nets started. */ + SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */ + SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */ + +/* ----- Private part ----- */ + SK_BOOL CheckSwitch; + SK_BOOL RlmtOff; /* set to zero if the Mac addresses + are equal or the second one + is zero */ + SK_U16 Align01; + +} SK_RLMT; + + +extern SK_MAC_ADDR BridgeMcAddr; +extern SK_MAC_ADDR SkRlmtMcAddr; + +/* function prototypes ********************************************************/ + + +#ifndef SK_KR_PROTO + +/* Functions provided by SkRlmt */ + +/* ANSI/C++ compliant function prototypes */ + +extern void SkRlmtInit( + SK_AC *pAC, + SK_IOC IoC, + int Level); + +extern int SkRlmtEvent( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 Event, + SK_EVPARA Para); + +#else /* defined(SK_KR_PROTO) */ + +/* Non-ANSI/C++ compliant function prototypes */ + +#error KR-style function prototypes are not yet provided. + +#endif /* defined(SK_KR_PROTO)) */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_SKRLMT_H */ diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h new file mode 100644 index 0000000000..36f8ccb6af --- /dev/null +++ b/drivers/net/sk98lin/h/sktimer.h @@ -0,0 +1,99 @@ +/****************************************************************************** + * + * Name: sktimer.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.9 $ + * Date: $Date: 1999/11/22 14:00:29 $ + * Purpose: Defines for the timer functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sktimer.h,v $ + * Revision 1.9 1999/11/22 14:00:29 cgoos + * Changed license header to GPL. + * + * Revision 1.8 1998/09/08 08:48:02 gklug + * add: init level handling + * + * Revision 1.7 1998/08/20 12:31:29 gklug + * fix: SK_TIMCTRL needs to be defined + * + * Revision 1.6 1998/08/19 09:51:00 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.5 1998/08/17 13:43:21 gklug + * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR + * + * Revision 1.4 1998/08/14 07:09:31 gklug + * fix: chg pAc -> pAC + * + * Revision 1.3 1998/08/07 12:54:24 gklug + * fix: first compiled version + * + * Revision 1.2 1998/08/07 09:35:29 gklug + * add: Timer control struct for Adapters context + * add: function prototypes + * + * Revision 1.1 1998/08/05 11:27:01 gklug + * First version: adapted from SMT + * + * + ******************************************************************************/ + +/* + * SKTIMER.H contains all defines and types for the timer functions + */ + +#ifndef _SKTIMER_H_ +#define _SKTIMER_H_ + +#include "h/skqueue.h" + +/* + * SK timer + * - needed wherever a timer is used. Put this in your data structure + * wherever you want. + */ +typedef struct s_Timer SK_TIMER; + +struct s_Timer { + SK_TIMER *TmNext ; /* linked list */ + SK_U32 TmClass ; /* Timer Event class */ + SK_U32 TmEvent ; /* Timer Event value */ + SK_EVPARA TmPara ; /* Timer Event parameter */ + SK_U32 TmDelta ; /* delta time */ + int TmActive ; /* flag : active/inactive */ +} ; + +/* + * Timer control struct. + * - use in Adapters context name pAC->Tim + */ +typedef struct s_TimCtrl { + SK_TIMER *StQueue ; /* Head of Timer queue */ +} SK_TIMCTRL ; + +extern void SkTimerInit(SK_AC *pAC,SK_IOC Ioc, int Level); +extern void SkTimerStop(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer); +extern void SkTimerStart(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer, + SK_U32 Time,SK_U32 Class,SK_U32 Event,SK_EVPARA Para); +extern void SkTimerDone(SK_AC *pAC,SK_IOC Ioc); +#endif /* _SKTIMER_H_ */ diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h new file mode 100644 index 0000000000..e657016e5b --- /dev/null +++ b/drivers/net/sk98lin/h/sktypes.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * Name: sktypes.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.3 $ + * Date: $Date: 2003/02/25 14:16:40 $ + * Purpose: Define data types for Linux + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + + /***************************************************************************** + * + * History: + * + * $Log: sktypes.h,v $ + * Revision 1.3 2003/02/25 14:16:40 mlindner + * Fix: Copyright statement + * + * Revision 1.2 1999/11/22 14:01:58 cgoos + * Changed license header to GPL. + * Now using Linux' fixed size types instead of standard types. + * + * Revision 1.1 1999/02/16 07:41:40 cgoos + * First version. + * + * + * + *****************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * In this file, all data types that are needed by the common modules + * are mapped to Linux data types. + * + * + * Include File Hierarchy: + * + * + ******************************************************************************/ + +#ifndef __INC_SKTYPES_H +#define __INC_SKTYPES_H + + +/* defines *******************************************************************/ + +/* + * Data types with a specific size. 'I' = signed, 'U' = unsigned. + */ +#define SK_I8 s8 +#define SK_U8 u8 +#define SK_I16 s16 +#define SK_U16 u16 +#define SK_I32 s32 +#define SK_U32 u32 +#define SK_I64 s64 +#define SK_U64 u64 + +#define SK_UPTR ulong /* casting pointer <-> integral */ + +/* +* Boolean type. +*/ +#define SK_BOOL SK_U8 +#define SK_FALSE 0 +#define SK_TRUE (!SK_FALSE) + +/* typedefs *******************************************************************/ + +/* function prototypes ********************************************************/ + +#endif /* __INC_SKTYPES_H */ diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h new file mode 100644 index 0000000000..ef466857d1 --- /dev/null +++ b/drivers/net/sk98lin/h/skversion.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Name: version.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.4 $ + * Date: $Date: 2003/02/25 14:16:40 $ + * Purpose: SK specific Error log support + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skversion.h,v $ + * Revision 1.4 2003/02/25 14:16:40 mlindner + * Fix: Copyright statement + * + * Revision 1.3 2003/02/25 13:30:18 mlindner + * Add: Support for various vendors + * + * Revision 1.1.2.1 2001/09/05 13:38:30 mlindner + * Removed FILE description + * + * Revision 1.1 2001/03/06 09:25:00 mlindner + * first version + * + * + * + ******************************************************************************/ + + +static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; +static const char SysKonnectBuildNumber[] = + "@(#)SK-BUILD: 6.05 PL: 01"; + +#define BOOT_STRING "sk98lin: Network Device Driver v6.05\n" \ + "(C)Copyright 1999-2003 Marvell(R)." + +#define VER_STRING "6.05" diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h new file mode 100644 index 0000000000..1be34c5a97 --- /dev/null +++ b/drivers/net/sk98lin/h/skvpd.h @@ -0,0 +1,335 @@ +/****************************************************************************** + * + * Name: skvpd.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.15 $ + * Date: $Date: 2003/01/13 10:39:38 $ + * Purpose: Defines and Macros for VPD handling + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skvpd.h,v $ + * Revision 1.15 2003/01/13 10:39:38 rschmidt + * Replaced define for PCI device Id for YUKON with GENESIS + * Editorial changes + * + * Revision 1.14 2002/11/14 15:18:10 gheinig + * Added const specifier to key and buf parameters for VpdPara,VpdRead + * and VpdWrite. This is necessary for the Diag 7 GUI API + * + * Revision 1.13 2002/10/14 15:58:18 rschmidt + * Added entry in rom_size struct s_vpd + * Editorial changes + * + * Revision 1.12 2002/09/09 14:43:51 mkarl + * added PCI Id of Yukon for reading VPD in diag before the adapter has + * been initialized + * editorial changes + * + * Revision 1.11 2002/07/26 13:19:16 mkarl + * added support for Yukon + * added vpd_size to VPD struct + * + * Revision 1.10 2000/08/10 11:29:07 rassmann + * Editorial changes. + * Preserving 32-bit alignment in structs for the adapter context. + * Removed unused function VpdWriteDword() (#if 0). + * Made VpdReadKeyword() available for SKDIAG only. + * + * Revision 1.9 1999/11/22 14:02:27 cgoos + * Changed license header to GPL. + * + * Revision 1.8 1999/03/11 14:26:40 malthoff + * Replace __STDC__ with SK_KR_PROTO. + * + * Revision 1.7 1998/10/28 07:27:17 gklug + * rmv: SWAP macros + * add: VPD_IN/OUT8 macros + * chg: interface definition + * + * Revision 1.6 1998/10/22 10:03:44 gklug + * fix: use SK_OUT16 instead of SK_OUTW + * + * Revision 1.5 1998/10/14 07:05:31 cgoos + * Changed constants in SK_SWAP_32 to UL. + * + * Revision 1.4 1998/08/19 08:14:09 gklug + * fix: remove struct keyword as much as possible from the C-code (see CCC) + * + * Revision 1.3 1998/08/18 08:18:56 malthoff + * Modify VPD in and out macros for SK_DIAG + * + * Revision 1.2 1998/07/03 14:49:08 malthoff + * Add VPD_INxx() and VPD_OUTxx() macros for the Diagnostics tool. + * + * Revision 1.1 1998/06/19 14:08:03 malthoff + * Created. + * + * + ******************************************************************************/ + +/* + * skvpd.h contains Diagnostic specific defines for VPD handling + */ + +#ifndef __INC_SKVPD_H_ +#define __INC_SKVPD_H_ + +/* + * Define Resource Type Identifiers and VPD keywords + */ +#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ +#define RES_VPD_R 0x90 /* start of VPD read only area */ +#define RES_VPD_W 0x91 /* start of VPD read/write area */ +#define RES_END 0x78 /* Resource Type End Tag */ + +#ifndef VPD_NAME +#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */ +#endif /* VPD_NAME */ +#define VPD_PN "PN" /* Adapter Part Number */ +#define VPD_EC "EC" /* Adapter Engineering Level */ +#define VPD_MN "MN" /* Manufacture ID */ +#define VPD_SN "SN" /* Serial Number */ +#define VPD_CP "CP" /* Extended Capability */ +#define VPD_RV "RV" /* Checksum and Reserved */ +#define VPD_YA "YA" /* Asset Tag Identifier */ +#define VPD_VL "VL" /* First Error Log Message (SK specific) */ +#define VPD_VF "VF" /* Second Error Log Message (SK specific) */ +#define VPD_RW "RW" /* Remaining Read / Write Area */ + +/* 'type' values for vpd_setup_para() */ +#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */ +#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */ + +/* 'op' values for vpd_setup_para() */ +#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ +#define OWR_KEY 2 /* overwrite key if already exists */ + +/* + * Define READ and WRITE Constants. + */ + +#define VPD_DEV_ID_GENESIS 0x4300 + +#define VPD_SIZE_YUKON 256 +#define VPD_SIZE_GENESIS 512 +#define VPD_SIZE 512 +#define VPD_READ 0x0000 +#define VPD_WRITE 0x8000 + +#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE) + +#define VPD_GET_RES_LEN(p) ((unsigned int) \ + (* (SK_U8 *)&(p)[1]) |\ + ((* (SK_U8 *)&(p)[2]) << 8)) +#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2])) +#define VPD_GET_VAL(p) ((char *)&(p)[3]) + +#define VPD_MAX_LEN 50 + +/* VPD status */ + /* bit 7..1 reserved */ +#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */ + /* and vpd_free_rw valid */ + +/* + * VPD structs + */ +typedef struct s_vpd_status { + unsigned short Align01; /* Alignment */ + unsigned short vpd_status; /* VPD status, description see above */ + int vpd_free_ro; /* unused bytes in read only area */ + int vpd_free_rw; /* bytes available in read/write area */ +} SK_VPD_STATUS; + +typedef struct s_vpd { + SK_VPD_STATUS v; /* VPD status structure */ + char vpd_buf[VPD_SIZE]; /* VPD buffer */ + int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */ + int vpd_size; /* saved VPD-size */ +} SK_VPD; + +typedef struct s_vpd_para { + unsigned int p_len; /* parameter length */ + char *p_val; /* points to the value */ +} SK_VPD_PARA; + +/* + * structure of Large Resource Type Identifiers + */ + +/* was removed because of alignment problems */ + +/* + * structure of VPD keywords + */ +typedef struct s_vpd_key { + char p_key[2]; /* 2 bytes ID string */ + unsigned char p_len; /* 1 byte length */ + char p_val; /* start of the value string */ +} SK_VPD_KEY; + + +/* + * System specific VPD macros + */ +#ifndef SKDIAG +#ifndef VPD_DO_IO +#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val) +#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val) +#define VPD_OUT32(pAC,IoC,Addr,Val) (void)SkPciWriteCfgDWord(pAC,Addr,Val) +#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal) +#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal) +#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal) +#else /* VPD_DO_IO */ +#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val) +#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val) +#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val) +#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal) +#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal) +#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal) +#endif /* VPD_DO_IO */ +#else /* SKDIAG */ +#define VPD_OUT8(pAC,Ioc,Addr,Val) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciWriteCfgByte(pAC,Addr,Val); \ + else \ + SK_OUT8(pAC,PCI_C(Addr),Val); \ + } +#define VPD_OUT16(pAC,Ioc,Addr,Val) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciWriteCfgWord(pAC,Addr,Val); \ + else \ + SK_OUT16(pAC,PCI_C(Addr),Val); \ + } +#define VPD_OUT32(pAC,Ioc,Addr,Val) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciWriteCfgDWord(pAC,Addr,Val); \ + else \ + SK_OUT32(pAC,PCI_C(Addr),Val); \ + } +#define VPD_IN8(pAC,Ioc,Addr,pVal) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciReadCfgByte(pAC,Addr,pVal); \ + else \ + SK_IN8(pAC,PCI_C(Addr),pVal); \ + } +#define VPD_IN16(pAC,Ioc,Addr,pVal) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciReadCfgWord(pAC,Addr,pVal); \ + else \ + SK_IN16(pAC,PCI_C(Addr),pVal); \ + } +#define VPD_IN32(pAC,Ioc,Addr,pVal) { \ + if ((pAC)->DgT.DgUseCfgCycle) \ + SkPciReadCfgDWord(pAC,Addr,pVal); \ + else \ + SK_IN32(pAC,PCI_C(Addr),pVal); \ + } +#endif /* nSKDIAG */ + +/* function prototypes ********************************************************/ + +#ifndef SK_KR_PROTO +#ifdef SKDIAG +extern SK_U32 VpdReadDWord( + SK_AC *pAC, + SK_IOC IoC, + int addr); +#endif /* SKDIAG */ + +extern int VpdSetupPara( + SK_AC *pAC, + const char *key, + const char *buf, + int len, + int type, + int op); + +extern SK_VPD_STATUS *VpdStat( + SK_AC *pAC, + SK_IOC IoC); + +extern int VpdKeys( + SK_AC *pAC, + SK_IOC IoC, + char *buf, + int *len, + int *elements); + +extern int VpdRead( + SK_AC *pAC, + SK_IOC IoC, + const char *key, + char *buf, + int *len); + +extern SK_BOOL VpdMayWrite( + char *key); + +extern int VpdWrite( + SK_AC *pAC, + SK_IOC IoC, + const char *key, + const char *buf); + +extern int VpdDelete( + SK_AC *pAC, + SK_IOC IoC, + char *key); + +extern int VpdUpdate( + SK_AC *pAC, + SK_IOC IoC); + +extern void VpdErrLog( + SK_AC *pAC, + SK_IOC IoC, + char *msg); + +#ifdef SKDIAG +extern int VpdReadBlock( + SK_AC *pAC, + SK_IOC IoC, + char *buf, + int addr, + int len); + +extern int VpdWriteBlock( + SK_AC *pAC, + SK_IOC IoC, + char *buf, + int addr, + int len); +#endif /* SKDIAG */ +#else /* SK_KR_PROTO */ +extern SK_U32 VpdReadDWord(); +extern int VpdSetupPara(); +extern SK_VPD_STATUS *VpdStat(); +extern int VpdKeys(); +extern int VpdRead(); +extern SK_BOOL VpdMayWrite(); +extern int VpdWrite(); +extern int VpdDelete(); +extern int VpdUpdate(); +extern void VpdErrLog(); +#endif /* SK_KR_PROTO */ + +#endif /* __INC_SKVPD_H_ */ diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h new file mode 100644 index 0000000000..2ef903a87d --- /dev/null +++ b/drivers/net/sk98lin/h/xmac_ii.h @@ -0,0 +1,1738 @@ +/****************************************************************************** + * + * Name: xmac_ii.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.46 $ + * Date: $Date: 2003/01/28 09:47:45 $ + * Purpose: Defines and Macros for Gigabit Ethernet Controller + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: xmac_ii.h,v $ + * Revision 1.46 2003/01/28 09:47:45 rschmidt + * Added defines for copper MDI/MDIX configuration + * Added defines for LED Control Register + * Editorial changes + * + * Revision 1.45 2002/12/10 14:35:13 rschmidt + * Corrected defines for Extended PHY Specific Control + * Added defines for Ext. PHY Specific Ctrl 2 Reg. (Fiber specific) + * + * Revision 1.44 2002/12/09 14:58:41 rschmidt + * Added defines for Ext. PHY Specific Ctrl Reg. (downshift feature) + * Added 'GMR_FS_UN_SIZE'-Bit to Rx GMAC FIFO Flush Mask + * + * Revision 1.43 2002/12/05 10:14:45 rschmidt + * Added define for GMAC's Half Duplex Burst Mode + * Added define for Rx GMAC FIFO Flush Mask (default) + * + * Revision 1.42 2002/11/12 16:48:19 rschmidt + * Added defines for Cable Diagnostic Register (GPHY) + * Editorial changes + * + * Revision 1.41 2002/10/21 11:20:22 rschmidt + * Added bit GMR_FS_GOOD_FC to GMR_FS_ANY_ERR + * Editorial changes + * + * Revision 1.40 2002/10/14 14:54:14 rschmidt + * Added defines for GPHY Specific Status and GPHY Interrupt Status + * Added bits PHY_M_IS_AN_ERROR and PHY_M_IS_FIFO_ERROR to PHY_M_DEF_MSK + * Editorial changes + * + * Revision 1.39 2002/10/10 15:53:44 mkarl + * added some bit definitions for link speed status and LED's + * + * Revision 1.38 2002/08/21 16:23:46 rschmidt + * Added defines for PHY Specific Ctrl Reg + * Editorial changes + * + * Revision 1.37 2002/08/16 14:50:33 rschmidt + * Added defines for Auto-Neg. Advertisement YUKON Fiber (88E1011S only) + * Changed define PHY_M_DEF_MSK for GPHY IRQ Mask + * Editorial changes + * + * Revision 1.36 2002/08/12 13:21:10 rschmidt + * Added defines for different Broadcom PHY Ids + * + * Revision 1.35 2002/08/08 15:58:01 rschmidt + * Added defines for Manual LED Override register (YUKON) + * Editorial changes + * + * Revision 1.34 2002/07/31 17:23:36 rwahl + * Added define GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR). + * + * Revision 1.33 2002/07/23 16:03:37 rschmidt + * Added defines for GPHY registers + * Editorial changes + * + * Revision 1.32 2002/07/15 18:14:37 rwahl + * Added GMAC MIB counters definitions. + * Editorial changes. + * + * Revision 1.31 2002/07/15 15:42:50 rschmidt + * Removed defines from PHY specific reg. which are + * common to all PHYs + * Added defines for GMAC MIB Counters + * Editorial changes + * + * Revision 1.30 2002/06/05 08:22:12 rschmidt + * Changed defines for GMAC Rx Control Register and Rx Status + * Editorial changes + * + * Revision 1.29 2002/04/25 11:43:56 rschmidt + * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. + * Added new registers and defines for YUKON (GMAC, GPHY) + * Added Receive Frame Status Encoding for YUKON + * Editorial changes + * + * Revision 1.28 2000/11/09 12:32:49 rassmann + * Renamed variables. + * + * Revision 1.27 2000/05/17 11:00:46 malthoff + * Add bit for enable/disable power management in BCOM chip. + * + * Revision 1.26 1999/11/22 14:03:00 cgoos + * Changed license header to GPL. + * + * Revision 1.25 1999/08/12 19:19:38 malthoff + * Add PHY_B_AC_TX_TST bit according to BCOM A1 errata sheet. + * + * Revision 1.24 1999/07/30 11:27:21 cgoos + * Fixed a missing end-of-comment. + * + * Revision 1.23 1999/07/30 07:03:31 malthoff + * Cut some long comments. + * Correct the XMAC PHY ID definitions. + * + * Revision 1.22 1999/05/19 07:33:18 cgoos + * Changes for 1000Base-T. + * + * Revision 1.21 1999/03/25 07:46:11 malthoff + * Add XM_HW_CFG, XM_TS_READ, and XM_TS_LOAD registers. + * + * Revision 1.20 1999/03/12 13:36:09 malthoff + * Remove __STDC__. + * + * Revision 1.19 1998/12/10 12:22:54 gklug + * fix: RX_PAGE must be in interrupt mask + * + * Revision 1.18 1998/12/10 10:36:36 gklug + * fix: swap of pause bits + * + * Revision 1.17 1998/11/18 13:21:45 gklug + * fix: Default interrupt mask + * + * Revision 1.16 1998/10/29 15:53:21 gklug + * fix: Default mask uses ASS (GP0) signal + * + * Revision 1.15 1998/10/28 13:52:52 malthoff + * Add new bits in RX_CMD register. + * + * Revision 1.14 1998/10/19 15:34:53 gklug + * fix: typos + * + * Revision 1.13 1998/10/14 07:19:03 malthoff + * bug fix: Every define which describes bit 31 + * must be declared as unsigned long 'UL'. + * fix bit definitions of PHY_AN_RFB and PHY_AN_PAUSE. + * Remove ANP defines. Rework the RFB defines. + * + * Revision 1.12 1998/10/14 06:22:44 cgoos + * Changed shifted constant to ULONG. + * + * Revision 1.11 1998/10/14 05:43:26 gklug + * add: shift pause coding + * fix: PAUSE bits definition + * + * Revision 1.10 1998/10/13 09:19:21 malthoff + * Again change XMR_FS_ANY_ERR because of new info from XaQti. + * + * Revision 1.9 1998/10/09 07:58:30 malthoff + * Add XMR_FS_FCS_ERR to XMR_FS_ANY_ERR. + * + * Revision 1.8 1998/10/09 07:18:17 malthoff + * bug fix of a bug fix: XM_PAUSE_MODE and XM_DEF_MODE + * are not inverted! Bug XM_DEF_MSK is inverted. + * + * Revision 1.7 1998/10/05 08:04:32 malthoff + * bug fix: XM_PAUSE_MODE and XM_DEF_MODE + * must be inverted declarations. + * + * Revision 1.6 1998/09/28 13:38:18 malthoff + * Add default modes and masks XM_DEF_MSK, + * XM_PAUSE_MODE and XM_DEF_MODE + * + * Revision 1.5 1998/09/16 14:42:04 malthoff + * Bug Fix: XM_GP_PORT is a 32 bit (not a 16 bit) register. + * + * Revision 1.4 1998/08/20 14:59:47 malthoff + * Rework this file after reading the XaQti data sheet + * "Differences between Rev. B2 & Rev. C XMAC II". + * This file is now 100% XMAC II Rev. C complained. + * + * Revision 1.3 1998/06/29 12:18:23 malthoff + * Correct XMR_FS_ANY_ERR definition. + * + * Revision 1.2 1998/06/29 12:10:56 malthoff + * Add define XMR_FS_ANY_ERR. + * + * Revision 1.1 1998/06/19 13:37:17 malthoff + * created. + * + * + ******************************************************************************/ + +#ifndef __INC_XMAC_H +#define __INC_XMAC_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines ********************************************************************/ + +/* + * XMAC II registers + * + * The XMAC registers are 16 or 32 bits wide. + * The XMACs host processor interface is set to 16 bit mode, + * therefore ALL registers will be addressed with 16 bit accesses. + * + * The following macros are provided to access the XMAC registers + * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(), + * XM_INHASH(), and XM_OUTHASH(). + * The macros are defined in SkGeHw.h. + * + * Note: NA reg = Network Address e.g DA, SA etc. + * + */ +#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */ + /* 0x0004: reserved */ +#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */ +#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/ +#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */ +#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */ + /* 0x0018 - 0x001e: reserved */ +#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */ +#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */ +#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */ +#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */ +#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */ +#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */ +#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */ + /* 0x003c: reserved */ +#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */ +#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */ +#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */ +#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */ + /* 0x0050 - 0x005e: reserved */ +#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */ +#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */ +#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */ +#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */ +#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */ + /* 0x006e: reserved */ +#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */ +#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */ +#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/ +#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */ + + /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */ + /* use the XM_EXM() macro to address */ +#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */ + + /* + * XM_EXM(Reg) + * + * returns the XMAC address offset of specified Exact Match Addr Reg + * + * para: Reg EXM register to addr (0 .. 15) + * + * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]); + */ +#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3)) + +#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */ +#define XM_SA 0x0108 /* NA reg r/w Station Address Register */ +#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */ +#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */ +#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */ +#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */ +#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */ +#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */ +#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */ + /* 0x012e: reserved */ +#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */ +#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */ + /* 0x0138 - 0x01fe: reserved */ +#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */ +#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */ +#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */ +#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */ +#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */ + /* 0x0204 - 0x027e: reserved */ +#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */ +#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/ +#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */ +#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */ +#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */ +#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */ +#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */ +#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */ +#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ +#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */ +#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */ +#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */ +#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */ +#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */ +#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */ +#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */ +#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */ +#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */ +#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */ + /* 0x02cc - 0x02ce: reserved */ +#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */ +#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */ +#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */ +#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */ +#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ +#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ + /* 0x02e8 - 0x02fe: reserved */ +#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */ +#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */ +#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/ +#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */ +#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */ +#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */ +#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ +#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */ +#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */ +#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ +#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */ +#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */ +#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */ +#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */ +#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */ +#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */ +#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */ +#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */ +#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */ +#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */ +#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */ +#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ + /* 0x0358 - 0x035a: reserved */ +#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ +#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */ + /* 0x0364 - 0x0366: reserved */ +#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */ +#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */ +#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */ +#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */ +#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ +#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ + /* 0x02e8 - 0x02fe: reserved */ + + +/*----------------------------------------------------------------------------*/ +/* + * XMAC Bit Definitions + * + * If the bit access behaviour differs from the register access behaviour + * (r/w, r/o) this is documented after the bit number. + * The following bit access behaviours are used: + * (sc) self clearing + * (ro) read only + */ + +/* XM_MMU_CMD 16 bit r/w MMU Command Register */ + /* Bit 15..13: reserved */ +#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */ +#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */ +#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */ +#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */ + /* Bit 8: reserved */ +#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */ +#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */ +#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */ +#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */ +#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */ +#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */ +#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */ +#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */ + + +/* XM_TX_CMD 16 bit r/w Transmit Command Register */ + /* Bit 15..7: reserved */ +#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ +#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */ +#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */ +#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */ +#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */ +#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */ +#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */ + + +/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ + /* Bit 15..5: reserved */ +#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ + + +/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ + /* Bit 15..7: reserved */ +#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ + + +/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ + /* Bit 15..8: reserved */ +#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ + + +/* XM_RX_CMD 16 bit r/w Receive Command Register */ + /* Bit 15..9: reserved */ +#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */ + /* inrange error packets */ +#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */ + /* jumbo packets */ +#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */ +#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */ +#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */ +#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */ +#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */ +#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */ +#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */ + + +/* XM_PHY_ADDR 16 bit r/w PHY Address Register */ + /* Bit 15..5: reserved */ +#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */ + + +/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ + /* Bit 31..7: reserved */ +#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */ +#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */ + /* Bit 4: reserved */ +#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */ +#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */ + /* Bit 1: reserved */ +#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */ + + +/* XM_IMSK 16 bit r/w Interrupt Mask Register */ +/* XM_ISRC 16 bit r/o Interrupt Status Register */ + /* Bit 15: reserved */ +#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */ +#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */ +#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */ +#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */ +#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */ +#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */ +#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */ +#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */ +#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */ +#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */ +#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */ +#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */ +#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */ +#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */ +#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */ + +#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\ + XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR)) + + +/* XM_HW_CFG 16 bit r/w Hardware Config Register */ + /* Bit 15.. 4: reserved */ +#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */ +#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/ + /* Bit 1: reserved */ +#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */ + + +/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ +/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ + /* Bit 15..10 reserved */ +#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ + +/* XM_TX_THR 16 bit r/w Tx Request Threshold */ +/* XM_HT_THR 16 bit r/w Host Request Threshold */ +/* XM_RX_THR 16 bit r/w Rx Request Threshold */ + /* Bit 15..11 reserved */ +#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ + + +/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ +#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */ +#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */ +#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */ +#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */ +#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */ +#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/ +#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */ +#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */ +#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */ +#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */ +#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */ +#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */ +#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */ +#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */ +#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */ + +/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ +/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ + /* Bit 15..11: reserved */ +#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ + + +/* XM_DEV_ID 32 bit r/o Device ID Register */ +#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ +#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ + + +/* XM_MODE 32 bit r/w Mode Register */ + /* Bit 31..27: reserved */ +#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */ +#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */ + /* extern generated */ +#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */ +#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */ + /* intern generated */ +#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */ +#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */ +#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */ +#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */ +#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */ + /* intern generated */ +#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */ + /* intern generated */ +#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */ +#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */ +#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */ +#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */ +#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */ +#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */ +#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */ +#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */ +#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */ +#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */ +#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */ +#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */ +#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */ +#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */ +#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */ +#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */ +#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */ + +#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) +#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ + XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA) + +/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ + /* Bit 16..6: reserved */ +#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */ +#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */ +#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ +#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */ +#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */ +#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ + + +/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ +/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ +#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ +#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/ +#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/ +#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/ +#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */ +#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */ +#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */ +#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */ +#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */ + /* Bit 22: reserved */ +#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */ +#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/ +#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */ +#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/ +#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */ + /* Bit 16: reserved */ +#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */ +#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */ +#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ +#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */ +#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */ +#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */ +#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/ +#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */ +#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ +#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ +#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/ +#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */ +#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */ +#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/ +#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/ +#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */ + +#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) + +/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ +/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ + /* Bit 31..26: reserved */ +#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ +#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/ +#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/ +#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/ +#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */ +#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */ +#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */ +#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */ +#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/ +#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ +#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */ +#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */ +#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */ +#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/ +#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */ +#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */ +#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/ +#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ +#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */ +#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */ +#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */ +#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */ +#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */ +#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/ +#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/ +#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */ + +#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) + +/* + * Receive Frame Status Encoding + */ +#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ +#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/ +#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/ +#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */ +#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */ +#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */ + /* Bit 12: reserved */ +#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */ +#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */ +#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */ +#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */ +#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */ +#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */ +#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */ +#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */ +#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */ +#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */ +#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */ +#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */ + +/* + * XMR_FS_ERR will be set if + * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, + * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR + * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue + * XMR_FS_ERR unless the corresponding bit in the Receive Command + * Register is set. + */ +#define XMR_FS_ANY_ERR XMR_FS_ERR + +/*----------------------------------------------------------------------------*/ +/* + * XMAC-PHY Registers, indirect addressed over the XMAC + */ +#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */ +#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */ +#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ +#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ +#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ +#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ +#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ +#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ +#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ + /* 0x09 - 0x0e: reserved */ +#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ +#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ + +/*----------------------------------------------------------------------------*/ +/* + * Broadcom-PHY Registers, indirect addressed over XMAC + */ +#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */ +#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */ +#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ +#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ +#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ +#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ +#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ +#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ + /* Broadcom-specific registers */ +#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ +#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ + /* 0x0b - 0x0e: reserved */ +#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ +#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ +#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ +#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ +#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carr Sense Cnt */ +#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ + /* 0x15 - 0x17: reserved */ +#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ +#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */ +#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */ +#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */ + /* 0x1c: reserved */ + /* 0x1d - 0x1f: test registers */ + +/*----------------------------------------------------------------------------*/ +/* + * Marvel-PHY Registers, indirect addressed over GMAC + */ +#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */ +#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */ +#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ +#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ +#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ +#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ +#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ +#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ + /* Marvel-specific registers */ +#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ +#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ + /* 0x0b - 0x0e: reserved */ +#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ +#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */ +#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */ +#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */ +#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ +#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */ +#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */ +#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */ + /* 0x17: reserved */ +#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */ +#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */ +#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */ +#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */ +#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */ + /* 0x1d - 0x1f: reserved */ + +/*----------------------------------------------------------------------------*/ +/* + * Level One-PHY Registers, indirect addressed over XMAC + */ +#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */ +#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */ +#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ +#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ +#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ +#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ +#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ +#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner*/ + /* Level One-specific registers */ +#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ +#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ + /* 0x0b -0x0e: reserved */ +#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ +#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/ +#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */ +#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */ +#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ +#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */ +#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */ +#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */ + /* 0x17 -0x1c: reserved */ + +/*----------------------------------------------------------------------------*/ +/* + * National-PHY Registers, indirect addressed over XMAC + */ +#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */ +#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */ +#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ +#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ +#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ +#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ +#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ +#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */ +#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */ + /* National-specific registers */ +#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ +#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ + /* 0x0b -0x0e: reserved */ +#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */ +#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */ +#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */ +#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */ +#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */ +#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */ + /* 0x15 -0x18: reserved */ +#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */ + + +/*----------------------------------------------------------------------------*/ + +/* + * PHY bit definitions + * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are + * Xmac/Broadcom/LevelOne/National-specific. + * All other are general. + */ + +/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ +/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ +/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ +#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ +#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ +#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */ +#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */ +#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */ +#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */ +#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ +#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */ +#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */ +#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */ + /* Bit 5..0: reserved */ + +#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */ +#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */ +#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */ + + +/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/ +/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/ +/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/ +/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/ + /* Bit 15..9: reserved */ + /* (BC/L1) 100/10 Mbps cap bits ignored*/ +#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */ + /* Bit 7: reserved */ +#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */ +#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */ +#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */ +#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */ +#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */ +#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */ +#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */ + + +/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ +#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */ +#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */ +#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */ + +/* different Broadcom PHY Ids */ +#define PHY_BCOM_ID1_A1 0x6041 +#define PHY_BCOM_ID1_B2 0x6043 +#define PHY_BCOM_ID1_C0 0x6044 +#define PHY_BCOM_ID1_C5 0x6047 + + +/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */ +#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ +#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */ + /* Bit 11.. 9: reserved */ +#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */ +#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */ +#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */ + /* Bit 4.. 0: reserved */ + +/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ + /* Bit 14: reserved */ +#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */ + /* Bit 12: reserved */ +#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ +#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */ + /* Bit 9..5: 100/10 BT cap bits ingnored */ +#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ + +/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ + /* Bit 14: reserved */ +#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */ + /* Bit 12: reserved */ +#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ +#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */ + /* Bit 9..5: 100/10 BT cap bits ingnored */ +#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ + +/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ + /* Bit 14: reserved */ +#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */ + /* Bit 12: reserved */ +#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */ +#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */ + /* Bit 9..5: 100/10 BT cap bits ingnored */ +#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ + +/* field type definition for PHY_x_AN_SEL */ +#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */ + +/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ + /* Bit 15..4: reserved */ +#define PHY_AN_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ +#define PHY_AN_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ +#define PHY_AN_RX_PG (1<<1) /* Bit 1: Page Received */ + /* Bit 0: reserved */ + +/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ + /* Bit 15..5: reserved */ +#define PHY_B_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ +/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ +/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ +/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ +#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ + +/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ +#define PHY_L_AN_BP (1<<5) /* Bit 5: Base Page Indication */ +#define PHY_L_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ +/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ +/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ +/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ +#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ + + +/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ +/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ +/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/ +/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/ +/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/ +/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/ +#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */ +#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack 1, for receiving a message*/ +#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */ +#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack 2, comply with msg content*/ +#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */ +#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */ + +/* + * XMAC-Specific + */ +/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ +#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */ +#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */ + /* Bit 13..0: reserved */ + +/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ + /* Bit 15..9: reserved */ +#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */ +#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ +#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ +#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ +#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability missmatch */ + /* Bit 2..0: reserved */ +/* + * Remote Fault Bits (PHY_X_AN_RFB) encoding + */ +#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */ +#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */ +#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */ +#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */ + +/* + * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding + */ +#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */ +#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */ +#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */ +#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */ + + +/* + * Broadcom-Specific + */ +/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ +#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ +#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ +#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ +#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ +#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ + /* Bit 7..0: reserved */ + +/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ +#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ +#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ +#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ +#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ +#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ + /* Bit 9..8: reserved */ +#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ + +/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ +#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ +#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ +#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ +#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ + /* Bit 11..0: reserved */ + +/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ +#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */ +#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */ +#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ +#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */ +#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */ +#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */ +#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */ +#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */ +#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */ +#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */ +#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */ +#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */ +#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */ +#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */ +#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */ +#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */ + +/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ + /* Bit 15..14: reserved */ +#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */ +#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */ +#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */ +#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */ +#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */ +#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */ +#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */ +#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */ +#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */ +#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */ +#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */ +#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */ +#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */ +#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */ + +/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ + /* Bit 15..8: reserved */ +#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */ + +/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ +#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */ +#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */ + +/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ +#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */ +#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */ +#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */ + /* Bit 11: reserved */ +#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */ + /* Bit 9.. 8: reserved */ +#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */ + /* Bit 6: reserved */ +#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */ + /* Bit 4: reserved */ +#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */ + /* Bit 2.. 0: reserved */ + +/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ +#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */ +#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */ +#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */ +#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */ +#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */ +#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */ +#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */ +#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */ +#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */ +#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */ +#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */ +#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */ +#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */ +#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */ + +#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) + +/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ +/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ + /* Bit 15: reserved */ +#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */ +#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */ +#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */ +#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */ +#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */ +#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */ +#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */ +#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */ +#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */ +#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */ +#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */ +#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */ +#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */ +#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */ +#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */ + +#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) + +/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ +#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ +#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ +#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ +#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ + +/* + * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) + */ +#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */ +#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */ +/* others: 100/10: invalid for us */ + +/* + * Level One-Specific + */ +/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ +#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ +#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ +#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ +#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ +#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ + /* Bit 7..0: reserved */ + +/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ +#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ +#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ +#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ +#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ +#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ + /* Bit 9..8: reserved */ +#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ + +/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/ +#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ +#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ +#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ +#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ + /* Bit 11..0: reserved */ + +/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/ +#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */ + /* Bit 14: reserved */ +#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ +#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */ +#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */ +#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */ +#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */ +#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */ +#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */ +#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */ +#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */ +#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */ +#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */ +#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */ +#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */ +#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */ + +/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/ +#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */ +#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */ +#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */ +#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */ +#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */ +#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */ +#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */ +#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */ +#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */ +#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */ +#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */ +#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */ +#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */ + +/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/ +/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/ + /* Bit 15..14: reserved */ +#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */ + /* Bit 12: not described */ +#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */ +#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used*/ +#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade*/ +#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */ +#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */ +#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */ +#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */ +#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */ +#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */ +#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */ +#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */ +#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */ + +/* int. mask */ +#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN) + +/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/ +#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */ +#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */ +#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */ +#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */ +#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */ +#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */ +#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */ +#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */ +#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */ + +/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/ +#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */ + /* Bit 14: reserved */ +#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */ +#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */ + /* Bit 11: reserved */ +#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/ + /* Bit 9..0: not described */ + +/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ +#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */ +#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */ + + +/* + * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding + */ +#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ +#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ +#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ +#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ + + +/* + * National-Specific + */ +/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ +#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ +#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ +#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ +#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ +#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ +#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */ + /* Bit 6..0: reserved */ + +/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ +#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ +#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ +#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ +#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ +#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ +#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */ + /* Bit 8: reserved */ +#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ + +/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/ +#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ +#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ +#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ +#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ + /* Bit 11..0: reserved */ + +/* todo: those are still missing */ +/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/ +/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/ +/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/ +/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/ +/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/ +/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/ + +/* + * Marvell-Specific + */ +/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ +/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/ +#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */ +#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */ +#define PHY_M_AN_RF BIT_13 /* Remote Fault */ + /* Bit 12: reserved */ +#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */ +#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */ +#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */ +#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */ +#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */ +#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */ + +/* special defines for FIBER (88E1011S only) */ +#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */ +#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */ +#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */ +#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */ + +/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ +#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */ +#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */ +#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */ +#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */ + +/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ +#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */ +#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */ +#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */ +#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ +#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ + /* Bit 7..0: reserved */ + +/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ + +#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ +#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ +#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ +#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */ +#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ +#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */ +#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ +#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */ +#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */ +#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */ +#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ +#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ + +#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) +#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ +#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ +#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */ + +/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ +#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ +#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */ +#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */ +#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ +#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */ +#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */ +#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */ +#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */ +#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */ +#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */ +#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */ +#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */ +#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */ +#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */ +#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */ +#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */ + +#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) + +/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ +/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/ +#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */ +#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */ +#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */ +#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */ +#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */ +#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */ +#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */ +#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */ +#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */ +#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */ +#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */ +#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */ + /* Bit 3..2: reserved */ +#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */ +#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */ + +#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \ + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) + +/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ +#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ +#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ +#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ + +#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ +#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ +#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */ + +#define MAC_TX_CLK_0_MHZ 2 +#define MAC_TX_CLK_2_5_MHZ 6 +#define MAC_TX_CLK_25_MHZ 7 + +/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ +#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */ +#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ +#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */ +#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ + /* Bit 7.. 5: reserved */ +#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ +#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */ +#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */ +#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */ + +#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */ + +#define PULS_NO_STR 0 /* no pulse stretching */ +#define PULS_21MS 1 /* 21 ms to 42 ms */ +#define PULS_42MS 2 /* 42 ms to 84 ms */ +#define PULS_84MS 3 /* 84 ms to 170 ms */ +#define PULS_170MS 4 /* 170 ms to 340 ms */ +#define PULS_340MS 5 /* 340 ms to 670 ms */ +#define PULS_670MS 6 /* 670 ms to 1.3 s */ +#define PULS_1300MS 7 /* 1.3 s to 2.7 s */ + +#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */ + +#define BLINK_42MS 0 /* 42 ms */ +#define BLINK_84MS 1 /* 84 ms */ +#define BLINK_170MS 2 /* 170 ms */ +#define BLINK_340MS 3 /* 340 ms */ +#define BLINK_670MS 4 /* 670 ms */ + /* values 5 - 7: reserved */ + +/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ +#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */ +#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */ +#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */ +#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */ +#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */ +#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */ + +#define MO_LED_NORM 0 +#define MO_LED_BLINK 1 +#define MO_LED_OFF 2 +#define MO_LED_ON 3 + +/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ + /* Bit 15.. 7: reserved */ +#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */ +#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */ +#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */ +#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ +#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ + +/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ +#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ +#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ + /* Bit 12.. 8: reserved */ +#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */ + +/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ +#define CABD_STAT_NORMAL 0 +#define CABD_STAT_SHORT 1 +#define CABD_STAT_OPEN 2 +#define CABD_STAT_FAIL 3 + + +/* + * GMAC registers + * + * The GMAC registers are 16 or 32 bits wide. + * The GMACs host processor interface is 16 bits wide, + * therefore ALL registers will be addressed with 16 bit accesses. + * + * The following macros are provided to access the GMAC registers + * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(), + * GM_INHASH(), and GM_OUTHASH(). + * The macros are defined in SkGeHw.h. + * + * Note: NA reg = Network Address e.g DA, SA etc. + * + */ + +/* Port Registers */ +#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */ +#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */ +#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */ +#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */ +#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow Control */ +#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */ +#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */ + +/* Source Address Registers */ +#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */ +#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */ +#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */ +#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */ +#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */ +#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */ + +/* Multicast Address Hash Registers */ +#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */ +#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */ +#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */ +#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */ + +/* Interrupt Source Registers */ +#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */ +#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */ +#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */ + +/* Interrupt Mask Registers */ +#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */ +#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */ +#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */ + +/* Serial Management Interface (SMI) Registers */ +#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */ +#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */ +#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */ + +/* MIB Counters */ +#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ +#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ + +/* + * MIB Counters base address definitions (low word) - + * use offset 4 for access to high word (32 bit r/o) + */ +#define GM_RXF_UC_OK \ + (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */ +#define GM_RXF_BC_OK \ + (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */ +#define GM_RXF_MPAUSE \ + (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */ +#define GM_RXF_MC_OK \ + (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */ +#define GM_RXF_FCS_ERR \ + (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */ + /* GM_MIB_CNT_BASE + 40: reserved */ +#define GM_RXO_OK_LO \ + (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */ +#define GM_RXO_OK_HI \ + (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */ +#define GM_RXO_ERR_LO \ + (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */ +#define GM_RXO_ERR_HI \ + (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */ +#define GM_RXF_SHT \ + (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ +#define GM_RXE_FRAG \ + (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Receeived with FCS Err */ +#define GM_RXF_64B \ + (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ +#define GM_RXF_127B \ + (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */ +#define GM_RXF_255B \ + (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */ +#define GM_RXF_511B \ + (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */ +#define GM_RXF_1023B \ + (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */ +#define GM_RXF_1518B \ + (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */ +#define GM_RXF_MAX_SZ \ + (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */ +#define GM_RXF_LNG_ERR \ + (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */ +#define GM_RXF_JAB_PKT \ + (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */ + /* GM_MIB_CNT_BASE + 168: reserved */ +#define GM_RXE_FIFO_OV \ + (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */ + /* GM_MIB_CNT_BASE + 184: reserved */ +#define GM_TXF_UC_OK \ + (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */ +#define GM_TXF_BC_OK \ + (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */ +#define GM_TXF_MPAUSE \ + (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */ +#define GM_TXF_MC_OK \ + (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */ +#define GM_TXO_OK_LO \ + (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */ +#define GM_TXO_OK_HI \ + (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */ +#define GM_TXF_64B \ + (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */ +#define GM_TXF_127B \ + (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */ +#define GM_TXF_255B \ + (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */ +#define GM_TXF_511B \ + (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */ +#define GM_TXF_1023B \ + (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */ +#define GM_TXF_1518B \ + (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */ +#define GM_TXF_MAX_SZ \ + (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */ + /* GM_MIB_CNT_BASE + 296: reserved */ +#define GM_TXF_COL \ + (GM_MIB_CNT_BASE + 304) /* Tx Collision */ +#define GM_TXF_LAT_COL \ + (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */ +#define GM_TXF_ABO_COL \ + (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */ +#define GM_TXF_MUL_COL \ + (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */ +#define GM_TXF_SNG_COL \ + (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */ +#define GM_TXE_FIFO_UR \ + (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */ + +/*----------------------------------------------------------------------------*/ +/* + * GMAC Bit Definitions + * + * If the bit access behaviour differs from the register access behaviour + * (r/w, r/o) this is documented after the bit number. + * The following bit access behaviours are used: + * (sc) self clearing + * (r/o) read only + */ + +/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ + +#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ +#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ +#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow Control Mode Disabled */ +#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */ +#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */ +#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */ +#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */ +#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */ + /* Bit 7..6: reserved */ +#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */ +#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ +#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */ +#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow Control Mode Disabled */ +#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */ + /* Bit 0: reserved */ + +/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ + /* Bit 15: reserved */ +#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */ +#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow Control Mode */ +#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */ +#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */ +#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */ +#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */ +#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */ +#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */ +#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */ +#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */ +#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow Control Mode */ +#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */ +#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update for Duplex */ +#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update for Flow-c. */ +#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update for Speed */ + +#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) +#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\ + GM_GPCR_AU_SPD_DIS) + +/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ + +#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ +#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ +#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ +#define GM_TXCR_COL_THR (4<<10) /* Bit 12..10: Collision Threshold */ + +/* GM_RX_CTRL 16 bit r/w Receive Control Register */ +#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ +#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */ +#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */ +#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */ + +/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ +#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */ +#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ +#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ + /* Bit 3..0: reserved */ +#define JAM_LEN_VAL(x) SHIFT14(x) +#define JAM_IPG_VAL(x) SHIFT9(x) +#define IPG_JAM_DATA(x) SHIFT4(x) + +/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ +#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder */ +#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive transmit trials */ +#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Length) */ +#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Length) */ + /* Bit 7..5: reserved */ +#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ + +#define DATA_BLIND_VAL(x) SHIFT11(x) +#define DATA_BLIND_FAST_ETH 0x1c +#define DATA_BLIND_GIGABIT 4 + +#define IPG_VAL_FAST_ETH 0x1e +#define IPG_VAL_GIGABIT 6 + +/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ + +#define GM_SMI_CT_PHY_AD(x) SHIFT11(x) +#define GM_SMI_CT_REG_AD(x) SHIFT6(x) +#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ +#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ +#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ + /* Bit 2..0: reserved */ + +/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ + /* Bit 15..6: reserved */ +#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ +#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ + /* Bit 3..0: reserved */ + +/* Receive Frame Status Encoding */ +#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ + /* Bit 15..14: reserved */ +#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */ +#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */ +#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */ +#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */ +#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */ +#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */ +#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */ +#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */ +#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */ +#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */ +#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */ + /* Bit 2: reserved */ +#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */ +#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */ + +/* + * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) + */ +#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \ + GMR_FS_LONG_ERR | \ + GMR_FS_MII_ERR | \ + GMR_FS_BAD_FC | \ + GMR_FS_GOOD_FC | \ + GMR_FS_JABBER) + +/* Rx GMAC FIFO Flush Mask (default) */ +#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \ + GMR_FS_RX_FF_OV | \ + GMR_FS_MII_ERR | \ + GMR_FS_BAD_FC | \ + GMR_FS_GOOD_FC | \ + GMR_FS_UN_SIZE | \ + GMR_FS_JABBER) + +/* typedefs *******************************************************************/ + + +/* function prototypes ********************************************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_XMAC_H */ diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c new file mode 100644 index 0000000000..ed79c049bb --- /dev/null +++ b/drivers/net/sk98lin/skaddr.c @@ -0,0 +1,1879 @@ +/****************************************************************************** + * + * Name: skaddr.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.48 $ + * Date: $Date: 2003/02/12 17:09:37 $ + * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skaddr.c,v $ + * Revision 1.48 2003/02/12 17:09:37 tschilli + * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses + * in case that both addresses are identical. + * + * Revision 1.47 2002/09/17 06:31:10 tschilli + * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate() + * and SkAddrGmacPromiscuousChange() fixed. + * Editorial changes. + * + * Revision 1.46 2002/08/22 07:55:41 tschilli + * New function SkGmacMcHash() for GMAC multicast hashing algorithm added. + * Editorial changes. + * + * Revision 1.45 2002/08/15 12:29:35 tschilli + * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed. + * + * Revision 1.44 2002/08/14 12:18:03 rschmidt + * Replaced direct handling of MAC Hashing (XMAC and GMAC) + * with routine SkMacHashing(). + * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode(). + * + * Revision 1.43 2002/08/13 09:37:43 rschmidt + * Corrected some SK_DBG_MSG outputs. + * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode(). + * Editorial changes. + * + * Revision 1.42 2002/08/12 11:24:36 rschmidt + * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit(). + * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC) + * with routine SkMacPromiscMode(). + * Editorial changes. + * + * Revision 1.41 2002/06/10 13:52:18 tschilli + * Changes for handling YUKON. + * All changes are internally and not visible to the programmer + * using this module. + * + * Revision 1.40 2001/02/14 14:04:59 rassmann + * Editorial changes. + * + * Revision 1.39 2001/01/30 10:30:04 rassmann + * Editorial changes. + * + * Revision 1.38 2001/01/25 16:26:52 rassmann + * Ensured that logical address overrides are done on net's active port. + * + * Revision 1.37 2001/01/22 13:41:34 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.36 2000/08/07 11:10:39 rassmann + * Editorial changes. + * + * Revision 1.35 2000/05/04 09:38:41 rassmann + * Editorial changes. + * Corrected multicast address hashing. + * + * Revision 1.34 1999/11/22 13:23:44 cgoos + * Changed license header to GPL. + * + * Revision 1.33 1999/05/28 10:56:06 rassmann + * Editorial changes. + * + * Revision 1.32 1999/03/31 10:59:20 rassmann + * Returning Success instead of DupAddr if address shall be overridden + * with same value. + * + * Revision 1.31 1999/01/14 16:18:17 rassmann + * Corrected multicast initialization. + * + * Revision 1.30 1999/01/04 10:30:35 rassmann + * SkAddrOverride only possible after SK_INIT_IO phase. + * + * Revision 1.29 1998/12/29 13:13:10 rassmann + * An address override is now preserved in the SK_INIT_IO phase. + * All functions return an int now. + * Extended parameter checking. + * + * Revision 1.28 1998/12/01 11:45:53 rassmann + * Code cleanup. + * + * Revision 1.27 1998/12/01 09:22:49 rassmann + * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT + * too often. + * + * Revision 1.26 1998/11/24 12:39:44 rassmann + * Reserved multicast entry for BPDU address. + * 13 multicast entries left for protocol. + * + * Revision 1.25 1998/11/17 16:54:23 rassmann + * Using exact match for up to 14 multicast addresses. + * Still receiving all multicasts if more addresses are added. + * + * Revision 1.24 1998/11/13 17:24:31 rassmann + * Changed return value of SkAddrOverride to int. + * + * Revision 1.23 1998/11/13 16:56:18 rassmann + * Added macro SK_ADDR_COMPARE. + * Changed return type of SkAddrOverride to SK_BOOL. + * + * Revision 1.22 1998/11/04 17:06:17 rassmann + * Corrected McUpdate and PromiscuousChange functions. + * + * Revision 1.21 1998/10/29 14:34:04 rassmann + * Clearing SK_ADDR struct at startup. + * + * Revision 1.20 1998/10/28 18:16:34 rassmann + * Avoiding I/Os before SK_INIT_RUN level. + * Aligning InexactFilter. + * + * Revision 1.19 1998/10/28 11:29:28 rassmann + * Programming physical address in SkAddrMcUpdate. + * Corrected programming of exact match entries. + * + * Revision 1.18 1998/10/28 10:34:48 rassmann + * Corrected reading of physical addresses. + * + * Revision 1.17 1998/10/28 10:26:13 rassmann + * Getting ports' current MAC addresses from EPROM now. + * Added debug output. + * + * Revision 1.16 1998/10/27 16:20:12 rassmann + * Reading MAC address byte by byte. + * + * Revision 1.15 1998/10/22 11:39:09 rassmann + * Corrected signed/unsigned mismatches. + * + * Revision 1.14 1998/10/19 17:12:35 rassmann + * Syntax corrections. + * + * Revision 1.13 1998/10/19 17:02:19 rassmann + * Now reading permanent MAC addresses from CRF. + * + * Revision 1.12 1998/10/15 15:15:48 rassmann + * Changed Flags Parameters from SK_U8 to int. + * Checked with lint. + * + * Revision 1.11 1998/09/24 19:15:12 rassmann + * Code cleanup. + * + * Revision 1.10 1998/09/18 20:18:54 rassmann + * Added HW access. + * Implemented swapping. + * + * Revision 1.9 1998/09/16 11:32:00 rassmann + * Including skdrv1st.h again. :( + * + * Revision 1.8 1998/09/16 11:09:34 rassmann + * Syntax corrections. + * + * Revision 1.7 1998/09/14 17:06:34 rassmann + * Minor changes. + * + * Revision 1.6 1998/09/07 08:45:41 rassmann + * Syntax corrections. + * + * Revision 1.5 1998/09/04 19:40:19 rassmann + * Interface enhancements. + * + * Revision 1.4 1998/09/04 12:14:12 rassmann + * Interface cleanup. + * + * Revision 1.3 1998/09/02 16:56:40 rassmann + * Updated interface. + * + * Revision 1.2 1998/08/27 14:26:09 rassmann + * Updated interface. + * + * Revision 1.1 1998/08/21 08:30:22 rassmann + * First public version. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This module is intended to manage multicast addresses, address override, + * and promiscuous mode on GEnesis and Yukon adapters. + * + * Address Layout: + * port address: physical MAC address + * 1st exact match: logical MAC address (GEnesis only) + * 2nd exact match: RLMT multicast (GEnesis only) + * exact match 3-13: OS-specific multicasts (GEnesis only) + * + * Include File Hierarchy: + * + * "skdrv1st.h" + * "skdrv2nd.h" + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#ifndef lint +static const char SysKonnectFileId[] = + "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect."; +#endif /* !defined(lint) */ + +#define __SKADDR_C + +#ifdef __cplusplus +#error C++ is not yet supported. +extern "C" { +#endif /* cplusplus */ + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/* defines ********************************************************************/ + + +#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ +#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */ +#define HASH_BITS 6 /* #bits in hash */ +#define SK_MC_BIT 0x01 + +/* Error numbers and messages. */ + +#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0) +#define SKERR_ADDR_E001MSG "Bad Flags." +#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1) +#define SKERR_ADDR_E002MSG "New Error." + +/* typedefs *******************************************************************/ + +/* None. */ + +/* global variables ***********************************************************/ + +/* 64-bit hash values with all bits set. */ + +SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; + +/* local variables ************************************************************/ + +#ifdef DEBUG +static int Next0[SK_MAX_MACS] = {0, 0}; +#endif /* DEBUG */ + +/* functions ******************************************************************/ + +/****************************************************************************** + * + * SkAddrInit - initialize data, set state to init + * + * Description: + * + * SK_INIT_DATA + * ============ + * + * This routine clears the multicast tables and resets promiscuous mode. + * Some entries are reserved for the "logical MAC address", the + * SK-RLMT multicast address, and the BPDU multicast address. + * + * + * SK_INIT_IO + * ========== + * + * All permanent MAC addresses are read from EPROM. + * If the current MAC addresses are not already set in software, + * they are set to the values of the permanent addresses. + * The current addresses are written to the corresponding MAC. + * + * + * SK_INIT_RUN + * =========== + * + * Nothing. + * + * Context: + * init, pageable + * + * Returns: + * SK_ADDR_SUCCESS + */ +int SkAddrInit( +SK_AC *pAC, /* the adapter context */ +SK_IOC IoC, /* I/O context */ +int Level) /* initialization level */ +{ + int j; + SK_U32 i; + SK_U8 *InAddr; + SK_U16 *OutAddr; + SK_ADDR_PORT *pAPort; + + switch (Level) { + case SK_INIT_DATA: + SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR)); + + for (i = 0; i < SK_MAX_MACS; i++) { + pAPort = &pAC->Addr.Port[i]; + pAPort->PromMode = SK_PROM_MODE_NONE; + + pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; + pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; + pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; + pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; + } +#ifdef xDEBUG + for (i = 0; i < SK_MAX_MACS; i++) { + if (pAC->Addr.Port[i].NextExactMatchRlmt < + SK_ADDR_FIRST_MATCH_RLMT) { + Next0[i] |= 4; + } + } +#endif /* DEBUG */ + /* pAC->Addr.InitDone = SK_INIT_DATA; */ + break; + + case SK_INIT_IO: + for (i = 0; i < SK_MAX_NETS; i++) { + pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort; + } +#ifdef xDEBUG + for (i = 0; i < SK_MAX_MACS; i++) { + if (pAC->Addr.Port[i].NextExactMatchRlmt < + SK_ADDR_FIRST_MATCH_RLMT) { + Next0[i] |= 8; + } + } +#endif /* DEBUG */ + + /* Read permanent logical MAC address from Control Register File. */ + for (j = 0; j < SK_MAC_ADDR_LEN; j++) { + InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j]; + SK_IN8(IoC, B2_MAC_1 + j, InAddr); + } + + if (!pAC->Addr.Net[0].CurrentMacAddressSet) { + /* Set the current logical MAC address to the permanent one. */ + pAC->Addr.Net[0].CurrentMacAddress = + pAC->Addr.Net[0].PermanentMacAddress; + pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE; + } + + /* Set the current logical MAC address. */ + pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] = + pAC->Addr.Net[0].CurrentMacAddress; +#if SK_MAX_NETS > 1 + /* Set logical MAC address for net 2 to (log | 3). */ + if (!pAC->Addr.Net[1].CurrentMacAddressSet) { + pAC->Addr.Net[1].PermanentMacAddress = + pAC->Addr.Net[0].PermanentMacAddress; + pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3; + /* Set the current logical MAC address to the permanent one. */ + pAC->Addr.Net[1].CurrentMacAddress = + pAC->Addr.Net[1].PermanentMacAddress; + pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE; + } +#endif /* SK_MAX_NETS > 1 */ + +#ifdef DEBUG + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, + ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", + i, + pAC->Addr.Net[i].PermanentMacAddress.a[0], + pAC->Addr.Net[i].PermanentMacAddress.a[1], + pAC->Addr.Net[i].PermanentMacAddress.a[2], + pAC->Addr.Net[i].PermanentMacAddress.a[3], + pAC->Addr.Net[i].PermanentMacAddress.a[4], + pAC->Addr.Net[i].PermanentMacAddress.a[5])) + + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, + ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", + i, + pAC->Addr.Net[i].CurrentMacAddress.a[0], + pAC->Addr.Net[i].CurrentMacAddress.a[1], + pAC->Addr.Net[i].CurrentMacAddress.a[2], + pAC->Addr.Net[i].CurrentMacAddress.a[3], + pAC->Addr.Net[i].CurrentMacAddress.a[4], + pAC->Addr.Net[i].CurrentMacAddress.a[5])) + } +#endif /* DEBUG */ + + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + pAPort = &pAC->Addr.Port[i]; + + /* Read permanent port addresses from Control Register File. */ + for (j = 0; j < SK_MAC_ADDR_LEN; j++) { + InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j]; + SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr); + } + + if (!pAPort->CurrentMacAddressSet) { + /* + * Set the current and previous physical MAC address + * of this port to its permanent MAC address. + */ + pAPort->CurrentMacAddress = pAPort->PermanentMacAddress; + pAPort->PreviousMacAddress = pAPort->PermanentMacAddress; + pAPort->CurrentMacAddressSet = SK_TRUE; + } + + /* Set port's current physical MAC address. */ + OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + XM_OUTADDR(IoC, i, XM_SA, OutAddr); + } + else { + GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr); + } +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, + ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAPort->PermanentMacAddress.a[0], + pAPort->PermanentMacAddress.a[1], + pAPort->PermanentMacAddress.a[2], + pAPort->PermanentMacAddress.a[3], + pAPort->PermanentMacAddress.a[4], + pAPort->PermanentMacAddress.a[5])) + + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, + ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAPort->CurrentMacAddress.a[0], + pAPort->CurrentMacAddress.a[1], + pAPort->CurrentMacAddress.a[2], + pAPort->CurrentMacAddress.a[3], + pAPort->CurrentMacAddress.a[4], + pAPort->CurrentMacAddress.a[5])) +#endif /* DEBUG */ + } + /* pAC->Addr.InitDone = SK_INIT_IO; */ + break; + + case SK_INIT_RUN: +#ifdef xDEBUG + for (i = 0; i < SK_MAX_MACS; i++) { + if (pAC->Addr.Port[i].NextExactMatchRlmt < + SK_ADDR_FIRST_MATCH_RLMT) { + Next0[i] |= 16; + } + } +#endif /* DEBUG */ + + /* pAC->Addr.InitDone = SK_INIT_RUN; */ + break; + + default: /* error */ + break; + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrInit */ + + +/****************************************************************************** + * + * SkAddrMcClear - clear the multicast table + * + * Description: + * This routine clears the multicast table. + * + * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated + * immediately. + * + * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according + * to the adapter in use. The real work is done there. + * + * Context: + * runtime, pageable + * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY + * may be called after SK_INIT_IO without limitation + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrMcClear( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Index of affected port */ +int Flags) /* permanent/non-perm, sw-only */ +{ + int ReturnCode; + + if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags); + } + else { + ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags); + } + + return (ReturnCode); + +} /* SkAddrMcClear */ + + +/****************************************************************************** + * + * SkAddrXmacMcClear - clear the multicast table + * + * Description: + * This routine clears the multicast table + * (either entry 2 or entries 3-16 and InexactFilter) of the given port. + * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated + * immediately. + * + * Context: + * runtime, pageable + * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY + * may be called after SK_INIT_IO without limitation + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrXmacMcClear( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Index of affected port */ +int Flags) /* permanent/non-perm, sw-only */ +{ + int i; + + if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ + + /* Clear RLMT multicast addresses. */ + pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; + } + else { /* not permanent => DRV */ + + /* Clear InexactFilter */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; + } + + /* Clear DRV multicast addresses. */ + + pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; + } + + if (!(Flags & SK_MC_SW_ONLY)) { + (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber); + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrXmacMcClear */ + + +/****************************************************************************** + * + * SkAddrGmacMcClear - clear the multicast table + * + * Description: + * This routine clears the multicast hashing table (InexactFilter) + * (either the RLMT or the driver bits) of the given port. + * + * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated + * immediately. + * + * Context: + * runtime, pageable + * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY + * may be called after SK_INIT_IO without limitation + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrGmacMcClear( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Index of affected port */ +int Flags) /* permanent/non-perm, sw-only */ +{ + int i; + +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) +#endif /* DEBUG */ + + /* Clear InexactFilter */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; + } + + if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ + + /* Copy DRV bits to InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; + + /* Clear InexactRlmtFilter. */ + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0; + + } + } + else { /* not permanent => DRV */ + + /* Copy RLMT bits to InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; + + /* Clear InexactDrvFilter. */ + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0; + } + } + +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) +#endif /* DEBUG */ + + if (!(Flags & SK_MC_SW_ONLY)) { + (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber); + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrGmacMcClear */ + +#ifndef SK_ADDR_CHEAT + +/****************************************************************************** + * + * SkXmacMcHash - hash multicast address + * + * Description: + * This routine computes the hash value for a multicast address. + * A CRC32 algorithm is used. + * + * Notes: + * The code was adapted from the XaQti data sheet. + * + * Context: + * runtime, pageable + * + * Returns: + * Hash value of multicast address. + */ +SK_U32 SkXmacMcHash( +unsigned char *pMc) /* Multicast address */ +{ + SK_U32 Idx; + SK_U32 Bit; + SK_U32 Data; + SK_U32 Crc; + + Crc = 0xFFFFFFFFUL; + for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) { + Data = *pMc++; + for (Bit = 0; Bit < 8; Bit++, Data >>= 1) { + Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0); + } + } + + return (Crc & ((1 << HASH_BITS) - 1)); + +} /* SkXmacMcHash */ + + +/****************************************************************************** + * + * SkGmacMcHash - hash multicast address + * + * Description: + * This routine computes the hash value for a multicast address. + * A CRC16 algorithm is used. + * + * Notes: + * + * + * Context: + * runtime, pageable + * + * Returns: + * Hash value of multicast address. + */ +SK_U32 SkGmacMcHash( +unsigned char *pMc) /* Multicast address */ +{ + SK_U32 Data; + SK_U32 TmpData; + SK_U32 Crc; + int Byte; + int Bit; + + Crc = 0xFFFFFFFFUL; + for (Byte = 0; Byte < 6; Byte++) { + /* Get next byte. */ + Data = (SK_U32) pMc[Byte]; + + /* Change bit order in byte. */ + TmpData = Data; + for (Bit = 0; Bit < 8; Bit++) { + if (TmpData & 1L) { + Data |= 1L << (7 - Bit); + } + else { + Data &= ~(1L << (7 - Bit)); + } + TmpData >>= 1; + } + + Crc ^= (Data << 24); + for (Bit = 0; Bit < 8; Bit++) { + if (Crc & 0x80000000) { + Crc = (Crc << 1) ^ GMAC_POLY; + } + else { + Crc <<= 1; + } + } + } + + return (Crc & ((1 << HASH_BITS) - 1)); + +} /* SkGmacMcHash */ + +#endif /* not SK_ADDR_CHEAT */ + +/****************************************************************************** + * + * SkAddrMcAdd - add a multicast address to a port + * + * Description: + * This routine enables reception for a given address on the given port. + * + * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the + * adapter in use. The real work is done there. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_DATA + * + * Returns: + * SK_MC_FILTERING_EXACT + * SK_MC_FILTERING_INEXACT + * SK_MC_ILLEGAL_ADDRESS + * SK_MC_ILLEGAL_PORT + * SK_MC_RLMT_OVERFLOW + */ +int SkAddrMcAdd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Port Number */ +SK_MAC_ADDR *pMc, /* multicast address to be added */ +int Flags) /* permanent/non-permanent */ +{ + int ReturnCode; + + if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); + } + else { + ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); + } + + return (ReturnCode); + +} /* SkAddrMcAdd */ + + +/****************************************************************************** + * + * SkAddrXmacMcAdd - add a multicast address to a port + * + * Description: + * This routine enables reception for a given address on the given port. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * The multicast bit is only checked if there are no free exact match + * entries. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_DATA + * + * Returns: + * SK_MC_FILTERING_EXACT + * SK_MC_FILTERING_INEXACT + * SK_MC_ILLEGAL_ADDRESS + * SK_MC_RLMT_OVERFLOW + */ +int SkAddrXmacMcAdd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Port Number */ +SK_MAC_ADDR *pMc, /* multicast address to be added */ +int Flags) /* permanent/non-permanent */ +{ + int i; + SK_U8 Inexact; +#ifndef SK_ADDR_CHEAT + SK_U32 HashBit; +#endif /* !defined(SK_ADDR_CHEAT) */ + + if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ +#ifdef xDEBUG + if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt < + SK_ADDR_FIRST_MATCH_RLMT) { + Next0[PortNumber] |= 1; + return (SK_MC_RLMT_OVERFLOW); + } +#endif /* DEBUG */ + + if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt > + SK_ADDR_LAST_MATCH_RLMT) { + return (SK_MC_RLMT_OVERFLOW); + } + + /* Set a RLMT multicast address. */ + + pAC->Addr.Port[PortNumber].Exact[ + pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc; + + return (SK_MC_FILTERING_EXACT); + } + +#ifdef xDEBUG + if (pAC->Addr.Port[PortNumber].NextExactMatchDrv < + SK_ADDR_FIRST_MATCH_DRV) { + Next0[PortNumber] |= 2; + return (SK_MC_RLMT_OVERFLOW); + } +#endif /* DEBUG */ + + if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { + + /* Set exact match entry. */ + pAC->Addr.Port[PortNumber].Exact[ + pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc; + + /* Clear InexactFilter */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; + } + } + else { + if (!(pMc->a[0] & SK_MC_BIT)) { + /* Hashing only possible with multicast addresses. */ + return (SK_MC_ILLEGAL_ADDRESS); + } +#ifndef SK_ADDR_CHEAT + /* Compute hash value of address. */ + HashBit = 63 - SkXmacMcHash(&pMc->a[0]); + + /* Add bit to InexactFilter. */ + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |= + 1 << (HashBit % 8); +#else /* SK_ADDR_CHEAT */ + /* Set all bits in InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; + } +#endif /* SK_ADDR_CHEAT */ + } + + for (Inexact = 0, i = 0; i < 8; i++) { + Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; + } + + if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) { + return (SK_MC_FILTERING_EXACT); + } + else { + return (SK_MC_FILTERING_INEXACT); + } + +} /* SkAddrXmacMcAdd */ + + +/****************************************************************************** + * + * SkAddrGmacMcAdd - add a multicast address to a port + * + * Description: + * This routine enables reception for a given address on the given port. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_DATA + * + * Returns: + * SK_MC_FILTERING_INEXACT + * SK_MC_ILLEGAL_ADDRESS + */ +int SkAddrGmacMcAdd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Port Number */ +SK_MAC_ADDR *pMc, /* multicast address to be added */ +int Flags) /* permanent/non-permanent */ +{ + int i; +#ifndef SK_ADDR_CHEAT + SK_U32 HashBit; +#endif /* !defined(SK_ADDR_CHEAT) */ + + if (!(pMc->a[0] & SK_MC_BIT)) { + /* Hashing only possible with multicast addresses. */ + return (SK_MC_ILLEGAL_ADDRESS); + } + +#ifndef SK_ADDR_CHEAT + + /* Compute hash value of address. */ + HashBit = SkGmacMcHash(&pMc->a[0]); + + if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ + + /* Add bit to InexactRlmtFilter. */ + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |= + 1 << (HashBit % 8); + + /* Copy bit to InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; + } +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6], + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])) +#endif /* DEBUG */ + } + else { /* not permanent => DRV */ + + /* Add bit to InexactDrvFilter. */ + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |= + 1 << (HashBit % 8); + + /* Copy bit to InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; + } +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6], + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])) +#endif /* DEBUG */ + } + +#else /* SK_ADDR_CHEAT */ + + /* Set all bits in InexactFilter. */ + for (i = 0; i < 8; i++) { + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; + } +#endif /* SK_ADDR_CHEAT */ + + return (SK_MC_FILTERING_INEXACT); + +} /* SkAddrGmacMcAdd */ + + +/****************************************************************************** + * + * SkAddrMcUpdate - update the HW MC address table and set the MAC address + * + * Description: + * This routine enables reception of the addresses contained in a local + * table for a given port. + * It also programs the port's current physical MAC address. + * + * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according + * to the adapter in use. The real work is done there. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_MC_FILTERING_EXACT + * SK_MC_FILTERING_INEXACT + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrMcUpdate( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber) /* Port Number */ +{ + int ReturnCode; + + if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber); + } + else { + ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber); + } + + return (ReturnCode); + +} /* SkAddrMcUpdate */ + + +/****************************************************************************** + * + * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address + * + * Description: + * This routine enables reception of the addresses contained in a local + * table for a given port. + * It also programs the port's current physical MAC address. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_MC_FILTERING_EXACT + * SK_MC_FILTERING_INEXACT + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrXmacMcUpdate( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber) /* Port Number */ +{ + SK_U32 i; + SK_U8 Inexact; + SK_U16 *OutAddr; + SK_ADDR_PORT *pAPort; + + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)) + + pAPort = &pAC->Addr.Port[PortNumber]; + +#ifdef DEBUG + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) +#endif /* DEBUG */ + + /* Start with 0 to also program the logical MAC address. */ + for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { + /* Set exact match address i on XMAC */ + OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; + XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); + } + + /* Clear other permanent exact match addresses on XMAC */ + if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) { + + SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt, + SK_ADDR_LAST_MATCH_RLMT); + } + + for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) { + OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; + XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); + } + + /* Clear other non-permanent exact match addresses on XMAC */ + if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { + + SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv, + SK_ADDR_LAST_MATCH_DRV); + } + + for (Inexact = 0, i = 0; i < 8; i++) { + Inexact |= pAPort->InexactFilter.Bytes[i]; + } + + if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { + + /* Set all bits in 64-bit hash register. */ + XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + else if (Inexact != 0) { + + /* Set 64-bit hash register to InexactFilter. */ + XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + else { + /* Disable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); + } + + if (pAPort->PromMode != SK_PROM_MODE_NONE) { + (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); + } + + /* Set port's current physical MAC address. */ + OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; + + XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); + +#ifdef xDEBUG + for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { + SK_U8 InAddr8[6]; + SK_U16 *InAddr; + + /* Get exact match address i from port PortNumber. */ + InAddr = (SK_U16 *) &InAddr8[0]; + + XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr); + + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrXmacMcUpdate: MC address %d on Port %u: ", + "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n", + i, + PortNumber, + InAddr8[0], + InAddr8[1], + InAddr8[2], + InAddr8[3], + InAddr8[4], + InAddr8[5], + pAPort->Exact[i].a[0], + pAPort->Exact[i].a[1], + pAPort->Exact[i].a[2], + pAPort->Exact[i].a[3], + pAPort->Exact[i].a[4], + pAPort->Exact[i].a[5])) + } +#endif /* DEBUG */ + + /* Determine return value. */ + if (Inexact == 0 && pAPort->PromMode == 0) { + return (SK_MC_FILTERING_EXACT); + } + else { + return (SK_MC_FILTERING_INEXACT); + } + +} /* SkAddrXmacMcUpdate */ + + +/****************************************************************************** + * + * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address + * + * Description: + * This routine enables reception of the addresses contained in a local + * table for a given port. + * It also programs the port's current physical MAC address. + * + * Notes: + * The return code is only valid for SK_PROM_MODE_NONE. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_MC_FILTERING_EXACT + * SK_MC_FILTERING_INEXACT + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrGmacMcUpdate( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber) /* Port Number */ +{ + SK_U32 i; + SK_U8 Inexact; + SK_U16 *OutAddr; + SK_ADDR_PORT *pAPort; + + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)) + + pAPort = &pAC->Addr.Port[PortNumber]; + +#ifdef DEBUG + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) +#endif /* DEBUG */ + + for (Inexact = 0, i = 0; i < 8; i++) { + Inexact |= pAPort->InexactFilter.Bytes[i]; + } + + /* Set 64-bit hash register to InexactFilter. */ + GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, + &pAPort->InexactFilter.Bytes[0]); + + if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { + + /* Set all bits in 64-bit hash register. */ + GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + else { + /* Enable Hashing. */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + + if (pAPort->PromMode != SK_PROM_MODE_NONE) { + (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); + } + + /* Set port's current physical MAC address. */ + OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; + GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); + + /* Set port's current logical MAC address. */ + OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0]; + GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr); + +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAPort->Exact[0].a[0], + pAPort->Exact[0].a[1], + pAPort->Exact[0].a[2], + pAPort->Exact[0].a[3], + pAPort->Exact[0].a[4], + pAPort->Exact[0].a[5])) + + SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAPort->CurrentMacAddress.a[0], + pAPort->CurrentMacAddress.a[1], + pAPort->CurrentMacAddress.a[2], + pAPort->CurrentMacAddress.a[3], + pAPort->CurrentMacAddress.a[4], + pAPort->CurrentMacAddress.a[5])) +#endif /* DEBUG */ + + /* Determine return value. */ + if (Inexact == 0 && pAPort->PromMode == 0) { + return (SK_MC_FILTERING_EXACT); + } + else { + return (SK_MC_FILTERING_INEXACT); + } + +} /* SkAddrGmacMcUpdate */ + + +/****************************************************************************** + * + * SkAddrOverride - override a port's MAC address + * + * Description: + * This routine overrides the MAC address of one port. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_ADDR_SUCCESS if successful. + * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address. + * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address. + * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before. + */ +int SkAddrOverride( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Port Number */ +SK_MAC_ADDR *pNewAddr, /* new MAC address */ +int Flags) /* logical/physical MAC address */ +{ + SK_EVPARA Para; + SK_U32 NetNumber; + SK_U32 i; + SK_U16 *OutAddr; + + NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber; + + if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) { + return (SK_ADDR_MULTICAST_ADDRESS); + } + + if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) { + return (SK_ADDR_TOO_EARLY); + } + + if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */ + /* Parameter *pNewAddr is ignored. */ + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (!pAC->Addr.Port[i].CurrentMacAddressSet) { + return (SK_ADDR_TOO_EARLY); + } + } + + /* Set PortNumber to number of net's active port. */ + PortNumber = pAC->Rlmt.Net[NetNumber]. + Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; + + pAC->Addr.Port[PortNumber].Exact[0] = + pAC->Addr.Net[NetNumber].CurrentMacAddress; + + /* Write address to first exact match entry of active port. */ + (void) SkAddrMcUpdate(pAC, IoC, PortNumber); + } + else if (Flags & SK_ADDR_CLEAR_LOGICAL) { + /* Deactivate logical MAC address. */ + /* Parameter *pNewAddr is ignored. */ + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (!pAC->Addr.Port[i].CurrentMacAddressSet) { + return (SK_ADDR_TOO_EARLY); + } + } + + /* Set PortNumber to number of net's active port. */ + PortNumber = pAC->Rlmt.Net[NetNumber]. + Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; + + for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) { + pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0; + } + + /* Write address to first exact match entry of active port. */ + (void) SkAddrMcUpdate(pAC, IoC, PortNumber); + } + else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */ + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { + return (SK_ADDR_DUPLICATE_ADDRESS); + } + + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (!pAC->Addr.Port[i].CurrentMacAddressSet) { + return (SK_ADDR_TOO_EARLY); + } + + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Port[i].CurrentMacAddress.a)) { + if (i == PortNumber) { + return (SK_ADDR_SUCCESS); + } + else { + return (SK_ADDR_DUPLICATE_ADDRESS); + } + } + } + + pAC->Addr.Port[PortNumber].PreviousMacAddress = + pAC->Addr.Port[PortNumber].CurrentMacAddress; + pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; + + /* Change port's physical MAC address. */ + OutAddr = (SK_U16 *) pNewAddr; + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); + } + else { + GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); + } + + /* Report address change to RLMT. */ + Para.Para32[0] = PortNumber; + Para.Para32[0] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); + } + else { /* Logical MAC address. */ + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { + return (SK_ADDR_SUCCESS); + } + + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (!pAC->Addr.Port[i].CurrentMacAddressSet) { + return (SK_ADDR_TOO_EARLY); + } + + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Port[i].CurrentMacAddress.a)) { + return (SK_ADDR_DUPLICATE_ADDRESS); + } + } + + /* + * In case that the physical and the logical MAC addresses are equal + * we must also change the physical MAC address here. + * In this case we have an adapter which initially was programmed with + * two identical MAC addresses. + */ + if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a, + pAC->Addr.Port[PortNumber].Exact[0].a)) { + + pAC->Addr.Port[PortNumber].PreviousMacAddress = + pAC->Addr.Port[PortNumber].CurrentMacAddress; + pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; + + /* Report address change to RLMT. */ + Para.Para32[0] = PortNumber; + Para.Para32[0] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); + } + + /* Set PortNumber to number of net's active port. */ + PortNumber = pAC->Rlmt.Net[NetNumber]. + Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; + + pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr; + pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr; +#ifdef DEBUG + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0], + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1], + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2], + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3], + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4], + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])) + + SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, + ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n", + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0], + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1], + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2], + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3], + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4], + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])) +#endif /* DEBUG */ + + /* Write address to first exact match entry of active port. */ + (void) SkAddrMcUpdate(pAC, IoC, PortNumber); + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrOverride */ + + +/****************************************************************************** + * + * SkAddrPromiscuousChange - set promiscuous mode for given port + * + * Description: + * This routine manages promiscuous mode: + * - none + * - all LLC frames + * - all MC frames + * + * It calls either SkAddrXmacPromiscuousChange or + * SkAddrGmacPromiscuousChange, according to the adapter in use. + * The real work is done there. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrPromiscuousChange( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* port whose promiscuous mode changes */ +int NewPromMode) /* new promiscuous mode */ +{ + int ReturnCode; + + if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); + } + else { + ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); + } + + return (ReturnCode); + +} /* SkAddrPromiscuousChange */ + + +/****************************************************************************** + * + * SkAddrXmacPromiscuousChange - set promiscuous mode for given port + * + * Description: + * This routine manages promiscuous mode: + * - none + * - all LLC frames + * - all MC frames + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrXmacPromiscuousChange( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* port whose promiscuous mode changes */ +int NewPromMode) /* new promiscuous mode */ +{ + int i; + SK_BOOL InexactModeBit; + SK_U8 Inexact; + SK_U8 HwInexact; + SK_FILTER64 HwInexactFilter; + SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */ + int CurPromMode = SK_PROM_MODE_NONE; + + /* Read CurPromMode from Hardware. */ + XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); + + if ((LoMode & XM_MD_ENA_PROM) != 0) { + /* Promiscuous mode! */ + CurPromMode |= SK_PROM_MODE_LLC; + } + + for (Inexact = 0xFF, i = 0; i < 8; i++) { + Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; + } + if (Inexact == 0xFF) { + CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); + } + else { + /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */ + XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); + + InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0; + + /* Read 64-bit hash register from XMAC */ + XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]); + + for (HwInexact = 0xFF, i = 0; i < 8; i++) { + HwInexact &= HwInexactFilter.Bytes[i]; + } + + if (InexactModeBit && (HwInexact == 0xFF)) { + CurPromMode |= SK_PROM_MODE_ALL_MC; + } + } + + pAC->Addr.Port[PortNumber].PromMode = NewPromMode; + + if (NewPromMode == CurPromMode) { + return (SK_ADDR_SUCCESS); + } + + if ((NewPromMode & SK_PROM_MODE_ALL_MC) && + !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */ + + /* Set all bits in 64-bit hash register. */ + XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + else if ((CurPromMode & SK_PROM_MODE_ALL_MC) && + !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */ + for (Inexact = 0, i = 0; i < 8; i++) { + Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; + } + if (Inexact == 0) { + /* Disable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); + } + else { + /* Set 64-bit hash register to InexactFilter. */ + XM_OUTHASH(IoC, PortNumber, XM_HSM, + &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + } + + if ((NewPromMode & SK_PROM_MODE_LLC) && + !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ + /* Set the MAC in Promiscuous Mode */ + SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); + } + else if ((CurPromMode & SK_PROM_MODE_LLC) && + !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */ + /* Clear Promiscuous Mode */ + SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrXmacPromiscuousChange */ + + +/****************************************************************************** + * + * SkAddrGmacPromiscuousChange - set promiscuous mode for given port + * + * Description: + * This routine manages promiscuous mode: + * - none + * - all LLC frames + * - all MC frames + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrGmacPromiscuousChange( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* port whose promiscuous mode changes */ +int NewPromMode) /* new promiscuous mode */ +{ + SK_U16 ReceiveControl; /* GMAC Receive Control Register */ + int CurPromMode = SK_PROM_MODE_NONE; + + /* Read CurPromMode from Hardware. */ + GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl); + + if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) { + /* Promiscuous mode! */ + CurPromMode |= SK_PROM_MODE_LLC; + } + + if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) { + /* All Multicast mode! */ + CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); + } + + pAC->Addr.Port[PortNumber].PromMode = NewPromMode; + + if (NewPromMode == CurPromMode) { + return (SK_ADDR_SUCCESS); + } + + if ((NewPromMode & SK_PROM_MODE_ALL_MC) && + !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */ + + /* Set all bits in 64-bit hash register. */ + GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + + if ((CurPromMode & SK_PROM_MODE_ALL_MC) && + !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */ + + /* Set 64-bit hash register to InexactFilter. */ + GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, + &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); + + /* Enable Hashing. */ + SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + } + + if ((NewPromMode & SK_PROM_MODE_LLC) && + !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ + + /* Set the MAC to Promiscuous Mode. */ + SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); + } + else if ((CurPromMode & SK_PROM_MODE_LLC) && + !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */ + + /* Clear Promiscuous Mode. */ + SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); + } + + return (SK_ADDR_SUCCESS); + +} /* SkAddrGmacPromiscuousChange */ + + +/****************************************************************************** + * + * SkAddrSwap - swap address info + * + * Description: + * This routine swaps address info of two ports. + * + * Context: + * runtime, pageable + * may be called after SK_INIT_IO + * + * Returns: + * SK_ADDR_SUCCESS + * SK_ADDR_ILLEGAL_PORT + */ +int SkAddrSwap( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 FromPortNumber, /* Port1 Index */ +SK_U32 ToPortNumber) /* Port2 Index */ +{ + int i; + SK_U8 Byte; + SK_MAC_ADDR MacAddr; + SK_U32 DWord; + + if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { + return (SK_ADDR_ILLEGAL_PORT); + } + + if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) { + return (SK_ADDR_ILLEGAL_PORT); + } + + /* + * Swap: + * - Exact Match Entries (GEnesis and Yukon) + * Yukon uses first entry for the logical MAC + * address (stored in the second GMAC register). + * - FirstExactMatchRlmt (GEnesis only) + * - NextExactMatchRlmt (GEnesis only) + * - FirstExactMatchDrv (GEnesis only) + * - NextExactMatchDrv (GEnesis only) + * - 64-bit filter (InexactFilter) + * - Promiscuous Mode + * of ports. + */ + + for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) { + MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i]; + pAC->Addr.Port[FromPortNumber].Exact[i] = + pAC->Addr.Port[ToPortNumber].Exact[i]; + pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr; + } + + for (i = 0; i < 8; i++) { + Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i]; + pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] = + pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i]; + pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte; + } + + i = pAC->Addr.Port[FromPortNumber].PromMode; + pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode; + pAC->Addr.Port[ToPortNumber].PromMode = i; + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt; + pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt = + pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt; + pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord; + + DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt; + pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt = + pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt; + pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord; + + DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv; + pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv = + pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv; + pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord; + + DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv; + pAC->Addr.Port[FromPortNumber].NextExactMatchDrv = + pAC->Addr.Port[ToPortNumber].NextExactMatchDrv; + pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord; + } + + /* CAUTION: Solution works if only ports of one adapter are in use. */ + for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber]. + Net->NetNumber].NumPorts; i++) { + if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. + Port[i]->PortNumber == ToPortNumber) { + pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. + ActivePort = i; + /* 20001207 RA: Was "ToPortNumber;". */ + } + } + + (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber); + (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber); + + return (SK_ADDR_SUCCESS); + +} /* SkAddrSwap */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skcsum.c b/drivers/net/sk98lin/skcsum.c new file mode 100644 index 0000000000..a5dc572587 --- /dev/null +++ b/drivers/net/sk98lin/skcsum.c @@ -0,0 +1,929 @@ +/****************************************************************************** + * + * Name: skcsum.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.10 $ + * Date: $Date: 2002/04/11 10:02:04 $ + * Purpose: Store/verify Internet checksum in send/receive packets. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skcsum.c,v $ + * Revision 1.10 2002/04/11 10:02:04 rwahl + * Fix in SkCsGetSendInfo(): + * - function did not return ProtocolFlags in every case. + * - pseudo header csum calculated wrong for big endian. + * + * Revision 1.9 2001/06/13 07:42:08 gklug + * fix: NetNumber was wrong in CLEAR_STAT event + * add: check for good NetNumber in Clear STAT + * + * Revision 1.8 2001/02/06 11:15:36 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.7 2000/06/29 13:17:05 rassmann + * Corrected reception of a packet with UDP checksum == 0 (which means there + * is no UDP checksum). + * + * Revision 1.6 2000/02/21 12:35:10 cgoos + * Fixed license header comment. + * + * Revision 1.5 2000/02/21 11:05:19 cgoos + * Merged changes back to common source. + * Fixed rx path for BIG ENDIAN architecture. + * + * Revision 1.1 1999/07/26 15:28:12 mkarl + * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and + * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester + * changed from common source to windows specific source + * therefore restarting with v1.0 + * + * Revision 1.3 1999/05/10 08:39:33 mkarl + * prevent overflows in SKCS_HTON16 + * fixed a bug in pseudo header checksum calculation + * added some comments + * + * Revision 1.2 1998/10/22 11:53:28 swolf + * Now using SK_DBG_MSG. + * + * Revision 1.1 1998/09/01 15:35:41 swolf + * initial revision + * + * 13-May-1998 sw Created. + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#ifdef SK_USE_CSUM /* Check if CSUM is to be used. */ + +#ifndef lint +static const char SysKonnectFileId[] = "@(#)" + "$Id: skcsum.c,v 1.10 2002/04/11 10:02:04 rwahl Exp $" + " (C) SysKonnect."; +#endif /* !lint */ + +/****************************************************************************** + * + * Description: + * + * This is the "GEnesis" common module "CSUM". + * + * This module contains the code necessary to calculate, store, and verify the + * Internet Checksum of IP, TCP, and UDP frames. + * + * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" + * and is the code name of this SysKonnect project. + * + * Compilation Options: + * + * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an + * empty module. + * + * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id + * definitions. In this case, all SKCS_PROTO_xxx definitions must be made + * external. + * + * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status + * definitions. In this case, all SKCS_STATUS_xxx definitions must be made + * external. + * + * Include File Hierarchy: + * + * "h/skdrv1st.h" + * "h/skcsum.h" + * "h/sktypes.h" + * "h/skqueue.h" + * "h/skdrv2nd.h" + * + ******************************************************************************/ + +#include "h/skdrv1st.h" +#include "h/skcsum.h" +#include "h/skdrv2nd.h" + +/* defines ********************************************************************/ + +/* The size of an Ethernet MAC header. */ +#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2) + +/* The size of the used topology's MAC header. */ +#define SKCS_MAC_HEADER_SIZE SKCS_ETHERNET_MAC_HEADER_SIZE + +/* The size of the IP header without any option fields. */ +#define SKCS_IP_HEADER_SIZE 20 + +/* + * Field offsets within the IP header. + */ + +/* "Internet Header Version" and "Length". */ +#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH 0 + +/* "Total Length". */ +#define SKCS_OFS_IP_TOTAL_LENGTH 2 + +/* "Flags" "Fragment Offset". */ +#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET 6 + +/* "Next Level Protocol" identifier. */ +#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9 + +/* Source IP address. */ +#define SKCS_OFS_IP_SOURCE_ADDRESS 12 + +/* Destination IP address. */ +#define SKCS_OFS_IP_DESTINATION_ADDRESS 16 + + +/* + * Field offsets within the UDP header. + */ + +/* UDP checksum. */ +#define SKCS_OFS_UDP_CHECKSUM 6 + +/* IP "Next Level Protocol" identifiers (see RFC 790). */ +#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */ +#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */ + +/* IP "Don't Fragment" bit. */ +#define SKCS_IP_DONT_FRAGMENT SKCS_HTON16(0x4000) + +/* Add a byte offset to a pointer. */ +#define SKCS_IDX(pPtr, Ofs) ((void *) ((char *) (pPtr) + (Ofs))) + +/* + * Macros that convert host to network representation and vice versa, i.e. + * little/big endian conversion on little endian machines only. + */ +#ifdef SK_LITTLE_ENDIAN +#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xFF) << 8)) +#endif /* SK_LITTLE_ENDIAN */ +#ifdef SK_BIG_ENDIAN +#define SKCS_HTON16(Val16) (Val16) +#endif /* SK_BIG_ENDIAN */ +#define SKCS_NTOH16(Val16) SKCS_HTON16(Val16) + +/* typedefs *******************************************************************/ + +/* function prototypes ********************************************************/ + +/****************************************************************************** + * + * SkCsGetSendInfo - get checksum information for a send packet + * + * Description: + * Get all checksum information necessary to send a TCP or UDP packet. The + * function checks the IP header passed to it. If the high-level protocol + * is either TCP or UDP the pseudo header checksum is calculated and + * returned. + * + * The function returns the total length of the IP header (including any + * IP option fields), which is the same as the start offset of the IP data + * which in turn is the start offset of the TCP or UDP header. + * + * The function also returns the TCP or UDP pseudo header checksum, which + * should be used as the start value for the hardware checksum calculation. + * (Note that any actual pseudo header checksum can never calculate to + * zero.) + * + * Note: + * There is a bug in the ASIC which may lead to wrong checksums. + * + * Arguments: + * pAc - A pointer to the adapter context struct. + * + * pIpHeader - Pointer to IP header. Must be at least the IP header *not* + * including any option fields, i.e. at least 20 bytes. + * + * Note: This pointer will be used to address 8-, 16-, and 32-bit + * variables with the respective alignment offsets relative to the pointer. + * Thus, the pointer should point to a 32-bit aligned address. If the + * target system cannot address 32-bit variables on non 32-bit aligned + * addresses, then the pointer *must* point to a 32-bit aligned address. + * + * pPacketInfo - A pointer to the packet information structure for this + * packet. Before calling this SkCsGetSendInfo(), the following field must + * be initialized: + * + * ProtocolFlags - Initialize with any combination of + * SKCS_PROTO_XXX bit flags. SkCsGetSendInfo() will only work on + * the protocols specified here. Any protocol(s) not specified + * here will be ignored. + * + * Note: Only one checksum can be calculated in hardware. Thus, if + * SKCS_PROTO_IP is specified in the 'ProtocolFlags', + * SkCsGetSendInfo() must calculate the IP header checksum in + * software. It might be a better idea to have the calling + * protocol stack calculate the IP header checksum. + * + * Returns: N/A + * On return, the following fields in 'pPacketInfo' may or may not have + * been filled with information, depending on the protocol(s) found in the + * packet: + * + * ProtocolFlags - Returns the SKCS_PROTO_XXX bit flags of the protocol(s) + * that were both requested by the caller and actually found in the packet. + * Protocol(s) not specified by the caller and/or not found in the packet + * will have their respective SKCS_PROTO_XXX bit flags reset. + * + * Note: For IP fragments, TCP and UDP packet information is ignored. + * + * IpHeaderLength - The total length in bytes of the complete IP header + * including any option fields is returned here. This is the start offset + * of the IP data, i.e. the TCP or UDP header if present. + * + * IpHeaderChecksum - If IP has been specified in the 'ProtocolFlags', the + * 16-bit Internet Checksum of the IP header is returned here. This value + * is to be stored into the packet's 'IP Header Checksum' field. + * + * PseudoHeaderChecksum - If this is a TCP or UDP packet and if TCP or UDP + * has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum + * of the TCP or UDP pseudo header is returned here. + */ +#if 0 +void SkCsGetSendInfo( +SK_AC *pAc, /* Adapter context struct. */ +void *pIpHeader, /* IP header. */ +SKCS_PACKET_INFO *pPacketInfo, /* Packet information struct. */ +int NetNumber) /* Net number */ +{ + /* Internet Header Version found in IP header. */ + unsigned InternetHeaderVersion; + + /* Length of the IP header as found in IP header. */ + unsigned IpHeaderLength; + + /* Bit field specifiying the desired/found protocols. */ + unsigned ProtocolFlags; + + /* Next level protocol identifier found in IP header. */ + unsigned NextLevelProtocol; + + /* Length of IP data portion. */ + unsigned IpDataLength; + + /* TCP/UDP pseudo header checksum. */ + unsigned long PseudoHeaderChecksum; + + /* Pointer to next level protocol statistics structure. */ + SKCS_PROTO_STATS *NextLevelProtoStats; + + /* Temporary variable. */ + unsigned Tmp; + + Tmp = *(SK_U8 *) + SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH); + + /* Get the Internet Header Version (IHV). */ + /* Note: The IHV is stored in the upper four bits. */ + + InternetHeaderVersion = Tmp >> 4; + + /* Check the Internet Header Version. */ + /* Note: We currently only support IP version 4. */ + + if (InternetHeaderVersion != 4) { /* IPv4? */ + SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX, + ("Tx: Unknown Internet Header Version %u.\n", + InternetHeaderVersion)); + pPacketInfo->ProtocolFlags = 0; + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++; + return; + } + + /* Get the IP header length (IHL). */ + /* + * Note: The IHL is stored in the lower four bits as the number of + * 4-byte words. + */ + + IpHeaderLength = (Tmp & 0xf) * 4; + pPacketInfo->IpHeaderLength = IpHeaderLength; + + /* Check the IP header length. */ + + /* 04-Aug-1998 sw - Really check the IHL? Necessary? */ + + if (IpHeaderLength < 5*4) { + SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX, + ("Tx: Invalid IP Header Length %u.\n", IpHeaderLength)); + pPacketInfo->ProtocolFlags = 0; + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++; + return; + } + + /* This is an IPv4 frame with a header of valid length. */ + + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxOkCts++; + + /* Check if we should calculate the IP header checksum. */ + + ProtocolFlags = pPacketInfo->ProtocolFlags; + + if (ProtocolFlags & SKCS_PROTO_IP) { + pPacketInfo->IpHeaderChecksum = + SkCsCalculateChecksum(pIpHeader, IpHeaderLength); + } + + /* Get the next level protocol identifier. */ + + NextLevelProtocol = + *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL); + + /* + * Check if this is a TCP or UDP frame and if we should calculate the + * TCP/UDP pseudo header checksum. + * + * Also clear all protocol bit flags of protocols not present in the + * frame. + */ + + if ((ProtocolFlags & SKCS_PROTO_TCP) != 0 && + NextLevelProtocol == SKCS_PROTO_ID_TCP) { + /* TCP/IP frame. */ + ProtocolFlags &= SKCS_PROTO_TCP | SKCS_PROTO_IP; + NextLevelProtoStats = + &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP]; + } + else if ((ProtocolFlags & SKCS_PROTO_UDP) != 0 && + NextLevelProtocol == SKCS_PROTO_ID_UDP) { + /* UDP/IP frame. */ + ProtocolFlags &= SKCS_PROTO_UDP | SKCS_PROTO_IP; + NextLevelProtoStats = + &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP]; + } + else { + /* + * Either not a TCP or UDP frame and/or TCP/UDP processing not + * specified. + */ + pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP; + return; + } + + /* Check if this is an IP fragment. */ + + /* + * Note: An IP fragment has a non-zero "Fragment Offset" field and/or + * the "More Fragments" bit set. Thus, if both the "Fragment Offset" + * and the "More Fragments" are zero, it is *not* a fragment. We can + * easily check both at the same time since they are in the same 16-bit + * word. + */ + + if ((*(SK_U16 *) + SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) & + ~SKCS_IP_DONT_FRAGMENT) != 0) { + /* IP fragment; ignore all other protocols. */ + pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP; + NextLevelProtoStats->TxUnableCts++; + return; + } + + /* + * Calculate the TCP/UDP pseudo header checksum. + */ + + /* Get total length of IP header and data. */ + + IpDataLength = + *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH); + + /* Get length of IP data portion. */ + + IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength; + + /* Calculate the sum of all pseudo header fields (16-bit). */ + + PseudoHeaderChecksum = + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_SOURCE_ADDRESS + 0) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_SOURCE_ADDRESS + 2) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_DESTINATION_ADDRESS + 0) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_DESTINATION_ADDRESS + 2) + + (unsigned long) SKCS_HTON16(NextLevelProtocol) + + (unsigned long) SKCS_HTON16(IpDataLength); + + /* Add-in any carries. */ + + SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0); + + /* Add-in any new carry. */ + + SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0); + + pPacketInfo->ProtocolFlags = ProtocolFlags; + NextLevelProtoStats->TxOkCts++; /* Success. */ +} /* SkCsGetSendInfo */ + + +/****************************************************************************** + * + * SkCsGetReceiveInfo - verify checksum information for a received packet + * + * Description: + * Verify a received frame's checksum. The function returns a status code + * reflecting the result of the verification. + * + * Note: + * Before calling this function you have to verify that the frame is + * not padded and Checksum1 and Checksum2 are bigger than 1. + * + * Arguments: + * pAc - Pointer to adapter context struct. + * + * pIpHeader - Pointer to IP header. Must be at least the length in bytes + * of the received IP header including any option fields. For UDP packets, + * 8 additional bytes are needed to access the UDP checksum. + * + * Note: The actual length of the IP header is stored in the lower four + * bits of the first octet of the IP header as the number of 4-byte words, + * so it must be multiplied by four to get the length in bytes. Thus, the + * maximum IP header length is 15 * 4 = 60 bytes. + * + * Checksum1 - The first 16-bit Internet Checksum calculated by the + * hardware starting at the offset returned by SkCsSetReceiveFlags(). + * + * Checksum2 - The second 16-bit Internet Checksum calculated by the + * hardware starting at the offset returned by SkCsSetReceiveFlags(). + * + * Returns: + * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. + * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. + * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. + * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame + * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). + * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). + * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). + * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). + * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. + * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. + * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. + * + * Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values + * returned here can be defined in some header file by the module using CSUM. + * In this way, the calling module can assign return values for its own needs, + * e.g. by assigning bit flags to the individual protocols. + */ +SKCS_STATUS SkCsGetReceiveInfo( +SK_AC *pAc, /* Adapter context struct. */ +void *pIpHeader, /* IP header. */ +unsigned Checksum1, /* Hardware checksum 1. */ +unsigned Checksum2, /* Hardware checksum 2. */ +int NetNumber) /* Net number */ +{ + /* Internet Header Version found in IP header. */ + unsigned InternetHeaderVersion; + + /* Length of the IP header as found in IP header. */ + unsigned IpHeaderLength; + + /* Length of IP data portion. */ + unsigned IpDataLength; + + /* IP header checksum. */ + unsigned IpHeaderChecksum; + + /* IP header options checksum, if any. */ + unsigned IpOptionsChecksum; + + /* IP data checksum, i.e. TCP/UDP checksum. */ + unsigned IpDataChecksum; + + /* Next level protocol identifier found in IP header. */ + unsigned NextLevelProtocol; + + /* The checksum of the "next level protocol", i.e. TCP or UDP. */ + unsigned long NextLevelProtocolChecksum; + + /* Pointer to next level protocol statistics structure. */ + SKCS_PROTO_STATS *NextLevelProtoStats; + + /* Temporary variable. */ + unsigned Tmp; + + Tmp = *(SK_U8 *) + SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH); + + /* Get the Internet Header Version (IHV). */ + /* Note: The IHV is stored in the upper four bits. */ + + InternetHeaderVersion = Tmp >> 4; + + /* Check the Internet Header Version. */ + /* Note: We currently only support IP version 4. */ + + if (InternetHeaderVersion != 4) { /* IPv4? */ + SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX, + ("Rx: Unknown Internet Header Version %u.\n", + InternetHeaderVersion)); + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++; + return (SKCS_STATUS_UNKNOWN_IP_VERSION); + } + + /* Get the IP header length (IHL). */ + /* + * Note: The IHL is stored in the lower four bits as the number of + * 4-byte words. + */ + + IpHeaderLength = (Tmp & 0xf) * 4; + + /* Check the IP header length. */ + + /* 04-Aug-1998 sw - Really check the IHL? Necessary? */ + + if (IpHeaderLength < 5*4) { + SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX, + ("Rx: Invalid IP Header Length %u.\n", IpHeaderLength)); + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++; + return (SKCS_STATUS_IP_CSUM_ERROR); + } + + /* This is an IPv4 frame with a header of valid length. */ + + /* Get the IP header and data checksum. */ + + IpDataChecksum = Checksum2; + + /* + * The IP header checksum is calculated as follows: + * + * IpHeaderChecksum = Checksum1 - Checksum2 + */ + + SKCS_OC_SUB(IpHeaderChecksum, Checksum1, Checksum2); + + /* Check if any IP header options. */ + + if (IpHeaderLength > SKCS_IP_HEADER_SIZE) { + + /* Get the IP options checksum. */ + + IpOptionsChecksum = SkCsCalculateChecksum( + SKCS_IDX(pIpHeader, SKCS_IP_HEADER_SIZE), + IpHeaderLength - SKCS_IP_HEADER_SIZE); + + /* Adjust the IP header and IP data checksums. */ + + SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum); + + SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum); + } + + /* + * Check if the IP header checksum is ok. + * + * NOTE: We must check the IP header checksum even if the caller just wants + * us to check upper-layer checksums, because we cannot do any further + * processing of the packet without a valid IP checksum. + */ + + /* Get the next level protocol identifier. */ + + NextLevelProtocol = *(SK_U8 *) + SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL); + + if (IpHeaderChecksum != 0xFFFF) { + pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++; + /* the NDIS tester wants to know the upper level protocol too */ + if (NextLevelProtocol == SKCS_PROTO_ID_TCP) { + return(SKCS_STATUS_IP_CSUM_ERROR_TCP); + } + else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) { + return(SKCS_STATUS_IP_CSUM_ERROR_UDP); + } + return (SKCS_STATUS_IP_CSUM_ERROR); + } + + /* + * Check if this is a TCP or UDP frame and if we should calculate the + * TCP/UDP pseudo header checksum. + * + * Also clear all protocol bit flags of protocols not present in the + * frame. + */ + + if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCP) != 0 && + NextLevelProtocol == SKCS_PROTO_ID_TCP) { + /* TCP/IP frame. */ + NextLevelProtoStats = + &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP]; + } + else if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDP) != 0 && + NextLevelProtocol == SKCS_PROTO_ID_UDP) { + /* UDP/IP frame. */ + NextLevelProtoStats = + &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP]; + } + else { + /* + * Either not a TCP or UDP frame and/or TCP/UDP processing not + * specified. + */ + return (SKCS_STATUS_IP_CSUM_OK); + } + + /* Check if this is an IP fragment. */ + + /* + * Note: An IP fragment has a non-zero "Fragment Offset" field and/or + * the "More Fragments" bit set. Thus, if both the "Fragment Offset" + * and the "More Fragments" are zero, it is *not* a fragment. We can + * easily check both at the same time since they are in the same 16-bit + * word. + */ + + if ((*(SK_U16 *) + SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) & + ~SKCS_IP_DONT_FRAGMENT) != 0) { + /* IP fragment; ignore all other protocols. */ + NextLevelProtoStats->RxUnableCts++; + return (SKCS_STATUS_IP_FRAGMENT); + } + + /* + * 08-May-2000 ra + * + * From RFC 768 (UDP) + * If the computed checksum is zero, it is transmitted as all ones (the + * equivalent in one's complement arithmetic). An all zero transmitted + * checksum value means that the transmitter generated no checksum (for + * debugging or for higher level protocols that don't care). + */ + + if (NextLevelProtocol == SKCS_PROTO_ID_UDP && + *(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) { + + NextLevelProtoStats->RxOkCts++; + + return (SKCS_STATUS_IP_CSUM_OK_NO_UDP); + } + + /* + * Calculate the TCP/UDP checksum. + */ + + /* Get total length of IP header and data. */ + + IpDataLength = + *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH); + + /* Get length of IP data portion. */ + + IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength; + + NextLevelProtocolChecksum = + + /* Calculate the pseudo header checksum. */ + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_SOURCE_ADDRESS + 0) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_SOURCE_ADDRESS + 2) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_DESTINATION_ADDRESS + 0) + + (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, + SKCS_OFS_IP_DESTINATION_ADDRESS + 2) + + (unsigned long) SKCS_HTON16(NextLevelProtocol) + + (unsigned long) SKCS_HTON16(IpDataLength) + + + /* Add the TCP/UDP header checksum. */ + + (unsigned long) IpDataChecksum; + + /* Add-in any carries. */ + + SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0); + + /* Add-in any new carry. */ + + SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0); + + /* Check if the TCP/UDP checksum is ok. */ + + if ((unsigned) NextLevelProtocolChecksum == 0xFFFF) { + + /* TCP/UDP checksum ok. */ + + NextLevelProtoStats->RxOkCts++; + + return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? + SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK); + } + + /* TCP/UDP checksum error. */ + + NextLevelProtoStats->RxErrCts++; + + return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? + SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR); +} /* SkCsGetReceiveInfo */ +#endif + + +/****************************************************************************** + * + * SkCsSetReceiveFlags - set checksum receive flags + * + * Description: + * Use this function to set the various receive flags. According to the + * protocol flags set by the caller, the start offsets within received + * packets of the two hardware checksums are returned. These offsets must + * be stored in all receive descriptors. + * + * Arguments: + * pAc - Pointer to adapter context struct. + * + * ReceiveFlags - Any combination of SK_PROTO_XXX flags of the protocols + * for which the caller wants checksum information on received frames. + * + * pChecksum1Offset - The start offset of the first receive descriptor + * hardware checksum to be calculated for received frames is returned + * here. + * + * pChecksum2Offset - The start offset of the second receive descriptor + * hardware checksum to be calculated for received frames is returned + * here. + * + * Returns: N/A + * Returns the two hardware checksum start offsets. + */ +void SkCsSetReceiveFlags( +SK_AC *pAc, /* Adapter context struct. */ +unsigned ReceiveFlags, /* New receive flags. */ +unsigned *pChecksum1Offset, /* Offset for hardware checksum 1. */ +unsigned *pChecksum2Offset, /* Offset for hardware checksum 2. */ +int NetNumber) +{ + /* Save the receive flags. */ + + pAc->Csum.ReceiveFlags[NetNumber] = ReceiveFlags; + + /* First checksum start offset is the IP header. */ + *pChecksum1Offset = SKCS_MAC_HEADER_SIZE; + + /* + * Second checksum start offset is the IP data. Note that this may vary + * if there are any IP header options in the actual packet. + */ + *pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE; +} /* SkCsSetReceiveFlags */ + +#ifndef SkCsCalculateChecksum + +/****************************************************************************** + * + * SkCsCalculateChecksum - calculate checksum for specified data + * + * Description: + * Calculate and return the 16-bit Internet Checksum for the specified + * data. + * + * Arguments: + * pData - Pointer to data for which the checksum shall be calculated. + * Note: The pointer should be aligned on a 16-bit boundary. + * + * Length - Length in bytes of data to checksum. + * + * Returns: + * The 16-bit Internet Checksum for the specified data. + * + * Note: The checksum is calculated in the machine's natural byte order, + * i.e. little vs. big endian. Thus, the resulting checksum is different + * for the same input data on little and big endian machines. + * + * However, when written back to the network packet, the byte order is + * always in correct network order. + */ +unsigned SkCsCalculateChecksum( +void *pData, /* Data to checksum. */ +unsigned Length) /* Length of data. */ +{ + SK_U16 *pU16; /* Pointer to the data as 16-bit words. */ + unsigned long Checksum; /* Checksum; must be at least 32 bits. */ + + /* Sum up all 16-bit words. */ + + pU16 = (SK_U16 *) pData; + for (Checksum = 0; Length > 1; Length -= 2) { + Checksum += *pU16++; + } + + /* If this is an odd number of bytes, add-in the last byte. */ + + if (Length > 0) { +#ifdef SK_BIG_ENDIAN + /* Add the last byte as the high byte. */ + Checksum += ((unsigned) *(SK_U8 *) pU16) << 8; +#else /* !SK_BIG_ENDIAN */ + /* Add the last byte as the low byte. */ + Checksum += *(SK_U8 *) pU16; +#endif /* !SK_BIG_ENDIAN */ + } + + /* Add-in any carries. */ + + SKCS_OC_ADD(Checksum, Checksum, 0); + + /* Add-in any new carry. */ + + SKCS_OC_ADD(Checksum, Checksum, 0); + + /* Note: All bits beyond the 16-bit limit are now zero. */ + + return ((unsigned) Checksum); +} /* SkCsCalculateChecksum */ + +#endif /* SkCsCalculateChecksum */ + +/****************************************************************************** + * + * SkCsEvent - the CSUM event dispatcher + * + * Description: + * This is the event handler for the CSUM module. + * + * Arguments: + * pAc - Pointer to adapter context. + * + * Ioc - I/O context. + * + * Event - Event id. + * + * Param - Event dependent parameter. + * + * Returns: + * The 16-bit Internet Checksum for the specified data. + * + * Note: The checksum is calculated in the machine's natural byte order, + * i.e. little vs. big endian. Thus, the resulting checksum is different + * for the same input data on little and big endian machines. + * + * However, when written back to the network packet, the byte order is + * always in correct network order. + */ +int SkCsEvent( +SK_AC *pAc, /* Pointer to adapter context. */ +SK_IOC Ioc, /* I/O context. */ +SK_U32 Event, /* Event id. */ +SK_EVPARA Param) /* Event dependent parameter. */ +{ + int ProtoIndex; + int NetNumber; + + switch (Event) { + /* + * Clear protocol statistics. + * + * Param - Protocol index, or -1 for all protocols. + * - Net number. + */ + case SK_CSUM_EVENT_CLEAR_PROTO_STATS: + + ProtoIndex = (int)Param.Para32[1]; + NetNumber = (int)Param.Para32[0]; + if (ProtoIndex < 0) { /* Clear for all protocols. */ + if (NetNumber >= 0) { + memset(&pAc->Csum.ProtoStats[NetNumber][0], 0, + sizeof(pAc->Csum.ProtoStats[NetNumber])); + } + } + else { /* Clear for individual protocol. */ + memset(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0, + sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex])); + } + break; + default: + break; + } + return (0); /* Success. */ +} /* SkCsEvent */ + +#endif /* SK_USE_CSUM */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c new file mode 100644 index 0000000000..61a6094230 --- /dev/null +++ b/drivers/net/sk98lin/skge.c @@ -0,0 +1,4864 @@ +/****************************************************************************** + * + * Name: skge.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.46 $ + * Date: $Date: 2003/02/25 14:16:36 $ + * Purpose: The main driver source module + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * Driver for SysKonnect Gigabit Ethernet Server Adapters: + * + * SK-9871 (single link 1000Base-ZX) + * SK-9872 (dual link 1000Base-ZX) + * SK-9861 (single link 1000Base-SX, VF45 Volition Plug) + * SK-9862 (dual link 1000Base-SX, VF45 Volition Plug) + * SK-9841 (single link 1000Base-LX) + * SK-9842 (dual link 1000Base-LX) + * SK-9843 (single link 1000Base-SX) + * SK-9844 (dual link 1000Base-SX) + * SK-9821 (single link 1000Base-T) + * SK-9822 (dual link 1000Base-T) + * SK-9881 (single link 1000Base-SX V2 LC) + * SK-9871 (single link 1000Base-ZX V2) + * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug) + * SK-9841 (single link 1000Base-LX V2) + * SK-9843 (single link 1000Base-SX V2) + * SK-9821 (single link 1000Base-T V2) + * + * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and + * SysKonnects GEnesis Solaris driver + * Author: Christoph Goos (cgoos@syskonnect.de) + * Mirko Lindner (mlindner@syskonnect.de) + * + * Address all question to: linux@syskonnect.de + * + * The technical manual for the adapters is available from SysKonnect's + * web pages: www.syskonnect.com + * Goto "Support" and search Knowledge Base for "manual". + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skge.c,v $ + * Revision 1.46 2003/02/25 14:16:36 mlindner + * Fix: Copyright statement + * + * Revision 1.45 2003/02/25 13:25:55 mlindner + * Add: Performance improvements + * Add: Support for various vendors + * Fix: Init function + * + * Revision 1.44 2003/01/09 09:25:26 mlindner + * Fix: Remove useless init_module/cleanup_module forward declarations + * + * Revision 1.43 2002/11/29 08:42:41 mlindner + * Fix: Boot message + * + * Revision 1.42 2002/11/28 13:30:23 mlindner + * Add: New frame check + * + * Revision 1.41 2002/11/27 13:55:18 mlindner + * Fix: Drop wrong csum packets + * Fix: Initialize proc_entry after hw check + * + * Revision 1.40 2002/10/31 07:50:37 tschilli + * Function SkGeInitAssignRamToQueues() from common module inserted. + * Autonegotiation is set to ON for all adapters. + * LinkSpeedUsed is used in link up status report. + * Role parameter will show up for 1000 Mbps links only. + * GetConfiguration() inserted after init level 1 in SkGeChangeMtu(). + * All return values of SkGeInit() and SkGeInitPort() are checked. + * + * Revision 1.39 2002/10/02 12:56:05 mlindner + * Add: Support for Yukon + * Add: Support for ZEROCOPY, scatter-gather and hw checksum + * Add: New transmit ring function (use SG and TCP/UDP hardware checksumming) + * Add: New init function + * Add: Speed check and setup + * Add: Merge source for kernel 2.2.x and 2.4.x + * Add: Opcode check for tcp + * Add: Frame length check + * Fix: Transmit complete interrupt + * Fix: Interrupt moderation + * + * Revision 1.29.2.13 2002/01/14 12:44:52 mlindner + * Fix: Rlmt modes + * + * Revision 1.29.2.12 2001/12/07 12:06:18 mlindner + * Fix: malloc -> slab changes + * + * Revision 1.29.2.11 2001/12/06 15:19:20 mlindner + * Add: DMA attributes + * Fix: Module initialisation + * Fix: pci_map_single and pci_unmap_single replaced + * + * Revision 1.29.2.10 2001/12/06 09:56:50 mlindner + * Corrected some printk's + * + * Revision 1.29.2.9 2001/09/05 12:15:34 mlindner + * Add: LBFO Changes + * Fix: Counter Errors (Jumbo == to long errors) + * Fix: Changed pAC->PciDev declaration + * Fix: too short counters + * + * Revision 1.29.2.8 2001/06/25 12:10:44 mlindner + * fix: ReceiveIrq() changed. + * + * Revision 1.29.2.7 2001/06/25 08:07:05 mlindner + * fix: RLMT locking in ReceiveIrq() changed. + * + * Revision 1.29.2.6 2001/05/21 07:59:29 mlindner + * fix: MTU init problems + * + * Revision 1.29.2.5 2001/05/08 11:25:08 mlindner + * fix: removed VLAN error message + * + * Revision 1.29.2.4 2001/05/04 13:31:43 gklug + * fix: do not handle eth_copy on bad fragments received. + * + * Revision 1.29.2.3 2001/04/23 08:06:43 mlindner + * Fix: error handling + * + * Revision 1.29.2.2 2001/03/15 12:04:54 mlindner + * Fixed memory problem + * + * Revision 1.29.2.1 2001/03/12 16:41:44 mlindner + * add: procfs function + * add: dual-net function + * add: RLMT networks + * add: extended PNMI features + * + * Kernel 2.4.x specific: + * Revision 1.xx 2000/09/12 13:31:56 cgoos + * Fixed missign "dev=NULL in skge_probe. + * Added counting for jumbo frames (corrects error statistic). + * Removed VLAN tag check (enables VLAN support). + * + * Kernel 2.2.x specific: + * Revision 1.29 2000/02/21 13:31:56 cgoos + * Fixed "unused" warning for UltraSPARC change. + * + * Partially kernel 2.2.x specific: + * Revision 1.28 2000/02/21 10:32:36 cgoos + * Added fixes for UltraSPARC. + * Now printing RlmtMode and PrefPort setting at startup. + * Changed XmitFrame return value. + * Fixed rx checksum calculation for BIG ENDIAN systems. + * Fixed rx jumbo frames counted as ierrors. + * + * + * Revision 1.27 1999/11/25 09:06:28 cgoos + * Changed base_addr to unsigned long. + * + * Revision 1.26 1999/11/22 13:29:16 cgoos + * Changed license header to GPL. + * Changes for inclusion in linux kernel (2.2.13). + * Removed 2.0.x defines. + * Changed SkGeProbe to skge_probe. + * Added checks in SkGeIoctl. + * + * Revision 1.25 1999/10/07 14:47:52 cgoos + * Changed 984x to 98xx. + * + * Revision 1.24 1999/09/30 07:21:01 cgoos + * Removed SK_RLMT_SLOW_LOOKAHEAD option. + * Giving spanning tree packets also to OS now. + * + * Revision 1.23 1999/09/29 07:36:50 cgoos + * Changed assignment for IsBc/IsMc. + * + * Revision 1.22 1999/09/28 12:57:09 cgoos + * Added CheckQueue also to Single-Port-ISR. + * + * Revision 1.21 1999/09/28 12:42:41 cgoos + * Changed parameter strings for RlmtMode. + * + * Revision 1.20 1999/09/28 12:37:57 cgoos + * Added CheckQueue for fast delivery of RLMT frames. + * + * Revision 1.19 1999/09/16 07:57:25 cgoos + * Copperfield changes. + * + * Revision 1.18 1999/09/03 13:06:30 cgoos + * Fixed RlmtMode=CheckSeg bug: wrong DEV_KFREE_SKB in RLMT_SEND caused + * double allocated skb's. + * FrameStat in ReceiveIrq was accessed via wrong Rxd. + * Queue size for async. standby Tx queue was zero. + * FillRxLimit of 0 could cause problems with ReQueue, changed to 1. + * Removed debug output of checksum statistic. + * + * Revision 1.17 1999/08/11 13:55:27 cgoos + * Transmit descriptor polling was not reenabled after SkGePortInit. + * + * Revision 1.16 1999/07/27 15:17:29 cgoos + * Added some "\n" in output strings (removed while debuging...). + * + * Revision 1.15 1999/07/23 12:09:30 cgoos + * Performance optimization, rx checksumming, large frame support. + * + * Revision 1.14 1999/07/14 11:26:27 cgoos + * Removed Link LED settings (now in RLMT). + * Added status output at NET UP. + * Fixed SMP problems with Tx and SWITCH running in parallel. + * Fixed return code problem at RLMT_SEND event. + * + * Revision 1.13 1999/04/07 10:11:42 cgoos + * Fixed Single Port problems. + * Fixed Multi-Adapter problems. + * Always display startup string. + * + * Revision 1.12 1999/03/29 12:26:37 cgoos + * Reversed locking to fine granularity. + * Fixed skb double alloc problem (caused by incorrect xmit return code). + * Enhanced function descriptions. + * + * Revision 1.11 1999/03/15 13:10:51 cgoos + * Changed device identifier in output string to ethX. + * + * Revision 1.10 1999/03/15 12:12:34 cgoos + * Changed copyright notice. + * + * Revision 1.9 1999/03/15 12:10:17 cgoos + * Changed locking to one driver lock. + * Added check of SK_AC-size (for consistency with library). + * + * Revision 1.8 1999/03/08 11:44:02 cgoos + * Fixed missing dev->tbusy in SkGeXmit. + * Changed large frame (jumbo) buffer number. + * Added copying of short frames. + * + * Revision 1.7 1999/03/04 13:26:57 cgoos + * Fixed spinlock calls for SMP. + * + * Revision 1.6 1999/03/02 09:53:51 cgoos + * Added descriptor revertion for big endian machines. + * + * Revision 1.5 1999/03/01 08:50:59 cgoos + * Fixed SkGeChangeMtu. + * Fixed pci config space accesses. + * + * Revision 1.4 1999/02/18 15:48:44 cgoos + * Corrected some printk's. + * + * Revision 1.3 1999/02/18 12:45:55 cgoos + * Changed SK_MAX_CARD_PARAM to default 16 + * + * Revision 1.2 1999/02/18 10:55:32 cgoos + * Removed SkGeDrvTimeStamp function. + * Printing "ethX:" before adapter type at adapter init. + * + * + * 10-Feb-1999 cg Created, based on Linux' acenic.c, 3c59x.c and + * SysKonnects GEnesis Solaris driver + * + ******************************************************************************/ + +/****************************************************************************** + * + * Possible compiler options (#define xxx / -Dxxx): + * + * debugging can be enable by changing SK_DEBUG_CHKMOD and + * SK_DEBUG_CHKCAT in makefile (described there). + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This is the main module of the Linux GE driver. + * + * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h + * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters. + * Those are used for drivers on multiple OS', so some thing may seem + * unnecessary complicated on Linux. Please do not try to 'clean up' + * them without VERY good reasons, because this will make it more + * difficult to keep the Linux driver in synchronisation with the + * other versions. + * + * Include file hierarchy: + * + * + * + * "h/skdrv1st.h" + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * those three depending on kernel version used: + * + * + * + * + * + * "h/skerror.h" + * "h/skdebug.h" + * "h/sktypes.h" + * "h/lm80.h" + * "h/xmac_ii.h" + * + * "h/skdrv2nd.h" + * "h/skqueue.h" + * "h/skgehwt.h" + * "h/sktimer.h" + * "h/ski2c.h" + * "h/skgepnmi.h" + * "h/skvpd.h" + * "h/skgehw.h" + * "h/skgeinit.h" + * "h/skaddr.h" + * "h/skgesirq.h" + * "h/skcsum.h" + * "h/skrlmt.h" + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skversion.h" +#if 0 +#include +#include +#include +#endif +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + + +/* defines ******************************************************************/ +/* for debuging on x86 only */ +/* #define BREAKPOINT() asm(" int $3"); */ + +/* use the scatter-gather functionality with sendfile() */ +#if 0 +#define SK_ZEROCOPY +#endif + +/* use of a transmit complete interrupt */ +#define USE_TX_COMPLETE + +/* use interrupt moderation (for tx complete only) */ +#define USE_INT_MOD +#define INTS_PER_SEC 1000 + +/* + * threshold for copying small receive frames + * set to 0 to avoid copying, set to 9001 to copy all frames + */ +#define SK_COPY_THRESHOLD 50 + +/* number of adapters that can be configured via command line params */ +#define SK_MAX_CARD_PARAM 16 + + +/* + * use those defines for a compile-in version of the driver instead + * of command line parameters + */ +/* #define LINK_SPEED_A {"Auto", } */ +/* #define LINK_SPEED_B {"Auto", } */ +/* #define AUTO_NEG_A {"Sense", } */ +/* #define AUTO_NEG_B {"Sense", } */ +/* #define DUP_CAP_A {"Both", } */ +/* #define DUP_CAP_B {"Both", } */ +/* #define FLOW_CTRL_A {"SymOrRem", } */ +/* #define FLOW_CTRL_B {"SymOrRem", } */ +/* #define ROLE_A {"Auto", } */ +/* #define ROLE_B {"Auto", } */ +/* #define PREF_PORT {"A", } */ +/* #define RLMT_MODE {"CheckLinkState", } */ + +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) +#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) +#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) + +/* function prototypes ******************************************************/ +static void FreeResources(struct SK_NET_DEVICE *dev); +static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC); +static SK_BOOL BoardAllocMem(SK_AC *pAC); +static void BoardFreeMem(SK_AC *pAC); +static void BoardInitMem(SK_AC *pAC); +static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, + int*, SK_BOOL); + +#if 0 +static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); +static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +static int SkGeOpen(struct SK_NET_DEVICE *dev); +static int SkGeClose(struct SK_NET_DEVICE *dev); +static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); +static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p); +static void SkGeSetRxMode(struct SK_NET_DEVICE *dev); +static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev); +static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd); +#else +void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); +void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +int SkGeOpen(struct SK_NET_DEVICE *dev); +int SkGeClose(struct SK_NET_DEVICE *dev); +int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); +#endif +static void GetConfiguration(SK_AC*); +static void ProductStr(SK_AC*); +static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*); +static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*); +static void FillRxRing(SK_AC*, RX_PORT*); +static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*); +#if 0 +static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); +#else +void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); +#endif +static void ClearAndStartRx(SK_AC*, int); +static void ClearTxIrq(SK_AC*, int, int); +static void ClearRxRing(SK_AC*, RX_PORT*); +static void ClearTxRing(SK_AC*, TX_PORT*); +#if 0 +static void SetQueueSizes(SK_AC *pAC); + +static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); +#endif +static void PortReInitBmu(SK_AC*, int); +#if 0 +static int SkGeIocMib(DEV_NET*, unsigned int, int); +static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); +#endif + +/*Extern */ + +/* external Proc function */ +extern int proc_read( + char *buffer, + char **buffer_location, + off_t offset, + int buffer_length, + int *eof, + void *data); + +#ifdef DEBUG +static void DumpMsg(struct sk_buff*, char*); +static void DumpData(char*, int); +static void DumpLong(char*, int); +#endif +void dump_frag( SK_U8 *data, int length); + +/* global variables *********************************************************/ +#if 0 +static const char *BootString = BOOT_STRING; +#endif +struct SK_NET_DEVICE *SkGeRootDev = NULL; +static int probed __initdata = 0; + +/* local variables **********************************************************/ +static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; +static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; + + +/* local variables **********************************************************/ +const char SK_Root_Dir_entry[8]; + +#if 0 +static struct proc_dir_entry *pSkRootDir; +#endif + + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_3COM, 0x1700}, + {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE}, + {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU}, + {} +}; + + +/***************************************************************************** + * + * skge_probe - find all SK-98xx adapters + * + * Description: + * This function scans the PCI bus for SK-98xx adapters. Resources for + * each adapter are allocated and the adapter is brought into Init 1 + * state. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +#if 0 +static int __init skge_probe (void) +#else +int skge_probe (struct eth_device ** ret_dev) +#endif +{ +#if 0 + int proc_root_initialized = 0; +#endif + int boards_found = 0; +#if 0 + int vendor_flag = SK_FALSE; +#endif + SK_AC *pAC; + DEV_NET *pNet = NULL; +#if 0 + struct proc_dir_entry *pProcFile; + struct pci_dev *pdev = NULL; + unsigned long base_address; +#else + u32 base_address; +#endif + struct SK_NET_DEVICE *dev = NULL; +#if 0 + SK_BOOL DeviceFound = SK_FALSE; +#endif + SK_BOOL BootStringCount = SK_FALSE; +#if 1 + pci_dev_t devno; +#endif + + if (probed) + return -ENODEV; + probed++; + + if (!pci_present()) /* is PCI support present? */ + return -ENODEV; + +#if 0 + while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) +#else + while((devno = pci_find_devices (supported, boards_found)) >= 0) +#endif + { + + dev = NULL; + pNet = NULL; + + +#if 0 + SK_PCI_ISCOMPLIANT(vendor_flag, pdev); + if (!vendor_flag) + continue; +#endif + +/* if ((pdev->vendor != PCI_VENDOR_ID_SYSKONNECT) && + ((pdev->device != PCI_DEVICE_ID_SYSKONNECT_GE) || + (pdev->device != PCI_DEVICE_ID_SYSKONNECT_YU))){ + continue; + } +*/ +#if 0 + /* Configure DMA attributes. */ + if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) && + pci_set_dma_mask(pdev, (u64) 0xffffffff)) + continue; +#endif + + +#if 0 + if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); + break; + } +#else + dev = malloc (sizeof *dev); + memset(dev, 0, sizeof(*dev)); + dev->priv = malloc(sizeof(DEV_NET)); +#endif + + if (dev->priv == NULL) { + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); + break; + } + + pNet = dev->priv; + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); + if (pNet->pAC == NULL){ + kfree(dev->priv); + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); + break; + } + + /* Print message */ + if (!BootStringCount) { + /* set display flag to TRUE so that */ + /* we only display this string ONCE */ + BootStringCount = SK_TRUE; +#ifdef SK98_INFO + printk("%s\n", BootString); +#endif + } + + memset(pNet->pAC, 0, sizeof(SK_AC)); + pAC = pNet->pAC; +#if 0 + pAC->PciDev = pdev; + pAC->PciDevId = pdev->device; + pAC->dev[0] = dev; + pAC->dev[1] = dev; +#else + pAC->PciDev = devno; + ret_dev[0] = pAC->dev[0] = dev; + ret_dev[1] = pAC->dev[1] = dev; +#endif + sprintf(pAC->Name, "SysKonnect SK-98xx"); + pAC->CheckQueue = SK_FALSE; + + pNet->Mtu = 1500; + pNet->Up = 0; +#if 0 + dev->irq = pdev->irq; + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; +#endif + +#ifdef SK_ZEROCOPY + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + /* Use only if yukon hardware */ + /* SK and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif + +#if 0 + /* + * Dummy value. + */ + dev->base_addr = 42; + pci_set_master(pdev); + + pci_set_master(pdev); + base_address = pci_resource_start (pdev, 0); +#else + pci_write_config_dword(devno, + PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, + &base_address); +#endif + +#ifdef SK_BIG_ENDIAN + /* + * On big endian machines, we use the adapter's aibility of + * reading the descriptors as big endian. + */ + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } +#endif + + /* + * Remap the regs into kernel space. + */ +#if 0 + pAC->IoBase = (char*)ioremap(base_address, 0x4000); +#else + pAC->IoBase = (char*)pci_mem_to_phys(devno, base_address); +#endif + + if (!pAC->IoBase){ + printk(KERN_ERR "%s: Unable to map I/O register, " + "SK 98xx No. %i will be disabled.\n", + dev->name, boards_found); + kfree(dev); + break; + } + + pAC->Index = boards_found; + if (SkGeBoardInit(dev, pAC)) { + FreeResources(dev); + kfree(dev); + continue; + } + +#if 0 + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); +#else + memcpy((caddr_t) &dev->enetaddr, + (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); +#endif + +#if 0 + /* First adapter... Create proc and print message */ + if (!DeviceFound) { + DeviceFound = SK_TRUE; + SK_MEMCPY(&SK_Root_Dir_entry, BootString, + sizeof(SK_Root_Dir_entry) - 1); + + /*Create proc (directory)*/ + if(!proc_root_initialized) { + pSkRootDir = create_proc_entry(SK_Root_Dir_entry, + S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); + proc_root_initialized = 1; + } + + pSkRootDir->owner = THIS_MODULE; + } + + + /* Create proc file */ + pProcFile = create_proc_entry(dev->name, + S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, + pSkRootDir); + + + pProcFile->read_proc = proc_read; + pProcFile->write_proc = NULL; + pProcFile->nlink = 1; + pProcFile->size = sizeof(dev->name + 1); + pProcFile->data = (void *)pProcFile; +#endif + + pNet->PortNr = 0; + pNet->NetNr = 0; + +#ifdef SK_ZEROCOPY + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + /* SG and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif + + boards_found++; + + /* More then one port found */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { +#if 0 + if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); + break; + } +#else + dev = malloc (sizeof *dev); + memset(dev, 0, sizeof(*dev)); + dev->priv = malloc(sizeof(DEV_NET)); +#endif + + pAC->dev[1] = dev; + pNet = dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + pNet->Mtu = 1500; + pNet->Up = 0; + +#if 0 + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; +#endif + +#ifdef SK_ZEROCOPY + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + /* SG and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif + +#if 0 + pProcFile = create_proc_entry(dev->name, + S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, + pSkRootDir); + + + pProcFile->read_proc = proc_read; + pProcFile->write_proc = NULL; + pProcFile->nlink = 1; + pProcFile->size = sizeof(dev->name + 1); + pProcFile->data = (void *)pProcFile; +#endif + +#if 0 + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); +#else + memcpy((caddr_t) &dev->enetaddr, + (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); +#endif + + printk("%s: %s\n", dev->name, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + + } + + + /* Save the hardware revision */ + pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + + (pAC->GIni.GIPciHwRev & 0x0F); + + /* + * This is bollocks, but we need to tell the net-init + * code that it shall go for the next device. + */ +#if 0 +#ifndef MODULE + dev->base_addr = 0; +#endif +#endif + } + + /* + * If we're at this point we're going through skge_probe() for + * the first time. Return success (0) if we've initialized 1 + * or more boards. Otherwise, return failure (-ENODEV). + */ + + return boards_found; +} /* skge_probe */ + + +/***************************************************************************** + * + * FreeResources - release resources allocated for adapter + * + * Description: + * This function releases the IRQ, unmaps the IO and + * frees the desriptor ring. + * + * Returns: N/A + * + */ +static void FreeResources(struct SK_NET_DEVICE *dev) +{ +SK_U32 AllocFlag; +DEV_NET *pNet; +SK_AC *pAC; + + if (dev->priv) { + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + AllocFlag = pAC->AllocFlag; +#if 0 + if (AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + if (pAC->IoBase) { + iounmap(pAC->IoBase); + } +#endif + if (pAC->pDescrMem) { + BoardFreeMem(pAC); + } + } + +} /* FreeResources */ + +#if 0 +MODULE_AUTHOR("Mirko Lindner "); +MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); +/* not used, just there because every driver should have them: */ +MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); +MODULE_PARM(debug, "i"); +#endif + + +#ifdef LINK_SPEED_A +static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED_A; +#else +static char *Speed_A[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef LINK_SPEED_B +static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED_B; +#else +static char *Speed_B[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef AUTO_NEG_A +static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A; +#else +static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef DUP_CAP_A +static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A; +#else +static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef FLOW_CTRL_A +static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A; +#else +static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef ROLE_A +static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A; +#else +static char *Role_A[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef AUTO_NEG_B +static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B; +#else +static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef DUP_CAP_B +static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B; +#else +static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef FLOW_CTRL_B +static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B; +#else +static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef ROLE_B +static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B; +#else +static char *Role_B[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef PREF_PORT +static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT; +#else +static char *PrefPort[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#ifdef RLMT_MODE +static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; +#else +static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; +#endif + +#if 0 +static int debug = 0; /* not used */ +static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ + + +/***************************************************************************** + * + * skge_init_module - module initialization function + * + * Description: + * Very simple, only call skge_probe and return approriate result. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int __init skge_init_module(void) +{ + int cards; + SkGeRootDev = NULL; + + /* just to avoid warnings ... */ + debug = 0; + options[0] = 0; + + cards = skge_probe(); + if (cards == 0) { + printk("sk98lin: No adapter found.\n"); + } + return cards ? 0 : -ENODEV; +} /* skge_init_module */ + + +/***************************************************************************** + * + * skge_cleanup_module - module unload function + * + * Description: + * Disable adapter if it is still running, free resources, + * free device struct. + * + * Returns: N/A + */ +static void __exit skge_cleanup_module(void) +{ +DEV_NET *pNet; +SK_AC *pAC; +struct SK_NET_DEVICE *next; +unsigned long Flags; +SK_EVPARA EvPara; + + while (SkGeRootDev) { + pNet = (DEV_NET*) SkGeRootDev->priv; + pAC = pNet->pAC; + next = pAC->Next; + + netif_stop_queue(SkGeRootDev); + SkGeYellowLED(pAC, pAC->IoBase, 0); + + if(pAC->BoardLevel == 2) { + /* board is still alive */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + EvPara.Para32[0] = 0; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + EvPara.Para32[0] = 1; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SkGeDeInit(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pAC->BoardLevel = 0; + /* We do NOT check here, if IRQ was pending, of course*/ + } + + if(pAC->BoardLevel == 1) { + /* board is still alive */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = 0; + } + + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ + unregister_netdev(pAC->dev[1]); + kfree(pAC->dev[1]); + } + + FreeResources(SkGeRootDev); + + SkGeRootDev->get_stats = NULL; + /* + * otherwise unregister_netdev calls get_stats with + * invalid IO ... :-( + */ + unregister_netdev(SkGeRootDev); + kfree(SkGeRootDev); + kfree(pAC); + SkGeRootDev = next; + } + + /* clear proc-dir */ + remove_proc_entry(pSkRootDir->name, proc_net); + +} /* skge_cleanup_module */ + +module_init(skge_init_module); +module_exit(skge_cleanup_module); +#endif + + +/***************************************************************************** + * + * SkGeBoardInit - do level 0 and 1 initialization + * + * Description: + * This function prepares the board hardware for running. The desriptor + * ring is set up, the IRQ is allocated and the configuration settings + * are examined. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) +{ +short i; +unsigned long Flags; +char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */ +char *VerStr = VER_STRING; +#if 0 +int Ret; /* return code of request_irq */ +#endif +SK_BOOL DualNet; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("IoBase: %08lX\n", (unsigned long)pAC->IoBase)); + for (i=0; iTxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0]; + pAC->TxPort[i][0].PortIndex = i; + pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i]; + pAC->RxPort[i].PortIndex = i; + } + + /* Initialize the mutexes */ + for (i=0; iTxPort[i][0].TxDesRingLock); + spin_lock_init(&pAC->RxPort[i].RxDesRingLock); + } + spin_lock_init(&pAC->SlowPathLock); + + /* level 0 init common modules here */ + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + /* Does a RESET on board ...*/ + if (SkGeInit(pAC, pAC->IoBase, 0) != 0) { + printk("HWInit (0) failed.\n"); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return(-EAGAIN); + } + SkI2cInit( pAC, pAC->IoBase, 0); + SkEventInit(pAC, pAC->IoBase, 0); + SkPnmiInit( pAC, pAC->IoBase, 0); + SkAddrInit( pAC, pAC->IoBase, 0); + SkRlmtInit( pAC, pAC->IoBase, 0); + SkTimerInit(pAC, pAC->IoBase, 0); + + pAC->BoardLevel = 0; + pAC->RxBufSize = ETH_BUF_SIZE; + + SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); + SK_PNMI_SET_DRIVER_VER(pAC, VerStr); + + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + /* level 1 init common modules here (HW init) */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { + printk("HWInit (1) failed.\n"); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return(-EAGAIN); + } + SkI2cInit( pAC, pAC->IoBase, 1); + SkEventInit(pAC, pAC->IoBase, 1); + SkPnmiInit( pAC, pAC->IoBase, 1); + SkAddrInit( pAC, pAC->IoBase, 1); + SkRlmtInit( pAC, pAC->IoBase, 1); + SkTimerInit(pAC, pAC->IoBase, 1); + + GetConfiguration(pAC); + if (pAC->RlmtNets == 2) { + pAC->GIni.GIPortUsage = SK_MUL_LINK; + } + + pAC->BoardLevel = 1; + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + +#if 0 + if (pAC->GIni.GIMacsFound == 2) { + Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + } else if (pAC->GIni.GIMacsFound == 1) { + Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, + pAC->Name, dev); + } else { + printk(KERN_WARNING "%s: Illegal number of ports: %d\n", + dev->name, pAC->GIni.GIMacsFound); + return -EAGAIN; + } + + if (Ret) { + printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n", + dev->name, dev->irq); + return -EAGAIN; + } +#endif + pAC->AllocFlag |= SK_ALLOC_IRQ; + + /* Alloc memory for this board (Mem for RxD/TxD) : */ + if(!BoardAllocMem(pAC)) { + printk("No memory for descriptor rings.\n"); + return(-EAGAIN); + } + + SkCsSetReceiveFlags(pAC, + SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, + &pAC->CsOfs1, &pAC->CsOfs2, 0); + pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1; + + BoardInitMem(pAC); +#if 0 + SetQueueSizes(pAC); +#else + /* tschilling: New common function with minimum size check. */ + DualNet = SK_FALSE; + if (pAC->RlmtNets == 2) { + DualNet = SK_TRUE; + } + + if (SkGeInitAssignRamToQueues( + pAC, + pAC->ActivePort, + DualNet)) { + BoardFreeMem(pAC); + printk("SkGeInitAssignRamToQueues failed.\n"); + return(-EAGAIN); + } +#endif + + /* Print adapter specific string from vpd */ + ProductStr(pAC); +#ifdef SK98_INFO + printk("%s: %s\n", dev->name, pAC->DeviceStr); + + /* Print configuration settings */ + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); +#endif + + SkGeYellowLED(pAC, pAC->IoBase, 1); + + /* + * Register the device here + */ + pAC->Next = SkGeRootDev; + SkGeRootDev = dev; + + return (0); +} /* SkGeBoardInit */ + + +/***************************************************************************** + * + * BoardAllocMem - allocate the memory for the descriptor rings + * + * Description: + * This function allocates the memory for all descriptor rings. + * Each ring is aligned for the desriptor alignment and no ring + * has a 4 GByte boundary in it (because the upper 32 bit must + * be constant for all descriptiors in one rings). + * + * Returns: + * SK_TRUE, if all memory could be allocated + * SK_FALSE, if not + */ +static SK_BOOL BoardAllocMem( +SK_AC *pAC) +{ +caddr_t pDescrMem; /* pointer to descriptor memory area */ +size_t AllocLength; /* length of complete descriptor area */ +int i; /* loop counter */ +unsigned long BusAddr; + + + /* rings plus one for alignment (do not cross 4 GB boundary) */ + /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */ +#if (BITS_PER_LONG == 32) + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; +#else + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + + RX_RING_SIZE + 8; +#endif + + pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength, + &pAC->pDescrMemDMA); + + if (pDescrMem == NULL) { + return (SK_FALSE); + } + pAC->pDescrMem = pDescrMem; + BusAddr = (unsigned long) pAC->pDescrMemDMA; + + /* Descriptors need 8 byte alignment, and this is ensured + * by pci_alloc_consistent. + */ + for (i=0; iGIni.GIMacsFound; i++) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n", + i, (unsigned long) pDescrMem, + BusAddr)); + pAC->TxPort[i][0].pTxDescrRing = pDescrMem; + pAC->TxPort[i][0].VTxDescrRing = BusAddr; + pDescrMem += TX_RING_SIZE; + BusAddr += TX_RING_SIZE; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", + i, (unsigned long) pDescrMem, + (unsigned long)BusAddr)); + pAC->RxPort[i].pRxDescrRing = pDescrMem; + pAC->RxPort[i].VRxDescrRing = BusAddr; + pDescrMem += RX_RING_SIZE; + BusAddr += RX_RING_SIZE; + } /* for */ + + return (SK_TRUE); +} /* BoardAllocMem */ + + +/**************************************************************************** + * + * BoardFreeMem - reverse of BoardAllocMem + * + * Description: + * Free all memory allocated in BoardAllocMem: adapter context, + * descriptor rings, locks. + * + * Returns: N/A + */ +static void BoardFreeMem( +SK_AC *pAC) +{ +size_t AllocLength; /* length of complete descriptor area */ + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("BoardFreeMem\n")); +#if (BITS_PER_LONG == 32) + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; +#else + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + + RX_RING_SIZE + 8; +#endif + + pci_free_consistent(pAC->PciDev, AllocLength, + pAC->pDescrMem, pAC->pDescrMemDMA); + pAC->pDescrMem = NULL; +} /* BoardFreeMem */ + + +/***************************************************************************** + * + * BoardInitMem - initiate the descriptor rings + * + * Description: + * This function sets the descriptor rings up in memory. + * The adapter is initialized with the descriptor start addresses. + * + * Returns: N/A + */ +static void BoardInitMem( +SK_AC *pAC) /* pointer to adapter context */ +{ +int i; /* loop counter */ +int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ +int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("BoardInitMem\n")); + + RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; + pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; + TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; + pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; + + for (i=0; iGIni.GIMacsFound; i++) { + SetupRing( + pAC, + pAC->TxPort[i][0].pTxDescrRing, + pAC->TxPort[i][0].VTxDescrRing, + (RXD**)&pAC->TxPort[i][0].pTxdRingHead, + (RXD**)&pAC->TxPort[i][0].pTxdRingTail, + (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, + &pAC->TxPort[i][0].TxdRingFree, + SK_TRUE); + SetupRing( + pAC, + pAC->RxPort[i].pRxDescrRing, + pAC->RxPort[i].VRxDescrRing, + &pAC->RxPort[i].pRxdRingHead, + &pAC->RxPort[i].pRxdRingTail, + &pAC->RxPort[i].pRxdRingPrev, + &pAC->RxPort[i].RxdRingFree, + SK_FALSE); + } +} /* BoardInitMem */ + + +/***************************************************************************** + * + * SetupRing - create one descriptor ring + * + * Description: + * This function creates one descriptor ring in the given memory area. + * The head, tail and number of free descriptors in the ring are set. + * + * Returns: + * none + */ +static void SetupRing( +SK_AC *pAC, +void *pMemArea, /* a pointer to the memory area for the ring */ +uintptr_t VMemArea, /* the virtual bus address of the memory area */ +RXD **ppRingHead, /* address where the head should be written */ +RXD **ppRingTail, /* address where the tail should be written */ +RXD **ppRingPrev, /* address where the tail should be written */ +int *pRingFree, /* address where the # of free descr. goes */ +SK_BOOL IsTx) /* flag: is this a tx ring */ +{ +int i; /* loop counter */ +int DescrSize; /* the size of a descriptor rounded up to alignment*/ +int DescrNum; /* number of descriptors per ring */ +RXD *pDescr; /* pointer to a descriptor (receive or transmit) */ +RXD *pNextDescr; /* pointer to the next descriptor */ +RXD *pPrevDescr; /* pointer to the previous descriptor */ +uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ + + if (IsTx == SK_TRUE) { + DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * + DESCR_ALIGN; + DescrNum = TX_RING_SIZE / DescrSize; + } else { + DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * + DESCR_ALIGN; + DescrNum = RX_RING_SIZE / DescrSize; + } + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Descriptor size: %d Descriptor Number: %d\n", + DescrSize,DescrNum)); + + pDescr = (RXD*) pMemArea; + pPrevDescr = NULL; + pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); + VNextDescr = VMemArea + DescrSize; + for(i=0; iVNextRxd = VNextDescr & 0xffffffffULL; + pDescr->pNextRxd = pNextDescr; + pDescr->TcpSumStarts = pAC->CsOfs; + + /* advance one step */ + pPrevDescr = pDescr; + pDescr = pNextDescr; + pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); + VNextDescr += DescrSize; + } + pPrevDescr->pNextRxd = (RXD*) pMemArea; + pPrevDescr->VNextRxd = VMemArea; + pDescr = (RXD*) pMemArea; + *ppRingHead = (RXD*) pMemArea; + *ppRingTail = *ppRingHead; + *ppRingPrev = pPrevDescr; + *pRingFree = DescrNum; +} /* SetupRing */ + + +/***************************************************************************** + * + * PortReInitBmu - re-initiate the descriptor rings for one port + * + * Description: + * This function reinitializes the descriptor rings of one port + * in memory. The port must be stopped before. + * The HW is initialized with the descriptor start addresses. + * + * Returns: + * none + */ +static void PortReInitBmu( +SK_AC *pAC, /* pointer to adapter context */ +int PortIndex) /* index of the port for which to re-init */ +{ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("PortReInitBmu ")); + + /* set address of first descriptor of ring in BMU */ + SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ + TX_Q_CUR_DESCR_LOW, + (uint32_t)(((caddr_t) + (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - + pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & + 0xFFFFFFFF)); + SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ + TX_Q_DESCR_HIGH, + (uint32_t)(((caddr_t) + (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - + pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); + SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW, + (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - + pAC->RxPort[PortIndex].pRxDescrRing + + pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); + SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH, + (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - + pAC->RxPort[PortIndex].pRxDescrRing + + pAC->RxPort[PortIndex].VRxDescrRing) >> 32)); +} /* PortReInitBmu */ + + +/**************************************************************************** + * + * SkGeIsr - handle adapter interrupts + * + * Description: + * The interrupt routine is called when the network adapter + * generates an interrupt. It may also be called if another device + * shares this interrupt vector with the driver. + * + * Returns: N/A + * + */ +#if 0 +static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) +#else +void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) +#endif +{ +struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; +DEV_NET *pNet; +SK_AC *pAC; +SK_U32 IntSrc; /* interrupts source register contents */ + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + /* + * Check and process if its our interrupt + */ + SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); + if (IntSrc == 0) { + return; + } + + while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { +#if 0 /* software irq currently not used */ + if (IntSrc & IRQ_SW) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("Software IRQ\n")); + } +#endif + if (IntSrc & IRQ_EOF_RX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF RX1 IRQ\n")); + ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + SK_PNMI_CNT_RX_INTR(pAC, 0); + } + if (IntSrc & IRQ_EOF_RX2) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF RX2 IRQ\n")); + ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); + SK_PNMI_CNT_RX_INTR(pAC, 1); + } +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IRQ_EOF_AS_TX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF AS TX1 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 0); + spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); + spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + } + if (IntSrc & IRQ_EOF_AS_TX2) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF AS TX2 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 1); + spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); + FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); + spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); + } +#if 0 /* only if sync. queues used */ + if (IntSrc & IRQ_EOF_SY_TX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF SY TX1 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 1); + spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); + FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); + spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); + ClearTxIrq(pAC, 0, TX_PRIO_HIGH); + } + if (IntSrc & IRQ_EOF_SY_TX2) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF SY TX2 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 1); + spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); + FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); + spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); + ClearTxIrq(pAC, 1, TX_PRIO_HIGH); + } +#endif +#endif + + /* do all IO at once */ + if (IntSrc & IRQ_EOF_RX1) + ClearAndStartRx(pAC, 0); + if (IntSrc & IRQ_EOF_RX2) + ClearAndStartRx(pAC, 1); +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IRQ_EOF_AS_TX1) + ClearTxIrq(pAC, 0, TX_PRIO_LOW); + if (IntSrc & IRQ_EOF_AS_TX2) + ClearTxIrq(pAC, 1, TX_PRIO_LOW); +#endif + SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); + } /* while (IntSrc & IRQ_MASK != 0) */ + + if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); + pAC->CheckQueue = SK_FALSE; + spin_lock(&pAC->SlowPathLock); + if (IntSrc & SPECIAL_IRQS) + SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); + + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock(&pAC->SlowPathLock); + } + /* + * do it all again is case we cleared an interrupt that + * came in after handling the ring (OUTs may be delayed + * in hardware buffers, but are through after IN) + */ + + ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); + + if (pAC->CheckQueue) { + pAC->CheckQueue = SK_FALSE; + spin_lock(&pAC->SlowPathLock); + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock(&pAC->SlowPathLock); + } + + + /* IRQ is processed - Enable IRQs again*/ + SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + + return; +} /* SkGeIsr */ + + +/**************************************************************************** + * + * SkGeIsrOnePort - handle adapter interrupts for single port adapter + * + * Description: + * The interrupt routine is called when the network adapter + * generates an interrupt. It may also be called if another device + * shares this interrupt vector with the driver. + * This is the same as above, but handles only one port. + * + * Returns: N/A + * + */ +#if 0 +static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) +#else +void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) +#endif +{ +struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; +DEV_NET *pNet; +SK_AC *pAC; +SK_U32 IntSrc; /* interrupts source register contents */ + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + /* + * Check and process if its our interrupt + */ + SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); + if (IntSrc == 0) { + return; + } + + while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { +#if 0 /* software irq currently not used */ + if (IntSrc & IRQ_SW) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("Software IRQ\n")); + } +#endif + if (IntSrc & IRQ_EOF_RX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF RX1 IRQ\n")); + ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + SK_PNMI_CNT_RX_INTR(pAC, 0); + } +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IRQ_EOF_AS_TX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF AS TX1 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 0); + spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); + spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + } +#if 0 /* only if sync. queues used */ + if (IntSrc & IRQ_EOF_SY_TX1) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("EOF SY TX1 IRQ\n")); + SK_PNMI_CNT_TX_INTR(pAC, 0); + spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); + FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); + spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); + ClearTxIrq(pAC, 0, TX_PRIO_HIGH); + } +#endif +#endif + + /* do all IO at once */ + if (IntSrc & IRQ_EOF_RX1) + ClearAndStartRx(pAC, 0); +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IRQ_EOF_AS_TX1) + ClearTxIrq(pAC, 0, TX_PRIO_LOW); +#endif + SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); + } /* while (IntSrc & IRQ_MASK != 0) */ + + if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); + pAC->CheckQueue = SK_FALSE; + spin_lock(&pAC->SlowPathLock); + if (IntSrc & SPECIAL_IRQS) + SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); + + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock(&pAC->SlowPathLock); + } + /* + * do it all again is case we cleared an interrupt that + * came in after handling the ring (OUTs may be delayed + * in hardware buffers, but are through after IN) + */ + ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + + /* IRQ is processed - Enable IRQs again*/ + SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + + return; +} /* SkGeIsrOnePort */ + + +/**************************************************************************** + * + * SkGeOpen - handle start of initialized adapter + * + * Description: + * This function starts the initialized adapter. + * The board level variable is set and the adapter is + * brought to full functionality. + * The device flags are set for operation. + * Do all necessary level 2 initialization, enable interrupts and + * give start command to RLMT. + * + * Returns: + * 0 on success + * != 0 on error + */ +#if 0 +static int SkGeOpen( +#else +int SkGeOpen( +#endif +struct SK_NET_DEVICE *dev) +{ + DEV_NET *pNet; + SK_AC *pAC; + unsigned long Flags; /* for spin lock */ + int i; + SK_EVPARA EvPara; /* an event parameter union */ + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); + + if (pAC->BoardLevel == 0) { + /* level 1 init common modules here */ + if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { + printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); + return (-1); + } + SkI2cInit (pAC, pAC->IoBase, 1); + SkEventInit (pAC, pAC->IoBase, 1); + SkPnmiInit (pAC, pAC->IoBase, 1); + SkAddrInit (pAC, pAC->IoBase, 1); + SkRlmtInit (pAC, pAC->IoBase, 1); + SkTimerInit (pAC, pAC->IoBase, 1); + pAC->BoardLevel = 1; + } + + if (pAC->BoardLevel != 2) { + /* tschilling: Level 2 init modules here, check return value. */ + if (SkGeInit(pAC, pAC->IoBase, 2) != 0) { + printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); + return (-1); + } + SkI2cInit (pAC, pAC->IoBase, 2); + SkEventInit (pAC, pAC->IoBase, 2); + SkPnmiInit (pAC, pAC->IoBase, 2); + SkAddrInit (pAC, pAC->IoBase, 2); + SkRlmtInit (pAC, pAC->IoBase, 2); + SkTimerInit (pAC, pAC->IoBase, 2); + pAC->BoardLevel = 2; + } + + for (i=0; iGIni.GIMacsFound; i++) { + /* Enable transmit descriptor polling. */ + SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); + FillRxRing(pAC, &pAC->RxPort[i]); + } + SkGeYellowLED(pAC, pAC->IoBase, 1); + +#ifdef USE_INT_MOD +/* moderate only TX complete interrupts (these are not time critical) */ +#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2) + { + unsigned long ModBase; + ModBase = 53125000 / INTS_PER_SEC; + SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); + SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); + SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); + } +#endif + + /* enable Interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + + if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { + EvPara.Para32[0] = pAC->RlmtNets; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, + EvPara); + EvPara.Para32[0] = pAC->RlmtMode; + EvPara.Para32[1] = 0; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, + EvPara); + } + + EvPara.Para32[0] = pNet->NetNr; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + pAC->MaxPorts++; + pNet->Up = 1; + + MOD_INC_USE_COUNT; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeOpen suceeded\n")); + + return (0); +} /* SkGeOpen */ + + +/**************************************************************************** + * + * SkGeClose - Stop initialized adapter + * + * Description: + * Close initialized adapter. + * + * Returns: + * 0 - on success + * error code - on error + */ +#if 0 +static int SkGeClose( +#else +int SkGeClose( +#endif +struct SK_NET_DEVICE *dev) +{ + DEV_NET *pNet; + SK_AC *pAC; + + unsigned long Flags; /* for spin lock */ + int i; + int PortIdx; + SK_EVPARA EvPara; + + netif_stop_queue(dev); + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + if (pAC->RlmtNets == 1) + PortIdx = pAC->ActivePort; + else + PortIdx = pNet->NetNr; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); + + /* + * Clear multicast table, promiscuous mode .... + */ + SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); + SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, + SK_PROM_MODE_NONE); + + if (pAC->MaxPorts == 1) { + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + EvPara.Para32[0] = pNet->NetNr; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + /* stop the hardware */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = 0; + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } else { + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + EvPara.Para32[0] = pNet->NetNr; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + /* Stop port */ + spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] + [TX_PRIO_LOW].TxDesRingLock, Flags); + SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, + SK_STOP_ALL, SK_HARD_RST); + spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] + [TX_PRIO_LOW].TxDesRingLock, Flags); + } + + if (pAC->RlmtNets == 1) { + /* clear all descriptor rings */ + for (i=0; iGIni.GIMacsFound; i++) { + ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); + ClearRxRing(pAC, &pAC->RxPort[i]); + ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); + } + } else { + /* clear port descriptor rings */ + ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); + ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); + ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); + } + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeClose: done ")); + + pAC->MaxPorts--; + pNet->Up = 0; + MOD_DEC_USE_COUNT; + + return (0); +} /* SkGeClose */ + + +/***************************************************************************** + * + * SkGeXmit - Linux frame transmit function + * + * Description: + * The system calls this function to send frames onto the wire. + * It puts the frame in the tx descriptor ring. If the ring is + * full then, the 'tbusy' flag is set. + * + * Returns: + * 0, if everything is ok + * !=0, on error + * WARNING: returning 1 in 'tbusy' case caused system crashes (double + * allocated skb's) !!! + */ +#if 0 +static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) +#else +int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) +#endif +{ +DEV_NET *pNet; +SK_AC *pAC; +int Rc; /* return code of XmitFrame */ + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + +#if 0 + if ((!skb_shinfo(skb)->nr_frags) || +#else + if (1 || +#endif + (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { + /* Don't activate scatter-gather and hardware checksum */ + + if (pAC->RlmtNets == 2) + Rc = XmitFrame( + pAC, + &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], + skb); + else + Rc = XmitFrame( + pAC, + &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], + skb); + } else { +#if 0 + /* scatter-gather and hardware TCP checksumming anabled*/ + if (pAC->RlmtNets == 2) + Rc = XmitFrameSG( + pAC, + &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], + skb); + else + Rc = XmitFrameSG( + pAC, + &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], + skb); +#endif + } + + /* Transmitter out of resources? */ + if (Rc <= 0) { + netif_stop_queue(dev); + } + + /* If not taken, give buffer ownership back to the + * queueing layer. + */ + if (Rc < 0) + return (1); + +#if 0 + dev->trans_start = jiffies; +#endif + return (0); +} /* SkGeXmit */ + + +/***************************************************************************** + * + * XmitFrame - fill one socket buffer into the transmit ring + * + * Description: + * This function puts a message into the transmit descriptor ring + * if there is a descriptors left. + * Linux skb's consist of only one continuous buffer. + * The first step locks the ring. It is held locked + * all time to avoid problems with SWITCH_../PORT_RESET. + * Then the descriptoris allocated. + * The second part is linking the buffer to the descriptor. + * At the very last, the Control field of the descriptor + * is made valid for the BMU and a start TX command is given + * if necessary. + * + * Returns: + * > 0 - on succes: the number of bytes in the message + * = 0 - on resource shortage: this frame sent or dropped, now + * the ring is full ( -> set tbusy) + * < 0 - on failure: other problems ( -> return failure to upper layers) + */ +static int XmitFrame( +SK_AC *pAC, /* pointer to adapter context */ +TX_PORT *pTxPort, /* pointer to struct of port to send to */ +struct sk_buff *pMessage) /* pointer to send-message */ +{ +TXD *pTxd; /* the rxd to fill */ +unsigned long Flags; +SK_U64 PhysAddr; +int BytesSend; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("X")); + + spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); +#ifndef USE_TX_COMPLETE + FreeTxDescriptors(pAC, pTxPort); +#endif + if (pTxPort->TxdRingFree == 0) { + /* no enough free descriptors in ring at the moment */ + FreeTxDescriptors(pAC, pTxPort); + if (pTxPort->TxdRingFree == 0) { + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); + SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS, + ("XmitFrame failed\n")); + /* this message can not be sent now */ + /* Because tbusy seems to be set, the message should not be freed here */ + /* It will be used by the scheduler of the ethernet handler */ + return (-1); + } + } + /* advance head counter behind descriptor needed for this frame */ + pTxd = pTxPort->pTxdRingHead; + pTxPort->pTxdRingHead = pTxd->pNextTxd; + pTxPort->TxdRingFree--; + /* the needed descriptor is reserved now */ + + /* + * everything allocated ok, so add buffer to descriptor + */ + +#ifdef SK_DUMP_TX + DumpMsg(pMessage, "XmitFrame"); +#endif + + /* set up descriptor and CONTROL dword */ +#if 0 + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + virt_to_page(pMessage->data), + ((unsigned long) pMessage->data & + ~PAGE_MASK), + pMessage->len, + PCI_DMA_TODEVICE); +#else + PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32) pMessage->data); +#endif + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); + pTxd->pMBuf = pMessage; + pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF | + TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE | +#ifdef USE_TX_COMPLETE + TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len; +#else + TX_CTRL_EOF | pMessage->len; +#endif + + if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { + /* previous descriptor already done, so give tx start cmd */ + /* StartTx(pAC, pTxPort->HwAddr); */ + SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); + } + pTxPort->pTxdRingPrev = pTxd; + + + BytesSend = pMessage->len; + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); + /* after releasing the lock, the skb may be immidiately freed */ + if (pTxPort->TxdRingFree != 0) + return (BytesSend); + else + return (0); + +} /* XmitFrame */ + +/***************************************************************************** + * + * XmitFrameSG - fill one socket buffer into the transmit ring + * (use SG and TCP/UDP hardware checksumming) + * + * Description: + * This function puts a message into the transmit descriptor ring + * if there is a descriptors left. + * + * Returns: + * > 0 - on succes: the number of bytes in the message + * = 0 - on resource shortage: this frame sent or dropped, now + * the ring is full ( -> set tbusy) + * < 0 - on failure: other problems ( -> return failure to upper layers) + */ +#if 0 +static int XmitFrameSG( +SK_AC *pAC, /* pointer to adapter context */ +TX_PORT *pTxPort, /* pointer to struct of port to send to */ +struct sk_buff *pMessage) /* pointer to send-message */ +{ + + int i; + int BytesSend; + int hlength; + int protocol; + skb_frag_t *sk_frag; + TXD *pTxd; + TXD *pTxdFst; + TXD *pTxdLst; + SK_U64 PhysAddr; + unsigned long Flags; + + spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); +#ifndef USE_TX_COMPLETE + FreeTxDescriptors(pAC, pTxPort); +#endif + if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) { + FreeTxDescriptors(pAC, pTxPort); + if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) { + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); + SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS, + ("XmitFrameSG failed - Ring full\n")); + /* this message can not be sent now */ + return(-1); + } + } + + + pTxd = pTxPort->pTxdRingHead; + pTxdFst = pTxd; + pTxdLst = pTxd; + BytesSend = 0; + protocol = 0; + + /* map first fragment (header) */ + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + virt_to_page(pMessage->data), + ((unsigned long) pMessage->data & ~PAGE_MASK), + skb_headlen(pMessage), + PCI_DMA_TODEVICE); + + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); + + /* HW checksum? */ + if (pMessage->ip_summed == CHECKSUM_HW) { + pTxd->TBControl = TX_CTRL_STF | + TX_CTRL_ST_FWD | + skb_headlen(pMessage); + + /* We have to use the opcode for tcp here because the opcode for + udp is not working in the hardware yet (revision 2.0)*/ + protocol = ((SK_U8)pMessage->data[23] & 0xf); + if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) + pTxd->TBControl |= BMU_UDP_CHECK; + else + pTxd->TBControl |= BMU_TCP_CHECK ; + + hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4; + pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ + pTxd->TcpSumSt = 14+hlength+16; + pTxd->TcpSumWr = 14+hlength; + + } else { + pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | + TX_CTRL_SOFTWARE | + TX_CTRL_STF | + skb_headlen(pMessage); + } + + pTxd = pTxd->pNextTxd; + pTxPort->TxdRingFree--; + BytesSend += skb_headlen(pMessage); + + + /* Map SG fragments */ + for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) { + sk_frag = &skb_shinfo(pMessage)->frags[i]; + + /* we already have the proper value in entry */ + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + sk_frag->page, + sk_frag->page_offset, + sk_frag->size, + PCI_DMA_TODEVICE); + + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); + pTxd->pMBuf = pMessage; + + /* HW checksum */ + if (pMessage->ip_summed == CHECKSUM_HW) { + pTxd->TBControl = TX_CTRL_OWN_BMU | + TX_CTRL_SOFTWARE | + TX_CTRL_ST_FWD; + + /* We have to use the opcode for tcp here because the opcode for + udp is not working in the hardware yet (revision 2.0)*/ + if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) + pTxd->TBControl |= BMU_UDP_CHECK ; + else + pTxd->TBControl |= BMU_TCP_CHECK ; + + } else { + pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | + TX_CTRL_SOFTWARE | + TX_CTRL_OWN_BMU; + } + + /* Last fragment */ + if( (i+1) == skb_shinfo(pMessage)->nr_frags ) { +#ifdef USE_TX_COMPLETE + pTxd->TBControl |= TX_CTRL_EOF | + TX_CTRL_EOF_IRQ | + sk_frag->size; +#else + pTxd->TBControl |= TX_CTRL_EOF | + sk_frag->size; +#endif + pTxdFst->TBControl |= TX_CTRL_OWN_BMU | + TX_CTRL_SOFTWARE; + + } else { + pTxd->TBControl |= sk_frag->size; + } + pTxdLst = pTxd; + pTxd = pTxd->pNextTxd; + pTxPort->TxdRingFree--; + BytesSend += sk_frag->size; + } + + if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { + /* previous descriptor already done, so give tx start cmd */ + /* StartTx(pAC, pTxPort->HwAddr); */ + SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); + } + + pTxPort->pTxdRingPrev = pTxdLst; + pTxPort->pTxdRingHead = pTxd; + + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); + + if (pTxPort->TxdRingFree > 0) + return (BytesSend); + else + return (0); +} +#endif + + +void dump_frag( SK_U8 *data, int length) +{ + int i; + + printk("Length: %d\n", length); + for( i=0; i < length; i++ ) { + printk(" %02x", (SK_U8)*(data + i) ); + if( !((i+1) % 20) ) + printk("\n"); + } + printk("\n\n"); + +} + + +/***************************************************************************** + * + * FreeTxDescriptors - release descriptors from the descriptor ring + * + * Description: + * This function releases descriptors from a transmit ring if they + * have been sent by the BMU. + * If a descriptors is sent, it can be freed and the message can + * be freed, too. + * The SOFTWARE controllable bit is used to prevent running around a + * completely free ring for ever. If this bit is no set in the + * frame (by XmitFrame), this frame has never been sent or is + * already freed. + * The Tx descriptor ring lock must be held while calling this function !!! + * + * Returns: + * none + */ +static void FreeTxDescriptors( +SK_AC *pAC, /* pointer to the adapter context */ +TX_PORT *pTxPort) /* pointer to destination port structure */ +{ +TXD *pTxd; /* pointer to the checked descriptor */ +TXD *pNewTail; /* pointer to 'end' of the ring */ +SK_U32 Control; /* TBControl field of descriptor */ +SK_U64 PhysAddr; /* address of DMA mapping */ + + pNewTail = pTxPort->pTxdRingTail; + pTxd = pNewTail; + /* + * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame + * or TX_CTRL_OWN_BMU bit set in any frame + */ + while (1) { + Control = pTxd->TBControl; + if ((Control & TX_CTRL_SOFTWARE) == 0) { + /* + * software controllable bit is set in first + * fragment when given to BMU. Not set means that + * this fragment was never sent or is already + * freed ( -> ring completely free now). + */ + pTxPort->pTxdRingTail = pTxd; + netif_wake_queue(pAC->dev[pTxPort->PortIndex]); + return; + } + if (Control & TX_CTRL_OWN_BMU) { + pTxPort->pTxdRingTail = pTxd; + if (pTxPort->TxdRingFree > 0) { + netif_wake_queue(pAC->dev[pTxPort->PortIndex]); + } + return; + } + + /* release the DMA mapping */ + PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; + PhysAddr |= (SK_U64) pTxd->VDataLow; + pci_unmap_page(pAC->PciDev, PhysAddr, + pTxd->pMBuf->len, + PCI_DMA_TODEVICE); + + if (Control & TX_CTRL_EOF) + DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ + + pTxPort->TxdRingFree++; + pTxd->TBControl &= ~TX_CTRL_SOFTWARE; + pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ + } /* while(forever) */ +} /* FreeTxDescriptors */ + +/***************************************************************************** + * + * FillRxRing - fill the receive ring with valid descriptors + * + * Description: + * This function fills the receive ring descriptors with data + * segments and makes them valid for the BMU. + * The active ring is filled completely, if possible. + * The non-active ring is filled only partial to save memory. + * + * Description of rx ring structure: + * head - points to the descriptor which will be used next by the BMU + * tail - points to the next descriptor to give to the BMU + * + * Returns: N/A + */ +static void FillRxRing( +SK_AC *pAC, /* pointer to the adapter context */ +RX_PORT *pRxPort) /* ptr to port struct for which the ring + should be filled */ +{ +unsigned long Flags; + + spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); + while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { + if(!FillRxDescriptor(pAC, pRxPort)) + break; + } + spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); +} /* FillRxRing */ + + +/***************************************************************************** + * + * FillRxDescriptor - fill one buffer into the receive ring + * + * Description: + * The function allocates a new receive buffer and + * puts it into the next descriptor. + * + * Returns: + * SK_TRUE - a buffer was added to the ring + * SK_FALSE - a buffer could not be added + */ +static SK_BOOL FillRxDescriptor( +SK_AC *pAC, /* pointer to the adapter context struct */ +RX_PORT *pRxPort) /* ptr to port struct of ring to fill */ +{ +struct sk_buff *pMsgBlock; /* pointer to a new message block */ +RXD *pRxd; /* the rxd to fill */ +SK_U16 Length; /* data fragment length */ +SK_U64 PhysAddr; /* physical address of a rx buffer */ + + pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); + if (pMsgBlock == NULL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_ENTRY, + ("%s: Allocation of rx buffer failed !\n", + pAC->dev[pRxPort->PortIndex]->name)); + SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex); + return(SK_FALSE); + } + skb_reserve(pMsgBlock, 2); /* to align IP frames */ + /* skb allocated ok, so add buffer */ + pRxd = pRxPort->pRxdRingTail; + pRxPort->pRxdRingTail = pRxd->pNextRxd; + pRxPort->RxdRingFree--; + Length = pAC->RxBufSize; +#if 0 + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + virt_to_page(pMsgBlock->data), + ((unsigned long) pMsgBlock->data & + ~PAGE_MASK), + pAC->RxBufSize - 2, + PCI_DMA_FROMDEVICE); +#else + PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32)pMsgBlock->data); +#endif + pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); + pRxd->pMBuf = pMsgBlock; + pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | + RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; + return (SK_TRUE); + +} /* FillRxDescriptor */ + + +/***************************************************************************** + * + * ReQueueRxBuffer - fill one buffer back into the receive ring + * + * Description: + * Fill a given buffer back into the rx ring. The buffer + * has been previously allocated and aligned, and its phys. + * address calculated, so this is no more necessary. + * + * Returns: N/A + */ +static void ReQueueRxBuffer( +SK_AC *pAC, /* pointer to the adapter context struct */ +RX_PORT *pRxPort, /* ptr to port struct of ring to fill */ +struct sk_buff *pMsg, /* pointer to the buffer */ +SK_U32 PhysHigh, /* phys address high dword */ +SK_U32 PhysLow) /* phys address low dword */ +{ +RXD *pRxd; /* the rxd to fill */ +SK_U16 Length; /* data fragment length */ + + pRxd = pRxPort->pRxdRingTail; + pRxPort->pRxdRingTail = pRxd->pNextRxd; + pRxPort->RxdRingFree--; + Length = pAC->RxBufSize; + pRxd->VDataLow = PhysLow; + pRxd->VDataHigh = PhysHigh; + pRxd->pMBuf = pMsg; + pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | + RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; + return; +} /* ReQueueRxBuffer */ + + +/***************************************************************************** + * + * ReceiveIrq - handle a receive IRQ + * + * Description: + * This function is called when a receive IRQ is set. + * It walks the receive descriptor ring and sends up all + * frames that are complete. + * + * Returns: N/A + */ +#if 0 +static void ReceiveIrq( +#else +void ReceiveIrq( +#endif + SK_AC *pAC, /* pointer to adapter context */ + RX_PORT *pRxPort, /* pointer to receive port struct */ + SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ +{ +RXD *pRxd; /* pointer to receive descriptors */ +SK_U32 Control; /* control field of descriptor */ +struct sk_buff *pMsg; /* pointer to message holding frame */ +struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ +int FrameLength; /* total length of received frame */ +SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ +SK_EVPARA EvPara; /* an event parameter union */ +unsigned long Flags; /* for spin lock */ +int PortIndex = pRxPort->PortIndex; +unsigned int Offset; +unsigned int NumBytes; +unsigned int ForRlmt; +SK_BOOL IsBc; +SK_BOOL IsMc; +SK_BOOL IsBadFrame; /* Bad frame */ + +SK_U32 FrameStat; +unsigned short Csum1; +unsigned short Csum2; +unsigned short Type; +#if 0 +int Result; +#endif +SK_U64 PhysAddr; + +rx_start: + /* do forever; exit if RX_CTRL_OWN_BMU found */ + for ( pRxd = pRxPort->pRxdRingHead ; + pRxPort->RxdRingFree < pAC->RxDescrPerRing ; + pRxd = pRxd->pNextRxd, + pRxPort->pRxdRingHead = pRxd, + pRxPort->RxdRingFree ++) { + + /* + * For a better understanding of this loop + * Go through every descriptor beginning at the head + * Please note: the ring might be completely received so the OWN bit + * set is not a good crirteria to leave that loop. + * Therefore the RingFree counter is used. + * On entry of this loop pRxd is a pointer to the Rxd that needs + * to be checked next. + */ + + Control = pRxd->RBControl; + + /* check if this descriptor is ready */ + if ((Control & RX_CTRL_OWN_BMU) != 0) { + /* this descriptor is not yet ready */ + /* This is the usual end of the loop */ + /* We don't need to start the ring again */ + FillRxRing(pAC, pRxPort); + return; + } + + /* get length of frame and check it */ + FrameLength = Control & RX_CTRL_LEN_MASK; + if (FrameLength > pAC->RxBufSize) { + goto rx_failed; + } + + /* check for STF and EOF */ + if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) != + (RX_CTRL_STF | RX_CTRL_EOF)) { + goto rx_failed; + } + + /* here we have a complete frame in the ring */ + pMsg = pRxd->pMBuf; + + FrameStat = pRxd->FrameStat; + + /* check for frame length mismatch */ +#define XMR_FS_LEN_SHIFT 18 +#define GMR_FS_LEN_SHIFT 16 + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("skge: Frame length mismatch (%u/%u).\n", + FrameLength, + (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); + goto rx_failed; + } + } + else { + if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("skge: Frame length mismatch (%u/%u).\n", + FrameLength, + (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); + goto rx_failed; + } + } + + /* Set Rx Status */ + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + IsBc = (FrameStat & XMR_FS_BC) != 0; + IsMc = (FrameStat & XMR_FS_MC) != 0; + IsBadFrame = (FrameStat & + (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0; + } else { + IsBc = (FrameStat & GMR_FS_BC) != 0; + IsMc = (FrameStat & GMR_FS_MC) != 0; + IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) || + ((FrameStat & GMR_FS_RX_OK) == 0)); + } + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, + ("Received frame of length %d on port %d\n", + FrameLength, PortIndex)); + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, + ("Number of free rx descriptors: %d\n", + pRxPort->RxdRingFree)); +/* DumpMsg(pMsg, "Rx"); */ + + if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID || + (IsBadFrame)) { +#if 0 + (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) { +#endif + /* there is a receive error in this frame */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("skge: Error in received frame, dropped!\n" + "Control: %x\nRxStat: %x\n", + Control, FrameStat)); + + PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; + PhysAddr |= (SK_U64) pRxd->VDataLow; + pci_dma_sync_single(pAC->PciDev, + (dma_addr_t) PhysAddr, + FrameLength, + PCI_DMA_FROMDEVICE); + ReQueueRxBuffer(pAC, pRxPort, pMsg, + pRxd->VDataHigh, pRxd->VDataLow); + + continue; + } + + /* + * if short frame then copy data to reduce memory waste + */ + if ((FrameLength < SK_COPY_THRESHOLD) && + ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) { + /* + * Short frame detected and allocation successfull + */ + /* use new skb and copy data */ + skb_reserve(pNewMsg, 2); + skb_put(pNewMsg, FrameLength); + PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; + PhysAddr |= (SK_U64) pRxd->VDataLow; + + pci_dma_sync_single(pAC->PciDev, + (dma_addr_t) PhysAddr, + FrameLength, + PCI_DMA_FROMDEVICE); + eth_copy_and_sum(pNewMsg, pMsg->data, + FrameLength, 0); + ReQueueRxBuffer(pAC, pRxPort, pMsg, + pRxd->VDataHigh, pRxd->VDataLow); + pMsg = pNewMsg; + + } + else { + /* + * if large frame, or SKB allocation failed, pass + * the SKB directly to the networking + */ + + PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; + PhysAddr |= (SK_U64) pRxd->VDataLow; + + /* release the DMA mapping */ + pci_unmap_single(pAC->PciDev, + PhysAddr, + pAC->RxBufSize - 2, + PCI_DMA_FROMDEVICE); + + /* set length in message */ + skb_put(pMsg, FrameLength); + /* hardware checksum */ + Type = ntohs(*((short*)&pMsg->data[12])); + if (Type == 0x800) { + Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); + Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff); +#if 0 + if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) && + (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + Result = SkCsGetReceiveInfo(pAC, + &pMsg->data[14], + Csum1, Csum2, pRxPort->PortIndex); + if (Result == + SKCS_STATUS_IP_FRAGMENT || + Result == + SKCS_STATUS_IP_CSUM_OK || + Result == + SKCS_STATUS_TCP_CSUM_OK || + Result == + SKCS_STATUS_UDP_CSUM_OK) { + pMsg->ip_summed = + CHECKSUM_UNNECESSARY; + } else { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("skge: CRC error. Frame dropped!\n")); + goto rx_failed; + } + }/* checksumControl calculation valid */ +#endif + } /* IP frame */ + } /* frame > SK_COPY_TRESHOLD */ + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); + ForRlmt = SK_RLMT_RX_PROTOCOL; +#if 0 + IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC; +#endif + SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, + IsBc, &Offset, &NumBytes); + if (NumBytes != 0) { +#if 0 + IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC; +#endif + SK_RLMT_LOOKAHEAD(pAC, PortIndex, + &pMsg->data[Offset], + IsBc, IsMc, &ForRlmt); + } + if (ForRlmt == SK_RLMT_RX_PROTOCOL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); + /* send up only frames from active port */ + if ((PortIndex == pAC->ActivePort) || + (pAC->RlmtNets == 2)) { + /* frame for upper layer */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U")); +#ifdef xDEBUG + DumpMsg(pMsg, "Rx"); +#endif + SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, + FrameLength, pRxPort->PortIndex); + +#if 0 + pMsg->dev = pAC->dev[pRxPort->PortIndex]; + pMsg->protocol = eth_type_trans(pMsg, + pAC->dev[pRxPort->PortIndex]); + netif_rx(pMsg); + pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; +#else + NetReceive(pMsg->data, pMsg->len); + dev_kfree_skb_any(pMsg); +#endif + } + else { + /* drop frame */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("D")); + DEV_KFREE_SKB(pMsg); + } + + } /* if not for rlmt */ + else { + /* packet for rlmt */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, ("R")); + pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, + pAC->IoBase, FrameLength); + if (pRlmtMbuf != NULL) { + pRlmtMbuf->pNext = NULL; + pRlmtMbuf->Length = FrameLength; + pRlmtMbuf->PortIdx = PortIndex; + EvPara.pParaPtr = pRlmtMbuf; + memcpy((char*)(pRlmtMbuf->pData), + (char*)(pMsg->data), + FrameLength); + + /* SlowPathLock needed? */ + if (SlowPathLock == SK_TRUE) { + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + SkEventQueue(pAC, SKGE_RLMT, + SK_RLMT_PACKET_RECEIVED, + EvPara); + pAC->CheckQueue = SK_TRUE; + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } else { + SkEventQueue(pAC, SKGE_RLMT, + SK_RLMT_PACKET_RECEIVED, + EvPara); + pAC->CheckQueue = SK_TRUE; + } + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("Q")); + } +#if 0 + if ((pAC->dev[pRxPort->PortIndex]->flags & + (IFF_PROMISC | IFF_ALLMULTI)) != 0 || + (ForRlmt & SK_RLMT_RX_PROTOCOL) == + SK_RLMT_RX_PROTOCOL) { + pMsg->dev = pAC->dev[pRxPort->PortIndex]; + pMsg->protocol = eth_type_trans(pMsg, + pAC->dev[pRxPort->PortIndex]); + netif_rx(pMsg); + pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; + } +#else + if (0) { + } +#endif + else { + DEV_KFREE_SKB(pMsg); + } + + } /* if packet for rlmt */ + } /* for ... scanning the RXD ring */ + + /* RXD ring is empty -> fill and restart */ + FillRxRing(pAC, pRxPort); + /* do not start if called from Close */ + if (pAC->BoardLevel > 0) { + ClearAndStartRx(pAC, PortIndex); + } + return; + +rx_failed: + /* remove error frame */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, + ("Schrottdescriptor, length: 0x%x\n", FrameLength)); + + /* release the DMA mapping */ + + PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; + PhysAddr |= (SK_U64) pRxd->VDataLow; + pci_unmap_page(pAC->PciDev, + PhysAddr, + pAC->RxBufSize - 2, + PCI_DMA_FROMDEVICE); + DEV_KFREE_SKB_IRQ(pRxd->pMBuf); + pRxd->pMBuf = NULL; + pRxPort->RxdRingFree++; + pRxPort->pRxdRingHead = pRxd->pNextRxd; + goto rx_start; + +} /* ReceiveIrq */ + + +/***************************************************************************** + * + * ClearAndStartRx - give a start receive command to BMU, clear IRQ + * + * Description: + * This function sends a start command and a clear interrupt + * command for one receive queue to the BMU. + * + * Returns: N/A + * none + */ +static void ClearAndStartRx( +SK_AC *pAC, /* pointer to the adapter context */ +int PortIndex) /* index of the receive port (XMAC) */ +{ + SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL, + RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF); +} /* ClearAndStartRx */ + + +/***************************************************************************** + * + * ClearTxIrq - give a clear transmit IRQ command to BMU + * + * Description: + * This function sends a clear tx IRQ command for one + * transmit queue to the BMU. + * + * Returns: N/A + */ +static void ClearTxIrq( +SK_AC *pAC, /* pointer to the adapter context */ +int PortIndex, /* index of the transmit port (XMAC) */ +int Prio) /* priority or normal queue */ +{ + SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL, + TX_Q_CTRL_CLR_I_EOF); +} /* ClearTxIrq */ + + +/***************************************************************************** + * + * ClearRxRing - remove all buffers from the receive ring + * + * Description: + * This function removes all receive buffers from the ring. + * The receive BMU must be stopped before calling this function. + * + * Returns: N/A + */ +static void ClearRxRing( +SK_AC *pAC, /* pointer to adapter context */ +RX_PORT *pRxPort) /* pointer to rx port struct */ +{ +RXD *pRxd; /* pointer to the current descriptor */ +unsigned long Flags; +SK_U64 PhysAddr; + + if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) { + return; + } + spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); + pRxd = pRxPort->pRxdRingHead; + do { + if (pRxd->pMBuf != NULL) { + + PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; + PhysAddr |= (SK_U64) pRxd->VDataLow; + pci_unmap_page(pAC->PciDev, + PhysAddr, + pAC->RxBufSize - 2, + PCI_DMA_FROMDEVICE); + DEV_KFREE_SKB(pRxd->pMBuf); + pRxd->pMBuf = NULL; + } + pRxd->RBControl &= RX_CTRL_OWN_BMU; + pRxd = pRxd->pNextRxd; + pRxPort->RxdRingFree++; + } while (pRxd != pRxPort->pRxdRingTail); + pRxPort->pRxdRingTail = pRxPort->pRxdRingHead; + spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); +} /* ClearRxRing */ + + +/***************************************************************************** + * + * ClearTxRing - remove all buffers from the transmit ring + * + * Description: + * This function removes all transmit buffers from the ring. + * The transmit BMU must be stopped before calling this function + * and transmitting at the upper level must be disabled. + * The BMU own bit of all descriptors is cleared, the rest is + * done by calling FreeTxDescriptors. + * + * Returns: N/A + */ +static void ClearTxRing( +SK_AC *pAC, /* pointer to adapter context */ +TX_PORT *pTxPort) /* pointer to tx prt struct */ +{ +TXD *pTxd; /* pointer to the current descriptor */ +int i; +unsigned long Flags; + + spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); + pTxd = pTxPort->pTxdRingHead; + for (i=0; iTxDescrPerRing; i++) { + pTxd->TBControl &= ~TX_CTRL_OWN_BMU; + pTxd = pTxd->pNextTxd; + } + FreeTxDescriptors(pAC, pTxPort); + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); +} /* ClearTxRing */ + + +#if 0 +/***************************************************************************** + * + * SetQueueSizes - configure the sizes of rx and tx queues + * + * Description: + * This function assigns the sizes for active and passive port + * to the appropriate HWinit structure variables. + * The passive port(s) get standard values, all remaining RAM + * is given to the active port. + * The queue sizes are in kbyte and must be multiple of 8. + * The limits for the number of buffers filled into the rx rings + * is also set in this routine. + * + * Returns: + * none + */ +static void SetQueueSizes( +SK_AC *pAC) /* pointer to the adapter context */ +{ +int StandbyRam; /* adapter RAM used for a standby port */ +int RemainingRam; /* adapter RAM available for the active port */ +int RxRam; /* RAM used for the active port receive queue */ +int i; /* loop counter */ + +if (pAC->RlmtNets == 1) { + StandbyRam = SK_RLMT_STANDBY_QRXSIZE + SK_RLMT_STANDBY_QXASIZE + + SK_RLMT_STANDBY_QXSSIZE; + RemainingRam = pAC->GIni.GIRamSize - + (pAC->GIni.GIMacsFound-1) * StandbyRam; + for (i=0; iGIni.GIMacsFound; i++) { + pAC->GIni.GP[i].PRxQSize = SK_RLMT_STANDBY_QRXSIZE; + pAC->GIni.GP[i].PXSQSize = SK_RLMT_STANDBY_QXSSIZE; + pAC->GIni.GP[i].PXAQSize = SK_RLMT_STANDBY_QXASIZE; + } + RxRam = (RemainingRam * 8 / 10) & ~7; + pAC->GIni.GP[pAC->ActivePort].PRxQSize = RxRam; + pAC->GIni.GP[pAC->ActivePort].PXSQSize = 0; + pAC->GIni.GP[pAC->ActivePort].PXAQSize = + (RemainingRam - RxRam) & ~7; + pAC->RxQueueSize = RxRam; + pAC->TxSQueueSize = 0; + pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("queue sizes settings - rx:%d txA:%d txS:%d\n", + pAC->RxQueueSize,pAC->TxAQueueSize, pAC->TxSQueueSize)); +} else { + RemainingRam = pAC->GIni.GIRamSize/pAC->GIni.GIMacsFound; + RxRam = (RemainingRam * 8 / 10) & ~7; + for (i=0; iGIni.GIMacsFound; i++) { + pAC->GIni.GP[i].PRxQSize = RxRam; + pAC->GIni.GP[i].PXSQSize = 0; + pAC->GIni.GP[i].PXAQSize = (RemainingRam - RxRam) & ~7; + } + + pAC->RxQueueSize = RxRam; + pAC->TxSQueueSize = 0; + pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; +} + for (i=0; iRxPort[i].RxFillLimit = pAC->RxDescrPerRing; + } + + if (pAC->RlmtNets == 2) { + for (i=0; iGIni.GIMacsFound; i++) { + pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; + } + } else { + for (i=0; iGIni.GIMacsFound; i++) { + pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; + } + /* + * Do not set the Limit to 0, because this could cause + * wrap around with ReQueue'ed buffers (a buffer could + * be requeued in the same position, made accessable to + * the hardware, and the hardware could change its + * contents! + */ + pAC->RxPort[pAC->ActivePort].RxFillLimit = 1; + } + +#ifdef DEBUG + for (i=0; iGIni.GIMacsFound; i++) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("i: %d, RxQSize: %d, PXSQsize: %d, PXAQSize: %d\n", + i, + pAC->GIni.GP[i].PRxQSize, + pAC->GIni.GP[i].PXSQSize, + pAC->GIni.GP[i].PXAQSize)); + } +#endif +} /* SetQueueSizes */ + + +/***************************************************************************** + * + * SkGeSetMacAddr - Set the hardware MAC address + * + * Description: + * This function sets the MAC address used by the adapter. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) +{ + +DEV_NET *pNet = (DEV_NET*) dev->priv; +SK_AC *pAC = pNet->pAC; + +struct sockaddr *addr = p; +unsigned long Flags; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeSetMacAddr starts now...\n")); + if(netif_running(dev)) + return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + + if (pAC->RlmtNets == 2) + SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, + (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); + else + SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, + (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); + + + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return 0; +} /* SkGeSetMacAddr */ +#endif + + +/***************************************************************************** + * + * SkGeSetRxMode - set receive mode + * + * Description: + * This function sets the receive mode of an adapter. The adapter + * supports promiscuous mode, allmulticast mode and a number of + * multicast addresses. If more multicast addresses the available + * are selected, a hash function in the hardware is used. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +#if 0 +static void SkGeSetRxMode(struct SK_NET_DEVICE *dev) +{ + +DEV_NET *pNet; +SK_AC *pAC; + +struct dev_mc_list *pMcList; +int i; +int PortIdx; +unsigned long Flags; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeSetRxMode starts now... ")); + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + if (pAC->RlmtNets == 1) + PortIdx = pAC->ActivePort; + else + PortIdx = pNet->NetNr; + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + if (dev->flags & IFF_PROMISC) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("PROMISCUOUS mode\n")); + SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, + SK_PROM_MODE_LLC); + } else if (dev->flags & IFF_ALLMULTI) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("ALLMULTI mode\n")); + SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, + SK_PROM_MODE_ALL_MC); + } else { + SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, + SK_PROM_MODE_NONE); + SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("Number of MC entries: %d ", dev->mc_count)); + + pMcList = dev->mc_list; + for (i=0; imc_count; i++, pMcList = pMcList->next) { + SkAddrMcAdd(pAC, pAC->IoBase, PortIdx, + (SK_MAC_ADDR*)pMcList->dmi_addr, 0); + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA, + ("%02x:%02x:%02x:%02x:%02x:%02x\n", + pMcList->dmi_addr[0], + pMcList->dmi_addr[1], + pMcList->dmi_addr[2], + pMcList->dmi_addr[3], + pMcList->dmi_addr[4], + pMcList->dmi_addr[5])); + } + SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx); + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + return; +} /* SkGeSetRxMode */ + + +/***************************************************************************** + * + * SkGeChangeMtu - set the MTU to another value + * + * Description: + * This function sets is called whenever the MTU size is changed + * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard + * ethernet MTU size, long frame support is activated. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) +{ +DEV_NET *pNet; +DEV_NET *pOtherNet; +SK_AC *pAC; +unsigned long Flags; +int i; +SK_EVPARA EvPara; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeChangeMtu starts now...\n")); + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { + return -EINVAL; + } + + if(pAC->BoardLevel != 2) { + return -EINVAL; + } + + pNet->Mtu = NewMtu; + pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv; + if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) { + return(0); + } + + EvPara.Para32[0] = pNet->NetNr; + EvPara.Para32[1] = -1; + + pAC->RxBufSize = NewMtu + 32; + dev->mtu = NewMtu; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("New MTU: %d\n", NewMtu)); + + /* prevent reconfiguration while changing the MTU */ + + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + + /* Found more than one port */ + if ((pAC->GIni.GIMacsFound == 2 ) && + (pAC->RlmtNets == 2)) { + /* Stop both ports */ + EvPara.Para32[0] = 0; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + EvPara.Para32[0] = 1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + } else { + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + } + + SkEventDispatcher(pAC, pAC->IoBase); + + for (i=0; iGIni.GIMacsFound; i++) { + spin_lock_irqsave( + &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); + netif_stop_queue(pAC->dev[i]); + + } + + /* + * adjust number of rx buffers allocated + */ + if (NewMtu > 1500) { + /* use less rx buffers */ + for (i=0; iGIni.GIMacsFound; i++) { + /* Found more than one port */ + if ((pAC->GIni.GIMacsFound == 2 ) && + (pAC->RlmtNets == 2)) { + pAC->RxPort[i].RxFillLimit = + pAC->RxDescrPerRing - 100; + } else { + if (i == pAC->ActivePort) + pAC->RxPort[i].RxFillLimit = + pAC->RxDescrPerRing - 100; + else + pAC->RxPort[i].RxFillLimit = + pAC->RxDescrPerRing - 10; + } + } + } + else { + /* use normal amount of rx buffers */ + for (i=0; iGIni.GIMacsFound; i++) { + /* Found more than one port */ + if ((pAC->GIni.GIMacsFound == 2 ) && + (pAC->RlmtNets == 2)) { + pAC->RxPort[i].RxFillLimit = 1; + } else { + if (i == pAC->ActivePort) + pAC->RxPort[i].RxFillLimit = 1; + else + pAC->RxPort[i].RxFillLimit = + pAC->RxDescrPerRing - 100; + } + } + } + + SkGeDeInit(pAC, pAC->IoBase); + + /* + * enable/disable hardware support for long frames + */ + if (NewMtu > 1500) { +/* pAC->JumboActivated = SK_TRUE; /#* is never set back !!! */ + pAC->GIni.GIPortUsage = SK_JUMBO_LINK; + } + else { + if ((pAC->GIni.GIMacsFound == 2 ) && + (pAC->RlmtNets == 2)) { + pAC->GIni.GIPortUsage = SK_MUL_LINK; + } else { + pAC->GIni.GIPortUsage = SK_RED_LINK; + } + } + + SkGeInit( pAC, pAC->IoBase, 1); + SkI2cInit( pAC, pAC->IoBase, 1); + SkEventInit(pAC, pAC->IoBase, 1); + SkPnmiInit( pAC, pAC->IoBase, 1); + SkAddrInit( pAC, pAC->IoBase, 1); + SkRlmtInit( pAC, pAC->IoBase, 1); + SkTimerInit(pAC, pAC->IoBase, 1); + + /* + * tschilling: + * Speed and others are set back to default in level 1 init! + */ + GetConfiguration(pAC); + + SkGeInit( pAC, pAC->IoBase, 2); + SkI2cInit( pAC, pAC->IoBase, 2); + SkEventInit(pAC, pAC->IoBase, 2); + SkPnmiInit( pAC, pAC->IoBase, 2); + SkAddrInit( pAC, pAC->IoBase, 2); + SkRlmtInit( pAC, pAC->IoBase, 2); + SkTimerInit(pAC, pAC->IoBase, 2); + + /* + * clear and reinit the rx rings here + */ + for (i=0; iGIni.GIMacsFound; i++) { + ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); + ClearRxRing(pAC, &pAC->RxPort[i]); + FillRxRing(pAC, &pAC->RxPort[i]); + + /* Enable transmit descriptor polling. */ + SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); + FillRxRing(pAC, &pAC->RxPort[i]); + }; + + SkGeYellowLED(pAC, pAC->IoBase, 1); + +#ifdef USE_INT_MOD + { + unsigned long ModBase; + ModBase = 53125000 / INTS_PER_SEC; + SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); + SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); + SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); + } +#endif + + netif_start_queue(pAC->dev[pNet->PortNr]); + for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { + spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); + } + + /* enable Interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); + + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + + /* Found more than one port */ + if ((pAC->GIni.GIMacsFound == 2 ) && + (pAC->RlmtNets == 2)) { + /* Start both ports */ + EvPara.Para32[0] = pAC->RlmtNets; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, + EvPara); + + + EvPara.Para32[1] = -1; + EvPara.Para32[0] = pNet->PortNr; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); + + if (pOtherNet->Up) { + EvPara.Para32[0] = pOtherNet->PortNr; + SkEventQueue(pAC, SKGE_RLMT, + SK_RLMT_START, EvPara); + } + } else { + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); + } + + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + return 0; +} /* SkGeChangeMtu */ + + +/***************************************************************************** + * + * SkGeStats - return ethernet device statistics + * + * Description: + * This function return statistic data about the ethernet device + * to the operating system. + * + * Returns: + * pointer to the statistic structure. + */ +static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) +{ +DEV_NET *pNet = (DEV_NET*) dev->priv; +SK_AC *pAC = pNet->pAC; +SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */ +SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */ +SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */ +unsigned int Size; /* size of pnmi struct */ +unsigned long Flags; /* for spin lock */ + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeStats starts now...\n")); + pPnmiStruct = &pAC->PnmiStruct; + memset(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + Size = SK_PNMI_STRUCT_SIZE; + SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pPnmiStat = &pPnmiStruct->Stat[0]; + pPnmiConf = &pPnmiStruct->Conf[0]; + + pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF; + pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF; + pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; + pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; + + if (pNet->Mtu <= 1500) { + pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; + } else { + pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - + pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF); + } + + + if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12) + pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts; + + pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; + pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF; + pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF; + pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF; + pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; + + /* detailed rx_errors: */ + pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF; + pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; + pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF; + pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF; + pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; + pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF; + + /* detailed tx_errors */ + pAC->stats.tx_aborted_errors = (SK_U32) 0; + pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; + pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF; + pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; + pAC->stats.tx_window_errors = (SK_U32) 0; + + return(&pAC->stats); +} /* SkGeStats */ + + +/***************************************************************************** + * + * SkGeIoctl - IO-control function + * + * Description: + * This function is called if an ioctl is issued on the device. + * There are three subfunction for reading, writing and test-writing + * the private MIB data structure (usefull for SysKonnect-internal tools). + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd) +{ +DEV_NET *pNet; +SK_AC *pAC; + +SK_GE_IOCTL Ioctl; +unsigned int Err = 0; +int Size; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeIoctl starts now...\n")); + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { + return -EFAULT; + } + + switch(cmd) { + case SK_IOCTL_SETMIB: + case SK_IOCTL_PRESETMIB: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + case SK_IOCTL_GETMIB: + if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, + Ioctl.LenPnmiStruct)? + Ioctl.Len : sizeof(pAC->PnmiStruct))) { + return -EFAULT; + } + Size = SkGeIocMib(pNet, Ioctl.Len, cmd); + if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct, + Ioctl.Lenifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { + return -EFAULT; + } + break; + default: + Err = -EOPNOTSUPP; + } + return(Err); +} /* SkGeIoctl */ + + +/***************************************************************************** + * + * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message + * + * Description: + * This function reads/writes the MIB data using PNMI (Private Network + * Management Interface). + * The destination for the data must be provided with the + * ioctl call and is given to the driver in the form of + * a user space address. + * Copying from the user-provided data area into kernel messages + * and back is done by copy_from_user and copy_to_user calls in + * SkGeIoctl. + * + * Returns: + * returned size from PNMI call + */ +static int SkGeIocMib( +DEV_NET *pNet, /* pointer to the adapter context */ +unsigned int Size, /* length of ioctl data */ +int mode) /* flag for set/preset */ +{ +unsigned long Flags; /* for spin lock */ +SK_AC *pAC; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeIocMib starts now...\n")); + pAC = pNet->pAC; + /* access MIB */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + switch(mode) { + case SK_IOCTL_GETMIB: + SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, + pNet->NetNr); + break; + case SK_IOCTL_PRESETMIB: + SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, + pNet->NetNr); + break; + case SK_IOCTL_SETMIB: + SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, + pNet->NetNr); + break; + default: + break; + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("MIB data access succeeded\n")); + return (Size); +} /* SkGeIocMib */ +#endif + + +/***************************************************************************** + * + * GetConfiguration - read configuration information + * + * Description: + * This function reads per-adapter configuration information from + * the options provided on the command line. + * + * Returns: + * none + */ +static void GetConfiguration( +SK_AC *pAC) /* pointer to the adapter context structure */ +{ +SK_I32 Port; /* preferred port */ +int LinkSpeed; /* Link speed */ +int AutoNeg; /* auto negotiation off (0) or on (1) */ +int DuplexCap; /* duplex capabilities (0=both, 1=full, 2=half */ +int MSMode; /* master / slave mode selection */ +SK_BOOL AutoSet; +SK_BOOL DupSet; +/* + * The two parameters AutoNeg. and DuplexCap. map to one configuration + * parameter. The mapping is described by this table: + * DuplexCap -> | both | full | half | + * AutoNeg | | | | + * ----------------------------------------------------------------- + * Off | illegal | Full | Half | + * ----------------------------------------------------------------- + * On | AutoBoth | AutoFull | AutoHalf | + * ----------------------------------------------------------------- + * Sense | AutoSense | AutoSense | AutoSense | + */ +int Capabilities[3][3] = + { { -1, SK_LMODE_FULL, SK_LMODE_HALF}, + {SK_LMODE_AUTOBOTH, SK_LMODE_AUTOFULL, SK_LMODE_AUTOHALF}, + {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} }; +#define DC_BOTH 0 +#define DC_FULL 1 +#define DC_HALF 2 +#define AN_OFF 0 +#define AN_ON 1 +#define AN_SENS 2 + + /* settings for port A */ + /* settings link speed */ + LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ + if (Speed_A != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(Speed_A[pAC->Index],"")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } + else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } + else if (strcmp(Speed_A[pAC->Index],"10")==0) { + LinkSpeed = SK_LSPEED_10MBPS; + } + else if (strcmp(Speed_A[pAC->Index],"100")==0) { + LinkSpeed = SK_LSPEED_100MBPS; + } + else if (strcmp(Speed_A[pAC->Index],"1000")==0) { + LinkSpeed = SK_LSPEED_1000MBPS; + } + else printk("%s: Illegal value for Speed_A\n", + pAC->dev[0]->name); + } + + /* Check speed parameter */ + /* Only copper type adapter and GE V2 cards */ + if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || + (pAC->GIni.GICopperType != SK_TRUE)) && + ((LinkSpeed != SK_LSPEED_AUTO) && + (LinkSpeed != SK_LSPEED_1000MBPS))) { + printk("%s: Illegal value for Speed_A. " + "Not a copper card or GE V2 card\n Using " + "speed 1000\n", pAC->dev[0]->name); + LinkSpeed = SK_LSPEED_1000MBPS; + } + pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; + + /* Autonegotiation */ + AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */ + AutoSet = SK_FALSE; + if (AutoNeg_A != NULL && pAC->IndexIndex] != NULL) { + AutoSet = SK_TRUE; + if (strcmp(AutoNeg_A[pAC->Index],"")==0) { + AutoSet = SK_FALSE; + } + else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { + AutoNeg = AN_ON; + } + else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { + AutoNeg = AN_OFF; + } + else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { + AutoNeg = AN_SENS; + } + else printk("%s: Illegal value for AutoNeg_A\n", + pAC->dev[0]->name); + } + + DuplexCap = DC_BOTH; + DupSet = SK_FALSE; + if (DupCap_A != NULL && pAC->IndexIndex] != NULL) { + DupSet = SK_TRUE; + if (strcmp(DupCap_A[pAC->Index],"")==0) { + DupSet = SK_FALSE; + } + else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { + DuplexCap = DC_BOTH; + } + else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { + DuplexCap = DC_FULL; + } + else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { + DuplexCap = DC_HALF; + } + else printk("%s: Illegal value for DupCap_A\n", + pAC->dev[0]->name); + } + + /* check for illegal combinations */ + if (AutoSet && AutoNeg==AN_SENS && DupSet) { + printk("%s, Port A: DuplexCapabilities" + " ignored using Sense mode\n", pAC->dev[0]->name); + } + if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ + printk("%s, Port A: Illegal combination" + " of values AutoNeg. and DuplexCap.\n Using " + "Full Duplex\n", pAC->dev[0]->name); + + DuplexCap = DC_FULL; + } + if (AutoSet && AutoNeg==AN_OFF && !DupSet) { + DuplexCap = DC_FULL; + } + + if (!AutoSet && DupSet) { + printk("%s, Port A: Duplex setting not" + " possible in\n default AutoNegotiation mode" + " (Sense).\n Using AutoNegotiation On\n", + pAC->dev[0]->name); + AutoNeg = AN_ON; + } + + /* set the desired mode */ + pAC->GIni.GP[0].PLinkModeConf = + Capabilities[AutoNeg][DuplexCap]; + + pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + if (FlowCtrl_A != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) { + } + else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { + pAC->GIni.GP[0].PFlowCtrlMode = + SK_FLOW_MODE_SYM_OR_REM; + } + else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { + pAC->GIni.GP[0].PFlowCtrlMode = + SK_FLOW_MODE_SYMMETRIC; + } + else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { + pAC->GIni.GP[0].PFlowCtrlMode = + SK_FLOW_MODE_LOC_SEND; + } + else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { + pAC->GIni.GP[0].PFlowCtrlMode = + SK_FLOW_MODE_NONE; + } + else printk("Illegal value for FlowCtrl_A\n"); + } + if (AutoNeg==AN_OFF && pAC->GIni.GP[0].PFlowCtrlMode!= + SK_FLOW_MODE_NONE) { + printk("%s, Port A: FlowControl" + " impossible without AutoNegotiation," + " disabled\n", pAC->dev[0]->name); + pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_NONE; + } + + MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ + if (Role_A != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(Role_A[pAC->Index],"")==0) { + } + else if (strcmp(Role_A[pAC->Index],"Auto")==0) { + MSMode = SK_MS_MODE_AUTO; + } + else if (strcmp(Role_A[pAC->Index],"Master")==0) { + MSMode = SK_MS_MODE_MASTER; + } + else if (strcmp(Role_A[pAC->Index],"Slave")==0) { + MSMode = SK_MS_MODE_SLAVE; + } + else printk("%s: Illegal value for Role_A\n", + pAC->dev[0]->name); + } + pAC->GIni.GP[0].PMSMode = MSMode; + + + /* settings for port B */ + /* settings link speed */ + LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ + if (Speed_B != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(Speed_B[pAC->Index],"")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } + else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } + else if (strcmp(Speed_B[pAC->Index],"10")==0) { + LinkSpeed = SK_LSPEED_10MBPS; + } + else if (strcmp(Speed_B[pAC->Index],"100")==0) { + LinkSpeed = SK_LSPEED_100MBPS; + } + else if (strcmp(Speed_B[pAC->Index],"1000")==0) { + LinkSpeed = SK_LSPEED_1000MBPS; + } + else printk("%s: Illegal value for Speed_B\n", + pAC->dev[1]->name); + } + + /* Check speed parameter */ + /* Only copper type adapter and GE V2 cards */ + if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || + (pAC->GIni.GICopperType != SK_TRUE)) && + ((LinkSpeed != SK_LSPEED_AUTO) && + (LinkSpeed != SK_LSPEED_1000MBPS))) { + printk("%s: Illegal value for Speed_B. " + "Not a copper card or GE V2 card\n Using " + "speed 1000\n", pAC->dev[1]->name); + LinkSpeed = SK_LSPEED_1000MBPS; + } + pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; + + /* Auto negotiation */ + AutoNeg = AN_SENS; /* default: do auto Sense */ + AutoSet = SK_FALSE; + if (AutoNeg_B != NULL && pAC->IndexIndex] != NULL) { + AutoSet = SK_TRUE; + if (strcmp(AutoNeg_B[pAC->Index],"")==0) { + AutoSet = SK_FALSE; + } + else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { + AutoNeg = AN_ON; + } + else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { + AutoNeg = AN_OFF; + } + else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { + AutoNeg = AN_SENS; + } + else printk("Illegal value for AutoNeg_B\n"); + } + + DuplexCap = DC_BOTH; + DupSet = SK_FALSE; + if (DupCap_B != NULL && pAC->IndexIndex] != NULL) { + DupSet = SK_TRUE; + if (strcmp(DupCap_B[pAC->Index],"")==0) { + DupSet = SK_FALSE; + } + else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { + DuplexCap = DC_BOTH; + } + else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { + DuplexCap = DC_FULL; + } + else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { + DuplexCap = DC_HALF; + } + else printk("Illegal value for DupCap_B\n"); + } + + /* check for illegal combinations */ + if (AutoSet && AutoNeg==AN_SENS && DupSet) { + printk("%s, Port B: DuplexCapabilities" + " ignored using Sense mode\n", pAC->dev[1]->name); + } + if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ + printk("%s, Port B: Illegal combination" + " of values AutoNeg. and DuplexCap.\n Using " + "Full Duplex\n", pAC->dev[1]->name); + + DuplexCap = DC_FULL; + } + if (AutoSet && AutoNeg==AN_OFF && !DupSet) { + DuplexCap = DC_FULL; + } + + if (!AutoSet && DupSet) { + printk("%s, Port B: Duplex setting not" + " possible in\n default AutoNegotiation mode" + " (Sense).\n Using AutoNegotiation On\n", + pAC->dev[1]->name); + AutoNeg = AN_ON; + } + + /* set the desired mode */ + pAC->GIni.GP[1].PLinkModeConf = + Capabilities[AutoNeg][DuplexCap]; + + pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + if (FlowCtrl_B != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) { + } + else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { + pAC->GIni.GP[1].PFlowCtrlMode = + SK_FLOW_MODE_SYM_OR_REM; + } + else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { + pAC->GIni.GP[1].PFlowCtrlMode = + SK_FLOW_MODE_SYMMETRIC; + } + else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { + pAC->GIni.GP[1].PFlowCtrlMode = + SK_FLOW_MODE_LOC_SEND; + } + else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { + pAC->GIni.GP[1].PFlowCtrlMode = + SK_FLOW_MODE_NONE; + } + else printk("Illegal value for FlowCtrl_B\n"); + } + if (AutoNeg==AN_OFF && pAC->GIni.GP[1].PFlowCtrlMode!= + SK_FLOW_MODE_NONE) { + printk("%s, Port B: FlowControl" + " impossible without AutoNegotiation," + " disabled\n", pAC->dev[1]->name); + pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_NONE; + } + + MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ + if (Role_B != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(Role_B[pAC->Index],"")==0) { + } + else if (strcmp(Role_B[pAC->Index],"Auto")==0) { + MSMode = SK_MS_MODE_AUTO; + } + else if (strcmp(Role_B[pAC->Index],"Master")==0) { + MSMode = SK_MS_MODE_MASTER; + } + else if (strcmp(Role_B[pAC->Index],"Slave")==0) { + MSMode = SK_MS_MODE_SLAVE; + } + else printk("%s: Illegal value for Role_B\n", + pAC->dev[1]->name); + } + pAC->GIni.GP[1].PMSMode = MSMode; + + + /* settings for both ports */ + pAC->ActivePort = 0; + if (PrefPort != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ + pAC->ActivePort = 0; + pAC->Rlmt.Net[0].Preference = -1; /* auto */ + pAC->Rlmt.Net[0].PrefPort = 0; + } + else if (strcmp(PrefPort[pAC->Index],"A") == 0) { + /* + * do not set ActivePort here, thus a port + * switch is issued after net up. + */ + Port = 0; + pAC->Rlmt.Net[0].Preference = Port; + pAC->Rlmt.Net[0].PrefPort = Port; + } + else if (strcmp(PrefPort[pAC->Index],"B") == 0) { + /* + * do not set ActivePort here, thus a port + * switch is issued after net up. + */ + Port = 1; + pAC->Rlmt.Net[0].Preference = Port; + pAC->Rlmt.Net[0].PrefPort = Port; + } + else printk("%s: Illegal value for PrefPort\n", + pAC->dev[0]->name); + } + + pAC->RlmtNets = 1; + + if (RlmtMode != NULL && pAC->IndexIndex] != NULL) { + if (strcmp(RlmtMode[pAC->Index], "") == 0) { + pAC->RlmtMode = 0; + } + else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + } + else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK | + SK_RLMT_CHECK_LOC_LINK; + } + else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK | + SK_RLMT_CHECK_LOC_LINK | + SK_RLMT_CHECK_SEG; + } + else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && + (pAC->GIni.GIMacsFound == 2)) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + pAC->RlmtNets = 2; + } + else { + printk("%s: Illegal value for" + " RlmtMode, using default\n", pAC->dev[0]->name); + pAC->RlmtMode = 0; + } + } + else { + pAC->RlmtMode = 0; + } +} /* GetConfiguration */ + + +/***************************************************************************** + * + * ProductStr - return a adapter identification string from vpd + * + * Description: + * This function reads the product name string from the vpd area + * and puts it the field pAC->DeviceString. + * + * Returns: N/A + */ +static void ProductStr( +SK_AC *pAC /* pointer to adapter context */ +) +{ +int StrLen = 80; /* length of the string, defined in SK_AC */ +char Keyword[] = VPD_NAME; /* vpd productname identifier */ +int ReturnCode; /* return code from vpd_read */ +unsigned long Flags; + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr, + &StrLen); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + if (ReturnCode != 0) { + /* there was an error reading the vpd data */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, + ("Error reading VPD data: %d\n", ReturnCode)); + pAC->DeviceStr[0] = '\0'; + } +} /* ProductStr */ + + +/****************************************************************************/ +/* functions for common modules *********************************************/ +/****************************************************************************/ + + +/***************************************************************************** + * + * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf + * + * Description: + * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure + * is embedded into a socket buff data area. + * + * Context: + * runtime + * + * Returns: + * NULL or pointer to Mbuf. + */ +SK_MBUF *SkDrvAllocRlmtMbuf( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* the IO-context */ +unsigned BufferSize) /* size of the requested buffer */ +{ +SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */ +struct sk_buff *pMsgBlock; /* pointer to a new message block */ + + pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC); + if (pMsgBlock == NULL) { + return (NULL); + } + pRlmtMbuf = (SK_MBUF*) pMsgBlock->data; + skb_reserve(pMsgBlock, sizeof(SK_MBUF)); + pRlmtMbuf->pNext = NULL; + pRlmtMbuf->pOs = pMsgBlock; + pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */ + pRlmtMbuf->Size = BufferSize; /* Data buffer size. */ + pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */ + return (pRlmtMbuf); + +} /* SkDrvAllocRlmtMbuf */ + + +/***************************************************************************** + * + * SkDrvFreeRlmtMbuf - free an RLMT mbuf + * + * Description: + * This routine frees one or more RLMT mbuf(s). + * + * Context: + * runtime + * + * Returns: + * Nothing + */ +void SkDrvFreeRlmtMbuf( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* the IO-context */ +SK_MBUF *pMbuf) /* size of the requested buffer */ +{ +SK_MBUF *pFreeMbuf; +SK_MBUF *pNextMbuf; + + pFreeMbuf = pMbuf; + do { + pNextMbuf = pFreeMbuf->pNext; + DEV_KFREE_SKB_ANY(pFreeMbuf->pOs); + pFreeMbuf = pNextMbuf; + } while ( pFreeMbuf != NULL ); +} /* SkDrvFreeRlmtMbuf */ + + +/***************************************************************************** + * + * SkOsGetTime - provide a time value + * + * Description: + * This routine provides a time value. The unit is 1/HZ (defined by Linux). + * It is not used for absolute time, but only for time differences. + * + * + * Returns: + * Time value + */ +SK_U64 SkOsGetTime(SK_AC *pAC) +{ +#if 0 + return jiffies; +#else + return get_timer(0); +#endif +} /* SkOsGetTime */ + + +/***************************************************************************** + * + * SkPciReadCfgDWord - read a 32 bit value from pci config space + * + * Description: + * This routine reads a 32 bit value from the pci configuration + * space. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciReadCfgDWord( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U32 *pVal) /* pointer to store the read value */ +{ + pci_read_config_dword(pAC->PciDev, PciAddr, pVal); + return(0); +} /* SkPciReadCfgDWord */ + + +/***************************************************************************** + * + * SkPciReadCfgWord - read a 16 bit value from pci config space + * + * Description: + * This routine reads a 16 bit value from the pci configuration + * space. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciReadCfgWord( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U16 *pVal) /* pointer to store the read value */ +{ + pci_read_config_word(pAC->PciDev, PciAddr, pVal); + return(0); +} /* SkPciReadCfgWord */ + + +/***************************************************************************** + * + * SkPciReadCfgByte - read a 8 bit value from pci config space + * + * Description: + * This routine reads a 8 bit value from the pci configuration + * space. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciReadCfgByte( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U8 *pVal) /* pointer to store the read value */ +{ + pci_read_config_byte(pAC->PciDev, PciAddr, pVal); + return(0); +} /* SkPciReadCfgByte */ + + +/***************************************************************************** + * + * SkPciWriteCfgDWord - write a 32 bit value to pci config space + * + * Description: + * This routine writes a 32 bit value to the pci configuration + * space. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciWriteCfgDWord( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U32 Val) /* pointer to store the read value */ +{ + pci_write_config_dword(pAC->PciDev, PciAddr, Val); + return(0); +} /* SkPciWriteCfgDWord */ + + +/***************************************************************************** + * + * SkPciWriteCfgWord - write a 16 bit value to pci config space + * + * Description: + * This routine writes a 16 bit value to the pci configuration + * space. The flag PciConfigUp indicates whether the config space + * is accesible or must be set up first. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciWriteCfgWord( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U16 Val) /* pointer to store the read value */ +{ + pci_write_config_word(pAC->PciDev, PciAddr, Val); + return(0); +} /* SkPciWriteCfgWord */ + + +/***************************************************************************** + * + * SkPciWriteCfgWord - write a 8 bit value to pci config space + * + * Description: + * This routine writes a 8 bit value to the pci configuration + * space. The flag PciConfigUp indicates whether the config space + * is accesible or must be set up first. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +int SkPciWriteCfgByte( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U8 Val) /* pointer to store the read value */ +{ + pci_write_config_byte(pAC->PciDev, PciAddr, Val); + return(0); +} /* SkPciWriteCfgByte */ + + +/***************************************************************************** + * + * SkDrvEvent - handle driver events + * + * Description: + * This function handles events from all modules directed to the driver + * + * Context: + * Is called under protection of slow path lock. + * + * Returns: + * 0 if everything ok + * < 0 on error + * + */ +int SkDrvEvent( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* io-context */ +SK_U32 Event, /* event-id */ +SK_EVPARA Param) /* event-parameter */ +{ +SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ +struct sk_buff *pMsg; /* pointer to a message block */ +int FromPort; /* the port from which we switch away */ +int ToPort; /* the port we switch to */ +SK_EVPARA NewPara; /* parameter for further events */ +#if 0 +int Stat; +#endif +unsigned long Flags; +SK_BOOL DualNet; + + switch (Event) { + case SK_DRV_ADAP_FAIL: + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("ADAPTER FAIL EVENT\n")); + printk("%s: Adapter failed.\n", pAC->dev[0]->name); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + /* cgoos */ + break; + case SK_DRV_PORT_FAIL: + FromPort = Param.Para32[0]; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("PORT FAIL EVENT, Port: %d\n", FromPort)); + if (FromPort == 0) { + printk("%s: Port A failed.\n", pAC->dev[0]->name); + } else { + printk("%s: Port B failed.\n", pAC->dev[1]->name); + } + /* cgoos */ + break; + case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */ + /* action list 4 */ + FromPort = Param.Para32[0]; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("PORT RESET EVENT, Port: %d ", FromPort)); + NewPara.Para64 = FromPort; + SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); +#if 0 + pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; +#endif + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + + /* clear rx ring from received frames */ + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); + + ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + + /* tschilling: Handling of return value inserted. */ + if (SkGeInitPort(pAC, IoC, FromPort)) { + if (FromPort == 0) { + printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); + } else { + printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); + } + } + SkAddrMcUpdate(pAC,IoC, FromPort); + PortReInitBmu(pAC, FromPort); + SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); + ClearAndStartRx(pAC, FromPort); + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + break; + case SK_DRV_NET_UP: /* SK_U32 PortIdx */ + /* action list 5 */ + FromPort = Param.Para32[0]; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("NET UP EVENT, Port: %d ", Param.Para32[0])); +#ifdef SK98_INFO + printk("%s: network connection up using" + " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); + + /* tschilling: Values changed according to LinkSpeedUsed. */ + Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; + if (Stat == SK_LSPEED_STAT_10MBPS) { + printk(" speed: 10\n"); + } else if (Stat == SK_LSPEED_STAT_100MBPS) { + printk(" speed: 100\n"); + } else if (Stat == SK_LSPEED_STAT_1000MBPS) { + printk(" speed: 1000\n"); + } else { + printk(" speed: unknown\n"); + } + + Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; + if (Stat == SK_LMODE_STAT_AUTOHALF || + Stat == SK_LMODE_STAT_AUTOFULL) { + printk(" autonegotiation: yes\n"); + } + else { + printk(" autonegotiation: no\n"); + } + if (Stat == SK_LMODE_STAT_AUTOHALF || + Stat == SK_LMODE_STAT_HALF) { + printk(" duplex mode: half\n"); + } + else { + printk(" duplex mode: full\n"); + } + Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; + if (Stat == SK_FLOW_STAT_REM_SEND ) { + printk(" flowctrl: remote send\n"); + } + else if (Stat == SK_FLOW_STAT_LOC_SEND ){ + printk(" flowctrl: local send\n"); + } + else if (Stat == SK_FLOW_STAT_SYMMETRIC ){ + printk(" flowctrl: symmetric\n"); + } + else { + printk(" flowctrl: none\n"); + } + + /* tschilling: Check against CopperType now. */ + if ((pAC->GIni.GICopperType == SK_TRUE) && + (pAC->GIni.GP[FromPort].PLinkSpeedUsed == + SK_LSPEED_STAT_1000MBPS)) { + Stat = pAC->GIni.GP[FromPort].PMSStatus; + if (Stat == SK_MS_STAT_MASTER ) { + printk(" role: master\n"); + } + else if (Stat == SK_MS_STAT_SLAVE ) { + printk(" role: slave\n"); + } + else { + printk(" role: ???\n"); + } + } + +#ifdef SK_ZEROCOPY + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) + printk(" scatter-gather: enabled\n"); + else + printk(" scatter-gather: disabled\n"); + +#else + printk(" scatter-gather: disabled\n"); +#endif +#endif /* SK98_INFO */ + + if ((Param.Para32[0] != pAC->ActivePort) && + (pAC->RlmtNets == 1)) { + NewPara.Para32[0] = pAC->ActivePort; + NewPara.Para32[1] = Param.Para32[0]; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, + NewPara); + } + + /* Inform the world that link protocol is up. */ +#if 0 + pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING; +#endif + + break; + case SK_DRV_NET_DOWN: /* SK_U32 Reason */ + /* action list 7 */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("NET DOWN EVENT ")); +#ifdef SK98_INFO + printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name); +#endif +#if 0 + pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; +#endif + break; + case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("PORT SWITCH HARD ")); + case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ + /* action list 6 */ + printk("%s: switching to port %c\n", pAC->dev[0]->name, + 'A'+Param.Para32[1]); + case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ + FromPort = Param.Para32[0]; + ToPort = Param.Para32[1]; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ", + FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort)); + NewPara.Para64 = FromPort; + SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); + NewPara.Para64 = ToPort; + SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + spin_lock_irqsave( + &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); + SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); + spin_unlock_irqrestore( + &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ + ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ + + ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + spin_lock_irqsave( + &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + pAC->ActivePort = ToPort; +#if 0 + SetQueueSizes(pAC); +#else + /* tschilling: New common function with minimum size check. */ + DualNet = SK_FALSE; + if (pAC->RlmtNets == 2) { + DualNet = SK_TRUE; + } + + if (SkGeInitAssignRamToQueues( + pAC, + pAC->ActivePort, + DualNet)) { + spin_unlock_irqrestore( + &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + printk("SkGeInitAssignRamToQueues failed.\n"); + break; + } +#endif + /* tschilling: Handling of return values inserted. */ + if (SkGeInitPort(pAC, IoC, FromPort) || + SkGeInitPort(pAC, IoC, ToPort)) { + printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); + } + if (Event == SK_DRV_SWITCH_SOFT) { + SkMacRxTxEnable(pAC, IoC, FromPort); + } + SkMacRxTxEnable(pAC, IoC, ToPort); + SkAddrSwap(pAC, IoC, FromPort, ToPort); + SkAddrMcUpdate(pAC, IoC, FromPort); + SkAddrMcUpdate(pAC, IoC, ToPort); + PortReInitBmu(pAC, FromPort); + PortReInitBmu(pAC, ToPort); + SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); + SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); + ClearAndStartRx(pAC, FromPort); + ClearAndStartRx(pAC, ToPort); + spin_unlock_irqrestore( + &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + break; + case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("RLS ")); + pRlmtMbuf = (SK_MBUF*) Param.pParaPtr; + pMsg = (struct sk_buff*) pRlmtMbuf->pOs; + skb_put(pMsg, pRlmtMbuf->Length); + if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], + pMsg) < 0) + + DEV_KFREE_SKB_ANY(pMsg); + break; + default: + break; + } + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("END EVENT ")); + + return (0); +} /* SkDrvEvent */ + + +/***************************************************************************** + * + * SkErrorLog - log errors + * + * Description: + * This function logs errors to the system buffer and to the console + * + * Returns: + * 0 if everything ok + * < 0 on error + * + */ +void SkErrorLog( +SK_AC *pAC, +int ErrClass, +int ErrNum, +char *pErrorMsg) +{ +char ClassStr[80]; + + switch (ErrClass) { + case SK_ERRCL_OTHER: + strcpy(ClassStr, "Other error"); + break; + case SK_ERRCL_CONFIG: + strcpy(ClassStr, "Configuration error"); + break; + case SK_ERRCL_INIT: + strcpy(ClassStr, "Initialization error"); + break; + case SK_ERRCL_NORES: + strcpy(ClassStr, "Out of resources error"); + break; + case SK_ERRCL_SW: + strcpy(ClassStr, "internal Software error"); + break; + case SK_ERRCL_HW: + strcpy(ClassStr, "Hardware failure"); + break; + case SK_ERRCL_COMM: + strcpy(ClassStr, "Communication error"); + break; + } + printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n" + " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name, + ClassStr, ErrNum, pErrorMsg); + +} /* SkErrorLog */ + +#ifdef DEBUG +/****************************************************************************/ +/* "debug only" section *****************************************************/ +/****************************************************************************/ + + +/***************************************************************************** + * + * DumpMsg - print a frame + * + * Description: + * This function prints frames to the system logfile/to the console. + * + * Returns: N/A + * + */ +static void DumpMsg(struct sk_buff *skb, char *str) +{ + int msglen; + + if (skb == NULL) { + printk("DumpMsg(): NULL-Message\n"); + return; + } + + if (skb->data == NULL) { + printk("DumpMsg(): Message empty\n"); + return; + } + + msglen = skb->len; + if (msglen > 64) + msglen = 64; + + printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len); + + DumpData((char *)skb->data, msglen); + + printk("------- End of message ---------\n"); +} /* DumpMsg */ + + +/***************************************************************************** + * + * DumpData - print a data area + * + * Description: + * This function prints a area of data to the system logfile/to the + * console. + * + * Returns: N/A + * + */ +static void DumpData(char *p, int size) +{ +register int i; +int haddr, addr; +char hex_buffer[180]; +char asc_buffer[180]; +char HEXCHAR[] = "0123456789ABCDEF"; + + addr = 0; + haddr = 0; + hex_buffer[0] = 0; + asc_buffer[0] = 0; + for (i=0; i < size; ) { + if (*p >= '0' && *p <='z') + asc_buffer[addr] = *p; + else + asc_buffer[addr] = '.'; + addr++; + asc_buffer[addr] = 0; + hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4]; + haddr++; + hex_buffer[haddr] = HEXCHAR[*p & 0x0f]; + haddr++; + hex_buffer[haddr] = ' '; + haddr++; + hex_buffer[haddr] = 0; + p++; + i++; + if (i%16 == 0) { + printk("%s %s\n", hex_buffer, asc_buffer); + addr = 0; + haddr = 0; + } + } +} /* DumpData */ + + +/***************************************************************************** + * + * DumpLong - print a data area as long values + * + * Description: + * This function prints a area of data to the system logfile/to the + * console. + * + * Returns: N/A + * + */ +static void DumpLong(char *pc, int size) +{ +register int i; +int haddr, addr; +char hex_buffer[180]; +char asc_buffer[180]; +char HEXCHAR[] = "0123456789ABCDEF"; +long *p; +int l; + + addr = 0; + haddr = 0; + hex_buffer[0] = 0; + asc_buffer[0] = 0; + p = (long*) pc; + for (i=0; i < size; ) { + l = (long) *p; + hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf]; + haddr++; + hex_buffer[haddr] = HEXCHAR[l & 0x0f]; + haddr++; + hex_buffer[haddr] = ' '; + haddr++; + hex_buffer[haddr] = 0; + p++; + i++; + if (i%8 == 0) { + printk("%4x %s\n", (i-8)*4, hex_buffer); + haddr = 0; + } + } + printk("------------------------\n"); +} /* DumpLong */ + +#endif + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c new file mode 100644 index 0000000000..f8681a8b0f --- /dev/null +++ b/drivers/net/sk98lin/skgehwt.c @@ -0,0 +1,220 @@ +/****************************************************************************** + * + * Name: skgehwt.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.13 $ + * Date: $Date: 1999/11/22 13:31:12 $ + * Purpose: Hardware Timer. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgehwt.c,v $ + * Revision 1.13 1999/11/22 13:31:12 cgoos + * Changed license header to GPL. + * + * Revision 1.12 1998/10/15 15:11:34 gklug + * fix: ID_sccs to SysKonnectFileId + * + * Revision 1.11 1998/10/08 15:27:51 gklug + * chg: correction factor is host clock dependent + * + * Revision 1.10 1998/09/15 14:18:31 cgoos + * Changed more BOOLEANs to SK_xxx + * + * Revision 1.9 1998/09/15 14:16:06 cgoos + * Changed line 107: FALSE to SK_FALSE + * + * Revision 1.8 1998/08/24 13:04:44 gklug + * fix: typo + * + * Revision 1.7 1998/08/19 09:50:49 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.6 1998/08/17 09:59:02 gklug + * fix: typos + * + * Revision 1.5 1998/08/14 07:09:10 gklug + * fix: chg pAc -> pAC + * + * Revision 1.4 1998/08/10 14:14:52 gklug + * rmv: unneccessary SK_ADDR macro + * + * Revision 1.3 1998/08/07 12:53:44 gklug + * fix: first compiled version + * + * Revision 1.2 1998/08/07 09:19:29 gklug + * adapt functions to the C coding conventions + * rmv unneccessary functions. + * + * Revision 1.1 1998/08/05 11:28:36 gklug + * first version: adapted from SMT/FDDI + * + * + * + * + ******************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +/* + Event queue and dispatcher +*/ +static const char SysKonnectFileId[] = + "$Header: /usr56/projects/ge/schedule/skgehwt.c,v 1.13 1999/11/22 13:31:12 cgoos Exp $" ; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef __C2MAN__ +/* + Hardware Timer function queue management. + + General Description: + + */ +intro() +{} +#endif + +/* + * Prototypes of local functions. + */ +#define SK_HWT_MAX (65000) + +/* correction factor */ +#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100) + +/* + * Initialize hardware timer. + * + * Must be called during init level 1. + */ +void SkHwtInit( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc) /* IoContext */ +{ + pAC->Hwt.TStart = 0 ; + pAC->Hwt.TStop = 0 ; + pAC->Hwt.TActive = SK_FALSE ; + + SkHwtStop(pAC,Ioc) ; +} + +/* + * + * Start hardware timer (clock ticks are 16us). + * + */ +void SkHwtStart( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc, /* IoContext */ +SK_U32 Time) /* Time in units of 16us to load the timer with. */ +{ + SK_U32 Cnt ; + + if (Time > SK_HWT_MAX) + Time = SK_HWT_MAX ; + + pAC->Hwt.TStart = Time ; + pAC->Hwt.TStop = 0L ; + + Cnt = Time ; + + /* + * if time < 16 us + * time = 16 us + */ + if (!Cnt) { + Cnt++ ; + } + + SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC) ; + SK_OUT16(Ioc, B2_TI_CRTL, TIM_START) ; /* Start timer. */ + + pAC->Hwt.TActive = SK_TRUE ; +} + +/* + * Stop hardware timer. + * and clear the timer IRQ + */ +void SkHwtStop( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc) /* IoContext */ +{ + SK_OUT16(Ioc, B2_TI_CRTL, TIM_STOP) ; + SK_OUT16(Ioc, B2_TI_CRTL, TIM_CLR_IRQ) ; + + pAC->Hwt.TActive = SK_FALSE ; +} + + +/* + * Stop hardware timer and read time elapsed since last start. + * + * returns + * The elapsed time since last start in units of 16us. + * + */ +SK_U32 SkHwtRead( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc) /* IoContext */ +{ + SK_U32 TRead ; + SK_U32 IStatus ; + + if (pAC->Hwt.TActive) { + SkHwtStop(pAC,Ioc) ; + + SK_IN32(Ioc, B2_TI_VAL, &TRead); + TRead /= SK_HWT_FAC; + + SK_IN32(Ioc, B0_ISRC, &IStatus); + + /* Check if timer expired (or wraparound). */ + if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { + SkHwtStop(pAC,Ioc) ; + pAC->Hwt.TStop = pAC->Hwt.TStart ; + } else { + pAC->Hwt.TStop = pAC->Hwt.TStart - TRead ; + } + } + return (pAC->Hwt.TStop) ; +} + +/* + * interrupt source= timer + */ +void SkHwtIsr( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc) /* IoContext */ +{ + SkHwtStop(pAC,Ioc); + pAC->Hwt.TStop = pAC->Hwt.TStart; + SkTimerDone(pAC,Ioc) ; +} + +#endif /* CONFIG_SK98 */ + +/* End of file */ diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c new file mode 100644 index 0000000000..a18dc0a488 --- /dev/null +++ b/drivers/net/sk98lin/skgeinit.c @@ -0,0 +1,2372 @@ +/****************************************************************************** + * + * Name: skgeinit.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.85 $ + * Date: $Date: 2003/02/05 15:30:33 $ + * Purpose: Contains functions to initialize the GE HW + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgeinit.c,v $ + * Revision 1.85 2003/02/05 15:30:33 rschmidt + * Corrected setting of GIHstClkFact (Host Clock Factor) and + * GIPollTimerVal (Descr. Poll Timer Init Value) for YUKON. + * Editorial changes. + * + * Revision 1.84 2003/01/28 09:57:25 rschmidt + * Added detection of YUKON-Lite Rev. A0 (stored in GIYukonLite). + * Disabled Rx GMAC FIFO Flush for YUKON-Lite Rev. A0. + * Added support for CLK_RUN (YUKON-Lite). + * Added additional check of PME from D3cold for setting GIVauxAvail. + * Editorial changes. + * + * Revision 1.83 2002/12/17 16:15:41 rschmidt + * Added default setting of PhyType (Copper) for YUKON. + * Added define around check for HW self test results. + * Editorial changes. + * + * Revision 1.82 2002/12/05 13:40:21 rschmidt + * Added setting of Rx GMAC FIFO Flush Mask register. + * Corrected PhyType with new define SK_PHY_MARV_FIBER when + * YUKON Fiber board was found. + * Editorial changes. + * + * Revision 1.81 2002/11/15 12:48:35 rschmidt + * Replaced message SKERR_HWI_E018 with SKERR_HWI_E024 for Rx queue error + * in SkGeStopPort(). + * Added init for pAC->GIni.GIGenesis with SK_FALSE in YUKON-branch. + * Editorial changes. + * + * Revision 1.80 2002/11/12 17:28:30 rschmidt + * Initialized GIPciSlot64 and GIPciClock66 in SkGeInit1(). + * Reduced PCI FIFO watermarks for 32bit/33MHz bus in SkGeInitBmu(). + * Editorial changes. + * + * Revision 1.79 2002/10/21 09:31:02 mkarl + * Changed SkGeInitAssignRamToQueues(), removed call to + * SkGeInitAssignRamToQueues in SkGeInit1 and fixed compiler warning in + * SkGeInit1. + * + * Revision 1.78 2002/10/16 15:55:07 mkarl + * Fixed a bug in SkGeInitAssignRamToQueues. + * + * Revision 1.77 2002/10/14 15:07:22 rschmidt + * Corrected timeout handling for Rx queue in SkGeStopPort() (#10748) + * Editorial changes. + * + * Revision 1.76 2002/10/11 09:24:38 mkarl + * Added check for HW self test results. + * + * Revision 1.75 2002/10/09 16:56:44 mkarl + * Now call SkGeInitAssignRamToQueues() in Init Level 1 in order to assign + * the adapter memory to the queues. This default assignment is not suitable + * for dual net mode. + * + * Revision 1.74 2002/09/12 08:45:06 rwahl + * Set defaults for PMSCap, PLinkSpeed & PLinkSpeedCap dependent on PHY. + * + * Revision 1.73 2002/08/16 15:19:45 rschmidt + * Corrected check for Tx queues in SkGeCheckQSize(). + * Added init for new entry GIGenesis and GICopperType + * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. + * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. + * + * Revision 1.72 2002/08/12 13:38:55 rschmidt + * Added check if VAUX is available (stored in GIVauxAvail) + * Initialized PLinkSpeedCap in Port struct with SK_LSPEED_CAP_1000MBPS + * Editorial changes. + * + * Revision 1.71 2002/08/08 16:32:58 rschmidt + * Added check for Tx queues in SkGeCheckQSize(). + * Added start of Time Stamp Timer (YUKON) in SkGeInit2(). + * Editorial changes. + * + * Revision 1.70 2002/07/23 16:04:26 rschmidt + * Added init for GIWolOffs (HW-Bug in YUKON 1st rev.) + * Minor changes + * + * Revision 1.69 2002/07/17 17:07:08 rwahl + * - SkGeInit1(): fixed PHY type debug output; corrected init of GIFunc + * table & GIMacType. + * - Editorial changes. + * + * Revision 1.68 2002/07/15 18:38:31 rwahl + * Added initialization for MAC type dependent function table. + * + * Revision 1.67 2002/07/15 15:45:39 rschmidt + * Added Tx Store & Forward for YUKON (GMAC Tx FIFO is only 1 kB) + * Replaced SK_PHY_MARV by SK_PHY_MARV_COPPER + * Editorial changes + * + * Revision 1.66 2002/06/10 09:35:08 rschmidt + * Replaced C++ comments (//) + * Editorial changes + * + * Revision 1.65 2002/06/05 08:33:37 rschmidt + * Changed GIRamSize and Reset sequence for YUKON. + * SkMacInit() replaced by SkXmInitMac() resp. SkGmInitMac() + * + * Revision 1.64 2002/04/25 13:03:20 rschmidt + * Changes for handling YUKON. + * Removed reference to xmac_ii.h (not necessary). + * Moved all defines into header file. + * Replaced all SkXm...() functions with SkMac...() to handle also + * YUKON's GMAC. + * Added handling for GMAC FIFO in SkGeInitMacFifo(), SkGeStopPort(). + * Removed 'goto'-directive from SkGeCfgSync(), SkGeCheckQSize(). + * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), + * SkMacFlushTxFifo(). + * Optimized timeout handling in SkGeStopPort(). + * Initialized PLinkSpeed in Port struct with SK_LSPEED_AUTO. + * Release of GMAC Link Control reset in SkGeInit1(). + * Initialized GIChipId and GIChipRev in GE Init structure. + * Added GIRamSize and PhyType values for YUKON. + * Removed use of PRxCmd to setup XMAC. + * Moved setting of XM_RX_DIS_CEXT to SkXmInitMac(). + * Use of SkGeXmitLED() only for GENESIS. + * Changes for V-CPU support. + * Editorial changes. + * + * Revision 1.63 2001/04/05 11:02:09 rassmann + * Stop Port check of the STOP bit did not take 2/18 sec as wanted. + * + * Revision 1.62 2001/02/07 07:54:21 rassmann + * Corrected copyright. + * + * Revision 1.61 2001/01/31 15:31:40 gklug + * fix: problem with autosensing an SR8800 switch + * + * Revision 1.60 2000/10/18 12:22:21 cgoos + * Added workaround for half duplex hangup. + * + * Revision 1.59 2000/10/10 11:22:06 gklug + * add: in manual half duplex mode ignore carrier extension errors + * + * Revision 1.58 2000/10/02 14:10:27 rassmann + * Reading BCOM PHY after releasing reset until it returns a valid value. + * + * Revision 1.57 2000/08/03 14:55:28 rassmann + * Waiting for I2C to be ready before de-initializing adapter + * (prevents sensors from hanging up). + * + * Revision 1.56 2000/07/27 12:16:48 gklug + * fix: Stop Port check of the STOP bit does now take 2/18 sec as wanted + * + * Revision 1.55 1999/11/22 13:32:26 cgoos + * Changed license header to GPL. + * + * Revision 1.54 1999/10/26 07:32:54 malthoff + * Initialize PHWLinkUp with SK_FALSE. Required for Diagnostics. + * + * Revision 1.53 1999/08/12 19:13:50 malthoff + * Fix for 1000BT. Do not owerwrite XM_MMU_CMD when + * disabling receiver and transmitter. Other bits + * may be lost. + * + * Revision 1.52 1999/07/01 09:29:54 gklug + * fix: DoInitRamQueue needs pAC + * + * Revision 1.51 1999/07/01 08:42:21 gklug + * chg: use Store & forward for RAM buffer when Jumbos are used + * + * Revision 1.50 1999/05/27 13:19:38 cgoos + * Added Tx PCI watermark initialization. + * Removed Tx RAM queue Store & Forward setting. + * + * Revision 1.49 1999/05/20 14:32:45 malthoff + * SkGeLinkLED() is completly removed now. + * + * Revision 1.48 1999/05/19 07:28:24 cgoos + * SkGeLinkLED no more available for drivers. + * Changes for 1000Base-T. + * + * Revision 1.47 1999/04/08 13:57:45 gklug + * add: Init of new port struct fiels PLinkResCt + * chg: StopPort Timer check + * + * Revision 1.46 1999/03/25 07:42:15 malthoff + * SkGeStopPort(): Add workaround for cache incoherency. + * Create error log entry, disable port, and + * exit loop if it does not terminate. + * Add XM_RX_LENERR_OK to the default value for the + * XMAC receive command register. + * + * Revision 1.45 1999/03/12 16:24:47 malthoff + * Remove PPollRxD and PPollTxD. + * Add check for GIPollTimerVal. + * + * Revision 1.44 1999/03/12 13:40:23 malthoff + * Fix: SkGeXmitLED(), SK_LED_TST mode does not work. + * Add: Jumbo frame support. + * Chg: Resolution of parameter IntTime in SkGeCfgSync(). + * + * Revision 1.43 1999/02/09 10:29:46 malthoff + * Bugfix: The previous modification again also for the second location. + * + * Revision 1.42 1999/02/09 09:35:16 malthoff + * Bugfix: The bits '66 MHz Capable' and 'NEWCAP are reset while + * clearing the error bits in the PCI status register. + * + * Revision 1.41 1999/01/18 13:07:02 malthoff + * Bugfix: Do not use CFG cycles after during Init- or Runtime, because + * they may not be available after Boottime. + * + * Revision 1.40 1999/01/11 12:40:49 malthoff + * Bug fix: PCI_STATUS: clearing error bits sets the UDF bit. + * + * Revision 1.39 1998/12/11 15:17:33 gklug + * chg: Init LipaAutoNeg with Unknown + * + * Revision 1.38 1998/12/10 11:02:57 malthoff + * Disable Error Log Message when calling SkGeInit(level 2) + * more than once. + * + * Revision 1.37 1998/12/07 12:18:25 gklug + * add: refinement of autosense mode: take into account the autoneg cap of LiPa + * + * Revision 1.36 1998/12/07 07:10:39 gklug + * fix: init values of LinkBroken/ Capabilities for management + * + * Revision 1.35 1998/12/02 10:56:20 gklug + * fix: do NOT init LoinkSync Counter. + * + * Revision 1.34 1998/12/01 10:53:21 gklug + * add: init of additional Counters for workaround + * + * Revision 1.33 1998/12/01 10:00:49 gklug + * add: init PIsave var in Port struct + * + * Revision 1.32 1998/11/26 14:50:40 gklug + * chg: Default is autosensing with AUTOFULL mode + * + * Revision 1.31 1998/11/25 15:36:16 gklug + * fix: do NOT stop LED Timer when port should be stopped + * + * Revision 1.30 1998/11/24 13:15:28 gklug + * add: Init PCkeckPar struct member + * + * Revision 1.29 1998/11/18 13:19:27 malthoff + * Disable packet arbiter timeouts on receive side. + * Use maximum timeout value for packet arbiter + * transmit timeouts. + * Add TestStopBit() function to handle stop RX/TX + * problem with active descriptor poll timers. + * Bug Fix: Descriptor Poll Timer not started, because + * GIPollTimerVal was initialized with 0. + * + * Revision 1.28 1998/11/13 14:24:26 malthoff + * Bug Fix: SkGeStopPort() may hang if a Packet Arbiter Timout + * is pending or occurs while waiting for TX_STOP and RX_STOP. + * The PA timeout is cleared now while waiting for TX- or RX_STOP. + * + * Revision 1.27 1998/11/02 11:04:36 malthoff + * fix the last fix + * + * Revision 1.26 1998/11/02 10:37:03 malthoff + * Fix: SkGePollTxD() enables always the synchronounous poll timer. + * + * Revision 1.25 1998/10/28 07:12:43 cgoos + * Fixed "LED_STOP" in SkGeLnkSyncCnt, "== SK_INIT_IO" in SkGeInit. + * Removed: Reset of RAM Interface in SkGeStopPort. + * + * Revision 1.24 1998/10/27 08:13:12 malthoff + * Remove temporary code. + * + * Revision 1.23 1998/10/26 07:45:03 malthoff + * Add Address Calculation Workaround: If the EPROM byte + * Id is 3, the address offset is 512 kB. + * Initialize default values for PLinkMode and PFlowCtrlMode. + * + * Revision 1.22 1998/10/22 09:46:47 gklug + * fix SysKonnectFileId typo + * + * Revision 1.21 1998/10/20 12:11:56 malthoff + * Don't dendy the Queue config if the size of the unused + * Rx qeueu is zero. + * + * Revision 1.20 1998/10/19 07:27:58 malthoff + * SkGeInitRamIface() is public to be called by diagnostics. + * + * Revision 1.19 1998/10/16 13:33:45 malthoff + * Fix: enabling descriptor polling is not allowed until + * the descriptor addresses are set. Descriptor polling + * must be handled by the driver. + * + * Revision 1.18 1998/10/16 10:58:27 malthoff + * Remove temp. code for Diag prototype. + * Remove lint warning for dummy reads. + * Call SkGeLoadLnkSyncCnt() during SkGeInitPort(). + * + * Revision 1.17 1998/10/14 09:16:06 malthoff + * Change parameter LimCount and programming of + * the limit counter in SkGeCfgSync(). + * + * Revision 1.16 1998/10/13 09:21:16 malthoff + * Don't set XM_RX_SELF_RX in RxCmd Reg, because it's + * like a Loopback Mode in half duplex. + * + * Revision 1.15 1998/10/09 06:47:40 malthoff + * SkGeInitMacArb(): set recovery counters init value + * to zero although this counters are not uesd. + * Bug fix in Rx Upper/Lower Pause Threshold calculation. + * Add XM_RX_SELF_RX to RxCmd. + * + * Revision 1.14 1998/10/06 15:15:53 malthoff + * Make sure no pending IRQ is cleared in SkGeLoadLnkSyncCnt(). + * + * Revision 1.13 1998/10/06 14:09:36 malthoff + * Add SkGeLoadLnkSyncCnt(). Modify + * the 'port stopped' condition according + * to the current problem report. + * + * Revision 1.12 1998/10/05 08:17:21 malthoff + * Add functions: SkGePollRxD(), SkGePollTxD(), + * DoCalcAddr(), SkGeCheckQSize(), + * DoInitRamQueue(), and SkGeCfgSync(). + * Add coding for SkGeInitMacArb(), SkGeInitPktArb(), + * SkGeInitMacFifo(), SkGeInitRamBufs(), + * SkGeInitRamIface(), and SkGeInitBmu(). + * + * Revision 1.11 1998/09/29 08:26:29 malthoff + * bug fix: SkGeInit0() 'i' should be increment. + * + * Revision 1.10 1998/09/28 13:19:01 malthoff + * Coding time: Save the done work. + * Modify SkGeLinkLED(), add SkGeXmitLED(), + * define SkGeCheckQSize(), SkGeInitMacArb(), + * SkGeInitPktArb(), SkGeInitMacFifo(), + * SkGeInitRamBufs(), SkGeInitRamIface(), + * and SkGeInitBmu(). Do coding for SkGeStopPort(), + * SkGeInit1(), SkGeInit2(), and SkGeInit3(). + * Do coding for SkGeDinit() and SkGeInitPort(). + * + * Revision 1.9 1998/09/16 14:29:05 malthoff + * Some minor changes. + * + * Revision 1.8 1998/09/11 05:29:14 gklug + * add: init state of a port + * + * Revision 1.7 1998/09/04 09:26:25 malthoff + * Short temporary modification. + * + * Revision 1.6 1998/09/04 08:27:59 malthoff + * Remark the do-while in StopPort() because it never ends + * without a GE adapter. + * + * Revision 1.5 1998/09/03 14:05:45 malthoff + * Change comment for SkGeInitPort(). Do not + * repair the queue sizes if invalid. + * + * Revision 1.4 1998/09/03 10:03:19 malthoff + * Implement the new interface according to the + * reviewed interface specification. + * + * Revision 1.3 1998/08/19 09:11:25 gklug + * fix: struct are removed from c-source (see CCC) + * + * Revision 1.2 1998/07/28 12:33:58 malthoff + * Add 'IoC' parameter in function declaration and SK IO macros. + * + * Revision 1.1 1998/07/23 09:48:57 malthoff + * Creation. First dummy 'C' file. + * SkGeInit(Level 0) is card_start for GE. + * SkGeDeInit() is card_stop for GE. + * + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/* global variables ***********************************************************/ + +/* local variables ************************************************************/ + +static const char SysKonnectFileId[] = + "@(#)$Id: skgeinit.c,v 1.85 2003/02/05 15:30:33 rschmidt Exp $ (C) SK "; + +struct s_QOffTab { + int RxQOff; /* Receive Queue Address Offset */ + int XsQOff; /* Sync Tx Queue Address Offset */ + int XaQOff; /* Async Tx Queue Address Offset */ +}; +static struct s_QOffTab QOffTab[] = { + {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2} +}; + + +/****************************************************************************** + * + * SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring + * + * Description: + * Enable or disable the descriptor polling of the receive descriptor + * ring (RxD) for port 'Port'. + * The new configuration is *not* saved over any SkGeStopPort() and + * SkGeInitPort() calls. + * + * Returns: + * nothing + */ +void SkGePollRxD( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ? + CSR_ENA_POL : CSR_DIS_POL); +} /* SkGePollRxD */ + + +/****************************************************************************** + * + * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings + * + * Description: + * Enable or disable the descriptor polling of the transmit descriptor + * ring(s) (TxD) for port 'Port'. + * The new configuration is *not* saved over any SkGeStopPort() and + * SkGeInitPort() calls. + * + * Returns: + * nothing + */ +void SkGePollTxD( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ +{ + SK_GEPORT *pPrt; + SK_U32 DWord; + + pPrt = &pAC->GIni.GP[Port]; + + DWord = (PollTxD) ? CSR_ENA_POL : CSR_DIS_POL; + + if (pPrt->PXSQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord); + } + + if (pPrt->PXAQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord); + } +} /* SkGePollTxD */ + + +/****************************************************************************** + * + * SkGeYellowLED() - Switch the yellow LED on or off. + * + * Description: + * Switch the yellow LED on or off. + * + * Note: + * This function may be called any time after SkGeInit(Level 1). + * + * Returns: + * nothing + */ +void SkGeYellowLED( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int State) /* yellow LED state, 0 = OFF, 0 != ON */ +{ + if (State == 0) { + /* Switch yellow LED OFF */ + SK_OUT8(IoC, B0_LED, LED_STAT_OFF); + } + else { + /* Switch yellow LED ON */ + SK_OUT8(IoC, B0_LED, LED_STAT_ON); + } +} /* SkGeYellowLED */ + + +/****************************************************************************** + * + * SkGeXmitLED() - Modify the Operational Mode of a transmission LED. + * + * Description: + * The Rx or Tx LED which is specified by 'Led' will be + * enabled, disabled or switched on in test mode. + * + * Note: + * 'Led' must contain the address offset of the LEDs INI register. + * + * Usage: + * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); + * + * Returns: + * nothing + */ +void SkGeXmitLED( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Led, /* offset to the LED Init Value register */ +int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ +{ + SK_U32 LedIni; + + switch (Mode) { + case SK_LED_ENA: + LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; + SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni); + SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); + break; + case SK_LED_TST: + SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON); + SK_OUT32(IoC, Led + XMIT_LED_CNT, 100); + SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); + break; + case SK_LED_DIS: + default: + /* + * Do NOT stop the LED Timer here. The LED might be + * in on state. But it needs to go off. + */ + SK_OUT32(IoC, Led + XMIT_LED_CNT, 0); + SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF); + break; + } + + /* + * 1000BT: The Transmit LED is driven by the PHY. + * But the default LED configuration is used for + * Level One and Broadcom PHYs. + * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.) + * (In this case it has to be added here. But we will see. XXX) + */ +} /* SkGeXmitLED */ + + +/****************************************************************************** + * + * DoCalcAddr() - Calculates the start and the end address of a queue. + * + * Description: + * This function calculates the start and the end address of a queue. + * Afterwards the 'StartVal' is incremented to the next start position. + * If the port is already initialized the calculated values + * will be checked against the configured values and an + * error will be returned, if they are not equal. + * If the port is not initialized the values will be written to + * *StartAdr and *EndAddr. + * + * Returns: + * 0: success + * 1: configuration error + */ +static int DoCalcAddr( +SK_AC *pAC, /* adapter context */ +SK_GEPORT *pPrt, /* port index */ +int QuSize, /* size of the queue to configure in kB */ +SK_U32 *StartVal, /* start value for address calculation */ +SK_U32 *QuStartAddr, /* start addr to calculate */ +SK_U32 *QuEndAddr) /* end address to calculate */ +{ + SK_U32 EndVal; + SK_U32 NextStart; + int Rtv; + + Rtv = 0; + if (QuSize == 0) { + EndVal = *StartVal; + NextStart = EndVal; + } + else { + EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1; + NextStart = EndVal + 1; + } + + if (pPrt->PState >= SK_PRT_INIT) { + if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) { + Rtv = 1; + } + } + else { + *QuStartAddr = *StartVal; + *QuEndAddr = EndVal; + } + + *StartVal = NextStart; + return(Rtv); +} /* DoCalcAddr */ + +/****************************************************************************** + * + * SkGeInitAssignRamToQueues() - allocate default queue sizes + * + * Description: + * This function assigns the memory to the different queues and ports. + * When DualNet is set to SK_TRUE all ports get the same amount of memory. + * Otherwise the first port gets most of the memory and all the + * other ports just the required minimum. + * This function can only be called when pAC->GIni.GIRamSize and + * pAC->GIni.GIMacsFound have been initialized, usually this happens + * at init level 1 + * + * Returns: + * 0 - ok + * 1 - invalid input values + * 2 - not enough memory + */ + +int SkGeInitAssignRamToQueues( +SK_AC *pAC, /* Adapter context */ +int ActivePort, /* Active Port in RLMT mode */ +SK_BOOL DualNet) /* adapter context */ +{ + int i; + int UsedKilobytes; /* memory already assigned */ + int ActivePortKilobytes; /* memory available for active port */ + SK_GEPORT *pGePort; + + UsedKilobytes = 0; + + if (ActivePort >= pAC->GIni.GIMacsFound) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n", + ActivePort)); + return(1); + } + if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) + + ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n", + pAC->GIni.GIRamSize)); + return(2); + } + + + if (DualNet) { + /* every port gets the same amount of memory */ + ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound; + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + pGePort = &pAC->GIni.GP[i]; + + /* take away the minimum memory for active queues */ + ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); + + /* receive queue gets the minimum + 80% of the rest */ + pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB(( + ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100)) + + SK_MIN_RXQ_SIZE; + + ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); + + /* synchronous transmit queue */ + pGePort->PXSQSize = 0; + + /* asynchronous transmit queue */ + pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes + + SK_MIN_TXQ_SIZE); + } + } + else { + /* Rlmt Mode or single link adapter */ + + /* Set standby queue size defaults for all standby ports */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + if (i != ActivePort) { + pGePort = &pAC->GIni.GP[i]; + + pGePort->PRxQSize = SK_MIN_RXQ_SIZE; + pGePort->PXAQSize = SK_MIN_TXQ_SIZE; + pGePort->PXSQSize = 0; + + /* Count used RAM */ + UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize; + } + } + /* what's left? */ + ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes; + + /* assign it to the active port */ + /* first take away the minimum memory */ + ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); + pGePort = &pAC->GIni.GP[ActivePort]; + + /* receive queue get's the minimum + 80% of the rest */ + pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes * + (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE; + + ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); + + /* synchronous transmit queue */ + pGePort->PXSQSize = 0; + + /* asynchronous transmit queue */ + pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) + + SK_MIN_TXQ_SIZE; + } +#ifdef VCPU + VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n", + pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize); +#endif /* VCPU */ + + return(0); +} /* SkGeInitAssignRamToQueues */ + +/****************************************************************************** + * + * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration + * + * Description: + * This function verifies the Queue Size Configuration specified + * in the variables PRxQSize, PXSQSize, and PXAQSize of all + * used ports. + * This requirements must be fullfilled to have a valid configuration: + * - The size of all queues must not exceed GIRamSize. + * - The queue sizes must be specified in units of 8 kB. + * - The size of Rx queues of available ports must not be + * smaller than 16 kB. + * - The size of at least one Tx queue (synch. or asynch.) + * of available ports must not be smaller than 16 kB + * when Jumbo Frames are used. + * - The RAM start and end addresses must not be changed + * for ports which are already initialized. + * Furthermore SkGeCheckQSize() defines the Start and End Addresses + * of all ports and stores them into the HWAC port structure. + * + * Returns: + * 0: Queue Size Configuration valid + * 1: Queue Size Configuration invalid + */ +static int SkGeCheckQSize( +SK_AC *pAC, /* adapter context */ +int Port) /* port index */ +{ + SK_GEPORT *pPrt; + int UsedMem; /* total memory used (max. found ports) */ + int i; + int Rtv; + int Rtv2; + SK_U32 StartAddr; + + UsedMem = 0; + Rtv = 0; + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + pPrt = &pAC->GIni.GP[i]; + + if ((pPrt->PRxQSize & QZ_UNITS) != 0 || + (pPrt->PXSQSize & QZ_UNITS) != 0 || + (pPrt->PXAQSize & QZ_UNITS) != 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); + return(1); + } + + if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG); + return(1); + } + + /* + * the size of at least one Tx queue (synch. or asynch.) has to be > 0. + * if Jumbo Frames are used, this size has to be >= 16 kB. + */ + if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) || + (pAC->GIni.GIPortUsage == SK_JUMBO_LINK && + ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || + (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG); + return(1); + } + + UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize; + } + + if (UsedMem > pAC->GIni.GIRamSize) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); + return(1); + } + + /* Now start address calculation */ + StartAddr = pAC->GIni.GIRamOffs; + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + pPrt = &pAC->GIni.GP[i]; + + /* Calculate/Check values for the receive queue */ + Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr, + &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd); + Rtv |= Rtv2; + + /* Calculate/Check values for the synchronous Tx queue */ + Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr, + &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd); + Rtv |= Rtv2; + + /* Calculate/Check values for the asynchronous Tx queue */ + Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr, + &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd); + Rtv |= Rtv2; + + if (Rtv) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG); + return(1); + } + } + + return(0); +} /* SkGeCheckQSize */ + + +/****************************************************************************** + * + * SkGeInitMacArb() - Initialize the MAC Arbiter + * + * Description: + * This function initializes the MAC Arbiter. + * It must not be called if there is still an + * initialized or active port. + * + * Returns: + * nothing + */ +static void SkGeInitMacArb( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + /* release local reset */ + SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR); + + /* configure timeout values */ + SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53); + SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53); + SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53); + SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53); + + SK_OUT8(IoC, B3_MA_RCINI_RX1, 0); + SK_OUT8(IoC, B3_MA_RCINI_RX2, 0); + SK_OUT8(IoC, B3_MA_RCINI_TX1, 0); + SK_OUT8(IoC, B3_MA_RCINI_TX2, 0); + + /* recovery values are needed for XMAC II Rev. B2 only */ + /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */ + + /* + * There is no start or enable button to push, therefore + * the MAC arbiter is configured and enabled now. + */ +} /* SkGeInitMacArb */ + + +/****************************************************************************** + * + * SkGeInitPktArb() - Initialize the Packet Arbiter + * + * Description: + * This function initializes the Packet Arbiter. + * It must not be called if there is still an + * initialized or active port. + * + * Returns: + * nothing + */ +static void SkGeInitPktArb( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + /* release local reset */ + SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR); + + /* configure timeout values */ + SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); + SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); + SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); + SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); + + /* + * enable timeout timers if jumbo frames not used + * NOTE: the packet arbiter timeout interrupt is needed for + * half duplex hangup workaround + */ + if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) { + if (pAC->GIni.GIMacsFound == 1) { + SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1); + } + else { + SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2); + } + } +} /* SkGeInitPktArb */ + + +/****************************************************************************** + * + * SkGeInitMacFifo() - Initialize the MAC FIFOs + * + * Description: + * Initialize all MAC FIFOs of the specified port + * + * Returns: + * nothing + */ +static void SkGeInitMacFifo( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 Word; +#ifdef VCPU + SK_U32 DWord; +#endif /* VCPU */ + /* + * For each FIFO: + * - release local reset + * - use default value for MAC FIFO size + * - setup defaults for the control register + * - enable the FIFO + */ + + Word = GMF_RX_CTRL_DEF; + + if (pAC->GIni.GIGenesis) { + /* Configure Rx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR); + SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF); + SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD); + + /* Configure Tx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR); + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); + SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD); + + /* Enable frame flushing if jumbo frames used */ + if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH); + } + } + else { + /* set Rx GMAC FIFO Flush Mask */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); + + if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { + + Word &= ~GMF_RX_F_FL_ON; + } + + /* Configure Rx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word); + + /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); + + /* Configure Tx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); + SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF); + +#ifdef VCPU + SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord); + SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord); +#endif /* VCPU */ + + /* set Tx GMAC FIFO Almost Empty Threshold */ +/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */ + } +} /* SkGeInitMacFifo */ + + +/****************************************************************************** + * + * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting + * + * Description: + * This function starts the Link Sync Counter of the specified + * port and enables the generation of an Link Sync IRQ. + * The Link Sync Counter may be used to detect an active link, + * if autonegotiation is not used. + * + * Note: + * o To ensure receiving the Link Sync Event the LinkSyncCounter + * should be initialized BEFORE clearing the XMAC's reset! + * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this + * function. + * + * Returns: + * nothing + */ +void SkGeLoadLnkSyncCnt( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U32 CntVal) /* Counter value */ +{ + SK_U32 OrgIMsk; + SK_U32 NewIMsk; + SK_U32 ISrc; + SK_BOOL IrqPend; + + /* stop counter */ + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP); + + /* + * ASIC problem: + * Each time starting the Link Sync Counter an IRQ is generated + * by the adapter. See problem report entry from 21.07.98 + * + * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ + * if no IRQ is already pending. + */ + IrqPend = SK_FALSE; + SK_IN32(IoC, B0_ISRC, &ISrc); + SK_IN32(IoC, B0_IMSK, &OrgIMsk); + if (Port == MAC_1) { + NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1; + if ((ISrc & IS_LNK_SYNC_M1) != 0) { + IrqPend = SK_TRUE; + } + } + else { + NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2; + if ((ISrc & IS_LNK_SYNC_M2) != 0) { + IrqPend = SK_TRUE; + } + } + if (!IrqPend) { + SK_OUT32(IoC, B0_IMSK, NewIMsk); + } + + /* load counter */ + SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal); + + /* start counter */ + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START); + + if (!IrqPend) { + /* clear the unexpected IRQ, and restore the interrupt mask */ + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ); + SK_OUT32(IoC, B0_IMSK, OrgIMsk); + } +} /* SkGeLoadLnkSyncCnt*/ + + +/****************************************************************************** + * + * SkGeCfgSync() - Configure synchronous bandwidth for this port. + * + * Description: + * This function may be used to configure synchronous bandwidth + * to the specified port. This may be done any time after + * initializing the port. The configuration values are NOT saved + * in the HWAC port structure and will be overwritten any + * time when stopping and starting the port. + * Any values for the synchronous configuration will be ignored + * if the size of the synchronous queue is zero! + * + * The default configuration for the synchronous service is + * TXA_ENA_FSYNC. This means if the size of + * the synchronous queue is unequal zero but no specific + * synchronous bandwidth is configured, the synchronous queue + * will always have the 'unlimited' transmit priority! + * + * This mode will be restored if the synchronous bandwidth is + * deallocated ('IntTime' = 0 and 'LimCount' = 0). + * + * Returns: + * 0: success + * 1: parameter configuration error + * 2: try to configure quality of service although no + * synchronous queue is configured + */ +int SkGeCfgSync( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U32 IntTime, /* Interval Timer Value in units of 8ns */ +SK_U32 LimCount, /* Number of bytes to transfer during IntTime */ +int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ +{ + int Rtv; + + Rtv = 0; + + /* check the parameters */ + if (LimCount > IntTime || + (LimCount == 0 && IntTime != 0) || + (LimCount != 0 && IntTime == 0)) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); + return(1); + } + + if (pAC->GIni.GP[Port].PXSQSize == 0) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG); + return(2); + } + + /* calculate register values */ + IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100; + LimCount = LimCount / 8; + + if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); + return(1); + } + + /* + * - Enable 'Force Sync' to ensure the synchronous queue + * has the priority while configuring the new values. + * - Also 'disable alloc' to ensure the settings complies + * to the SyncMode parameter. + * - Disable 'Rate Control' to configure the new values. + * - write IntTime and LimCount + * - start 'Rate Control' and disable 'Force Sync' + * if Interval Timer or Limit Counter not zero. + */ + SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), + TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); + + SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime); + SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount); + + SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), + (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC))); + + if (IntTime != 0 || LimCount != 0) { + SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC); + } + + return(0); +} /* SkGeCfgSync */ + + +/****************************************************************************** + * + * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue + * + * Desccription: + * If the queue is used, enable and initialize it. + * Make sure the queue is still reset, if it is not used. + * + * Returns: + * nothing + */ +static void DoInitRamQueue( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int QuIoOffs, /* Queue IO Address Offset */ +SK_U32 QuStartAddr, /* Queue Start Address */ +SK_U32 QuEndAddr, /* Queue End Address */ +int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ +{ + SK_U32 RxUpThresVal; + SK_U32 RxLoThresVal; + + if (QuStartAddr != QuEndAddr) { + /* calculate thresholds, assume we have a big Rx queue */ + RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8; + RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8; + + /* build HW address format */ + QuStartAddr = QuStartAddr / 8; + QuEndAddr = QuEndAddr / 8; + + /* release local reset */ + SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR); + + /* configure addresses */ + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr); + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr); + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr); + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr); + + switch (QuType) { + case SK_RX_SRAM_Q: + /* configure threshold for small Rx Queue */ + RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8; + + /* continue with SK_RX_BRAM_Q */ + case SK_RX_BRAM_Q: + /* write threshold for Rx Queue */ + + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal); + SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal); + + /* the high priority threshold not used */ + break; + case SK_TX_RAM_Q: + /* + * Do NOT use Store & Forward under normal operation due to + * performance optimization (GENESIS only). + * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB) + * or YUKON is used ((GMAC Tx FIFO is only 1 kB) + * we NEED Store & Forward of the RAM buffer. + */ + if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK || + !pAC->GIni.GIGenesis) { + /* enable Store & Forward Mode for the Tx Side */ + SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD); + } + break; + } + + /* set queue operational */ + SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD); + } + else { + /* ensure the queue is still disabled */ + SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET); + } +} /* DoInitRamQueue */ + + +/****************************************************************************** + * + * SkGeInitRamBufs() - Initialize the RAM Buffer Queues + * + * Description: + * Initialize all RAM Buffer Queues of the specified port + * + * Returns: + * nothing + */ +static void SkGeInitRamBufs( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + int RxQType; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) { + RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ + } + else { + RxQType = SK_RX_BRAM_Q; /* big Rx Queue */ + } + + DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart, + pPrt->PRxQRamEnd, RxQType); + + DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart, + pPrt->PXsQRamEnd, SK_TX_RAM_Q); + + DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart, + pPrt->PXaQRamEnd, SK_TX_RAM_Q); + +} /* SkGeInitRamBufs */ + + +/****************************************************************************** + * + * SkGeInitRamIface() - Initialize the RAM Interface + * + * Description: + * This function initializes the Adapters RAM Interface. + * + * Note: + * This function is used in the diagnostics. + * + * Returns: + * nothing + */ +void SkGeInitRamIface( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + /* release local reset */ + SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR); + + /* configure timeout values */ + SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53); + SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53); + +} /* SkGeInitRamIface */ + + +/****************************************************************************** + * + * SkGeInitBmu() - Initialize the BMU state machines + * + * Description: + * Initialize all BMU state machines of the specified port + * + * Returns: + * nothing + */ +static void SkGeInitBmu( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U32 RxWm; + SK_U32 TxWm; + + pPrt = &pAC->GIni.GP[Port]; + + RxWm = SK_BMU_RX_WM; + TxWm = SK_BMU_TX_WM; + + if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { + /* for better performance */ + RxWm /= 2; + TxWm /= 2; + } + + /* Rx Queue: Release all local resets and set the watermark */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); + + /* + * Tx Queue: Release all local resets if the queue is used ! + * set watermark + */ + if (pPrt->PXSQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); + } + + if (pPrt->PXAQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); + } + /* + * Do NOT enable the descriptor poll timers here, because + * the descriptor addresses are not specified yet. + */ +} /* SkGeInitBmu */ + + +/****************************************************************************** + * + * TestStopBit() - Test the stop bit of the queue + * + * Description: + * Stopping a queue is not as simple as it seems to be. + * If descriptor polling is enabled, it may happen + * that RX/TX stop is done and SV idle is NOT set. + * In this case we have to issue another stop command. + * + * Returns: + * The queues control status register + */ +static SK_U32 TestStopBit( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int QuIoOffs) /* Queue IO Address Offset */ +{ + SK_U32 QuCsr; /* CSR contents */ + + SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); + + if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { + /* Stop Descriptor overridden by start command */ + SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); + + SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); + } + + return(QuCsr); +} /* TestStopBit */ + + +/****************************************************************************** + * + * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'. + * + * Description: + * After calling this function the descriptor rings and Rx and Tx + * queues of this port may be reconfigured. + * + * It is possible to stop the receive and transmit path separate or + * both together. + * + * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC. + * The receive queue is still active and + * the pending Rx frames may be still transferred + * into the RxD. + * SK_STOP_RX Stop the receive path. The tansmit path + * has to be stopped once before. + * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX + * + * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. + * SK_HARD_RST Resets the MAC and the PHY. + * + * Example: + * 1) A Link Down event was signaled for a port. Therefore the activity + * of this port should be stopped and a hardware reset should be issued + * to enable the workaround of XMAC errata #2. But the received frames + * should not be discarded. + * ... + * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); + * (transfer all pending Rx frames) + * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST); + * ... + * + * 2) An event was issued which request the driver to switch + * the 'virtual active' link to an other already active port + * as soon as possible. The frames in the receive queue of this + * port may be lost. But the PHY must not be reset during this + * event. + * ... + * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST); + * ... + * + * Extended Description: + * If SK_STOP_TX is set, + * o disable the MAC's receive and transmitter to prevent + * from sending incomplete frames + * o stop the port's transmit queues before terminating the + * BMUs to prevent from performing incomplete PCI cycles + * on the PCI bus + * - The network Rx and Tx activity and PCI Tx transfer is + * disabled now. + * o reset the MAC depending on the RstMode + * o Stop Interval Timer and Limit Counter of Tx Arbiter, + * also disable Force Sync bit and Enable Alloc bit. + * o perform a local reset of the port's Tx path + * - reset the PCI FIFO of the async Tx queue + * - reset the PCI FIFO of the sync Tx queue + * - reset the RAM Buffer async Tx queue + * - reset the RAM Buffer sync Tx queue + * - reset the MAC Tx FIFO + * o switch Link and Tx LED off, stop the LED counters + * + * If SK_STOP_RX is set, + * o stop the port's receive queue + * - The path data transfer activity is fully stopped now. + * o perform a local reset of the port's Rx path + * - reset the PCI FIFO of the Rx queue + * - reset the RAM Buffer receive queue + * - reset the MAC Rx FIFO + * o switch Rx LED off, stop the LED counter + * + * If all ports are stopped, + * o reset the RAM Interface. + * + * Notes: + * o This function may be called during the driver states RESET_PORT and + * SWITCH_PORT. + */ +void SkGeStopPort( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +int Port, /* port to stop (MAC_1 + n) */ +int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ +int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ +{ +#ifndef SK_DIAG + SK_EVPARA Para; +#endif /* !SK_DIAG */ + SK_GEPORT *pPrt; + SK_U32 DWord; + SK_U32 XsCsr; + SK_U32 XaCsr; + SK_U64 ToutStart; + int i; + int ToutCnt; + + pPrt = &pAC->GIni.GP[Port]; + + if ((Dir & SK_STOP_TX) != 0) { + /* disable receiver and transmitter */ + SkMacRxTxDisable(pAC, IoC, Port); + + /* stop both transmit queues */ + /* + * If the BMU is in the reset state CSR_STOP will terminate + * immediately. + */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); + + ToutStart = SkOsGetTime(pAC); + ToutCnt = 0; + do { + /* + * Clear packet arbiter timeout to make sure + * this loop will terminate. + */ + SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_TX1 : + PA_CLR_TO_TX2); + + /* + * If the transfer stucks at the MAC the STOP command will not + * terminate if we don't flush the XMAC's transmit FIFO ! + */ + SkMacFlushTxFifo(pAC, IoC, Port); + + XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); + XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); + + if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { + /* + * Timeout of 1/18 second reached. + * This needs to be checked at 1/18 sec only. + */ + ToutCnt++; + if (ToutCnt > 1) { + /* Might be a problem when the driver event handler + * calls StopPort again. XXX. + */ + + /* Fatal Error, Loop aborted */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, + SKERR_HWI_E018MSG); +#ifndef SK_DIAG + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); +#endif /* !SK_DIAG */ + return; + } + /* + * Cache incoherency workaround: Assume a start command + * has been lost while sending the frame. + */ + ToutStart = SkOsGetTime(pAC); + + if ((XsCsr & CSR_STOP) != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); + } + if ((XaCsr & CSR_STOP) != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); + } + } + + /* + * Because of the ASIC problem report entry from 21.08.1998 it is + * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. + */ + } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || + (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); + + /* Reset the MAC depending on the RstMode */ + if (RstMode == SK_SOFT_RST) { + SkMacSoftRst(pAC, IoC, Port); + } + else { + SkMacHardRst(pAC, IoC, Port); + } + + /* Disable Force Sync bit and Enable Alloc bit */ + SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), + TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); + + /* Stop Interval Timer and Limit Counter of Tx Arbiter */ + SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L); + SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); + + /* Perform a local reset of the port's Tx path */ + + /* Reset the PCI FIFO of the async Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); + /* Reset the PCI FIFO of the sync Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); + /* Reset the RAM Buffer async Tx queue */ + SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); + /* Reset the RAM Buffer sync Tx queue */ + SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); + + /* Reset Tx MAC FIFO */ + if (pAC->GIni.GIGenesis) { + /* Note: MFF_RST_SET does NOT reset the XMAC ! */ + SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); + + /* switch Link and Tx LED off, stop the LED counters */ + /* Link LED is switched off by the RLMT and the Diag itself */ + SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); + } + else { + /* Reset TX MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); + } + } + + if ((Dir & SK_STOP_RX) != 0) { + /* + * The RX Stop Command will not terminate if no buffers + * are queued in the RxD ring. But it will always reach + * the Idle state. Therefore we can use this feature to + * stop the transfer of received packets. + */ + /* stop the port's receive queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); + + i = 100; + do { + /* + * Clear packet arbiter timeout to make sure + * this loop will terminate + */ + SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_RX1 : + PA_CLR_TO_RX2); + + DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); + + /* timeout if i==0 (bug fix for #10748) */ + if (--i == 0) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, + SKERR_HWI_E024MSG); + break; + } + /* + * because of the ASIC problem report entry from 21.08.98 + * it is required to wait until CSR_STOP is reset and + * CSR_SV_IDLE is set. + */ + } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); + + /* The path data transfer activity is fully stopped now */ + + /* Perform a local reset of the port's Rx path */ + + /* Reset the PCI FIFO of the Rx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); + /* Reset the RAM Buffer receive queue */ + SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); + + /* Reset Rx MAC FIFO */ + if (pAC->GIni.GIGenesis) { + + SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); + + /* switch Rx LED off, stop the LED counter */ + SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); + } + else { + /* Reset Rx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); + } + } +} /* SkGeStopPort */ + + +/****************************************************************************** + * + * SkGeInit0() - Level 0 Initialization + * + * Description: + * - Initialize the BMU address offsets + * + * Returns: + * nothing + */ +static void SkGeInit0( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + int i; + SK_GEPORT *pPrt; + + for (i = 0; i < SK_MAX_MACS; i++) { + pPrt = &pAC->GIni.GP[i]; + + pPrt->PState = SK_PRT_RESET; + pPrt->PRxQOff = QOffTab[i].RxQOff; + pPrt->PXsQOff = QOffTab[i].XsQOff; + pPrt->PXaQOff = QOffTab[i].XaQOff; + pPrt->PCheckPar = SK_FALSE; + pPrt->PIsave = 0; + pPrt->PPrevShorts = 0; + pPrt->PLinkResCt = 0; + pPrt->PAutoNegTOCt = 0; + pPrt->PPrevRx = 0; + pPrt->PPrevFcs = 0; + pPrt->PRxLim = SK_DEF_RX_WA_LIM; + pPrt->PLinkMode = SK_LMODE_AUTOFULL; + pPrt->PLinkSpeedCap = SK_LSPEED_CAP_1000MBPS; + pPrt->PLinkSpeed = SK_LSPEED_1000MBPS; + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_UNKNOWN; + pPrt->PLinkModeConf = SK_LMODE_AUTOSENSE; + pPrt->PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + pPrt->PLinkBroken = SK_TRUE; /* See WA code */ + pPrt->PLinkCap = (SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | + SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); + pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + pPrt->PFlowCtrlCap = SK_FLOW_MODE_SYM_OR_REM; + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + pPrt->PMSCap = 0; + pPrt->PMSMode = SK_MS_MODE_AUTO; + pPrt->PMSStatus = SK_MS_STAT_UNSET; + pPrt->PAutoNegFail = SK_FALSE; + pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; + pPrt->PHWLinkUp = SK_FALSE; + } + + pAC->GIni.GIPortUsage = SK_RED_LINK; + +} /* SkGeInit0*/ + +#ifdef SK_PCI_RESET + +/****************************************************************************** + * + * SkGePciReset() - Reset PCI interface + * + * Description: + * o Read PCI configuration. + * o Change power state to 3. + * o Change power state to 0. + * o Restore PCI configuration. + * + * Returns: + * 0: Success. + * 1: Power state could not be changed to 3. + */ +static int SkGePciReset( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + int i; + SK_U16 PmCtlSts; + SK_U32 Bp1; + SK_U32 Bp2; + SK_U16 PciCmd; + SK_U8 Cls; + SK_U8 Lat; + SK_U8 ConfigSpace[PCI_CFG_SIZE]; + + /* + * Note: Switching to D3 state is like a software reset. + * Switching from D3 to D0 is a hardware reset. + * We have to save and restore the configuration space. + */ + for (i = 0; i < PCI_CFG_SIZE; i++) { + SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]); + } + + /* We know the RAM Interface Arbiter is enabled. */ + SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3); + SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); + + if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) { + return(1); + } + + /* Return to D0 state. */ + SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D0); + + /* Check for D0 state. */ + SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); + + if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) { + return(1); + } + + /* Check PCI Config Registers. */ + SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd); + SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls); + SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1); + SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2); + SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat); + + if (PciCmd != 0 || Cls != 0 || (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1 || + Lat != 0) { + return(1); + } + + /* Restore PCI Config Space. */ + for (i = 0; i < PCI_CFG_SIZE; i++) { + SkPciWriteCfgDWord(pAC, i*4, ConfigSpace[i]); + } + + return(0); +} /* SkGePciReset */ + +#endif /* SK_PCI_RESET */ + +/****************************************************************************** + * + * SkGeInit1() - Level 1 Initialization + * + * Description: + * o Do a software reset. + * o Clear all reset bits. + * o Verify that the detected hardware is present. + * Return an error if not. + * o Get the hardware configuration + * + Read the number of MACs/Ports. + * + Read the RAM size. + * + Read the PCI Revision Id. + * + Find out the adapters host clock speed + * + Read and check the PHY type + * + * Returns: + * 0: success + * 5: Unexpected PHY type detected + * 6: HW self test failed + */ +static int SkGeInit1( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + SK_U8 Byte; + SK_U16 Word; + SK_U16 CtrlStat; + SK_U32 FlashAddr; + int RetVal; + int i; + + RetVal = 0; + + /* save CLK_RUN bits (YUKON-Lite) */ + SK_IN16(IoC, B0_CTST, &CtrlStat); + +#ifdef SK_PCI_RESET + (void)SkGePciReset(pAC, IoC); +#endif /* SK_PCI_RESET */ + + /* do the SW-reset */ + SK_OUT8(IoC, B0_CTST, CS_RST_SET); + + /* release the SW-reset */ + SK_OUT8(IoC, B0_CTST, CS_RST_CLR); + + /* reset all error bits in the PCI STATUS register */ + /* + * Note: PCI Cfg cycles cannot be used, because they are not + * available on some platforms after 'boot time'. + */ + SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + /* release Master Reset */ + SK_OUT8(IoC, B0_CTST, CS_MRST_CLR); + +#ifdef CLK_RUN + CtrlStat |= CS_CLK_RUN_ENA; +#endif /* CLK_RUN */ + + /* restore CLK_RUN bits */ + SK_OUT16(IoC, B0_CTST, CtrlStat & + (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)); + + /* read Chip Identification Number */ + SK_IN8(IoC, B2_CHIP_ID, &Byte); + pAC->GIni.GIChipId = Byte; + + /* read number of MACs */ + SK_IN8(IoC, B2_MAC_CFG, &Byte); + pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; + + /* get Chip Revision Number */ + pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4); + + /* get diff. PCI parameters */ + SK_IN16(IoC, B0_CTST, &CtrlStat); + + /* read the adapters RAM size */ + SK_IN8(IoC, B2_E_0, &Byte); + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + + pAC->GIni.GIGenesis = SK_TRUE; + + if (Byte == 3) { + /* special case: 4 x 64k x 36, offset = 0x80000 */ + pAC->GIni.GIRamSize = 1024; + pAC->GIni.GIRamOffs = (SK_U32)512 * 1024; + } + else { + pAC->GIni.GIRamSize = (int)Byte * 512; + pAC->GIni.GIRamOffs = 0; + } + /* all GE adapters work with 53.125 MHz host clock */ + pAC->GIni.GIHstClkFact = SK_FACT_53; + + /* set Descr. Poll Timer Init Value to 250 ms */ + pAC->GIni.GIPollTimerVal = + SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100; + } + else { + pAC->GIni.GIGenesis = SK_FALSE; + +#ifndef VCPU + pAC->GIni.GIRamSize = (Byte == 0) ? 128 : (int)Byte * 4; +#else + pAC->GIni.GIRamSize = 128; +#endif + pAC->GIni.GIRamOffs = 0; + + /* WA for chip Rev. A */ + pAC->GIni.GIWolOffs = (pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; + + /* get PM Capabilities of PCI config space */ + SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word); + + /* check if VAUX is available */ + if (((CtrlStat & CS_VAUX_AVAIL) != 0) && + /* check also if PME from D3cold is set */ + ((Word & PCI_PME_D3C_SUP) != 0)) { + /* set entry in GE init struct */ + pAC->GIni.GIVauxAvail = SK_TRUE; + } + + /* save Flash-Address Register */ + SK_IN32(IoC, B2_FAR, &FlashAddr); + + /* test Flash-Address Register */ + SK_OUT8(IoC, B2_FAR + 3, 0xff); + SK_IN8(IoC, B2_FAR + 3, &Byte); + + pAC->GIni.GIYukonLite = (SK_BOOL)(Byte != 0); + + /* restore Flash-Address Register */ + SK_OUT32(IoC, B2_FAR, FlashAddr); + + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + /* set GMAC Link Control reset */ + SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); + + /* clear GMAC Link Control reset */ + SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + } + /* all YU chips work with 78.125 MHz host clock */ + pAC->GIni.GIHstClkFact = SK_FACT_78; + + pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ + } + + /* check if 64-bit PCI Slot is present */ + pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); + + /* check if 66 MHz PCI Clock is active */ + pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); + + /* read PCI HW Revision Id. */ + SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte); + pAC->GIni.GIPciHwRev = Byte; + + /* read the PMD type */ + SK_IN8(IoC, B2_PMD_TYP, &Byte); + pAC->GIni.GICopperType = (SK_U8)(Byte == 'T'); + + /* read the PHY type */ + SK_IN8(IoC, B2_E_1, &Byte); + + Byte &= 0x0f; /* the PHY type is stored in the lower nibble */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + if (pAC->GIni.GIGenesis) { + switch (Byte) { + case SK_PHY_XMAC: + pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC; + break; + case SK_PHY_BCOM: + pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM; + pAC->GIni.GP[i].PMSCap = + SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE; + break; + case SK_PHY_NAT: + pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT; + break; +#endif /* OTHER_PHY */ + default: + /* ERROR: unexpected PHY type detected */ + RetVal = 5; + break; + } + } + else { + if (Byte == 0) { + /* if this field is not initialized */ + Byte = SK_PHY_MARV_COPPER; + pAC->GIni.GICopperType = SK_TRUE; + } + pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV; + + if (pAC->GIni.GICopperType) { + pAC->GIni.GP[i].PLinkSpeedCap = SK_LSPEED_CAP_AUTO | + SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS | + SK_LSPEED_CAP_1000MBPS; + pAC->GIni.GP[i].PLinkSpeed = SK_LSPEED_AUTO; + pAC->GIni.GP[i].PMSCap = + SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; + } + else { + Byte = SK_PHY_MARV_FIBER; + } + } + + pAC->GIni.GP[i].PhyType = Byte; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("PHY type: %d PHY addr: %04x\n", Byte, + pAC->GIni.GP[i].PhyAddr)); + } + + /* get Mac Type & set function pointers dependent on */ + if (pAC->GIni.GIGenesis) { + pAC->GIni.GIMacType = SK_MAC_XMAC; + + pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats; + pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic; + pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter; + pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus; + } + else { + pAC->GIni.GIMacType = SK_MAC_GMAC; + + pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats; + pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic; + pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter; + pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus; + +#ifdef SPECIAL_HANDLING + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + /* check HW self test result */ + SK_IN8(IoC, B2_E_3, &Byte); + if ((Byte & B2_E3_RES_MASK) != 0) { + RetVal = 6; + } + } +#endif + } + return(RetVal); +} /* SkGeInit1 */ + + +/****************************************************************************** + * + * SkGeInit2() - Level 2 Initialization + * + * Description: + * - start the Blink Source Counter + * - start the Descriptor Poll Timer + * - configure the MAC-Arbiter + * - configure the Packet-Arbiter + * - enable the Tx Arbiters + * - enable the RAM Interface Arbiter + * + * Returns: + * nothing + */ +static void SkGeInit2( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + SK_U32 DWord; + int i; + + /* start the Descriptor Poll Timer */ + if (pAC->GIni.GIPollTimerVal != 0) { + if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) { + pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG); + } + SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal); + SK_OUT8(IoC, B28_DPT_CTRL, DPT_START); + } + + if (pAC->GIni.GIGenesis) { + /* start the Blink Source Counter */ + DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; + + SK_OUT32(IoC, B2_BSC_INI, DWord); + SK_OUT8(IoC, B2_BSC_CTRL, BSC_START); + + /* + * Configure the MAC Arbiter and the Packet Arbiter. + * They will be started once and never be stopped. + */ + SkGeInitMacArb(pAC, IoC); + + SkGeInitPktArb(pAC, IoC); + } + else { + /* start Time Stamp Timer */ + SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START); + } + + /* enable the Tx Arbiters */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB); + } + + /* enable the RAM Interface Arbiter */ + SkGeInitRamIface(pAC, IoC); + +} /* SkGeInit2 */ + +/****************************************************************************** + * + * SkGeInit() - Initialize the GE Adapter with the specified level. + * + * Description: + * Level 0: Initialize the Module structures. + * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has + * to be set before calling this level. + * + * o Do a software reset. + * o Clear all reset bits. + * o Verify that the detected hardware is present. + * Return an error if not. + * o Get the hardware configuration + * + Set GIMacsFound with the number of MACs. + * + Store the RAM size in GIRamSize. + * + Save the PCI Revision ID in GIPciHwRev. + * o return an error + * if Number of MACs > SK_MAX_MACS + * + * After returning from Level 0 the adapter + * may be accessed with IO operations. + * + * Level 2: start the Blink Source Counter + * + * Returns: + * 0: success + * 1: Number of MACs exceeds SK_MAX_MACS (after level 1) + * 2: Adapter not present or not accessible + * 3: Illegal initialization level + * 4: Initialization Level 1 Call missing + * 5: Unexpected PHY type detected + * 6: HW self test failed + */ +int SkGeInit( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Level) /* initialization level */ +{ + int RetVal; /* return value */ + SK_U32 DWord; + + RetVal = 0; + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("SkGeInit(Level %d)\n", Level)); + + switch (Level) { + case SK_INIT_DATA: + /* Initialization Level 0 */ + SkGeInit0(pAC, IoC); + pAC->GIni.GILevel = SK_INIT_DATA; + break; + + case SK_INIT_IO: + /* Initialization Level 1 */ + RetVal = SkGeInit1(pAC, IoC); + if (RetVal != 0) { + break; + } + + /* check if the adapter seems to be accessible */ + SK_OUT32(IoC, B2_IRQM_INI, 0x11335577L); + SK_IN32(IoC, B2_IRQM_INI, &DWord); + SK_OUT32(IoC, B2_IRQM_INI, 0L); + + if (DWord != 0x11335577L) { + RetVal = 2; + break; + } + + /* check if the number of GIMacsFound matches SK_MAX_MACS */ + if (pAC->GIni.GIMacsFound > SK_MAX_MACS) { + RetVal = 1; + break; + } + + /* Level 1 successfully passed */ + pAC->GIni.GILevel = SK_INIT_IO; + break; + + case SK_INIT_RUN: + /* Initialization Level 2 */ + if (pAC->GIni.GILevel != SK_INIT_IO) { +#ifndef SK_DIAG + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG); +#endif /* !SK_DIAG */ + RetVal = 4; + break; + } + SkGeInit2(pAC, IoC); + + /* Level 2 successfully passed */ + pAC->GIni.GILevel = SK_INIT_RUN; + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG); + RetVal = 3; + break; + } + + return(RetVal); +} /* SkGeInit */ + + +/****************************************************************************** + * + * SkGeDeInit() - Deinitialize the adapter + * + * Description: + * All ports of the adapter will be stopped if not already done. + * Do a software reset and switch off all LEDs. + * + * Returns: + * nothing + */ +void SkGeDeInit( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC) /* IO context */ +{ + int i; + SK_U16 Word; + +#ifndef VCPU + /* ensure I2C is ready */ + SkI2cWaitIrq(pAC, IoC); +#endif + + /* stop all current transfer activity */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (pAC->GIni.GP[i].PState != SK_PRT_STOP && + pAC->GIni.GP[i].PState != SK_PRT_RESET) { + + SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); + } + } + + /* Reset all bits in the PCI STATUS register */ + /* + * Note: PCI Cfg cycles cannot be used, because they are not + * available on some platforms after 'boot time'. + */ + SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + /* do the reset, all LEDs are switched off now */ + SK_OUT8(IoC, B0_CTST, CS_RST_SET); +} /* SkGeDeInit */ + + +/****************************************************************************** + * + * SkGeInitPort() Initialize the specified port. + * + * Description: + * PRxQSize, PXSQSize, and PXAQSize has to be + * configured for the specified port before calling this function. + * The descriptor rings has to be initialized too. + * + * o (Re)configure queues of the specified port. + * o configure the MAC of the specified port. + * o put ASIC and MAC(s) in operational mode. + * o initialize Rx/Tx and Sync LED + * o initialize RAM Buffers and MAC FIFOs + * + * The port is ready to connect when returning. + * + * Note: + * The MAC's Rx and Tx state machine is still disabled when returning. + * + * Returns: + * 0: success + * 1: Queue size initialization error. The configured values + * for PRxQSize, PXSQSize, or PXAQSize are invalid for one + * or more queues. The specified port was NOT initialized. + * An error log entry was generated. + * 2: The port has to be stopped before it can be initialized again. + */ +int SkGeInitPort( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port to configure */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (SkGeCheckQSize(pAC, Port) != 0) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG); + return(1); + } + + if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG); + return(2); + } + + /* configuration ok, initialize the Port now */ + + if (pAC->GIni.GIGenesis) { + /* initialize Rx, Tx and Link LED */ + /* + * If 1000BT Phy needs LED initialization than swap + * LED and XMAC initialization order + */ + SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); + SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA); + /* The Link LED is initialized by RLMT or Diagnostics itself */ + + SkXmInitMac(pAC, IoC, Port); + } + else { + + SkGmInitMac(pAC, IoC, Port); + } + + /* do NOT initialize the Link Sync Counter */ + + SkGeInitMacFifo(pAC, IoC, Port); + + SkGeInitRamBufs(pAC, IoC, Port); + + if (pPrt->PXSQSize != 0) { + /* enable Force Sync bit if synchronous queue available */ + SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC); + } + + SkGeInitBmu(pAC, IoC, Port); + + /* mark port as initialized */ + pPrt->PState = SK_PRT_INIT; + + return(0); +} /* SkGeInitPort */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c new file mode 100644 index 0000000000..4a9e9e6af1 --- /dev/null +++ b/drivers/net/sk98lin/skgemib.c @@ -0,0 +1,1060 @@ +/***************************************************************************** + * + * Name: skgemib.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.7 $ + * Date: $Date: 2002/12/16 09:04:34 $ + * Purpose: Private Network Management Interface Management Database + * + ****************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/***************************************************************************** + * + * History: + * + * $Log: skgemib.c,v $ + * Revision 1.7 2002/12/16 09:04:34 tschilli + * Code for VCT handling added. + * + * Revision 1.6 2002/08/09 15:40:21 rwahl + * Editorial change (renamed ConfSpeedCap). + * + * Revision 1.5 2002/08/09 11:05:34 rwahl + * Added oid handling for link speed cap. + * + * Revision 1.4 2002/08/09 09:40:27 rwahl + * Added support for NDIS OID_PNP_xxx. + * + * Revision 1.3 2002/07/17 19:39:54 rwahl + * Added handler for OID_SKGE_SPEED_MODE & OID_SKGE_SPEED_STATUS. + * + * Revision 1.2 2002/05/22 08:59:00 rwahl + * - static functions only for release build. + * - Source file must be included. + * + * Revision 1.1 2002/05/22 08:12:42 rwahl + * Initial version. + * + ****************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +/* + * PRIVATE OID handler function prototypes + */ +PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action, + SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action, + SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int* pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); + +#ifdef SK_POWER_MGMT +PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +#endif + + +/* defines *******************************************************************/ +#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0])) + + +/* global variables **********************************************************/ + +/* + * Table to correlate OID with handler function and index to + * hardware register stored in StatAddress if applicable. + */ +PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { + {OID_GEN_XMIT_OK, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX}, + {OID_GEN_RCV_OK, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX}, + {OID_GEN_XMIT_ERROR, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, + {OID_GEN_RCV_ERROR, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, + {OID_GEN_RCV_NO_BUFFER, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, + {OID_GEN_DIRECTED_FRAMES_XMIT, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST}, + {OID_GEN_MULTICAST_FRAMES_XMIT, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST}, + {OID_GEN_BROADCAST_FRAMES_XMIT, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST}, + {OID_GEN_DIRECTED_FRAMES_RCV, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST}, + {OID_GEN_MULTICAST_FRAMES_RCV, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST}, + {OID_GEN_BROADCAST_FRAMES_RCV, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST}, + {OID_GEN_RCV_CRC_ERROR, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS}, + {OID_GEN_TRANSMIT_QUEUE_LENGTH, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, + {OID_802_3_PERMANENT_ADDRESS, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, 0}, + {OID_802_3_CURRENT_ADDRESS, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, 0}, + {OID_802_3_RCV_ERROR_ALIGNMENT, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING}, + {OID_802_3_XMIT_ONE_COLLISION, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL}, + {OID_802_3_XMIT_MORE_COLLISIONS, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL}, + {OID_802_3_XMIT_DEFERRED, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL}, + {OID_802_3_XMIT_MAX_COLLISIONS, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL}, + {OID_802_3_RCV_OVERRUN, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW}, + {OID_802_3_XMIT_UNDERRUN, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN}, + {OID_802_3_XMIT_TIMES_CRS_LOST, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER}, + {OID_802_3_XMIT_LATE_COLLISIONS, + 0, + 0, + 0, + SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL}, +#ifdef SK_POWER_MGMT + {OID_PNP_CAPABILITIES, + 0, + 0, + 0, + SK_PNMI_RO, PowerManagement, 0}, + {OID_PNP_SET_POWER, + 0, + 0, + 0, + SK_PNMI_WO, PowerManagement, 0}, + {OID_PNP_QUERY_POWER, + 0, + 0, + 0, + SK_PNMI_RO, PowerManagement, 0}, + {OID_PNP_ADD_WAKE_UP_PATTERN, + 0, + 0, + 0, + SK_PNMI_WO, PowerManagement, 0}, + {OID_PNP_REMOVE_WAKE_UP_PATTERN, + 0, + 0, + 0, + SK_PNMI_WO, PowerManagement, 0}, + {OID_PNP_ENABLE_WAKE_UP, + 0, + 0, + 0, + SK_PNMI_RW, PowerManagement, 0}, +#endif /* SK_POWER_MGMT */ + {OID_SKGE_MDB_VERSION, + 1, + 0, + SK_PNMI_MAI_OFF(MgmtDBVersion), + SK_PNMI_RO, General, 0}, + {OID_SKGE_SUPPORTED_LIST, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, + {OID_SKGE_ALL_DATA, + 0, + 0, + 0, + SK_PNMI_RW, OidStruct, 0}, + {OID_SKGE_VPD_FREE_BYTES, + 1, + 0, + SK_PNMI_MAI_OFF(VpdFreeBytes), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_ENTRIES_LIST, + 1, + 0, + SK_PNMI_MAI_OFF(VpdEntriesList), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_ENTRIES_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(VpdEntriesNumber), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_KEY, + SK_PNMI_VPD_ENTRIES, + sizeof(SK_PNMI_VPD), + SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_VALUE, + SK_PNMI_VPD_ENTRIES, + sizeof(SK_PNMI_VPD), + SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_ACCESS, + SK_PNMI_VPD_ENTRIES, + sizeof(SK_PNMI_VPD), + SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess), + SK_PNMI_RO, Vpd, 0}, + {OID_SKGE_VPD_ACTION, + SK_PNMI_VPD_ENTRIES, + sizeof(SK_PNMI_VPD), + SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction), + SK_PNMI_RW, Vpd, 0}, + {OID_SKGE_PORT_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(PortNumber), + SK_PNMI_RO, General, 0}, + {OID_SKGE_DEVICE_TYPE, + 1, + 0, + SK_PNMI_MAI_OFF(DeviceType), + SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_DESCR, + 1, + 0, + SK_PNMI_MAI_OFF(DriverDescr), + SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_VERSION, + 1, + 0, + SK_PNMI_MAI_OFF(DriverVersion), + SK_PNMI_RO, General, 0}, + {OID_SKGE_HW_DESCR, + 1, + 0, + SK_PNMI_MAI_OFF(HwDescr), + SK_PNMI_RO, General, 0}, + {OID_SKGE_HW_VERSION, + 1, + 0, + SK_PNMI_MAI_OFF(HwVersion), + SK_PNMI_RO, General, 0}, + {OID_SKGE_CHIPSET, + 1, + 0, + SK_PNMI_MAI_OFF(Chipset), + SK_PNMI_RO, General, 0}, + {OID_SKGE_ACTION, + 1, + 0, + SK_PNMI_MAI_OFF(Action), + SK_PNMI_RW, Perform, 0}, + {OID_SKGE_RESULT, + 1, + 0, + SK_PNMI_MAI_OFF(TestResult), + SK_PNMI_RO, General, 0}, + {OID_SKGE_BUS_TYPE, + 1, + 0, + SK_PNMI_MAI_OFF(BusType), + SK_PNMI_RO, General, 0}, + {OID_SKGE_BUS_SPEED, + 1, + 0, + SK_PNMI_MAI_OFF(BusSpeed), + SK_PNMI_RO, General, 0}, + {OID_SKGE_BUS_WIDTH, + 1, + 0, + SK_PNMI_MAI_OFF(BusWidth), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_SW_QUEUE_LEN, + 1, + 0, + SK_PNMI_MAI_OFF(TxSwQueueLen), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_SW_QUEUE_MAX, + 1, + 0, + SK_PNMI_MAI_OFF(TxSwQueueMax), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_RETRY, + 1, + 0, + SK_PNMI_MAI_OFF(TxRetryCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RX_INTR_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RxIntrCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_INTR_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(TxIntrCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RX_NO_BUF_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RxNoBufCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_NO_BUF_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(TxNoBufCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_USED_DESCR_NO, + 1, + 0, + SK_PNMI_MAI_OFF(TxUsedDescrNo), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RX_DELIVERED_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RxDeliveredCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RX_OCTETS_DELIV_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RxOctetsDeliveredCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RX_HW_ERROR_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RxHwErrorsCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TX_HW_ERROR_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(TxHwErrorsCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_IN_ERRORS_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(InErrorsCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_OUT_ERROR_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(OutErrorsCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_ERR_RECOVERY_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(ErrRecoveryCts), + SK_PNMI_RO, General, 0}, + {OID_SKGE_SYSUPTIME, + 1, + 0, + SK_PNMI_MAI_OFF(SysUpTime), + SK_PNMI_RO, General, 0}, + {OID_SKGE_SENSOR_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(SensorNumber), + SK_PNMI_RO, General, 0}, + {OID_SKGE_SENSOR_INDEX, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_DESCR, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_TYPE, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_VALUE, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_WAR_THRES_LOW, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_WAR_THRES_UPP, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_ERR_THRES_LOW, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_ERR_THRES_UPP, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_STATUS, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_WAR_CTS, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_ERR_CTS, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_WAR_TIME, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_SENSOR_ERR_TIME, + SK_PNMI_SENSOR_ENTRIES, + sizeof(SK_PNMI_SENSOR), + SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp), + SK_PNMI_RO, SensorStat, 0}, + {OID_SKGE_CHKSM_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(ChecksumNumber), + SK_PNMI_RO, General, 0}, + {OID_SKGE_CHKSM_RX_OK_CTS, + SKCS_NUM_PROTOCOLS, + sizeof(SK_PNMI_CHECKSUM), + SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts), + SK_PNMI_RO, CsumStat, 0}, + {OID_SKGE_CHKSM_RX_UNABLE_CTS, + SKCS_NUM_PROTOCOLS, + sizeof(SK_PNMI_CHECKSUM), + SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts), + SK_PNMI_RO, CsumStat, 0}, + {OID_SKGE_CHKSM_RX_ERR_CTS, + SKCS_NUM_PROTOCOLS, + sizeof(SK_PNMI_CHECKSUM), + SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts), + SK_PNMI_RO, CsumStat, 0}, + {OID_SKGE_CHKSM_TX_OK_CTS, + SKCS_NUM_PROTOCOLS, + sizeof(SK_PNMI_CHECKSUM), + SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts), + SK_PNMI_RO, CsumStat, 0}, + {OID_SKGE_CHKSM_TX_UNABLE_CTS, + SKCS_NUM_PROTOCOLS, + sizeof(SK_PNMI_CHECKSUM), + SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts), + SK_PNMI_RO, CsumStat, 0}, + {OID_SKGE_STAT_TX, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX}, + {OID_SKGE_STAT_TX_OCTETS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET}, + {OID_SKGE_STAT_TX_BROADCAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST}, + {OID_SKGE_STAT_TX_MULTICAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST}, + {OID_SKGE_STAT_TX_UNICAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST}, + {OID_SKGE_STAT_TX_LONGFRAMES, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES}, + {OID_SKGE_STAT_TX_BURST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST}, + {OID_SKGE_STAT_TX_PFLOWC, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC}, + {OID_SKGE_STAT_TX_FLOWC, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC}, + {OID_SKGE_STAT_TX_SINGLE_COL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL}, + {OID_SKGE_STAT_TX_MULTI_COL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL}, + {OID_SKGE_STAT_TX_EXCESS_COL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL}, + {OID_SKGE_STAT_TX_LATE_COL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL}, + {OID_SKGE_STAT_TX_DEFFERAL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL}, + {OID_SKGE_STAT_TX_EXCESS_DEF, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF}, + {OID_SKGE_STAT_TX_UNDERRUN, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN}, + {OID_SKGE_STAT_TX_CARRIER, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER}, +/* {OID_SKGE_STAT_TX_UTIL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization), + SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ + {OID_SKGE_STAT_TX_64, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64}, + {OID_SKGE_STAT_TX_127, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127}, + {OID_SKGE_STAT_TX_255, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255}, + {OID_SKGE_STAT_TX_511, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511}, + {OID_SKGE_STAT_TX_1023, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023}, + {OID_SKGE_STAT_TX_MAX, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX}, + {OID_SKGE_STAT_TX_SYNC, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC}, + {OID_SKGE_STAT_TX_SYNC_OCTETS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET}, + {OID_SKGE_STAT_RX, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX}, + {OID_SKGE_STAT_RX_OCTETS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET}, + {OID_SKGE_STAT_RX_BROADCAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST}, + {OID_SKGE_STAT_RX_MULTICAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST}, + {OID_SKGE_STAT_RX_UNICAST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST}, + {OID_SKGE_STAT_RX_LONGFRAMES, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES}, + {OID_SKGE_STAT_RX_PFLOWC, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC}, + {OID_SKGE_STAT_RX_FLOWC, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC}, + {OID_SKGE_STAT_RX_PFLOWC_ERR, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR}, + {OID_SKGE_STAT_RX_FLOWC_UNKWN, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN}, + {OID_SKGE_STAT_RX_BURST, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST}, + {OID_SKGE_STAT_RX_MISSED, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED}, + {OID_SKGE_STAT_RX_FRAMING, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING}, + {OID_SKGE_STAT_RX_OVERFLOW, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW}, + {OID_SKGE_STAT_RX_JABBER, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER}, + {OID_SKGE_STAT_RX_CARRIER, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER}, + {OID_SKGE_STAT_RX_IR_LENGTH, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH}, + {OID_SKGE_STAT_RX_SYMBOL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL}, + {OID_SKGE_STAT_RX_SHORTS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS}, + {OID_SKGE_STAT_RX_RUNT, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT}, + {OID_SKGE_STAT_RX_CEXT, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT}, + {OID_SKGE_STAT_RX_TOO_LONG, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG}, + {OID_SKGE_STAT_RX_FCS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS}, +/* {OID_SKGE_STAT_RX_UTIL, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization), + SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ + {OID_SKGE_STAT_RX_64, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64}, + {OID_SKGE_STAT_RX_127, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127}, + {OID_SKGE_STAT_RX_255, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255}, + {OID_SKGE_STAT_RX_511, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511}, + {OID_SKGE_STAT_RX_1023, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023}, + {OID_SKGE_STAT_RX_MAX, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_STAT), + SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts), + SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX}, + {OID_SKGE_PHYS_CUR_ADDR, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr), + SK_PNMI_RW, Addr, 0}, + {OID_SKGE_PHYS_FAC_ADDR, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr), + SK_PNMI_RO, Addr, 0}, + {OID_SKGE_PMD, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_CONNECTOR, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_LINK_CAP, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_LINK_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode), + SK_PNMI_RW, MacPrivateConf, 0}, + {OID_SKGE_LINK_MODE_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_LINK_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_FLOWCTRL_CAP, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_FLOWCTRL_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode), + SK_PNMI_RW, MacPrivateConf, 0}, + {OID_SKGE_FLOWCTRL_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_PHY_OPERATION_CAP, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_PHY_OPERATION_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode), + SK_PNMI_RW, MacPrivateConf, 0}, + {OID_SKGE_PHY_OPERATION_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_SPEED_CAP, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_SPEED_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode), + SK_PNMI_RW, MacPrivateConf, 0}, + {OID_SKGE_SPEED_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus), + SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_TRAP, + 1, + 0, + SK_PNMI_MAI_OFF(Trap), + SK_PNMI_RO, General, 0}, + {OID_SKGE_TRAP_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(TrapNumber), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RLMT_MODE, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtMode), + SK_PNMI_RW, Rlmt, 0}, + {OID_SKGE_RLMT_PORT_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtPortNumber), + SK_PNMI_RO, Rlmt, 0}, + {OID_SKGE_RLMT_PORT_ACTIVE, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtPortActive), + SK_PNMI_RO, Rlmt, 0}, + {OID_SKGE_RLMT_PORT_PREFERRED, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtPortPreferred), + SK_PNMI_RW, Rlmt, 0}, + {OID_SKGE_RLMT_CHANGE_CTS, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtChangeCts), + SK_PNMI_RO, Rlmt, 0}, + {OID_SKGE_RLMT_CHANGE_TIME, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtChangeTime), + SK_PNMI_RO, Rlmt, 0}, + {OID_SKGE_RLMT_CHANGE_ESTIM, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtChangeEstimate), + SK_PNMI_RO, Rlmt, 0}, + {OID_SKGE_RLMT_CHANGE_THRES, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtChangeThreshold), + SK_PNMI_RW, Rlmt, 0}, + {OID_SKGE_RLMT_PORT_INDEX, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_STATUS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_TX_HELLO_CTS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_RX_HELLO_CTS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_TX_SP_REQ_CTS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_RX_SP_CTS, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_RLMT), + SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts), + SK_PNMI_RO, RlmtStat, 0}, + {OID_SKGE_RLMT_MONITOR_NUMBER, + 1, + 0, + SK_PNMI_MAI_OFF(RlmtMonitorNumber), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RLMT_MONITOR_INDEX, + SK_PNMI_MONITOR_ENTRIES, + sizeof(SK_PNMI_RLMT_MONITOR), + SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex), + SK_PNMI_RO, Monitor, 0}, + {OID_SKGE_RLMT_MONITOR_ADDR, + SK_PNMI_MONITOR_ENTRIES, + sizeof(SK_PNMI_RLMT_MONITOR), + SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr), + SK_PNMI_RO, Monitor, 0}, + {OID_SKGE_RLMT_MONITOR_ERRS, + SK_PNMI_MONITOR_ENTRIES, + sizeof(SK_PNMI_RLMT_MONITOR), + SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts), + SK_PNMI_RO, Monitor, 0}, + {OID_SKGE_RLMT_MONITOR_TIMESTAMP, + SK_PNMI_MONITOR_ENTRIES, + sizeof(SK_PNMI_RLMT_MONITOR), + SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp), + SK_PNMI_RO, Monitor, 0}, + {OID_SKGE_RLMT_MONITOR_ADMIN, + SK_PNMI_MONITOR_ENTRIES, + sizeof(SK_PNMI_RLMT_MONITOR), + SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin), + SK_PNMI_RW, Monitor, 0}, + {OID_SKGE_MTU, + 1, + 0, + SK_PNMI_MAI_OFF(MtuSize), + SK_PNMI_RW, MacPrivateConf, 0}, + {OID_SKGE_VCT_GET, + 0, + 0, + 0, + SK_PNMI_RO, Vct, 0}, + {OID_SKGE_VCT_SET, + 0, + 0, + 0, + SK_PNMI_WO, Vct, 0}, + {OID_SKGE_VCT_STATUS, + 0, + 0, + 0, + SK_PNMI_RO, Vct, 0}, +}; + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c new file mode 100644 index 0000000000..b5d32b04c1 --- /dev/null +++ b/drivers/net/sk98lin/skgepnmi.c @@ -0,0 +1,8310 @@ +/***************************************************************************** + * + * Name: skgepnmi.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.102 $ + * Date: $Date: 2002/12/16 14:03:24 $ + * Purpose: Private Network Management Interface + * + ****************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/***************************************************************************** + * + * History: + * + * $Log: skgepnmi.c,v $ + * Revision 1.102 2002/12/16 14:03:24 tschilli + * VCT code in Vct() changed. + * + * Revision 1.101 2002/12/16 09:04:10 tschilli + * Code for VCT handling added. + * + * Revision 1.100 2002/09/26 14:28:13 tschilli + * For XMAC the values in the SK_PNMI_PORT Port struct are copied to + * the new SK_PNMI_PORT BufPort struct during a MacUpdate() call. + * These values are used when GetPhysStatVal() is called. With this + * mechanism you get the best results when software corrections for + * counters are needed. Example: RX_LONGFRAMES. + * + * Revision 1.99 2002/09/17 12:31:19 tschilli + * OID_SKGE_TX_HW_ERROR_CTS, OID_SKGE_OUT_ERROR_CTS, OID_GEN_XMIT_ERROR: + * Double count of SK_PNMI_HTX_EXCESS_COL in function General() removed. + * OID_PNP_CAPABILITIES: sizeof(SK_PM_WAKE_UP_CAPABILITIES) changed to + * sizeof(SK_PNP_CAPABILITIES) in function PowerManagement(). + * + * Revision 1.98 2002/09/10 09:00:03 rwahl + * Adapted boolean definitions according sktypes. + * + * Revision 1.97 2002/09/05 15:07:03 rwahl + * Editorial changes. + * + * Revision 1.96 2002/09/05 11:04:14 rwahl + * - Rx/Tx packets statistics of virtual port were zero on link down (#10750) + * - For GMAC the overflow IRQ for Rx longframe counter was not counted. + * - Incorrect calculation for oids OID_SKGE_RX_HW_ERROR_CTS, + * OID_SKGE_IN_ERRORS_CTS, OID_GEN_RCV_ERROR. + * - Moved correction for OID_SKGE_STAT_RX_TOO_LONG to GetPhysStatVal(). + * - Editorial changes. + * + * Revision 1.95 2002/09/04 08:53:37 rwahl + * - Incorrect statistics for Rx_too_long counter with jumbo frame (#10751) + * - StatRxFrameTooLong & StatRxPMaccErr counters were not reset. + * - Fixed compiler warning for debug msg arg types. + * + * Revision 1.94 2002/08/09 15:42:14 rwahl + * - Fixed StatAddr table for GMAC. + * - VirtualConf(): returned indeterminated status for speed oids if no + * active port. + * + * Revision 1.93 2002/08/09 11:04:59 rwahl + * Added handler for link speed caps. + * + * Revision 1.92 2002/08/09 09:43:03 rwahl + * - Added handler for NDIS OID_PNP_xxx ids. + * + * Revision 1.91 2002/07/17 19:53:03 rwahl + * - Added StatOvrflwBit table for XMAC & GMAC. + * - Extended StatAddr table for GMAC. Added check of number of counters + * in enumeration and size of StatAddr table on init level. + * - Added use of GIFunc table. + * - ChipSet is not static anymore, + * - Extended SIRQ event handler for both mac types. + * - Fixed rx short counter bug (#10620) + * - Added handler for oids SKGE_SPEED_MODE & SKGE_SPEED_STATUS. + * - Extendet GetPhysStatVal() for GMAC. + * - Editorial changes. + * + * Revision 1.90 2002/05/22 08:56:25 rwahl + * - Moved OID table to separate source file. + * - Fix: TX_DEFFERAL counter incremented in full-duplex mode. + * - Use string definitions for error msgs. + * + * Revision 1.89 2001/09/18 10:01:30 mkunz + * some OID's fixed for dualnetmode + * + * Revision 1.88 2001/08/02 07:58:08 rwahl + * - Fixed NetIndex to csum module at ResetCounter(). + * + * Revision 1.87 2001/04/06 13:35:09 mkunz + * -Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's + * + * Revision 1.86 2001/03/09 09:18:03 mkunz + * Changes in SK_DBG_MSG + * + * Revision 1.85 2001/03/08 09:37:31 mkunz + * Bugfix in ResetCounter for Pnmi.Port structure + * + * Revision 1.84 2001/03/06 09:04:55 mkunz + * Made some changes in instance calculation + * + * Revision 1.83 2001/02/15 09:15:32 mkunz + * Necessary changes for dual net mode added + * + * Revision 1.82 2001/02/07 08:24:19 mkunz + * -Made changes in handling of OID_SKGE_MTU + * + * Revision 1.81 2001/02/06 09:58:00 mkunz + * -Vpd bug fixed + * -OID_SKGE_MTU added + * -pnmi support for dual net mode. Interface function and macros extended + * + * Revision 1.80 2001/01/22 13:41:35 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.79 2000/12/05 14:57:40 cgoos + * SetStruct failed before first Link Up (link mode of virtual + * port "INDETERMINATED"). + * + * Revision 1.78 2000/09/12 10:44:58 cgoos + * Fixed SK_PNMI_STORE_U32 calls with typecasted argument. + * + * Revision 1.77 2000/09/07 08:10:19 rwahl + * - Modified algorithm for 64bit NDIS statistic counters; + * returns 64bit or 32bit value depending on passed buffer + * size. Indicate capability for 64bit NDIS counter, if passed + * buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, + * and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too. + * - corrected OID_SKGE_RLMT_PORT_PREFERRED. + * + * Revision 1.76 2000/08/03 15:23:39 rwahl + * - Correction for FrameTooLong counter has to be moved to OID handling + * routines (instead of statistic counter routine). + * - Fix in XMAC Reset Event handling: Only offset counter for hardware + * statistic registers are updated. + * + * Revision 1.75 2000/08/01 16:46:05 rwahl + * - Added StatRxLongFrames counter and correction of FrameTooLong counter. + * - Added directive to control width (default = 32bit) of NDIS statistic + * counters (SK_NDIS_64BIT_CTR). + * + * Revision 1.74 2000/07/04 11:41:53 rwahl + * - Added volition connector type. + * + * Revision 1.73 2000/03/15 16:33:10 rwahl + * Fixed bug 10510; wrong reset of virtual port statistic counters. + * + * Revision 1.72 1999/12/06 16:15:53 rwahl + * Fixed problem of instance range for current and factory MAC address. + * + * Revision 1.71 1999/12/06 10:14:20 rwahl + * Fixed bug 10476; set operation for PHY_OPERATION_MODE. + * + * Revision 1.70 1999/11/22 13:33:34 cgoos + * Changed license header to GPL. + * + * Revision 1.69 1999/10/18 11:42:15 rwahl + * Added typecasts for checking event dependent param (debug only). + * + * Revision 1.68 1999/10/06 09:35:59 cgoos + * Added state check to PHY_READ call (hanged if called during startup). + * + * Revision 1.67 1999/09/22 09:53:20 rwahl + * - Read Broadcom register for updating fcs error counter (1000Base-T). + * + * Revision 1.66 1999/08/26 13:47:56 rwahl + * Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap. + * + * Revision 1.65 1999/07/26 07:49:35 cgoos + * Added two typecasts to avoid compiler warnings. + * + * Revision 1.64 1999/05/20 09:24:12 cgoos + * Changes for 1000Base-T (sensors, Master/Slave). + * + * Revision 1.63 1999/04/13 15:11:58 mhaveman + * Moved include of rlmt.h to header skgepnmi.h because some macros + * are needed there. + * + * Revision 1.62 1999/04/13 15:08:07 mhaveman + * Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK + * to grant unified interface by only using the PNMI header file. + * SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK. + * + * Revision 1.61 1999/04/13 15:02:48 mhaveman + * Changes caused by review: + * -Changed some comments + * -Removed redundant check for OID_SKGE_PHYS_FAC_ADDR + * -Optimized PRESET check. + * -Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same + * address will now not cause this error. Removed corresponding check. + * + * Revision 1.60 1999/03/23 10:41:23 mhaveman + * Added comments. + * + * Revision 1.59 1999/02/19 08:01:28 mhaveman + * Fixed bug 10372 that after counter reset all ports were displayed + * as inactive. + * + * Revision 1.58 1999/02/16 18:04:47 mhaveman + * Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME. + * + * Revision 1.56 1999/01/27 12:29:11 mhaveman + * SkTimerStart was called with time value in milli seconds but needs + * micro seconds. + * + * Revision 1.55 1999/01/25 15:00:38 mhaveman + * Added support to allow multiple ports to be active. If this feature in + * future will be used, the Management Data Base variables PORT_ACTIVE + * and PORT_PREFERED should be moved to the port specific part of RLMT. + * Currently they return the values of the first active physical port + * found. A set to the virtual port will actually change all active + * physical ports. A get returns the melted values of all active physical + * ports. If the port values differ a return value INDETERMINATED will + * be returned. This effects especially the CONF group. + * + * Revision 1.54 1999/01/19 10:10:22 mhaveman + * -Fixed bug 10354: Counter values of virtual port were wrong after port + * switches + * -Added check if a switch to the same port is notified. + * + * Revision 1.53 1999/01/07 09:25:21 mhaveman + * Forgot to initialize a variable. + * + * Revision 1.52 1999/01/05 10:34:33 mhaveman + * Fixed little error in RlmtChangeEstimate calculation. + * + * Revision 1.51 1999/01/05 09:59:07 mhaveman + * -Moved timer start to init level 2 + * -Redesigned port switch average calculation to avoid 64bit + * arithmetic. + * + * Revision 1.50 1998/12/10 15:13:59 mhaveman + * -Fixed: PHYS_CUR_ADDR returned wrong addresses + * -Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned + * always BAD_VALUE. + * -Fixed: TRAP buffer seemed to sometimes suddenly empty + * + * Revision 1.49 1998/12/09 16:17:07 mhaveman + * Fixed: Couldnot delete VPD keys on UNIX. + * + * Revision 1.48 1998/12/09 14:11:10 mhaveman + * -Add: Debugmessage for XMAC_RESET supressed to minimize output. + * -Fixed: RlmtChangeThreshold will now be initialized. + * -Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char. + * -Fixed: On VPD key creation an invalid key name could be created + * (e.g. A5) + * -Some minor changes in comments and code. + * + * Revision 1.47 1998/12/08 16:00:31 mhaveman + * -Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port + * is active. + * -Fixed: For the RLMT statistics group only the last value was + * returned and the rest of the buffer was filled with 0xff + * -Fixed: Mysteriously the preset on RLMT_MODE still returned + * BAD_VALUE. + * Revision 1.46 1998/12/08 10:04:56 mhaveman + * -Fixed: Preset on RLMT_MODE returned always BAD_VALUE error. + * -Fixed: Alignment error in GetStruct + * -Fixed: If for Get/Preset/SetStruct the buffer size is equal or + * larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored + * to the buffer. In this case the caller should always return + * ok to its upper routines. Only if the buffer size is less + * than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal + * to 0, an error should be returned by the caller. + * -Fixed: Wrong number of instances with RLMT statistic. + * -Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0. + * + * Revision 1.45 1998/12/03 17:17:24 mhaveman + * -Removed for VPD create action the buffer size limitation to 4 bytes. + * -Pass now physical/active physical port to ADDR for CUR_ADDR set + * + * Revision 1.44 1998/12/03 15:14:35 mhaveman + * Another change to Vpd instance evaluation. + * + * Revision 1.43 1998/12/03 14:18:10 mhaveman + * -Fixed problem in PnmiSetStruct. It was impossible to set any value. + * -Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION. + * + * Revision 1.42 1998/12/03 11:31:47 mhaveman + * Inserted cast to satisfy lint. + * + * Revision 1.41 1998/12/03 11:28:16 mhaveman + * Removed SK_PNMI_CHECKPTR + * + * Revision 1.40 1998/12/03 11:19:07 mhaveman + * Fixed problems + * -A set to virtual port will now be ignored. A set with broadcast + * address to any port will be ignored. + * -GetStruct function made VPD instance calculation wrong. + * -Prefered port returned -1 instead of 0. + * + * Revision 1.39 1998/11/26 15:30:29 mhaveman + * Added sense mode to link mode. + * + * Revision 1.38 1998/11/23 15:34:00 mhaveman + * -Fixed bug for RX counters. On an RX overflow interrupt the high + * words of all RX counters were incremented. + * -SET operations on FLOWCTRL_MODE and LINK_MODE accept now the + * value 0, which has no effect. It is usefull for multiple instance + * SETs. + * + * Revision 1.37 1998/11/20 08:02:04 mhaveman + * -Fixed: Ports were compared with MAX_SENSORS + * -Fixed: Crash in GetTrapEntry with MEMSET macro + * -Fixed: Conversions between physical, logical port index and instance + * + * Revision 1.36 1998/11/16 07:48:53 mhaveman + * Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings + * on Solaris. + * + * Revision 1.35 1998/11/16 07:45:34 mhaveman + * SkAddrOverride now returns value and will be checked. + * + * Revision 1.34 1998/11/10 13:40:37 mhaveman + * Needed to change interface, because NT driver needs a return value + * of needed buffer space on TOO_SHORT errors. Therefore all + * SkPnmiGet/Preset/Set functions now have a pointer to the length + * parameter, where the needed space on error is returned. + * + * Revision 1.33 1998/11/03 13:52:46 mhaveman + * Made file lint conform. + * + * Revision 1.32 1998/11/03 13:19:07 mhaveman + * The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in + * Para32[0] the physical MAC index and in Para32[1] the new mode. + * + * Revision 1.31 1998/11/03 12:30:40 gklug + * fix: compiler warning memset + * + * Revision 1.30 1998/11/03 12:04:46 mhaveman + * Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end + * Fixed alignment problem with CHIPSET. + * + * Revision 1.29 1998/11/02 11:23:54 mhaveman + * Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry. + * + * Revision 1.28 1998/11/02 10:47:16 mhaveman + * Added syslog messages for internal errors. + * + * Revision 1.27 1998/10/30 15:48:06 mhaveman + * Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and + * RlmtChangeThreshold calculation. + * + * Revision 1.26 1998/10/29 15:36:55 mhaveman + * -Fixed bug in trap buffer handling. + * -OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR, + * OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY, + * OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with + * a leading octet before each string storing the string length. + * -Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize + * RlmtUpdate calls in GetStatVal. + * -Inserted SK_PNMI_CHECKFLAGS macro increase readability. + * + * Revision 1.25 1998/10/29 08:50:36 mhaveman + * Fixed problems after second event simulation. + * + * Revision 1.24 1998/10/28 08:44:37 mhaveman + * -Fixed alignment problem + * -Fixed problems during event simulation + * -Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT) + * -Changed type of parameter Instance back to SK_U32 because of VPD + * -Updated new VPD function calls + * + * Revision 1.23 1998/10/23 10:16:37 mhaveman + * Fixed bugs after buffer test simulation. + * + * Revision 1.22 1998/10/21 13:23:52 mhaveman + * -Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc). + * -Changed calculation of hundrets of seconds. + * + * Revision 1.20 1998/10/20 07:30:45 mhaveman + * Made type changes to unsigned integer where possible. + * + * Revision 1.19 1998/10/19 10:51:30 mhaveman + * -Made Bug fixes after simulation run + * -Renamed RlmtMAC... to RlmtPort... + * -Marked workarounds with Errata comments + * + * Revision 1.18 1998/10/14 07:50:08 mhaveman + * -For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT + * to HWACCESS. + * -Provided all MEMCPY/MEMSET macros with (char *) pointers, because + * Solaris throwed warnings when mapping to bcopy/bset. + * + * Revision 1.17 1998/10/13 07:42:01 mhaveman + * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA + * -Removed old cvs history entries + * -Renamed MacNumber to PortNumber + * + * Revision 1.16 1998/10/07 10:52:49 mhaveman + * -Inserted handling of some OID_GEN_ Ids for windows + * -Fixed problem with 803.2 statistic. + * + * Revision 1.15 1998/10/01 09:16:29 mhaveman + * Added Debug messages for function call and UpdateFlag tracing. + * + * Revision 1.14 1998/09/30 13:39:09 mhaveman + * -Reduced namings of 'MAC' by replacing them with 'PORT'. + * -Completed counting of OID_SKGE_RX_HW_ERROR_CTS, + * OID_SKGE_TX_HW_ERROR_CTS, + * OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS. + * -SET check for RlmtMode + * + * Revision 1.13 1998/09/28 13:13:08 mhaveman + * Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN, + * and SK_STRNCPY. (Same reasons as for mem.. and MEM..) + * + * Revision 1.12 1998/09/16 08:18:36 cgoos + * Fix: XM_INxx and XM_OUTxx called with different parameter order: + * sometimes IoC,Mac,... sometimes Mac,IoC,... Now always first variant. + * Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version. + * Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY + * + * Revision 1.11 1998/09/04 17:01:45 mhaveman + * Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to + * OID_SKGE_RX_NO_BUF_CTS. + * + * Revision 1.10 1998/09/04 14:35:35 mhaveman + * Added macro counters, that are counted by driver. + * + ****************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +static const char SysKonnectFileId[] = + "@(#) $Id: skgepnmi.c,v 1.102 2002/12/16 14:03:24 tschilli Exp $" + " (C) SysKonnect."; + +#include "h/skdrv1st.h" +#include "h/sktypes.h" +#include "h/xmac_ii.h" +#include "h/skdebug.h" +#include "h/skqueue.h" +#include "h/skgepnmi.h" +#include "h/skgesirq.h" +#include "h/skcsum.h" +#include "h/skvpd.h" +#include "h/skgehw.h" +#include "h/skgeinit.h" +#include "h/skdrv2nd.h" +#include "h/skgepnm2.h" +#ifdef SK_POWER_MGMT +#include "h/skgepmgt.h" +#endif +/* defines *******************************************************************/ + +#ifndef DEBUG +#define PNMI_STATIC static +#else /* DEBUG */ +#define PNMI_STATIC +#endif /* DEBUG */ + +/* + * Public Function prototypes + */ +int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); +int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, + unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, + unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, + unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, + unsigned int *pLen, SK_U32 NetIndex); +int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, + unsigned int *pLen, SK_U32 NetIndex); +int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, + unsigned int *pLen, SK_U32 NetIndex); +int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); + + +/* + * Private Function prototypes + */ + +PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int + PhysPortIndex); +PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int + PhysPortIndex); +PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac); +PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf); +PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC, + unsigned int PhysPortIndex, unsigned int StatIndex); +PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex, + unsigned int StatIndex, SK_U32 NetIndex); +PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size); +PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen, + unsigned int *pEntries); +PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr, + unsigned int KeyArrLen, unsigned int *pKeyNo); +PNMI_STATIC int LookupId(SK_U32 Id); +PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac, + unsigned int LastMac); +PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf, + unsigned int *pLen, SK_U32 NetIndex); +PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); +PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac); +PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId, + unsigned int PortIndex); +PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId, + unsigned int SensorIndex); +PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId); +PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); +PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); +PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); +PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); +PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, + unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); +PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); + +/* + * Table to correlate OID with handler function and index to + * hardware register stored in StatAddress if applicable. + */ +#include "skgemib.c" + +/* global variables **********************************************************/ + +/* + * Overflow status register bit table and corresponding counter + * dependent on MAC type - the number relates to the size of overflow + * mask returned by the pFnMacOverflow function + */ +PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = { +/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST}, +/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST}, +/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC}, +/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST}, +/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW}, +/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH}, +/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64}, +/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127}, +/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255}, +/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511}, +/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023}, +/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX}, +/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES}, +/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED}, +/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL}, +/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL}, +/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL}, +/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL}, +/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL}, +/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN}, +/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED}, +/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED}, +/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED}, +/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED}, +/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED}, +/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED}, +/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, +/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST}, +/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST}, +/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC}, +/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST}, +/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS}, +/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED}, +/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW}, +/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH}, +/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW}, +/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH}, +/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE}, +/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT}, +/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64}, +/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127}, +/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255}, +/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511}, +/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023}, +/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX}, +/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES}, +/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG}, +/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER}, +/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED}, +/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW}, +/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED}, +/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED}, +/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED}, +/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED}, +/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED}, +/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED}, +/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED}, +/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED}, +/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED} +}; + +/* + * Table for hardware register saving on resets and port switches + */ +PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = { + /* SK_PNMI_HTX */ + {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_OCTETHIGH */ + {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}}, + /* SK_PNMI_HTX_OCTETLOW */ + {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}}, + /* SK_PNMI_HTX_BROADCAST */ + {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}}, + /* SK_PNMI_HTX_MULTICAST */ + {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}}, + /* SK_PNMI_HTX_UNICAST */ + {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}}, + /* SK_PNMI_HTX_BURST */ + {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_PMACC */ + {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}}, + /* SK_PNMI_HTX_MACC */ + {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_COL */ + {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}}, + /* SK_PNMI_HTX_SINGLE_COL */ + {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}}, + /* SK_PNMI_HTX_MULTI_COL */ + {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}}, + /* SK_PNMI_HTX_EXCESS_COL */ + {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}}, + /* SK_PNMI_HTX_LATE_COL */ + {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}}, + /* SK_PNMI_HTX_DEFFERAL */ + {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_EXCESS_DEF */ + {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_UNDERRUN */ + {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}}, + /* SK_PNMI_HTX_CARRIER */ + {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_UTILUNDER */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_UTILOVER */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_64 */ + {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}}, + /* SK_PNMI_HTX_127 */ + {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}}, + /* SK_PNMI_HTX_255 */ + {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}}, + /* SK_PNMI_HTX_511 */ + {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}}, + /* SK_PNMI_HTX_1023 */ + {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}}, + /* SK_PNMI_HTX_MAX */ + {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}}, + /* SK_PNMI_HTX_LONGFRAMES */ + {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}}, + /* SK_PNMI_HTX_SYNC */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_SYNC_OCTET */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HTX_RESERVED */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX */ + {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_OCTETHIGH */ + {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}}, + /* SK_PNMI_HRX_OCTETLOW */ + {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}}, + /* SK_PNMI_HRX_BADOCTETHIGH */ + {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}}, + /* SK_PNMI_HRX_BADOCTETLOW */ + {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}}, + /* SK_PNMI_HRX_BROADCAST */ + {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}}, + /* SK_PNMI_HRX_MULTICAST */ + {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}}, + /* SK_PNMI_HRX_UNICAST */ + {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}}, + /* SK_PNMI_HRX_PMACC */ + {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}}, + /* SK_PNMI_HRX_MACC */ + {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_PMACC_ERR */ + {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_MACC_UNKWN */ + {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_BURST */ + {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_MISSED */ + {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_FRAMING */ + {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_UNDERSIZE */ + {{0, SK_FALSE},{GM_RXF_SHT, SK_TRUE}}, + /* SK_PNMI_HRX_OVERFLOW */ + {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, + /* SK_PNMI_HRX_JABBER */ + {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}}, + /* SK_PNMI_HRX_CARRIER */ + {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_IRLENGTH */ + {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_SYMBOL */ + {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_SHORTS */ + {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_RUNT */ + {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}}, + /* SK_PNMI_HRX_TOO_LONG */ + {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}}, + /* SK_PNMI_HRX_FCS */ + {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}}, + /* SK_PNMI_HRX_CEXT */ + {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_UTILUNDER */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_UTILOVER */ + {{0, SK_FALSE}, {0, SK_FALSE}}, + /* SK_PNMI_HRX_64 */ + {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}}, + /* SK_PNMI_HRX_127 */ + {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}}, + /* SK_PNMI_HRX_255 */ + {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}}, + /* SK_PNMI_HRX_511 */ + {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}}, + /* SK_PNMI_HRX_1023 */ + {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}}, + /* SK_PNMI_HRX_MAX */ + {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}}, + /* SK_PNMI_HRX_LONGFRAMES */ + {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}}, + /* SK_PNMI_HRX_RESERVED */ + {{0, SK_FALSE}, {0, SK_FALSE}} +}; + + +/***************************************************************************** + * + * Public functions + * + */ + +/***************************************************************************** + * + * SkPnmiInit - Init function of PNMI + * + * Description: + * SK_INIT_DATA: Initialises the data structures + * SK_INIT_IO: Resets the XMAC statistics, determines the device and + * connector type. + * SK_INIT_RUN: Starts a timer event for port switch per hour + * calculation. + * + * Returns: + * Always 0 + */ +int SkPnmiInit( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Level) /* Initialization level */ +{ + unsigned int PortMax; /* Number of ports */ + unsigned int PortIndex; /* Current port index in loop */ + SK_U16 Val16; /* Multiple purpose 16 bit variable */ + SK_U8 Val8; /* Mulitple purpose 8 bit variable */ + SK_EVPARA EventParam; /* Event struct for timer event */ + SK_GEPORT *pPrt; + SK_PNMI_VCT *pVctBackupData; + + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); + + switch (Level) { + + case SK_INIT_DATA: + SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); + pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; + pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); + pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; + for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { + + pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; + pAC->Pnmi.DualNetActiveFlag = SK_FALSE; + } + +#ifdef SK_PNMI_CHECK + if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, + ("CounterOffset struct size (%d) differs from" + "SK_PNMI_MAX_IDX (%d)\n", + SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); + BRK; + } + + if (SK_PNMI_MAX_IDX != + (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, + ("StatAddr table size (%d) differs from " + "SK_PNMI_MAX_IDX (%d)\n", + (sizeof(StatAddr) / + (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)), + SK_PNMI_MAX_IDX)); + BRK; + } +#endif /* SK_PNMI_CHECK */ + break; + + case SK_INIT_IO: + /* + * Reset MAC counters + */ + PortMax = pAC->GIni.GIMacsFound; + + for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { + + pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); + } + + /* Initialize DSP variables for Vct() to 0xff => Never written! */ + for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { + pPrt = &pAC->GIni.GP[PortIndex]; + pPrt->PCableLen =0xff; + pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; + pVctBackupData->PCableLen = 0xff; + } + + /* + * Get pci bus speed + */ + SK_IN16(IoC, B0_CTST, &Val16); + if ((Val16 & CS_BUS_CLOCK) == 0) { + + pAC->Pnmi.PciBusSpeed = 33; + } + else { + pAC->Pnmi.PciBusSpeed = 66; + } + + /* + * Get pci bus width + */ + SK_IN16(IoC, B0_CTST, &Val16); + if ((Val16 & CS_BUS_SLOT_SZ) == 0) { + + pAC->Pnmi.PciBusWidth = 32; + } + else { + pAC->Pnmi.PciBusWidth = 64; + } + + /* + * Get chipset + */ + switch (pAC->GIni.GIChipId) { + case CHIP_ID_GENESIS: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; + break; + + case CHIP_ID_YUKON: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; + break; + + default: + break; + } + + /* + * Get PMD and DeviceType + */ + SK_IN8(IoC, B2_PMD_TYP, &Val8); + switch (Val8) { + case 'S': + pAC->Pnmi.PMD = 3; + if (pAC->GIni.GIMacsFound > 1) { + + pAC->Pnmi.DeviceType = 0x00020002; + } + else { + pAC->Pnmi.DeviceType = 0x00020001; + } + break; + + case 'L': + pAC->Pnmi.PMD = 2; + if (pAC->GIni.GIMacsFound > 1) { + + pAC->Pnmi.DeviceType = 0x00020004; + } + else { + pAC->Pnmi.DeviceType = 0x00020003; + } + break; + + case 'C': + pAC->Pnmi.PMD = 4; + if (pAC->GIni.GIMacsFound > 1) { + + pAC->Pnmi.DeviceType = 0x00020006; + } + else { + pAC->Pnmi.DeviceType = 0x00020005; + } + break; + + case 'T': + pAC->Pnmi.PMD = 5; + if (pAC->GIni.GIMacsFound > 1) { + + pAC->Pnmi.DeviceType = 0x00020008; + } + else { + pAC->Pnmi.DeviceType = 0x00020007; + } + break; + + default : + pAC->Pnmi.PMD = 1; + pAC->Pnmi.DeviceType = 0; + break; + } + + /* + * Get connector + */ + SK_IN8(IoC, B2_CONN_TYP, &Val8); + switch (Val8) { + case 'C': + pAC->Pnmi.Connector = 2; + break; + + case 'D': + pAC->Pnmi.Connector = 3; + break; + + case 'F': + pAC->Pnmi.Connector = 4; + break; + + case 'J': + pAC->Pnmi.Connector = 5; + break; + + case 'V': + pAC->Pnmi.Connector = 6; + break; + + default: + pAC->Pnmi.Connector = 1; + break; + } + break; + + case SK_INIT_RUN: + /* + * Start timer for RLMT change counter + */ + SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); + SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, + 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, + EventParam); + break; + + default: + break; /* Nothing todo */ + } + + return (0); +} + +/***************************************************************************** + * + * SkPnmiGetVar - Retrieves the value of a single OID + * + * Description: + * Calls a general sub-function for all this stuff. If the instance + * -1 is passed, the values of all instances are returned in an + * array of values. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed + * SK_PNMI_ERR_GENERAL A general severe internal error occured + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take + * the data. + * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +int SkPnmiGetVar( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 Id, /* Object ID that is to be processed */ +void *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", + Id, *pLen, Instance, NetIndex)); + + return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, + Instance, NetIndex)); +} + +/***************************************************************************** + * + * SkPnmiPreSetVar - Presets the value of a single OID + * + * Description: + * Calls a general sub-function for all this stuff. The preset does + * the same as a set, but returns just before finally setting the + * new value. This is usefull to check if a set might be successfull. + * If as instance a -1 is passed, an array of values is supposed and + * all instance of the OID will be set. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +int SkPnmiPreSetVar( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 Id, /* Object ID that is to be processed */ +void *pBuf, /* Buffer which stores the mgmt data to be set */ +unsigned int *pLen, /* Total length of mgmt data */ +SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", + Id, *pLen, Instance, NetIndex)); + + + return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, + Instance, NetIndex)); +} + +/***************************************************************************** + * + * SkPnmiSetVar - Sets the value of a single OID + * + * Description: + * Calls a general sub-function for all this stuff. The preset does + * the same as a set, but returns just before finally setting the + * new value. This is usefull to check if a set might be successfull. + * If as instance a -1 is passed, an array of values is supposed and + * all instance of the OID will be set. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +int SkPnmiSetVar( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 Id, /* Object ID that is to be processed */ +void *pBuf, /* Buffer which stores the mgmt data to be set */ +unsigned int *pLen, /* Total length of mgmt data */ +SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", + Id, *pLen, Instance, NetIndex)); + + return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, + Instance, NetIndex)); +} + +/***************************************************************************** + * + * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA + * + * Description: + * Runs through the IdTable, queries the single OIDs and stores the + * returned data into the management database structure + * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure + * is stored in the IdTable. The return value of the function will also + * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the + * minimum size of SK_PNMI_MIN_STRUCT_SIZE. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed + * SK_PNMI_ERR_GENERAL A general severe internal error occured + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take + * the data. + * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist + */ +int SkPnmiGetStruct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +void *pBuf, /* Buffer which will store the retrieved data */ +unsigned int *pLen, /* Length of buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + unsigned int TableIndex; + unsigned int DstOffset; + unsigned int InstanceNo; + unsigned int InstanceCnt; + SK_U32 Instance; + unsigned int TmpLen; + char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; + + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", + *pLen, NetIndex)); + + if (*pLen < SK_PNMI_STRUCT_SIZE) { + + if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { + + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, + (SK_U32)(-1)); + } + + *pLen = SK_PNMI_STRUCT_SIZE; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Check NetIndex + */ + if (NetIndex >= pAC->Rlmt.NumNets) { + return (SK_PNMI_ERR_UNKNOWN_NET); + } + + /* Update statistic */ + SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); + + if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != + SK_PNMI_ERR_OK) { + + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + + if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { + + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + + if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { + + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + + /* + * Increment semaphores to indicate that an update was + * already done + */ + pAC->Pnmi.MacUpdatedFlag ++; + pAC->Pnmi.RlmtUpdatedFlag ++; + pAC->Pnmi.SirqUpdatedFlag ++; + + /* Get vpd keys for instance calculation */ + Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); + if (Ret != SK_PNMI_ERR_OK) { + + pAC->Pnmi.MacUpdatedFlag --; + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (SK_PNMI_ERR_GENERAL); + } + + /* Retrieve values */ + SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); + for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { + + InstanceNo = IdTable[TableIndex].InstanceNo; + for (InstanceCnt = 1; InstanceCnt <= InstanceNo; + InstanceCnt ++) { + + DstOffset = IdTable[TableIndex].Offset + + (InstanceCnt - 1) * + IdTable[TableIndex].StructSize; + + /* + * For the VPD the instance is not an index number + * but the key itself. Determin with the instance + * counter the VPD key to be used. + */ + if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY || + IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE || + IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS || + IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) { + + SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4); + } + else { + Instance = (SK_U32)InstanceCnt; + } + + TmpLen = *pLen - DstOffset; + Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, + IdTable[TableIndex].Id, (char *)pBuf + + DstOffset, &TmpLen, Instance, TableIndex, NetIndex); + + /* + * An unknown instance error means that we reached + * the last instance of that variable. Proceed with + * the next OID in the table and ignore the return + * code. + */ + if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { + + break; + } + + if (Ret != SK_PNMI_ERR_OK) { + + pAC->Pnmi.MacUpdatedFlag --; + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); + SK_PNMI_SET_STAT(pBuf, Ret, DstOffset); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + } + } + + pAC->Pnmi.MacUpdatedFlag --; + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + *pLen = SK_PNMI_STRUCT_SIZE; + SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA + * + * Description: + * Calls a general sub-function for all this set stuff. The preset does + * the same as a set, but returns just before finally setting the + * new value. This is usefull to check if a set might be successfull. + * The sub-function runs through the IdTable, checks which OIDs are able + * to set, and calls the handler function of the OID to perform the + * preset. The return value of the function will also be stored in + * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of + * SK_PNMI_MIN_STRUCT_SIZE. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + */ +int SkPnmiPreSetStruct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +void *pBuf, /* Buffer which contains the data to be set */ +unsigned int *pLen, /* Length of buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", + *pLen, NetIndex)); + + return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, + pLen, NetIndex)); +} + +/***************************************************************************** + * + * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA + * + * Description: + * Calls a general sub-function for all this set stuff. The return value + * of the function will also be stored in SK_PNMI_STRUCT_DATA if the + * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE. + * The sub-function runs through the IdTable, checks which OIDs are able + * to set, and calls the handler function of the OID to perform the + * set. The return value of the function will also be stored in + * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of + * SK_PNMI_MIN_STRUCT_SIZE. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + */ +int SkPnmiSetStruct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +void *pBuf, /* Buffer which contains the data to be set */ +unsigned int *pLen, /* Length of buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", + *pLen, NetIndex)); + + return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, + pLen, NetIndex)); +} + +/***************************************************************************** + * + * SkPnmiEvent - Event handler + * + * Description: + * Handles the following events: + * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an + * interrupt will be generated which is + * first handled by SIRQ which generates a + * this event. The event increments the + * upper 32 bit of the 64 bit counter. + * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module + * when a sensor reports a warning or + * error. The event will store a trap + * message in the trap buffer. + * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this + * module and is used to calculate the + * port switches per hour. + * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and + * timestamps. + * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver + * before a hard reset of the XMAC is + * performed. All counters will be saved + * and added to the hardware counter + * values after reset to grant continuous + * counter values. + * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port + * went logically up. A trap message will + * be stored to the trap buffer. + * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port + * went logically down. A trap message will + * be stored to the trap buffer. + * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two + * spanning tree root bridges were + * detected. A trap message will be stored + * to the trap buffer. + * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went + * down. PNMI will not further add the + * statistic values to the virtual port. + * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and + * is now an active port. PNMI will now + * add the statistic data of this port to + * the virtual port. + * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first Parameter + * contains the number of nets. 1 means single net, 2 means + * dual net. The second Parameter is -1 + * + * Returns: + * Always 0 + */ +int SkPnmiEvent( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 Event, /* Event-Id */ +SK_EVPARA Param) /* Event dependent parameter */ +{ + unsigned int PhysPortIndex; + unsigned int MaxNetNumber; + int CounterIndex; + int Ret; + SK_U16 MacStatus; + SK_U64 OverflowStatus; + SK_U64 Mask; + int MacType; + SK_U64 Value; + SK_U32 Val32; + SK_U16 Register; + SK_EVPARA EventParam; + SK_U64 NewestValue; + SK_U64 OldestValue; + SK_U64 Delta; + SK_PNMI_ESTIMATE *pEst; + SK_U32 NetIndex; + SK_GEPORT *pPrt; + SK_PNMI_VCT *pVctBackupData; + SK_U32 RetCode; + int i; + SK_U32 CableLength; + + +#ifdef DEBUG + if (Event != SK_PNMI_EVT_XMAC_RESET) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", + (unsigned int)Event, (unsigned int)Param.Para64)); + } +#endif + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); + + MacType = pAC->GIni.GIMacType; + + switch (Event) { + + case SK_PNMI_EVT_SIRQ_OVERFLOW: + PhysPortIndex = (int)Param.Para32[0]; + MacStatus = (SK_U16)Param.Para32[1]; +#ifdef DEBUG + if (PhysPortIndex >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter" + " wrong, PhysPortIndex=0x%x\n", + PhysPortIndex)); + return (0); + } +#endif + OverflowStatus = 0; + + /* + * Check which source caused an overflow interrupt. + */ + if ((pAC->GIni.GIFunc.pFnMacOverflow( + pAC, IoC, PhysPortIndex, MacStatus, &OverflowStatus) != 0) || + (OverflowStatus == 0)) { + + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); + return (0); + } + + /* + * Check the overflow status register and increment + * the upper dword of corresponding counter. + */ + for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8; + CounterIndex ++) { + + Mask = (SK_U64)1 << CounterIndex; + if ((OverflowStatus & Mask) == 0) { + + continue; + } + + switch (StatOvrflwBit[CounterIndex][MacType]) { + + case SK_PNMI_HTX_UTILUNDER: + case SK_PNMI_HTX_UTILOVER: + XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, + &Register); + Register |= XM_TX_SAM_LINE; + XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, + Register); + break; + + case SK_PNMI_HRX_UTILUNDER: + case SK_PNMI_HRX_UTILOVER: + XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, + &Register); + Register |= XM_RX_SAM_LINE; + XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, + Register); + break; + + case SK_PNMI_HTX_OCTETHIGH: + case SK_PNMI_HTX_OCTETLOW: + case SK_PNMI_HTX_RESERVED: + case SK_PNMI_HRX_OCTETHIGH: + case SK_PNMI_HRX_OCTETLOW: + case SK_PNMI_HRX_IRLENGTH: + case SK_PNMI_HRX_RESERVED: + + /* + * the following counters aren't be handled (id > 63) + */ + case SK_PNMI_HTX_SYNC: + case SK_PNMI_HTX_SYNC_OCTET: + break; + + case SK_PNMI_HRX_LONGFRAMES: + if (MacType == SK_MAC_GMAC) { + pAC->Pnmi.Port[PhysPortIndex]. + CounterHigh[CounterIndex] ++; + } + break; + + default: + pAC->Pnmi.Port[PhysPortIndex]. + CounterHigh[CounterIndex] ++; + } + } + break; + + case SK_PNMI_EVT_SEN_WAR_LOW: +#ifdef DEBUG + if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n", + (unsigned int)Param.Para64)); + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate + * an event for user space applications with the + * SK_DRIVER_SENDEVENT macro. + */ + QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW, + (unsigned int)Param.Para64); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + break; + + case SK_PNMI_EVT_SEN_WAR_UPP: +#ifdef DEBUG + if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR:SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", + (unsigned int)Param.Para64)); + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate + * an event for user space applications with the + * SK_DRIVER_SENDEVENT macro. + */ + QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP, + (unsigned int)Param.Para64); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + break; + + case SK_PNMI_EVT_SEN_ERR_LOW: +#ifdef DEBUG + if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n", + (unsigned int)Param.Para64)); + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate + * an event for user space applications with the + * SK_DRIVER_SENDEVENT macro. + */ + QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW, + (unsigned int)Param.Para64); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + break; + + case SK_PNMI_EVT_SEN_ERR_UPP: +#ifdef DEBUG + if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", + (unsigned int)Param.Para64)); + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate + * an event for user space applications with the + * SK_DRIVER_SENDEVENT macro. + */ + QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP, + (unsigned int)Param.Para64); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + break; + + case SK_PNMI_EVT_CHG_EST_TIMER: + /* + * Calculate port switch average on a per hour basis + * Time interval for check : 28125 ms + * Number of values for average : 8 + * + * Be careful in changing these values, on change check + * - typedef of SK_PNMI_ESTIMATE (Size of EstValue + * array one less than value number) + * - Timer initilization SkTimerStart() in SkPnmiInit + * - Delta value below must be multiplicated with + * power of 2 + * + */ + pEst = &pAC->Pnmi.RlmtChangeEstimate; + CounterIndex = pEst->EstValueIndex + 1; + if (CounterIndex == 7) { + + CounterIndex = 0; + } + pEst->EstValueIndex = CounterIndex; + + NewestValue = pAC->Pnmi.RlmtChangeCts; + OldestValue = pEst->EstValue[CounterIndex]; + pEst->EstValue[CounterIndex] = NewestValue; + + /* + * Calculate average. Delta stores the number of + * port switches per 28125 * 8 = 225000 ms + */ + if (NewestValue >= OldestValue) { + + Delta = NewestValue - OldestValue; + } + else { + /* Overflow situation */ + Delta = (SK_U64)(0 - OldestValue) + NewestValue; + } + + /* + * Extrapolate delta to port switches per hour. + * Estimate = Delta * (3600000 / 225000) + * = Delta * 16 + * = Delta << 4 + */ + pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4; + + /* + * Check if threshold is exceeded. If the threshold is + * permanently exceeded every 28125 ms an event will be + * generated to remind the user of this condition. + */ + if ((pAC->Pnmi.RlmtChangeThreshold != 0) && + (pAC->Pnmi.RlmtChangeEstimate.Estimate >= + pAC->Pnmi.RlmtChangeThreshold)) { + + QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + } + + SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); + SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, + 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, + EventParam); + break; + + case SK_PNMI_EVT_CLEAR_COUNTER: + /* + * Param.Para32[0] contains the NetIndex (0 ..1). + * Param.Para32[1] is reserved, contains -1. + */ + NetIndex = (SK_U32)Param.Para32[0]; + +#ifdef DEBUG + if (NetIndex >= pAC->Rlmt.NumNets) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n", + NetIndex)); + + return (0); + } +#endif + + /* + * Set all counters and timestamps to zero + */ + ResetCounter(pAC, IoC, NetIndex); /* the according NetIndex is required + as a Parameter of the Event */ + break; + + case SK_PNMI_EVT_XMAC_RESET: + /* + * To grant continuous counter values store the current + * XMAC statistic values to the entries 1..n of the + * CounterOffset array. XMAC Errata #2 + */ +#ifdef DEBUG + if ((unsigned int)Param.Para64 >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n", + (unsigned int)Param.Para64)); + return (0); + } +#endif + PhysPortIndex = (unsigned int)Param.Para64; + + /* + * Update XMAC statistic to get fresh values + */ + Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); + if (Ret != SK_PNMI_ERR_OK) { + + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); + return (0); + } + /* + * Increment semaphore to indicate that an update was + * already done + */ + pAC->Pnmi.MacUpdatedFlag ++; + + for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; + CounterIndex ++) { + + if (!StatAddr[CounterIndex][MacType].GetOffset) { + + continue; + } + + pAC->Pnmi.Port[PhysPortIndex]. + CounterOffset[CounterIndex] = GetPhysStatVal( + pAC, IoC, PhysPortIndex, CounterIndex); + pAC->Pnmi.Port[PhysPortIndex]. + CounterHigh[CounterIndex] = 0; + } + + pAC->Pnmi.MacUpdatedFlag --; + break; + + case SK_PNMI_EVT_RLMT_PORT_UP: + PhysPortIndex = (unsigned int)Param.Para32[0]; +#ifdef DEBUG + if (PhysPortIndex >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" + " wrong, PhysPortIndex=%d\n", PhysPortIndex)); + + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate an event for + * user space applications with the SK_DRIVER_SENDEVENT macro. + */ + QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + + /* Bugfix for XMAC errata (#10620)*/ + if (pAC->GIni.GIMacType == SK_MAC_XMAC){ + + /* Add incremental difference to offset (#10620)*/ + (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, + XM_RXE_SHT_ERR, &Val32); + + Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. + CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); + pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += + Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; + } + + /* Tell VctStatus() that a link was up meanwhile. */ + pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; + break; + + case SK_PNMI_EVT_RLMT_PORT_DOWN: + PhysPortIndex = (unsigned int)Param.Para32[0]; + +#ifdef DEBUG + if (PhysPortIndex >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" + " wrong, PhysPortIndex=%d\n", PhysPortIndex)); + + return (0); + } +#endif + /* + * Store a trap message in the trap buffer and generate an event for + * user space applications with the SK_DRIVER_SENDEVENT macro. + */ + QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + + /* Bugfix #10620 - get zero level for incremental difference */ + if ((pAC->GIni.GIMacType == SK_MAC_XMAC)) { + + (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, + XM_RXE_SHT_ERR, &Val32); + pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = + (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. + CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); + } + break; + + case SK_PNMI_EVT_RLMT_ACTIVE_DOWN: + PhysPortIndex = (unsigned int)Param.Para32[0]; + NetIndex = (SK_U32)Param.Para32[1]; + +#ifdef DEBUG + if (PhysPortIndex >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n", + PhysPortIndex)); + } + + if (NetIndex >= pAC->Rlmt.NumNets) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", + NetIndex)); + } +#endif + /* + * For now, ignore event if NetIndex != 0. + */ + if (Param.Para32[1] != 0) { + + return (0); + } + + /* + * Nothing to do if port is already inactive + */ + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + return (0); + } + + /* + * Update statistic counters to calculate new offset for the virtual + * port and increment semaphore to indicate that an update was already + * done. + */ + if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != + SK_PNMI_ERR_OK) { + + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); + return (0); + } + pAC->Pnmi.MacUpdatedFlag ++; + + /* + * Calculate new counter offset for virtual port to grant continous + * counting on port switches. The virtual port consists of all currently + * active ports. The port down event indicates that a port is removed + * from the virtual port. Therefore add the counter value of the removed + * port to the CounterOffset for the virtual port to grant the same + * counter value. + */ + for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; + CounterIndex ++) { + + if (!StatAddr[CounterIndex][MacType].GetOffset) { + + continue; + } + + Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); + + pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; + } + + /* + * Set port to inactive + */ + pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; + + pAC->Pnmi.MacUpdatedFlag --; + break; + + case SK_PNMI_EVT_RLMT_ACTIVE_UP: + PhysPortIndex = (unsigned int)Param.Para32[0]; + NetIndex = (SK_U32)Param.Para32[1]; + +#ifdef DEBUG + if (PhysPortIndex >= SK_MAX_MACS) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n", + PhysPortIndex)); + } + + if (NetIndex >= pAC->Rlmt.NumNets) { + + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", + NetIndex)); + } +#endif + /* + * For now, ignore event if NetIndex != 0. + */ + if (Param.Para32[1] != 0) { + + return (0); + } + + /* + * Nothing to do if port is already active + */ + if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + return (0); + } + + /* + * Statistic maintenance + */ + pAC->Pnmi.RlmtChangeCts ++; + pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); + + /* + * Store a trap message in the trap buffer and generate an event for + * user space applications with the SK_DRIVER_SENDEVENT macro. + */ + QueueRlmtNewMacTrap(pAC, PhysPortIndex); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + + /* + * Update statistic counters to calculate new offset for the virtual + * port and increment semaphore to indicate that an update was + * already done. + */ + if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != + SK_PNMI_ERR_OK) { + + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); + return (0); + } + pAC->Pnmi.MacUpdatedFlag ++; + + /* + * Calculate new counter offset for virtual port to grant continous + * counting on port switches. A new port is added to the virtual port. + * Therefore substract the counter value of the new port from the + * CounterOffset for the virtual port to grant the same value. + */ + for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; + CounterIndex ++) { + + if (!StatAddr[CounterIndex][MacType].GetOffset) { + + continue; + } + + Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); + + pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; + } + + /* + * Set port to active + */ + pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; + + pAC->Pnmi.MacUpdatedFlag --; + break; + + case SK_PNMI_EVT_RLMT_SEGMENTATION: + /* + * Para.Para32[0] contains the NetIndex. + */ + + /* + * Store a trap message in the trap buffer and generate an event for + * user space applications with the SK_DRIVER_SENDEVENT macro. + */ + QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION); + (void)SK_DRIVER_SENDEVENT(pAC, IoC); + break; + + case SK_PNMI_EVT_RLMT_SET_NETS: + /* + * Param.Para32[0] contains the number of Nets. + * Param.Para32[1] is reserved, contains -1. + */ + /* + * Check number of nets + */ + MaxNetNumber = pAC->GIni.GIMacsFound; + if (((unsigned int)Param.Para32[0] < 1) + || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { + return (SK_PNMI_ERR_UNKNOWN_NET); + } + + if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */ + pAC->Pnmi.DualNetActiveFlag = SK_FALSE; + } + else { /* dual net mode */ + pAC->Pnmi.DualNetActiveFlag = SK_TRUE; + } + break; + + case SK_PNMI_EVT_VCT_RESET: + PhysPortIndex = Param.Para32[0]; + pPrt = &pAC->GIni.GP[PhysPortIndex]; + pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; + + if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { + RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); + if (RetCode == 2) { + /* + * VCT test is still running. + * Start VCT timer counter again. + */ + SK_MEMSET((char *) &Param, 0, sizeof(Param)); + Param.Para32[0] = PhysPortIndex; + Param.Para32[1] = -1; + SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, + 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); + break; + } + pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; + pAC->Pnmi.VctStatus[PhysPortIndex] |= + (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); + + /* Copy results for later use to PNMI struct. */ + for (i = 0; i < 4; i++) { + if (pPrt->PMdiPairLen[i] > 35) { + CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); + } + else { + CableLength = 0; + } + pVctBackupData->PMdiPairLen[i] = CableLength; + pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; + } + + Param.Para32[0] = PhysPortIndex; + Param.Para32[1] = -1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); + SkEventDispatcher(pAC, IoC); + } + + break; + + default: + break; + } + + SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); + return (0); +} + + +/****************************************************************************** + * + * Private functions + * + */ + +/***************************************************************************** + * + * PnmiVar - Gets, presets, and sets single OIDs + * + * Description: + * Looks up the requested OID, calls the corresponding handler + * function, and passes the parameters with the get, preset, or + * set command. The function is called by SkGePnmiGetVar, + * SkGePnmiPreSetVar, or SkGePnmiSetVar. + * + * Returns: + * SK_PNMI_ERR_XXX. For details have a look to the description of the + * calling functions. + * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist + */ +PNMI_STATIC int PnmiVar( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer which stores the mgmt data to be set */ +unsigned int *pLen, /* Total length of mgmt data */ +SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int TableIndex; + int Ret; + + + if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_OID); + } + + /* + * Check NetIndex + */ + if (NetIndex >= pAC->Rlmt.NumNets) { + return (SK_PNMI_ERR_UNKNOWN_NET); + } + + SK_PNMI_CHECKFLAGS("PnmiVar: On call"); + + Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen, + Instance, TableIndex, NetIndex); + + SK_PNMI_CHECKFLAGS("PnmiVar: On return"); + + return (Ret); +} + +/***************************************************************************** + * + * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA + * + * Description: + * The return value of the function will also be stored in + * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of + * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable, + * checks which OIDs are able to set, and calls the handler function of + * the OID to perform the set. The return value of the function will + * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the + * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called + * by SkGePnmiPreSetStruct and SkGePnmiSetStruct. + * + * Returns: + * SK_PNMI_ERR_XXX. The codes are described in the calling functions. + * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist + */ +PNMI_STATIC int PnmiStruct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Set action to be performed */ +char *pBuf, /* Buffer which contains the data to be set */ +unsigned int *pLen, /* Length of buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + unsigned int TableIndex; + unsigned int DstOffset; + unsigned int Len; + unsigned int InstanceNo; + unsigned int InstanceCnt; + SK_U32 Instance; + SK_U32 Id; + + + /* Check if the passed buffer has the right size */ + if (*pLen < SK_PNMI_STRUCT_SIZE) { + + /* Check if we can return the error within the buffer */ + if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { + + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, + (SK_U32)(-1)); + } + + *pLen = SK_PNMI_STRUCT_SIZE; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Check NetIndex + */ + if (NetIndex >= pAC->Rlmt.NumNets) { + return (SK_PNMI_ERR_UNKNOWN_NET); + } + + SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); + + /* + * Update the values of RLMT and SIRQ and increment semaphores to + * indicate that an update was already done. + */ + if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { + + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + + if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { + + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (Ret); + } + + pAC->Pnmi.RlmtUpdatedFlag ++; + pAC->Pnmi.SirqUpdatedFlag ++; + + /* Preset/Set values */ + for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { + + if ((IdTable[TableIndex].Access != SK_PNMI_RW) && + (IdTable[TableIndex].Access != SK_PNMI_WO)) { + + continue; + } + + InstanceNo = IdTable[TableIndex].InstanceNo; + Id = IdTable[TableIndex].Id; + + for (InstanceCnt = 1; InstanceCnt <= InstanceNo; + InstanceCnt ++) { + + DstOffset = IdTable[TableIndex].Offset + + (InstanceCnt - 1) * + IdTable[TableIndex].StructSize; + + /* + * Because VPD multiple instance variables are + * not setable we do not need to evaluate VPD + * instances. Have a look to VPD instance + * calculation in SkPnmiGetStruct(). + */ + Instance = (SK_U32)InstanceCnt; + + /* + * Evaluate needed buffer length + */ + Len = 0; + Ret = IdTable[TableIndex].Func(pAC, IoC, + SK_PNMI_GET, IdTable[TableIndex].Id, + NULL, &Len, Instance, TableIndex, NetIndex); + + if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { + + break; + } + if (Ret != SK_PNMI_ERR_TOO_SHORT) { + + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); + SK_PNMI_SET_STAT(pBuf, + SK_PNMI_ERR_GENERAL, DstOffset); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (SK_PNMI_ERR_GENERAL); + } + if (Id == OID_SKGE_VPD_ACTION) { + + switch (*(pBuf + DstOffset)) { + + case SK_PNMI_VPD_CREATE: + Len = 3 + *(pBuf + DstOffset + 3); + break; + + case SK_PNMI_VPD_DELETE: + Len = 3; + break; + + default: + Len = 1; + break; + } + } + + /* Call the OID handler function */ + Ret = IdTable[TableIndex].Func(pAC, IoC, Action, + IdTable[TableIndex].Id, pBuf + DstOffset, + &Len, Instance, TableIndex, NetIndex); + + if (Ret != SK_PNMI_ERR_OK) { + + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, + DstOffset); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (SK_PNMI_ERR_BAD_VALUE); + } + } + } + + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; + + SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * LookupId - Lookup an OID in the IdTable + * + * Description: + * Scans the IdTable to find the table entry of an OID. + * + * Returns: + * The table index or -1 if not found. + */ +PNMI_STATIC int LookupId( +SK_U32 Id) /* Object identifier to be searched */ +{ + int i; + + for (i = 0; i < ID_TABLE_SIZE; i++) { + + if (IdTable[i].Id == Id) { + + return i; + } + } + + return (-1); +} + +/***************************************************************************** + * + * OidStruct - Handler of OID_SKGE_ALL_DATA + * + * Description: + * This OID performs a Get/Preset/SetStruct call and returns all data + * in a SK_PNMI_STRUCT_DATA structure. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int OidStruct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + if (Id != OID_SKGE_ALL_DATA) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, + SK_PNMI_ERR003MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Check instance. We only handle single instance variables + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + switch (Action) { + + case SK_PNMI_GET: + return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex)); + + case SK_PNMI_PRESET: + return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); + + case SK_PNMI_SET: + return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); + } + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); +} + +/***************************************************************************** + * + * Perform - OID handler of OID_SKGE_ACTION + * + * Description: + * None. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Perform( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + SK_U32 ActionOp; + + + /* + * Check instance. We only handle single instance variables + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* Check if a get should be performed */ + if (Action == SK_PNMI_GET) { + + /* A get is easy. We always return the same value */ + ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; + SK_PNMI_STORE_U32(pBuf, ActionOp); + *pLen = sizeof(SK_U32); + + return (SK_PNMI_ERR_OK); + } + + /* Continue with PRESET/SET action */ + if (*pLen > sizeof(SK_U32)) { + + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* Check if the command is a known one */ + SK_PNMI_READ_U32(pBuf, ActionOp); + if (*pLen > sizeof(SK_U32) || + (ActionOp != SK_PNMI_ACT_IDLE && + ActionOp != SK_PNMI_ACT_RESET && + ActionOp != SK_PNMI_ACT_SELFTEST && + ActionOp != SK_PNMI_ACT_RESETCNT)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* A preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + switch (ActionOp) { + + case SK_PNMI_ACT_IDLE: + /* Nothing to do */ + break; + + case SK_PNMI_ACT_RESET: + /* + * Perform a driver reset or something that comes near + * to this. + */ + Ret = SK_DRIVER_RESET(pAC, IoC); + if (Ret != 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, + SK_PNMI_ERR005MSG); + + return (SK_PNMI_ERR_GENERAL); + } + break; + + case SK_PNMI_ACT_SELFTEST: + /* + * Perform a driver selftest or something similar to this. + * Currently this feature is not used and will probably + * implemented in another way. + */ + Ret = SK_DRIVER_SELFTEST(pAC, IoC); + pAC->Pnmi.TestResult = Ret; + break; + + case SK_PNMI_ACT_RESETCNT: + /* Set all counters and timestamps to zero */ + ResetCounter(pAC, IoC, NetIndex); + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, + SK_PNMI_ERR006MSG); + + return (SK_PNMI_ERR_GENERAL); + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX + * + * Description: + * Retrieves the statistic values of the virtual port (logical + * index 0). Only special OIDs of NDIS are handled which consist + * of a 32 bit instead of a 64 bit value. The OIDs are public + * because perhaps some other platform can use them too. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Mac8023Stat( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + SK_U64 StatVal; + SK_U32 StatVal32; + SK_BOOL Is64BitReq = SK_FALSE; + + /* + * Only the active Mac is returned + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* + * Check action type + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Check length + */ + switch (Id) { + + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: + if (*pLen < sizeof(SK_MAC_ADDR)) { + + *pLen = sizeof(SK_MAC_ADDR); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: +#ifndef SK_NDIS_64BIT_CTR + if (*pLen < sizeof(SK_U32)) { + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + +#else /* SK_NDIS_64BIT_CTR */ + + /* + * for compatibility, at least 32bit are required for oid + */ + if (*pLen < sizeof(SK_U32)) { + /* + * but indicate handling for 64bit values, + * if insufficient space is provided + */ + *pLen = sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + + Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; +#endif /* SK_NDIS_64BIT_CTR */ + break; + } + + /* + * Update all statistics, because we retrieve virtual MAC, which + * consists of multiple physical statistics and increment semaphore + * to indicate that an update was already done. + */ + Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); + if ( Ret != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.MacUpdatedFlag ++; + + /* + * Get value (MAC Index 0 identifies the virtual MAC) + */ + switch (Id) { + + case OID_802_3_PERMANENT_ADDRESS: + CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress); + *pLen = sizeof(SK_MAC_ADDR); + break; + + case OID_802_3_CURRENT_ADDRESS: + CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress); + *pLen = sizeof(SK_MAC_ADDR); + break; + + default: + StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); + + /* + * by default 32bit values are evaluated + */ + if (!Is64BitReq) { + StatVal32 = (SK_U32)StatVal; + SK_PNMI_STORE_U32(pBuf, StatVal32); + *pLen = sizeof(SK_U32); + } + else { + SK_PNMI_STORE_U64(pBuf, StatVal); + *pLen = sizeof(SK_U64); + } + break; + } + + pAC->Pnmi.MacUpdatedFlag --; + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX + * + * Description: + * Retrieves the XMAC statistic data. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int MacPrivateStat( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int LogPortMax; + unsigned int LogPortIndex; + unsigned int PhysPortMax; + unsigned int Limit; + unsigned int Offset; + int Ret; + SK_U64 StatVal; + + + /* + * Calculate instance if wished. MAC index 0 is the virtual + * MAC. + */ + PhysPortMax = pAC->GIni.GIMacsFound; + LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); + + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + LogPortMax--; + } + + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ + /* Check instance range */ + if ((Instance < 1) || (Instance > LogPortMax)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); + Limit = LogPortIndex + 1; + } + + else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + + LogPortIndex = 0; + Limit = LogPortMax; + } + + + /* + * Check action + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Check length + */ + if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { + + *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Update XMAC statistic and increment semaphore to indicate that + * an update was already done. + */ + Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); + if (Ret != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.MacUpdatedFlag ++; + + /* + * Get value + */ + Offset = 0; + for (; LogPortIndex < Limit; LogPortIndex ++) { + + switch (Id) { + +/* XXX not yet implemented due to XMAC problems + case OID_SKGE_STAT_TX_UTIL: + return (SK_PNMI_ERR_GENERAL); +*/ +/* XXX not yet implemented due to XMAC problems + case OID_SKGE_STAT_RX_UTIL: + return (SK_PNMI_ERR_GENERAL); +*/ + case OID_SKGE_STAT_RX: + case OID_SKGE_STAT_TX: + switch (pAC->GIni.GIMacType) { + case SK_MAC_XMAC: + StatVal = GetStatVal(pAC, IoC, LogPortIndex, + IdTable[TableIndex].Param, NetIndex); + break; + + case SK_MAC_GMAC: + if (Id == OID_SKGE_STAT_TX) { + + StatVal = + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_BROADCAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_MULTICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_UNICAST, NetIndex); + } + else { + StatVal = + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_BROADCAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_MULTICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_UNICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_UNDERSIZE, NetIndex); + } + break; + + default: + StatVal = 0; + break; + } + + SK_PNMI_STORE_U64(pBuf + Offset, StatVal); + break; + + default: + StatVal = GetStatVal(pAC, IoC, LogPortIndex, + IdTable[TableIndex].Param, NetIndex); + SK_PNMI_STORE_U64(pBuf + Offset, StatVal); + break; + } + + Offset += sizeof(SK_U64); + } + *pLen = Offset; + + pAC->Pnmi.MacUpdatedFlag --; + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR + * + * Description: + * Get/Presets/Sets the current and factory MAC address. The MAC + * address of the virtual port, which is reported to the OS, may + * not be changed, but the physical ones. A set to the virtual port + * will be ignored. No error should be reported because otherwise + * a multiple instance set (-1) would always fail. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Addr( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + unsigned int LogPortMax; + unsigned int PhysPortMax; + unsigned int LogPortIndex; + unsigned int PhysPortIndex; + unsigned int Limit; + unsigned int Offset = 0; + + /* + * Calculate instance if wished. MAC index 0 is the virtual + * MAC. + */ + PhysPortMax = pAC->GIni.GIMacsFound; + LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); + + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + LogPortMax--; + } + + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ + /* Check instance range */ + if ((Instance < 1) || (Instance > LogPortMax)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); + Limit = LogPortIndex + 1; + } + + else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + + LogPortIndex = 0; + Limit = LogPortMax; + } + + /* + * Perform Action + */ + if (Action == SK_PNMI_GET) { + + /* + * Check length + */ + if (*pLen < (Limit - LogPortIndex) * 6) { + + *pLen = (Limit - LogPortIndex) * 6; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Get value + */ + for (; LogPortIndex < Limit; LogPortIndex ++) { + + switch (Id) { + + case OID_SKGE_PHYS_CUR_ADDR: + if (LogPortIndex == 0) { + CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); + } + else { + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + + CopyMac(pBuf + Offset, + &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); + } + Offset += 6; + break; + + case OID_SKGE_PHYS_FAC_ADDR: + if (LogPortIndex == 0) { + CopyMac(pBuf + Offset, + &pAC->Addr.Net[NetIndex].PermanentMacAddress); + } + else { + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + CopyMac(pBuf + Offset, + &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); + } + Offset += 6; + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, + SK_PNMI_ERR008MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + + *pLen = Offset; + } + else { + /* + * The logical MAC address may not be changed only + * the physical ones + */ + if (Id == OID_SKGE_PHYS_FAC_ADDR) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Only the current address may be changed + */ + if (Id != OID_SKGE_PHYS_CUR_ADDR) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, + SK_PNMI_ERR009MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Check length + */ + if (*pLen < (Limit - LogPortIndex) * 6) { + + *pLen = (Limit - LogPortIndex) * 6; + return (SK_PNMI_ERR_TOO_SHORT); + } + if (*pLen > (Limit - LogPortIndex) * 6) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* + * Check Action + */ + if (Action == SK_PNMI_PRESET) { + + *pLen = 0; + return (SK_PNMI_ERR_OK); + } + + /* + * Set OID_SKGE_MAC_CUR_ADDR + */ + for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { + + /* + * A set to virtual port and set of broadcast + * address will be ignored + */ + if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, + "\xff\xff\xff\xff\xff\xff", 6) == 0) { + + continue; + } + + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, + LogPortIndex); + + Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, + (SK_MAC_ADDR *)(pBuf + Offset), + (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : + SK_ADDR_PHYSICAL_ADDRESS)); + if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { + + return (SK_PNMI_ERR_GENERAL); + } + } + *pLen = Offset; + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX + * + * Description: + * Retrieves the statistic values of the CSUM module. The CSUM data + * structure must be available in the SK_AC even if the CSUM module + * is not included, because PNMI reads the statistic data from the + * CSUM part of SK_AC directly. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int CsumStat( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int Index; + unsigned int Limit; + unsigned int Offset = 0; + SK_U64 StatVal; + + + /* + * Calculate instance if wished + */ + if (Instance != (SK_U32)(-1)) { + + if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + Index = (unsigned int)Instance - 1; + Limit = Index + 1; + } + else { + Index = 0; + Limit = SKCS_NUM_PROTOCOLS; + } + + /* + * Check action + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Check length + */ + if (*pLen < (Limit - Index) * sizeof(SK_U64)) { + + *pLen = (Limit - Index) * sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Get value + */ + for (; Index < Limit; Index ++) { + + switch (Id) { + + case OID_SKGE_CHKSM_RX_OK_CTS: + StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; + break; + + case OID_SKGE_CHKSM_RX_UNABLE_CTS: + StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; + break; + + case OID_SKGE_CHKSM_RX_ERR_CTS: + StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; + break; + + case OID_SKGE_CHKSM_TX_OK_CTS: + StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; + break; + + case OID_SKGE_CHKSM_TX_UNABLE_CTS: + StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, + SK_PNMI_ERR010MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + SK_PNMI_STORE_U64(pBuf + Offset, StatVal); + Offset += sizeof(SK_U64); + } + + /* + * Store used buffer space + */ + *pLen = Offset; + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX + * + * Description: + * Retrieves the statistic values of the I2C module, which handles + * the temperature and voltage sensors. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int SensorStat( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int i; + unsigned int Index; + unsigned int Limit; + unsigned int Offset; + unsigned int Len; + SK_U32 Val32; + SK_U64 Val64; + + + /* + * Calculate instance if wished + */ + if ((Instance != (SK_U32)(-1))) { + + if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + Index = (unsigned int)Instance -1; + Limit = (unsigned int)Instance; + } + else { + Index = 0; + Limit = (unsigned int) pAC->I2c.MaxSens; + } + + /* + * Check action + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Check length + */ + switch (Id) { + + case OID_SKGE_SENSOR_VALUE: + case OID_SKGE_SENSOR_WAR_THRES_LOW: + case OID_SKGE_SENSOR_WAR_THRES_UPP: + case OID_SKGE_SENSOR_ERR_THRES_LOW: + case OID_SKGE_SENSOR_ERR_THRES_UPP: + if (*pLen < (Limit - Index) * sizeof(SK_U32)) { + + *pLen = (Limit - Index) * sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_SENSOR_DESCR: + for (Offset = 0, i = Index; i < Limit; i ++) { + + Len = (unsigned int) + SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; + if (Len >= SK_PNMI_STRINGLEN2) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, + SK_PNMI_ERR011MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + Offset += Len; + } + if (*pLen < Offset) { + + *pLen = Offset; + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_SENSOR_INDEX: + case OID_SKGE_SENSOR_TYPE: + case OID_SKGE_SENSOR_STATUS: + if (*pLen < Limit - Index) { + + *pLen = Limit - Index; + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_SENSOR_WAR_CTS: + case OID_SKGE_SENSOR_WAR_TIME: + case OID_SKGE_SENSOR_ERR_CTS: + case OID_SKGE_SENSOR_ERR_TIME: + if (*pLen < (Limit - Index) * sizeof(SK_U64)) { + + *pLen = (Limit - Index) * sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, + SK_PNMI_ERR012MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + + } + + /* + * Get value + */ + for (Offset = 0; Index < Limit; Index ++) { + + switch (Id) { + + case OID_SKGE_SENSOR_INDEX: + *(pBuf + Offset) = (char)Index; + Offset += sizeof(char); + break; + + case OID_SKGE_SENSOR_DESCR: + Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); + SK_MEMCPY(pBuf + Offset + 1, + pAC->I2c.SenTable[Index].SenDesc, Len); + *(pBuf + Offset) = (char)Len; + Offset += Len + 1; + break; + + case OID_SKGE_SENSOR_TYPE: + *(pBuf + Offset) = + (char)pAC->I2c.SenTable[Index].SenType; + Offset += sizeof(char); + break; + + case OID_SKGE_SENSOR_VALUE: + Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_WAR_THRES_LOW: + Val32 = (SK_U32)pAC->I2c.SenTable[Index]. + SenThreWarnLow; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_WAR_THRES_UPP: + Val32 = (SK_U32)pAC->I2c.SenTable[Index]. + SenThreWarnHigh; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_ERR_THRES_LOW: + Val32 = (SK_U32)pAC->I2c.SenTable[Index]. + SenThreErrLow; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_ERR_THRES_UPP: + Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_STATUS: + *(pBuf + Offset) = + (char)pAC->I2c.SenTable[Index].SenErrFlag; + Offset += sizeof(char); + break; + + case OID_SKGE_SENSOR_WAR_CTS: + Val64 = pAC->I2c.SenTable[Index].SenWarnCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_SENSOR_ERR_CTS: + Val64 = pAC->I2c.SenTable[Index].SenErrCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_SENSOR_WAR_TIME: + Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. + SenBegWarnTS); + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_SENSOR_ERR_TIME: + Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. + SenBegErrTS); + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("SensorStat: Unknown OID should be handled before")); + + return (SK_PNMI_ERR_GENERAL); + } + } + + /* + * Store used buffer space + */ + *pLen = Offset; + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * Vpd - OID handler function of OID_SKGE_VPD_XXX + * + * Description: + * Get/preset/set of VPD data. As instance the name of a VPD key + * can be passed. The Instance parameter is a SK_U32 and can be + * used as a string buffer for the VPD key, because their maximum + * length is 4 byte. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Vpd( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_VPD_STATUS *pVpdStatus; + unsigned int BufLen; + char Buf[256]; + char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; + char KeyStr[SK_PNMI_VPD_KEY_SIZE]; + unsigned int KeyNo; + unsigned int Offset; + unsigned int Index; + unsigned int FirstIndex; + unsigned int LastIndex; + unsigned int Len; + int Ret; + SK_U32 Val32; + + /* + * Get array of all currently stored VPD keys + */ + Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), + &KeyNo); + if (Ret != SK_PNMI_ERR_OK) { + *pLen = 0; + return (Ret); + } + + /* + * If instance is not -1, try to find the requested VPD key for + * the multiple instance variables. The other OIDs as for example + * OID VPD_ACTION are single instance variables and must be + * handled separatly. + */ + FirstIndex = 0; + LastIndex = KeyNo; + + if ((Instance != (SK_U32)(-1))) { + + if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || + Id == OID_SKGE_VPD_ACCESS) { + + SK_STRNCPY(KeyStr, (char *)&Instance, 4); + KeyStr[4] = 0; + + for (Index = 0; Index < KeyNo; Index ++) { + + if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { + FirstIndex = Index; + LastIndex = Index+1; + break; + } + } + if (Index == KeyNo) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + } + else if (Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + } + + /* + * Get value, if a query should be performed + */ + if (Action == SK_PNMI_GET) { + + switch (Id) { + + case OID_SKGE_VPD_FREE_BYTES: + /* Check length of buffer */ + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + /* Get number of free bytes */ + pVpdStatus = VpdStat(pAC, IoC); + if (pVpdStatus == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, + SK_PNMI_ERR017MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, + SK_PNMI_ERR018MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Val32 = (SK_U32)pVpdStatus->vpd_free_rw; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_VPD_ENTRIES_LIST: + /* Check length */ + for (Len = 0, Index = 0; Index < KeyNo; Index ++) { + + Len += SK_STRLEN(KeyArr[Index]) + 1; + } + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* Get value */ + *(pBuf) = (char)Len - 1; + for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { + + Len = SK_STRLEN(KeyArr[Index]); + SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); + + Offset += Len; + + if (Index < KeyNo - 1) { + + *(pBuf + Offset) = ' '; + Offset ++; + } + } + *pLen = Offset; + break; + + case OID_SKGE_VPD_ENTRIES_NUMBER: + /* Check length */ + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + + Val32 = (SK_U32)KeyNo; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_VPD_KEY: + /* Check buffer length, if it is large enough */ + for (Len = 0, Index = FirstIndex; + Index < LastIndex; Index ++) { + + Len += SK_STRLEN(KeyArr[Index]) + 1; + } + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Get the key to an intermediate buffer, because + * we have to prepend a length byte. + */ + for (Offset = 0, Index = FirstIndex; + Index < LastIndex; Index ++) { + + Len = SK_STRLEN(KeyArr[Index]); + + *(pBuf + Offset) = (char)Len; + SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], + Len); + Offset += Len + 1; + } + *pLen = Offset; + break; + + case OID_SKGE_VPD_VALUE: + /* Check the buffer length if it is large enough */ + for (Offset = 0, Index = FirstIndex; + Index < LastIndex; Index ++) { + + BufLen = 256; + if (VpdRead(pAC, IoC, KeyArr[Index], Buf, + (int *)&BufLen) > 0 || + BufLen >= SK_PNMI_VPD_DATALEN) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR021, + SK_PNMI_ERR021MSG); + + return (SK_PNMI_ERR_GENERAL); + } + Offset += BufLen + 1; + } + if (*pLen < Offset) { + + *pLen = Offset; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * Get the value to an intermediate buffer, because + * we have to prepend a length byte. + */ + for (Offset = 0, Index = FirstIndex; + Index < LastIndex; Index ++) { + + BufLen = 256; + if (VpdRead(pAC, IoC, KeyArr[Index], Buf, + (int *)&BufLen) > 0 || + BufLen >= SK_PNMI_VPD_DATALEN) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR022, + SK_PNMI_ERR022MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + *(pBuf + Offset) = (char)BufLen; + SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); + Offset += BufLen + 1; + } + *pLen = Offset; + break; + + case OID_SKGE_VPD_ACCESS: + if (*pLen < LastIndex - FirstIndex) { + + *pLen = LastIndex - FirstIndex; + return (SK_PNMI_ERR_TOO_SHORT); + } + + for (Offset = 0, Index = FirstIndex; + Index < LastIndex; Index ++) { + + if (VpdMayWrite(KeyArr[Index])) { + + *(pBuf + Offset) = SK_PNMI_VPD_RW; + } + else { + *(pBuf + Offset) = SK_PNMI_VPD_RO; + } + Offset ++; + } + *pLen = Offset; + break; + + case OID_SKGE_VPD_ACTION: + Offset = LastIndex - FirstIndex; + if (*pLen < Offset) { + + *pLen = Offset; + return (SK_PNMI_ERR_TOO_SHORT); + } + SK_MEMSET(pBuf, 0, Offset); + *pLen = Offset; + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, + SK_PNMI_ERR023MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + else { + /* The only OID which can be set is VPD_ACTION */ + if (Id != OID_SKGE_VPD_ACTION) { + + if (Id == OID_SKGE_VPD_FREE_BYTES || + Id == OID_SKGE_VPD_ENTRIES_LIST || + Id == OID_SKGE_VPD_ENTRIES_NUMBER || + Id == OID_SKGE_VPD_KEY || + Id == OID_SKGE_VPD_VALUE || + Id == OID_SKGE_VPD_ACCESS) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, + SK_PNMI_ERR024MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * From this point we handle VPD_ACTION. Check the buffer + * length. It should at least have the size of one byte. + */ + if (*pLen < 1) { + + *pLen = 1; + return (SK_PNMI_ERR_TOO_SHORT); + } + + /* + * The first byte contains the VPD action type we should + * perform. + */ + switch (*pBuf) { + + case SK_PNMI_VPD_IGNORE: + /* Nothing to do */ + break; + + case SK_PNMI_VPD_CREATE: + /* + * We have to create a new VPD entry or we modify + * an existing one. Check first the buffer length. + */ + if (*pLen < 4) { + + *pLen = 4; + return (SK_PNMI_ERR_TOO_SHORT); + } + KeyStr[0] = pBuf[1]; + KeyStr[1] = pBuf[2]; + KeyStr[2] = 0; + + /* + * Is the entry writable or does it belong to the + * read-only area? + */ + if (!VpdMayWrite(KeyStr)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + Offset = (int)pBuf[3] & 0xFF; + + SK_MEMCPY(Buf, pBuf + 4, Offset); + Buf[Offset] = 0; + + /* A preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + /* Write the new entry or modify an existing one */ + Ret = VpdWrite(pAC, IoC, KeyStr, Buf); + if (Ret == SK_PNMI_VPD_NOWRITE ) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + else if (Ret != SK_PNMI_VPD_OK) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, + SK_PNMI_ERR025MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Perform an update of the VPD data. This is + * not mandantory, but just to be sure. + */ + Ret = VpdUpdate(pAC, IoC); + if (Ret != SK_PNMI_VPD_OK) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, + SK_PNMI_ERR026MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + break; + + case SK_PNMI_VPD_DELETE: + /* Check if the buffer size is plausible */ + if (*pLen < 3) { + + *pLen = 3; + return (SK_PNMI_ERR_TOO_SHORT); + } + if (*pLen > 3) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + KeyStr[0] = pBuf[1]; + KeyStr[1] = pBuf[2]; + KeyStr[2] = 0; + + /* Find the passed key in the array */ + for (Index = 0; Index < KeyNo; Index ++) { + + if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { + + break; + } + } + /* + * If we cannot find the key it is wrong, so we + * return an appropriate error value. + */ + if (Index == KeyNo) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + /* Ok, you wanted it and you will get it */ + Ret = VpdDelete(pAC, IoC, KeyStr); + if (Ret != SK_PNMI_VPD_OK) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, + SK_PNMI_ERR027MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Perform an update of the VPD data. This is + * not mandantory, but just to be sure. + */ + Ret = VpdUpdate(pAC, IoC); + if (Ret != SK_PNMI_VPD_OK) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, + SK_PNMI_ERR028MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * General - OID handler function of various single instance OIDs + * + * Description: + * The code is simple. No description necessary. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int General( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + unsigned int Index; + unsigned int Len; + unsigned int Offset; + unsigned int Val; + SK_U8 Val8; + SK_U16 Val16; + SK_U32 Val32; + SK_U64 Val64; + SK_U64 Val64RxHwErrs = 0; + SK_U64 Val64TxHwErrs = 0; + SK_BOOL Is64BitReq = SK_FALSE; + char Buf[256]; + int MacType; + + /* + * Check instance. We only handle single instance variables + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* + * Check action. We only allow get requests. + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + MacType = pAC->GIni.GIMacType; + + /* + * Check length for the various supported OIDs + */ + switch (Id) { + + case OID_GEN_XMIT_ERROR: + case OID_GEN_RCV_ERROR: + case OID_GEN_RCV_NO_BUFFER: +#ifndef SK_NDIS_64BIT_CTR + if (*pLen < sizeof(SK_U32)) { + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + +#else /* SK_NDIS_64BIT_CTR */ + + /* + * for compatibility, at least 32bit are required for oid + */ + if (*pLen < sizeof(SK_U32)) { + /* + * but indicate handling for 64bit values, + * if insufficient space is provided + */ + *pLen = sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + + Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; +#endif /* SK_NDIS_64BIT_CTR */ + break; + + case OID_SKGE_PORT_NUMBER: + case OID_SKGE_DEVICE_TYPE: + case OID_SKGE_RESULT: + case OID_SKGE_RLMT_MONITOR_NUMBER: + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + case OID_SKGE_TRAP_NUMBER: + case OID_SKGE_MDB_VERSION: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_CHIPSET: + if (*pLen < sizeof(SK_U16)) { + + *pLen = sizeof(SK_U16); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_BUS_TYPE: + case OID_SKGE_BUS_SPEED: + case OID_SKGE_BUS_WIDTH: + case OID_SKGE_SENSOR_NUMBER: + case OID_SKGE_CHKSM_NUMBER: + if (*pLen < sizeof(SK_U8)) { + + *pLen = sizeof(SK_U8); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_TX_SW_QUEUE_LEN: + case OID_SKGE_TX_SW_QUEUE_MAX: + case OID_SKGE_TX_RETRY: + case OID_SKGE_RX_INTR_CTS: + case OID_SKGE_TX_INTR_CTS: + case OID_SKGE_RX_NO_BUF_CTS: + case OID_SKGE_TX_NO_BUF_CTS: + case OID_SKGE_TX_USED_DESCR_NO: + case OID_SKGE_RX_DELIVERED_CTS: + case OID_SKGE_RX_OCTETS_DELIV_CTS: + case OID_SKGE_RX_HW_ERROR_CTS: + case OID_SKGE_TX_HW_ERROR_CTS: + case OID_SKGE_IN_ERRORS_CTS: + case OID_SKGE_OUT_ERROR_CTS: + case OID_SKGE_ERR_RECOVERY_CTS: + case OID_SKGE_SYSUPTIME: + if (*pLen < sizeof(SK_U64)) { + + *pLen = sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + /* Checked later */ + break; + } + + /* Update statistic */ + if (Id == OID_SKGE_RX_HW_ERROR_CTS || + Id == OID_SKGE_TX_HW_ERROR_CTS || + Id == OID_SKGE_IN_ERRORS_CTS || + Id == OID_SKGE_OUT_ERROR_CTS || + Id == OID_GEN_XMIT_ERROR || + Id == OID_GEN_RCV_ERROR) { + + /* Force the XMAC to update its statistic counters and + * Increment semaphore to indicate that an update was + * already done. + */ + Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); + if (Ret != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.MacUpdatedFlag ++; + + /* + * Some OIDs consist of multiple hardware counters. Those + * values which are contained in all of them will be added + * now. + */ + switch (Id) { + + case OID_SKGE_RX_HW_ERROR_CTS: + case OID_SKGE_IN_ERRORS_CTS: + case OID_GEN_RCV_ERROR: + Val64RxHwErrs = + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); + break; + + case OID_SKGE_TX_HW_ERROR_CTS: + case OID_SKGE_OUT_ERROR_CTS: + case OID_GEN_XMIT_ERROR: + Val64TxHwErrs = + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); + break; + } + } + + /* + * Retrieve value + */ + switch (Id) { + + case OID_SKGE_SUPPORTED_LIST: + Len = ID_TABLE_SIZE * sizeof(SK_U32); + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + for (Offset = 0, Index = 0; Offset < Len; + Offset += sizeof(SK_U32), Index ++) { + + Val32 = (SK_U32)IdTable[Index].Id; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + } + *pLen = Len; + break; + + case OID_SKGE_PORT_NUMBER: + Val32 = (SK_U32)pAC->GIni.GIMacsFound; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_DEVICE_TYPE: + Val32 = (SK_U32)pAC->Pnmi.DeviceType; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_DRIVER_DESCR: + if (pAC->Pnmi.pDriverDescription == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, + SK_PNMI_ERR007MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, + SK_PNMI_ERR029MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); + *pLen = Len; + break; + + case OID_SKGE_DRIVER_VERSION: + if (pAC->Pnmi.pDriverVersion == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, + SK_PNMI_ERR030MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, + SK_PNMI_ERR031MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); + *pLen = Len; + break; + + case OID_SKGE_HW_DESCR: + /* + * The hardware description is located in the VPD. This + * query may move to the initialisation routine. But + * the VPD data is cached and therefore a call here + * will not make much difference. + */ + Len = 256; + if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, + SK_PNMI_ERR032MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + Len ++; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, + SK_PNMI_ERR033MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, Buf, Len - 1); + *pLen = Len; + break; + + case OID_SKGE_HW_VERSION: + /* Oh, I love to do some string manipulation */ + if (*pLen < 5) { + + *pLen = 5; + return (SK_PNMI_ERR_TOO_SHORT); + } + Val8 = (SK_U8)pAC->GIni.GIPciHwRev; + pBuf[0] = 4; + pBuf[1] = 'v'; + pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); + pBuf[3] = '.'; + pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); + *pLen = 5; + break; + + case OID_SKGE_CHIPSET: + Val16 = pAC->Pnmi.Chipset; + SK_PNMI_STORE_U16(pBuf, Val16); + *pLen = sizeof(SK_U16); + break; + + case OID_SKGE_BUS_TYPE: + *pBuf = (char)SK_PNMI_BUS_PCI; + *pLen = sizeof(char); + break; + + case OID_SKGE_BUS_SPEED: + *pBuf = pAC->Pnmi.PciBusSpeed; + *pLen = sizeof(char); + break; + + case OID_SKGE_BUS_WIDTH: + *pBuf = pAC->Pnmi.PciBusWidth; + *pLen = sizeof(char); + break; + + case OID_SKGE_RESULT: + Val32 = pAC->Pnmi.TestResult; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_SENSOR_NUMBER: + *pBuf = (char)pAC->I2c.MaxSens; + *pLen = sizeof(char); + break; + + case OID_SKGE_CHKSM_NUMBER: + *pBuf = SKCS_NUM_PROTOCOLS; + *pLen = sizeof(char); + break; + + case OID_SKGE_TRAP_NUMBER: + GetTrapQueueLen(pAC, &Len, &Val); + Val32 = (SK_U32)Val; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_TRAP: + GetTrapQueueLen(pAC, &Len, &Val); + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + CopyTrapQueue(pAC, pBuf); + *pLen = Len; + break; + + case OID_SKGE_RLMT_MONITOR_NUMBER: +/* XXX Not yet implemented by RLMT therefore we return zero elements */ + Val32 = 0; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_TX_SW_QUEUE_LEN: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + + pAC->Pnmi.BufPort[1].TxSwQueueLen; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + + pAC->Pnmi.Port[1].TxSwQueueLen; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + + case OID_SKGE_TX_SW_QUEUE_MAX: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + + pAC->Pnmi.BufPort[1].TxSwQueueMax; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + + pAC->Pnmi.Port[1].TxSwQueueMax; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_TX_RETRY: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + + pAC->Pnmi.BufPort[1].TxRetryCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxRetryCts + + pAC->Pnmi.Port[1].TxRetryCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RX_INTR_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + + pAC->Pnmi.BufPort[1].RxIntrCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].RxIntrCts + + pAC->Pnmi.Port[1].RxIntrCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_TX_INTR_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + + pAC->Pnmi.BufPort[1].TxIntrCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxIntrCts + + pAC->Pnmi.Port[1].TxIntrCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RX_NO_BUF_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + + pAC->Pnmi.BufPort[1].RxNoBufCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].RxNoBufCts + + pAC->Pnmi.Port[1].RxNoBufCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_TX_NO_BUF_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + + pAC->Pnmi.BufPort[1].TxNoBufCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxNoBufCts + + pAC->Pnmi.Port[1].TxNoBufCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_TX_USED_DESCR_NO: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + + pAC->Pnmi.BufPort[1].TxUsedDescrNo; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + + pAC->Pnmi.Port[1].TxUsedDescrNo; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RX_DELIVERED_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + + pAC->Pnmi.BufPort[1].RxDeliveredCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + + pAC->Pnmi.Port[1].RxDeliveredCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RX_OCTETS_DELIV_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + + pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + + pAC->Pnmi.Port[1].RxOctetsDeliveredCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RX_HW_ERROR_CTS: + SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_TX_HW_ERROR_CTS: + SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_IN_ERRORS_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; + } + /* Single net mode */ + else { + Val64 = Val64RxHwErrs + + pAC->Pnmi.BufPort[0].RxNoBufCts + + pAC->Pnmi.BufPort[1].RxNoBufCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; + } + /* Single net mode */ + else { + Val64 = Val64RxHwErrs + + pAC->Pnmi.Port[0].RxNoBufCts + + pAC->Pnmi.Port[1].RxNoBufCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_OUT_ERROR_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; + } + /* Single net mode */ + else { + Val64 = Val64TxHwErrs + + pAC->Pnmi.BufPort[0].TxNoBufCts + + pAC->Pnmi.BufPort[1].TxNoBufCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; + } + /* Single net mode */ + else { + Val64 = Val64TxHwErrs + + pAC->Pnmi.Port[0].TxNoBufCts + + pAC->Pnmi.Port[1].TxNoBufCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_ERR_RECOVERY_CTS: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + + pAC->Pnmi.BufPort[1].ErrRecoveryCts; + } + } + else { + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; + } + /* Single net mode */ + else { + Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + + pAC->Pnmi.Port[1].ErrRecoveryCts; + } + } + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_SYSUPTIME: + Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); + Val64 -= pAC->Pnmi.StartUpTime; + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_MDB_VERSION: + Val32 = SK_PNMI_MDB_VERSION; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_GEN_RCV_ERROR: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; + } + else { + Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; + } + + /* + * by default 32bit values are evaluated + */ + if (!Is64BitReq) { + Val32 = (SK_U32)Val64; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + } + else { + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + } + break; + + case OID_GEN_XMIT_ERROR: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; + } + else { + Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; + } + + /* + * by default 32bit values are evaluated + */ + if (!Is64BitReq) { + Val32 = (SK_U32)Val64; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + } + else { + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + } + break; + + case OID_GEN_RCV_NO_BUFFER: + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (MacType == SK_MAC_XMAC) { + Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; + } + else { + Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; + } + + /* + * by default 32bit values are evaluated + */ + if (!Is64BitReq) { + Val32 = (SK_U32)Val64; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + } + else { + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + } + break; + + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, + SK_PNMI_ERR034MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (Id == OID_SKGE_RX_HW_ERROR_CTS || + Id == OID_SKGE_TX_HW_ERROR_CTS || + Id == OID_SKGE_IN_ERRORS_CTS || + Id == OID_SKGE_OUT_ERROR_CTS || + Id == OID_GEN_XMIT_ERROR || + Id == OID_GEN_RCV_ERROR) { + + pAC->Pnmi.MacUpdatedFlag --; + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. + * + * Description: + * Get/Presets/Sets the RLMT OIDs. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Rlmt( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + int Ret; + unsigned int PhysPortIndex; + unsigned int PhysPortMax; + SK_EVPARA EventParam; + SK_U32 Val32; + SK_U64 Val64; + + + /* + * Check instance. Only single instance OIDs are allowed here. + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* + * Perform the requested action + */ + if (Action == SK_PNMI_GET) { + + /* + * Check if the buffer length is large enough. + */ + + switch (Id) { + + case OID_SKGE_RLMT_MODE: + case OID_SKGE_RLMT_PORT_ACTIVE: + case OID_SKGE_RLMT_PORT_PREFERRED: + if (*pLen < sizeof(SK_U8)) { + + *pLen = sizeof(SK_U8); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_RLMT_PORT_NUMBER: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_RLMT_CHANGE_CTS: + case OID_SKGE_RLMT_CHANGE_TIME: + case OID_SKGE_RLMT_CHANGE_ESTIM: + case OID_SKGE_RLMT_CHANGE_THRES: + if (*pLen < sizeof(SK_U64)) { + + *pLen = sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, + SK_PNMI_ERR035MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Update RLMT statistic and increment semaphores to indicate + * that an update was already done. Maybe RLMT will hold its + * statistic always up to date some time. Then we can + * remove this type of call. + */ + if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.RlmtUpdatedFlag ++; + + /* + * Retrieve Value + */ + switch (Id) { + + case OID_SKGE_RLMT_MODE: + *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; + *pLen = sizeof(char); + break; + + case OID_SKGE_RLMT_PORT_NUMBER: + Val32 = (SK_U32)pAC->GIni.GIMacsFound; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_RLMT_PORT_ACTIVE: + *pBuf = 0; + /* + * If multiple ports may become active this OID + * doesn't make sense any more. A new variable in + * the port structure should be created. However, + * for this variable the first active port is + * returned. + */ + PhysPortMax = pAC->GIni.GIMacsFound; + + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); + break; + } + } + *pLen = sizeof(char); + break; + + case OID_SKGE_RLMT_PORT_PREFERRED: + *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); + *pLen = sizeof(char); + break; + + case OID_SKGE_RLMT_CHANGE_CTS: + Val64 = pAC->Pnmi.RlmtChangeCts; + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_CHANGE_TIME: + Val64 = pAC->Pnmi.RlmtChangeTime; + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_CHANGE_ESTIM: + Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_CHANGE_THRES: + Val64 = pAC->Pnmi.RlmtChangeThreshold; + SK_PNMI_STORE_U64(pBuf, Val64); + *pLen = sizeof(SK_U64); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("Rlmt: Unknown OID should be handled before")); + + pAC->Pnmi.RlmtUpdatedFlag --; + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + pAC->Pnmi.RlmtUpdatedFlag --; + } + else { + /* Perform a preset or set */ + switch (Id) { + + case OID_SKGE_RLMT_MODE: + /* Check if the buffer length is plausible */ + if (*pLen < sizeof(char)) { + + *pLen = sizeof(char); + return (SK_PNMI_ERR_TOO_SHORT); + } + /* Check if the value range is correct */ + if (*pLen != sizeof(char) || + (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || + *(SK_U8 *)pBuf > 15) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + *pLen = 0; + return (SK_PNMI_ERR_OK); + } + /* Send an event to RLMT to change the mode */ + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] |= (SK_U32)(*pBuf); + EventParam.Para32[1] = 0; + if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, + SK_PNMI_ERR037MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + break; + + case OID_SKGE_RLMT_PORT_PREFERRED: + /* Check if the buffer length is plausible */ + if (*pLen < sizeof(char)) { + + *pLen = sizeof(char); + return (SK_PNMI_ERR_TOO_SHORT); + } + /* Check if the value range is correct */ + if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > + (SK_U8)pAC->GIni.GIMacsFound) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + *pLen = 0; + return (SK_PNMI_ERR_OK); + } + + /* + * Send an event to RLMT change the preferred port. + * A param of -1 means automatic mode. RLMT will + * make the decision which is the preferred port. + */ + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; + EventParam.Para32[1] = NetIndex; + if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, + SK_PNMI_ERR038MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + break; + + case OID_SKGE_RLMT_CHANGE_THRES: + /* Check if the buffer length is plausible */ + if (*pLen < sizeof(SK_U64)) { + + *pLen = sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + /* + * There are not many restrictions to the + * value range. + */ + if (*pLen != sizeof(SK_U64)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + /* A preset ends here */ + if (Action == SK_PNMI_PRESET) { + + *pLen = 0; + return (SK_PNMI_ERR_OK); + } + /* + * Store the new threshold, which will be taken + * on the next timer event. + */ + SK_PNMI_READ_U64(pBuf, Val64); + pAC->Pnmi.RlmtChangeThreshold = Val64; + break; + + default: + /* The other OIDs are not be able for set */ + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. + * + * Description: + * Performs get requests on multiple instance variables. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int RlmtStat( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int PhysPortMax; + unsigned int PhysPortIndex; + unsigned int Limit; + unsigned int Offset; + int Ret; + SK_U32 Val32; + SK_U64 Val64; + + /* + * Calculate the port indexes from the instance + */ + PhysPortMax = pAC->GIni.GIMacsFound; + + if ((Instance != (SK_U32)(-1))) { + /* Check instance range */ + if ((Instance < 1) || (Instance > PhysPortMax)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* Single net mode */ + PhysPortIndex = Instance - 1; + + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + PhysPortIndex = NetIndex; + } + + /* Both net modes */ + Limit = PhysPortIndex + 1; + } + else { + /* Single net mode */ + PhysPortIndex = 0; + Limit = PhysPortMax; + + /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + PhysPortIndex = NetIndex; + Limit = PhysPortIndex + 1; + } + } + + /* + * Currently only get requests are allowed. + */ + if (Action != SK_PNMI_GET) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Check if the buffer length is large enough. + */ + switch (Id) { + + case OID_SKGE_RLMT_PORT_INDEX: + case OID_SKGE_RLMT_STATUS: + if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { + + *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_RLMT_TX_HELLO_CTS: + case OID_SKGE_RLMT_RX_HELLO_CTS: + case OID_SKGE_RLMT_TX_SP_REQ_CTS: + case OID_SKGE_RLMT_RX_SP_CTS: + if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { + + *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, + SK_PNMI_ERR039MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + + } + + /* + * Update statistic and increment semaphores to indicate that + * an update was already done. + */ + if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.RlmtUpdatedFlag ++; + + /* + * Get value + */ + Offset = 0; + for (; PhysPortIndex < Limit; PhysPortIndex ++) { + + switch (Id) { + + case OID_SKGE_RLMT_PORT_INDEX: + Val32 = PhysPortIndex; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_RLMT_STATUS: + if (pAC->Rlmt.Port[PhysPortIndex].PortState == + SK_RLMT_PS_INIT || + pAC->Rlmt.Port[PhysPortIndex].PortState == + SK_RLMT_PS_DOWN) { + + Val32 = SK_PNMI_RLMT_STATUS_ERROR; + } + else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; + } + else { + Val32 = SK_PNMI_RLMT_STATUS_STANDBY; + } + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + case OID_SKGE_RLMT_TX_HELLO_CTS: + Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_RX_HELLO_CTS: + Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_TX_SP_REQ_CTS: + Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + case OID_SKGE_RLMT_RX_SP_CTS: + Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; + SK_PNMI_STORE_U64(pBuf + Offset, Val64); + Offset += sizeof(SK_U64); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("RlmtStat: Unknown OID should be errored before")); + + pAC->Pnmi.RlmtUpdatedFlag --; + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + *pLen = Offset; + + pAC->Pnmi.RlmtUpdatedFlag --; + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * MacPrivateConf - OID handler function of OIDs concerning the configuration + * + * Description: + * Get/Presets/Sets the OIDs concerning the configuration. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int MacPrivateConf( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int PhysPortMax; + unsigned int PhysPortIndex; + unsigned int LogPortMax; + unsigned int LogPortIndex; + unsigned int Limit; + unsigned int Offset; + char Val8; + int Ret; + SK_EVPARA EventParam; + SK_U32 Val32; + + + /* + * Calculate instance if wished. MAC index 0 is the virtual + * MAC. + */ + PhysPortMax = pAC->GIni.GIMacsFound; + LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); + + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + LogPortMax--; + } + + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ + /* Check instance range */ + if ((Instance < 1) || (Instance > LogPortMax)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); + Limit = LogPortIndex + 1; + } + + else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + + LogPortIndex = 0; + Limit = LogPortMax; + } + + /* + * Perform action + */ + if (Action == SK_PNMI_GET) { + + /* + * Check length + */ + switch (Id) { + + case OID_SKGE_PMD: + case OID_SKGE_CONNECTOR: + case OID_SKGE_LINK_CAP: + case OID_SKGE_LINK_MODE: + case OID_SKGE_LINK_MODE_STATUS: + case OID_SKGE_LINK_STATUS: + case OID_SKGE_FLOWCTRL_CAP: + case OID_SKGE_FLOWCTRL_MODE: + case OID_SKGE_FLOWCTRL_STATUS: + case OID_SKGE_PHY_OPERATION_CAP: + case OID_SKGE_PHY_OPERATION_MODE: + case OID_SKGE_PHY_OPERATION_STATUS: + case OID_SKGE_SPEED_CAP: + case OID_SKGE_SPEED_MODE: + case OID_SKGE_SPEED_STATUS: + if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { + + *pLen = (Limit - LogPortIndex) * + sizeof(SK_U8); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_MTU: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, + SK_PNMI_ERR041MSG); + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Update statistic and increment semaphore to indicate + * that an update was already done. + */ + if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { + + *pLen = 0; + return (Ret); + } + pAC->Pnmi.SirqUpdatedFlag ++; + + /* + * Get value + */ + Offset = 0; + for (; LogPortIndex < Limit; LogPortIndex ++) { + + switch (Id) { + + case OID_SKGE_PMD: + *(pBuf + Offset) = pAC->Pnmi.PMD; + Offset += sizeof(char); + break; + + case OID_SKGE_CONNECTOR: + *(pBuf + Offset) = pAC->Pnmi.Connector; + Offset += sizeof(char); + break; + + case OID_SKGE_LINK_CAP: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PLinkCap; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkCap; + Offset += sizeof(char); + } + break; + + case OID_SKGE_LINK_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PLinkModeConf; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkModeConf; + Offset += sizeof(char); + } + break; + + case OID_SKGE_LINK_MODE_STATUS: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = + CalculateLinkModeStatus(pAC, + IoC, PhysPortIndex); + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + *(pBuf + Offset) = CalculateLinkModeStatus(pAC, IoC, NetIndex); + Offset += sizeof(char); + } + break; + + case OID_SKGE_LINK_STATUS: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = + CalculateLinkStatus(pAC, + IoC, PhysPortIndex); + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = CalculateLinkStatus(pAC, IoC, NetIndex); + Offset += sizeof(char); + } + break; + + case OID_SKGE_FLOWCTRL_CAP: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PFlowCtrlCap; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlCap; + Offset += sizeof(char); + } + break; + + case OID_SKGE_FLOWCTRL_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PFlowCtrlMode; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlMode; + Offset += sizeof(char); + } + break; + + case OID_SKGE_FLOWCTRL_STATUS: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PFlowCtrlStatus; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; + Offset += sizeof(char); + } + break; + + case OID_SKGE_PHY_OPERATION_CAP: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PMSCap; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSCap; + Offset += sizeof(char); + } + break; + + case OID_SKGE_PHY_OPERATION_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PMSMode; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSMode; + Offset += sizeof(char); + } + break; + + case OID_SKGE_PHY_OPERATION_STATUS: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PMSStatus; + } + Offset += sizeof(char); + } + else { + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSStatus; + Offset += sizeof(char); + } + break; + + case OID_SKGE_SPEED_CAP: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + + Offset); + } + else { + /* Get value for physical ports */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PLinkSpeedCap; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedCap; + Offset += sizeof(char); + } + break; + + case OID_SKGE_SPEED_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PLinkSpeed; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeed; + Offset += sizeof(char); + } + break; + + case OID_SKGE_SPEED_STATUS: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (LogPortIndex == 0) { + + /* Get value for virtual port */ + VirtualConf(pAC, IoC, Id, pBuf + Offset); + } + else { + /* Get value for physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + + *(pBuf + Offset) = pAC->GIni.GP[ + PhysPortIndex].PLinkSpeedUsed; + } + Offset += sizeof(char); + } + else { /* DualNetMode */ + + *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; + Offset += sizeof(char); + } + break; + + case OID_SKGE_MTU: + Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("MacPrivateConf: Unknown OID should be handled before")); + + pAC->Pnmi.SirqUpdatedFlag --; + return (SK_PNMI_ERR_GENERAL); + } + } + *pLen = Offset; + pAC->Pnmi.SirqUpdatedFlag --; + + return (SK_PNMI_ERR_OK); + } + + /* + * From here SET or PRESET action. Check if the passed + * buffer length is plausible. + */ + switch (Id) { + + case OID_SKGE_LINK_MODE: + case OID_SKGE_FLOWCTRL_MODE: + case OID_SKGE_PHY_OPERATION_MODE: + case OID_SKGE_SPEED_MODE: + if (*pLen < Limit - LogPortIndex) { + + *pLen = Limit - LogPortIndex; + return (SK_PNMI_ERR_TOO_SHORT); + } + if (*pLen != Limit - LogPortIndex) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + break; + + case OID_SKGE_MTU: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + if (*pLen != sizeof(SK_U32)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Perform preset or set + */ + Offset = 0; + for (; LogPortIndex < Limit; LogPortIndex ++) { + + switch (Id) { + + case OID_SKGE_LINK_MODE: + /* Check the value range */ + Val8 = *(pBuf + Offset); + if (Val8 == 0) { + + Offset += sizeof(char); + break; + } + if (Val8 < SK_LMODE_HALF || + (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || + (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (LogPortIndex == 0) { + + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new link mode to SIRQ. + */ + for (PhysPortIndex = 0; + PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (!pAC->Pnmi.Port[PhysPortIndex]. + ActiveFlag) { + + continue; + } + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_LMODE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR043, + SK_PNMI_ERR043MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + } + else { + /* + * Send an event with the new link mode to + * the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR043, + SK_PNMI_ERR043MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + Offset += sizeof(char); + break; + + case OID_SKGE_FLOWCTRL_MODE: + /* Check the value range */ + Val8 = *(pBuf + Offset); + if (Val8 == 0) { + + Offset += sizeof(char); + break; + } + if (Val8 < SK_FLOW_MODE_NONE || + (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || + (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (LogPortIndex == 0) { + + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new flow control mode to SIRQ. + */ + for (PhysPortIndex = 0; + PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (!pAC->Pnmi.Port[PhysPortIndex]. + ActiveFlag) { + + continue; + } + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_FLOWMODE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR044, + SK_PNMI_ERR044MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + } + else { + /* + * Send an event with the new flow control + * mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_FLOWMODE, EventParam) + > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR044, + SK_PNMI_ERR044MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + Offset += sizeof(char); + break; + + case OID_SKGE_PHY_OPERATION_MODE : + /* Check the value range */ + Val8 = *(pBuf + Offset); + if (Val8 == 0) { + /* mode of this port remains unchanged */ + Offset += sizeof(char); + break; + } + if (Val8 < SK_MS_MODE_AUTO || + (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || + (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (LogPortIndex == 0) { + + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with new master/slave (role) mode to SIRQ. + */ + for (PhysPortIndex = 0; + PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (!pAC->Pnmi.Port[PhysPortIndex]. + ActiveFlag) { + + continue; + } + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_ROLE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR042, + SK_PNMI_ERR042MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + } + else { + /* + * Send an event with the new master/slave + * (role) mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_ROLE, EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR042, + SK_PNMI_ERR042MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + + Offset += sizeof(char); + break; + + case OID_SKGE_SPEED_MODE: + /* Check the value range */ + Val8 = *(pBuf + Offset); + if (Val8 == 0) { + + Offset += sizeof(char); + break; + } + if (Val8 < (SK_LSPEED_AUTO) || + (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || + (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (LogPortIndex == 0) { + + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new flow control mode to SIRQ. + */ + for (PhysPortIndex = 0; + PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + continue; + } + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_SPEED, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR045, + SK_PNMI_ERR045MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + } + else { + /* + * Send an event with the new flow control + * mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_SPEED, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR045, + SK_PNMI_ERR045MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + Offset += sizeof(char); + break; + + case OID_SKGE_MTU : + /* Check the value range */ + Val32 = *(SK_U32*)(pBuf + Offset); + if (Val32 == 0) { + /* mtu of this port remains unchanged */ + Offset += sizeof(SK_U32); + break; + } + if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + /* The preset ends here */ + if (Action == SK_PNMI_PRESET) { + return (SK_PNMI_ERR_OK); + } + + if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { + return (SK_PNMI_ERR_GENERAL); + } + + Offset += sizeof(SK_U32); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("MacPrivateConf: Unknown OID should be handled before set")); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * Monitor - OID handler function for RLMT_MONITOR_XXX + * + * Description: + * Because RLMT currently does not support the monitoring of + * remote adapter cards, we return always an empty table. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid + * value range. + * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +PNMI_STATIC int Monitor( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int Index; + unsigned int Limit; + unsigned int Offset; + unsigned int Entries; + + + /* + * Calculate instance if wished. + */ +/* XXX Not yet implemented. Return always an empty table. */ + Entries = 0; + + if ((Instance != (SK_U32)(-1))) { + + if ((Instance < 1) || (Instance > Entries)) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + Index = (unsigned int)Instance - 1; + Limit = (unsigned int)Instance; + } + else { + Index = 0; + Limit = Entries; + } + + /* + * Get/Set value + */ + if (Action == SK_PNMI_GET) { + + for (Offset=0; Index < Limit; Index ++) { + + switch (Id) { + + case OID_SKGE_RLMT_MONITOR_INDEX: + case OID_SKGE_RLMT_MONITOR_ADDR: + case OID_SKGE_RLMT_MONITOR_ERRS: + case OID_SKGE_RLMT_MONITOR_TIMESTAMP: + case OID_SKGE_RLMT_MONITOR_ADMIN: + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, + SK_PNMI_ERR046MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } + *pLen = Offset; + } + else { + /* Only MONITOR_ADMIN can be set */ + if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { + + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* Check if the length is plausible */ + if (*pLen < (Limit - Index)) { + + return (SK_PNMI_ERR_TOO_SHORT); + } + /* Okay, we have a wide value range */ + if (*pLen != (Limit - Index)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } +/* + for (Offset=0; Index < Limit; Index ++) { + } +*/ +/* + * XXX Not yet implemented. Return always BAD_VALUE, because the table + * is empty. + */ + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * VirtualConf - Calculates the values of configuration OIDs for virtual port + * + * Description: + * We handle here the get of the configuration group OIDs, which are + * a little bit complicated. The virtual port consists of all currently + * active physical ports. If multiple ports are active and configured + * differently we get in some trouble to return a single value. So we + * get the value of the first active port and compare it with that of + * the other active ports. If they are not the same, we return a value + * that indicates that the state is indeterminated. + * + * Returns: + * Nothing + */ +PNMI_STATIC void VirtualConf( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf) /* Buffer to which to mgmt data will be retrieved */ +{ + unsigned int PhysPortMax; + unsigned int PhysPortIndex; + SK_U8 Val8; + SK_BOOL PortActiveFlag; + + + *pBuf = 0; + PortActiveFlag = SK_FALSE; + PhysPortMax = pAC->GIni.GIMacsFound; + + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + /* Check if the physical port is active */ + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + continue; + } + + PortActiveFlag = SK_TRUE; + + switch (Id) { + + case OID_SKGE_LINK_CAP: + + /* + * Different capabilities should not happen, but + * in the case of the cases OR them all together. + * From a curious point of view the virtual port + * is capable of all found capabilities. + */ + *pBuf |= pAC->GIni.GP[PhysPortIndex].PLinkCap; + break; + + case OID_SKGE_LINK_MODE: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; + continue; + } + + /* + * If we find an active port with a different link + * mode than the first one we return a value that + * indicates that the link mode is indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkModeConf + ) { + + *pBuf = SK_LMODE_INDETERMINATED; + } + break; + + case OID_SKGE_LINK_MODE_STATUS: + /* Get the link mode of the physical port */ + Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); + + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = Val8; + continue; + } + + /* + * If we find an active port with a different link + * mode status than the first one we return a value + * that indicates that the link mode status is + * indeterminated. + */ + if (*pBuf != Val8) { + + *pBuf = SK_LMODE_STAT_INDETERMINATED; + } + break; + + case OID_SKGE_LINK_STATUS: + /* Get the link status of the physical port */ + Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); + + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = Val8; + continue; + } + + /* + * If we find an active port with a different link + * status than the first one, we return a value + * that indicates that the link status is + * indeterminated. + */ + if (*pBuf != Val8) { + + *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; + } + break; + + case OID_SKGE_FLOWCTRL_CAP: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; + continue; + } + + /* + * From a curious point of view the virtual port + * is capable of all found capabilities. + */ + *pBuf |= pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; + break; + + case OID_SKGE_FLOWCTRL_MODE: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; + continue; + } + + /* + * If we find an active port with a different flow + * control mode than the first one, we return a value + * that indicates that the mode is indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode) { + + *pBuf = SK_FLOW_MODE_INDETERMINATED; + } + break; + + case OID_SKGE_FLOWCTRL_STATUS: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; + continue; + } + + /* + * If we find an active port with a different flow + * control status than the first one, we return a + * value that indicates that the status is + * indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus) { + + *pBuf = SK_FLOW_STAT_INDETERMINATED; + } + break; + + case OID_SKGE_PHY_OPERATION_CAP: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PMSCap; + continue; + } + + /* + * From a curious point of view the virtual port + * is capable of all found capabilities. + */ + *pBuf |= pAC->GIni.GP[PhysPortIndex].PMSCap; + break; + + case OID_SKGE_PHY_OPERATION_MODE: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PMSMode; + continue; + } + + /* + * If we find an active port with a different master/ + * slave mode than the first one, we return a value + * that indicates that the mode is indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSMode) { + + *pBuf = SK_MS_MODE_INDETERMINATED; + } + break; + + case OID_SKGE_PHY_OPERATION_STATUS: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PMSStatus; + continue; + } + + /* + * If we find an active port with a different master/ + * slave status than the first one, we return a + * value that indicates that the status is + * indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSStatus) { + + *pBuf = SK_MS_STAT_INDETERMINATED; + } + break; + + case OID_SKGE_SPEED_MODE: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; + continue; + } + + /* + * If we find an active port with a different flow + * control mode than the first one, we return a value + * that indicates that the mode is indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeed) { + + *pBuf = SK_LSPEED_INDETERMINATED; + } + break; + + case OID_SKGE_SPEED_STATUS: + /* Check if it is the first active port */ + if (*pBuf == 0) { + + *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; + continue; + } + + /* + * If we find an active port with a different flow + * control status than the first one, we return a + * value that indicates that the status is + * indeterminated. + */ + if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed) { + + *pBuf = SK_LSPEED_STAT_INDETERMINATED; + } + break; + } + } + + /* + * If no port is active return an indeterminated answer + */ + if (!PortActiveFlag) { + + switch (Id) { + + case OID_SKGE_LINK_CAP: + *pBuf = SK_LMODE_CAP_INDETERMINATED; + break; + + case OID_SKGE_LINK_MODE: + *pBuf = SK_LMODE_INDETERMINATED; + break; + + case OID_SKGE_LINK_MODE_STATUS: + *pBuf = SK_LMODE_STAT_INDETERMINATED; + break; + + case OID_SKGE_LINK_STATUS: + *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; + break; + + case OID_SKGE_FLOWCTRL_CAP: + case OID_SKGE_FLOWCTRL_MODE: + *pBuf = SK_FLOW_MODE_INDETERMINATED; + break; + + case OID_SKGE_FLOWCTRL_STATUS: + *pBuf = SK_FLOW_STAT_INDETERMINATED; + break; + + case OID_SKGE_PHY_OPERATION_CAP: + *pBuf = SK_MS_CAP_INDETERMINATED; + break; + + case OID_SKGE_PHY_OPERATION_MODE: + *pBuf = SK_MS_MODE_INDETERMINATED; + break; + + case OID_SKGE_PHY_OPERATION_STATUS: + *pBuf = SK_MS_STAT_INDETERMINATED; + break; + case OID_SKGE_SPEED_CAP: + *pBuf = SK_LSPEED_CAP_INDETERMINATED; + break; + + case OID_SKGE_SPEED_MODE: + *pBuf = SK_LSPEED_INDETERMINATED; + break; + + case OID_SKGE_SPEED_STATUS: + *pBuf = SK_LSPEED_STAT_INDETERMINATED; + break; + } + } +} + +/***************************************************************************** + * + * CalculateLinkStatus - Determins the link status of a physical port + * + * Description: + * Determins the link status the following way: + * LSTAT_PHY_DOWN: Link is down + * LSTAT_AUTONEG: Auto-negotiation failed + * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port + * logically up. + * LSTAT_LOG_UP: RLMT marked the port as up + * + * Returns: + * Link status of physical port + */ +PNMI_STATIC SK_U8 CalculateLinkStatus( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +unsigned int PhysPortIndex) /* Physical port index */ +{ + SK_U8 Result; + + + if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { + + Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; + } + else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { + + Result = SK_PNMI_RLMT_LSTAT_AUTONEG; + } + else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { + + Result = SK_PNMI_RLMT_LSTAT_LOG_UP; + } + else { + Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; + } + + return (Result); +} + +/***************************************************************************** + * + * CalculateLinkModeStatus - Determins the link mode status of a phys. port + * + * Description: + * The COMMON module only tells us if the mode is half or full duplex. + * But in the decade of auto sensing it is usefull for the user to + * know if the mode was negotiated or forced. Therefore we have a + * look to the mode, which was last used by the negotiation process. + * + * Returns: + * The link mode status + */ +PNMI_STATIC SK_U8 CalculateLinkModeStatus( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +unsigned int PhysPortIndex) /* Physical port index */ +{ + SK_U8 Result; + + + /* Get the current mode, which can be full or half duplex */ + Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; + + /* Check if no valid mode could be found (link is down) */ + if (Result < SK_LMODE_STAT_HALF) { + + Result = SK_LMODE_STAT_UNKNOWN; + } + else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { + + /* + * Auto-negotiation was used to bring up the link. Change + * the already found duplex status that it indicates + * auto-negotiation was involved. + */ + if (Result == SK_LMODE_STAT_HALF) { + + Result = SK_LMODE_STAT_AUTOHALF; + } + else if (Result == SK_LMODE_STAT_FULL) { + + Result = SK_LMODE_STAT_AUTOFULL; + } + } + + return (Result); +} + +/***************************************************************************** + * + * GetVpdKeyArr - Obtain an array of VPD keys + * + * Description: + * Read the VPD keys and build an array of VPD keys, which are + * easy to access. + * + * Returns: + * SK_PNMI_ERR_OK Task successfully performed. + * SK_PNMI_ERR_GENERAL Something went wrong. + */ +PNMI_STATIC int GetVpdKeyArr( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +char *pKeyArr, /* Ptr KeyArray */ +unsigned int KeyArrLen, /* Length of array in bytes */ +unsigned int *pKeyNo) /* Number of keys */ +{ + unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE; + char BufKeys[SK_PNMI_VPD_BUFSIZE]; + unsigned int StartOffset; + unsigned int Offset; + int Index; + int Ret; + + + SK_MEMSET(pKeyArr, 0, KeyArrLen); + + /* + * Get VPD key list + */ + Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, + (int *)pKeyNo); + if (Ret > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, + SK_PNMI_ERR014MSG); + + return (SK_PNMI_ERR_GENERAL); + } + /* If no keys are available return now */ + if (*pKeyNo == 0 || BufKeysLen == 0) { + + return (SK_PNMI_ERR_OK); + } + /* + * If the key list is too long for us trunc it and give a + * errorlog notification. This case should not happen because + * the maximum number of keys is limited due to RAM limitations + */ + if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, + SK_PNMI_ERR015MSG); + + *pKeyNo = SK_PNMI_VPD_ENTRIES; + } + + /* + * Now build an array of fixed string length size and copy + * the keys together. + */ + for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; + Offset ++) { + + if (BufKeys[Offset] != 0) { + + continue; + } + + if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, + SK_PNMI_ERR016MSG); + return (SK_PNMI_ERR_GENERAL); + } + + SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, + &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); + + Index ++; + StartOffset = Offset + 1; + } + + /* Last key not zero terminated? Get it anyway */ + if (StartOffset < Offset) { + + SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, + &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * SirqUpdate - Let the SIRQ update its internal values + * + * Description: + * Just to be sure that the SIRQ module holds its internal data + * structures up to date, we send an update event before we make + * any access. + * + * Returns: + * SK_PNMI_ERR_OK Task successfully performed. + * SK_PNMI_ERR_GENERAL Something went wrong. + */ +PNMI_STATIC int SirqUpdate( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC) /* IO context handle */ +{ + SK_EVPARA EventParam; + + + /* Was the module already updated during the current PNMI call? */ + if (pAC->Pnmi.SirqUpdatedFlag > 0) { + + return (SK_PNMI_ERR_OK); + } + + /* Send an synchronuous update event to the module */ + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, + SK_PNMI_ERR047MSG); + + return (SK_PNMI_ERR_GENERAL); + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * RlmtUpdate - Let the RLMT update its internal values + * + * Description: + * Just to be sure that the RLMT module holds its internal data + * structures up to date, we send an update event before we make + * any access. + * + * Returns: + * SK_PNMI_ERR_OK Task successfully performed. + * SK_PNMI_ERR_GENERAL Something went wrong. + */ +PNMI_STATIC int RlmtUpdate( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + SK_EVPARA EventParam; + + + /* Was the module already updated during the current PNMI call? */ + if (pAC->Pnmi.RlmtUpdatedFlag > 0) { + + return (SK_PNMI_ERR_OK); + } + + /* Send an synchronuous update event to the module */ + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] = NetIndex; + EventParam.Para32[1] = (SK_U32)-1; + if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, + SK_PNMI_ERR048MSG); + + return (SK_PNMI_ERR_GENERAL); + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * MacUpdate - Force the XMAC to output the current statistic + * + * Description: + * The XMAC holds its statistic internally. To obtain the current + * values we send a command so that the statistic data will + * be written to apredefined memory area on the adapter. + * + * Returns: + * SK_PNMI_ERR_OK Task successfully performed. + * SK_PNMI_ERR_GENERAL Something went wrong. + */ +PNMI_STATIC int MacUpdate( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +unsigned int FirstMac, /* Index of the first Mac to be updated */ +unsigned int LastMac) /* Index of the last Mac to be updated */ +{ + unsigned int MacIndex; + + /* + * Were the statistics already updated during the + * current PNMI call? + */ + if (pAC->Pnmi.MacUpdatedFlag > 0) { + + return (SK_PNMI_ERR_OK); + } + + /* Send an update command to all MACs specified */ + for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { + + /* + * 2002-09-13 pweber: Freeze the current sw counters. + * (That should be done as close as + * possible to the update of the + * hw counters) + */ + if (pAC->GIni.GIMacType == SK_MAC_XMAC) { + pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; + } + + /* 2002-09-13 pweber: Update the hw counter */ + if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { + + return (SK_PNMI_ERR_GENERAL); + } + } + + return (SK_PNMI_ERR_OK); +} + +/***************************************************************************** + * + * GetStatVal - Retrieve an XMAC statistic counter + * + * Description: + * Retrieves the statistic counter of a virtual or physical port. The + * virtual port is identified by the index 0. It consists of all + * currently active ports. To obtain the counter value for this port + * we must add the statistic counter of all active ports. To grant + * continuous counter values for the virtual port even when port + * switches occur we must additionally add a delta value, which was + * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. + * + * Returns: + * Requested statistic value + */ +PNMI_STATIC SK_U64 GetStatVal( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +unsigned int LogPortIndex, /* Index of the logical Port to be processed */ +unsigned int StatIndex, /* Index to statistic value */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + unsigned int PhysPortIndex; + unsigned int PhysPortMax; + SK_U64 Val = 0; + + + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + + PhysPortIndex = NetIndex; + Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); + } + else { /* Single Net mode */ + + if (LogPortIndex == 0) { + + PhysPortMax = pAC->GIni.GIMacsFound; + + /* Add counter of all active ports */ + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { + + if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + + Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, + StatIndex); + } + } + + /* Correct value because of port switches */ + Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; + } + else { + /* Get counter value of physical port */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); + } + } + return (Val); +} + +/***************************************************************************** + * + * GetPhysStatVal - Get counter value for physical port + * + * Description: + * Builds a 64bit counter value. Except for the octet counters + * the lower 32bit are counted in hardware and the upper 32bit + * in software by monitoring counter overflow interrupts in the + * event handler. To grant continous counter values during XMAC + * resets (caused by a workaround) we must add a delta value. + * The delta was calculated in the event handler when a + * SK_PNMI_EVT_XMAC_RESET was received. + * + * Returns: + * Counter value + */ +PNMI_STATIC SK_U64 GetPhysStatVal( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +unsigned int PhysPortIndex, /* Index of the logical Port to be processed */ +unsigned int StatIndex) /* Index to statistic value */ +{ + SK_U64 Val = 0; + SK_U32 LowVal = 0; + SK_U32 HighVal = 0; + SK_U16 Word; + int MacType; + + SK_PNMI_PORT *pPnmiPrt; + SK_GEMACFUNC *pFnMac; + + MacType = pAC->GIni.GIMacType; + + /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + if (pAC->GIni.GIMacType == SK_MAC_XMAC) { + pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; + } + else { + pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; + } + + pFnMac = &pAC->GIni.GIFunc; + + switch (StatIndex) { + case SK_PNMI_HTX: + case SK_PNMI_HRX: + /* Not supported by GMAC */ + if (MacType == SK_MAC_GMAC) { + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HTX_OCTET: + case SK_PNMI_HRX_OCTET: + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &HighVal); + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex + 1][MacType].Reg, + &LowVal); + break; + + case SK_PNMI_HTX_BURST: + case SK_PNMI_HTX_EXCESS_DEF: + case SK_PNMI_HTX_CARRIER: + /* Not supported by GMAC */ + if (MacType == SK_MAC_GMAC) { + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HTX_MACC: + /* GMAC only supports PAUSE MAC control frames */ + if (MacType == SK_MAC_GMAC) { + Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, SK_PNMI_HTX_PMACC); + + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HTX_COL: + case SK_PNMI_HRX_UNDERSIZE: + /* Not supported by XMAC */ + if (MacType == SK_MAC_XMAC) { + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + + case SK_PNMI_HTX_DEFFERAL: + /* Not supported by GMAC */ + if (MacType == SK_MAC_GMAC) { + return (Val); + } + + /* + * XMAC counts frames with deferred transmission + * even in full-duplex mode. + * + * In full-duplex mode the counter remains constant! + */ + if ((pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || + (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_FULL)) { + + LowVal = 0; + HighVal = 0; + } + else { + /* Otherwise get contents of hardware register. */ + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HTX_DEFFERAL][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + } + break; + + case SK_PNMI_HRX_BADOCTET: + /* Not supported by XMAC */ + if (MacType == SK_MAC_XMAC) { + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &HighVal); + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex + 1][MacType].Reg, + &LowVal); + break; + + case SK_PNMI_HTX_OCTETLOW: + case SK_PNMI_HRX_OCTETLOW: + case SK_PNMI_HRX_BADOCTETLOW: + return (Val); + + case SK_PNMI_HRX_LONGFRAMES: + /* For XMAC the SW counter is managed by PNMI */ + if (MacType == SK_MAC_XMAC) { + return (pPnmiPrt->StatRxLongFrameCts); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HRX_TOO_LONG: + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + + Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); + + switch (MacType) { + case SK_MAC_GMAC: + /* For GMAC the SW counter is additionally managed by PNMI */ + Val += pPnmiPrt->StatRxFrameTooLongCts; + break; + + case SK_MAC_XMAC: + /* + * Frames longer than IEEE 802.3 frame max size are counted + * by XMAC in frame_too_long counter even reception of long + * frames was enabled and the frame was correct. + * So correct the value by subtracting RxLongFrame counter. + */ + Val -= pPnmiPrt->StatRxLongFrameCts; + break; + + default: + break; + } + + LowVal = (SK_U32)Val; + HighVal = (SK_U32)(Val >> 32); + break; + + case SK_PNMI_HRX_SHORTS: + /* Not supported by GMAC */ + if (MacType == SK_MAC_GMAC) { + /* GM_RXE_FRAG?? */ + return (Val); + } + + /* + * XMAC counts short frame errors even if link down (#10620) + * + * If link-down the counter remains constant + */ + if (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { + + /* Otherwise get incremental difference */ + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + + Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); + Val -= pPnmiPrt->RxShortZeroMark; + + LowVal = (SK_U32)Val; + HighVal = (SK_U32)(Val >> 32); + } + break; + + case SK_PNMI_HRX_MACC: + case SK_PNMI_HRX_MACC_UNKWN: + case SK_PNMI_HRX_BURST: + case SK_PNMI_HRX_MISSED: + case SK_PNMI_HRX_FRAMING: + case SK_PNMI_HRX_CARRIER: + case SK_PNMI_HRX_IRLENGTH: + case SK_PNMI_HRX_SYMBOL: + case SK_PNMI_HRX_CEXT: + /* Not supported by GMAC */ + if (MacType == SK_MAC_GMAC) { + /* GM_RXE_FRAG?? */ + return (Val); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HRX_PMACC_ERR: + /* For GMAC the SW counter is managed by PNMI */ + if (MacType == SK_MAC_GMAC) { + return (pPnmiPrt->StatRxPMaccErr); + } + + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + /* SW counter managed by PNMI */ + case SK_PNMI_HTX_SYNC: + LowVal = (SK_U32)pPnmiPrt->StatSyncCts; + HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); + break; + + /* SW counter managed by PNMI */ + case SK_PNMI_HTX_SYNC_OCTET: + LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; + HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); + break; + + case SK_PNMI_HRX_FCS: + /* + * Broadcom filters fcs errors and counts it in + * Receive Error Counter register + */ + if (pAC->GIni.GP[PhysPortIndex].PhyType == SK_PHY_BCOM) { + /* do not read while not initialized (PHY_READ hangs!)*/ + if (pAC->GIni.GP[PhysPortIndex].PState) { + PHY_READ(IoC, &pAC->GIni.GP[PhysPortIndex], + PhysPortIndex, PHY_BCOM_RE_CTR, + &Word); + + LowVal = Word; + } + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + } + else { + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + } + break; + + default: + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + } + + Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); + + /* Correct value because of possible XMAC reset. XMAC Errata #2 */ + Val += pPnmiPrt->CounterOffset[StatIndex]; + + return (Val); +} + +/***************************************************************************** + * + * ResetCounter - Set all counters and timestamps to zero + * + * Description: + * Notifies other common modules which store statistic data to + * reset their counters and finally reset our own counters. + * + * Returns: + * Nothing + */ +PNMI_STATIC void ResetCounter( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +SK_U32 NetIndex) +{ + unsigned int PhysPortIndex; + SK_EVPARA EventParam; + + + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + + /* Notify sensor module */ + SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); + + /* Notify RLMT module */ + EventParam.Para32[0] = NetIndex; + EventParam.Para32[1] = (SK_U32)-1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); + EventParam.Para32[1] = 0; + + /* Notify SIRQ module */ + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); + + /* Notify CSUM module */ +#ifdef SK_USE_CSUM + EventParam.Para32[0] = NetIndex; + EventParam.Para32[1] = (SK_U32)-1; + SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, + EventParam); +#endif + + /* Clear XMAC statistic */ + for (PhysPortIndex = 0; PhysPortIndex < + (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { + + (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); + + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, + 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. + CounterOffset, 0, sizeof(pAC->Pnmi.Port[ + PhysPortIndex].CounterOffset)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, + 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. + StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ + PhysPortIndex].StatSyncOctetsCts)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. + StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ + PhysPortIndex].StatRxLongFrameCts)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. + StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ + PhysPortIndex].StatRxFrameTooLongCts)); + SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. + StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ + PhysPortIndex].StatRxPMaccErr)); + } + + /* + * Clear local statistics + */ + SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, + sizeof(pAC->Pnmi.VirtualCounterOffset)); + pAC->Pnmi.RlmtChangeCts = 0; + pAC->Pnmi.RlmtChangeTime = 0; + SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, + sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); + pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; + pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; + pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; + pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; + pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; + pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; + pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; + pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; + pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; + pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; + pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; + pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; +} + +/***************************************************************************** + * + * GetTrapEntry - Get an entry in the trap buffer + * + * Description: + * The trap buffer stores various events. A user application somehow + * gets notified that an event occured and retrieves the trap buffer + * contens (or simply polls the buffer). The buffer is organized as + * a ring which stores the newest traps at the beginning. The oldest + * traps are overwritten by the newest ones. Each trap entry has a + * unique number, so that applications may detect new trap entries. + * + * Returns: + * A pointer to the trap entry + */ +PNMI_STATIC char* GetTrapEntry( +SK_AC *pAC, /* Pointer to adapter context */ +SK_U32 TrapId, /* SNMP ID of the trap */ +unsigned int Size) /* Space needed for trap entry */ +{ + unsigned int BufPad = pAC->Pnmi.TrapBufPad; + unsigned int BufFree = pAC->Pnmi.TrapBufFree; + unsigned int Beg = pAC->Pnmi.TrapQueueBeg; + unsigned int End = pAC->Pnmi.TrapQueueEnd; + char *pBuf = &pAC->Pnmi.TrapBuf[0]; + int Wrap; + unsigned int NeededSpace; + unsigned int EntrySize; + SK_U32 Val32; + SK_U64 Val64; + + + /* Last byte of entry will get a copy of the entry length */ + Size ++; + + /* + * Calculate needed buffer space */ + if (Beg >= Size) { + + NeededSpace = Size; + Wrap = SK_FALSE; + } + else { + NeededSpace = Beg + Size; + Wrap = SK_TRUE; + } + + /* + * Check if enough buffer space is provided. Otherwise + * free some entries. Leave one byte space between begin + * and end of buffer to make it possible to detect whether + * the buffer is full or empty + */ + while (BufFree < NeededSpace + 1) { + + if (End == 0) { + + End = SK_PNMI_TRAP_QUEUE_LEN; + } + + EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); + BufFree += EntrySize; + End -= EntrySize; +#ifdef DEBUG + SK_MEMSET(pBuf + End, (char)(-1), EntrySize); +#endif + if (End == BufPad) { +#ifdef DEBUG + SK_MEMSET(pBuf, (char)(-1), End); +#endif + BufFree += End; + End = 0; + BufPad = 0; + } + } + + /* + * Insert new entry as first entry. Newest entries are + * stored at the beginning of the queue. + */ + if (Wrap) { + + BufPad = Beg; + Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; + } + else { + Beg = Beg - Size; + } + BufFree -= NeededSpace; + + /* Save the current offsets */ + pAC->Pnmi.TrapQueueBeg = Beg; + pAC->Pnmi.TrapQueueEnd = End; + pAC->Pnmi.TrapBufPad = BufPad; + pAC->Pnmi.TrapBufFree = BufFree; + + /* Initialize the trap entry */ + *(pBuf + Beg + Size - 1) = (char)Size; + *(pBuf + Beg) = (char)Size; + Val32 = (pAC->Pnmi.TrapUnique) ++; + SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); + SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); + Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); + SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); + + return (pBuf + Beg); +} + +/***************************************************************************** + * + * CopyTrapQueue - Copies the trap buffer for the TRAP OID + * + * Description: + * On a query of the TRAP OID the trap buffer contents will be + * copied continuously to the request buffer, which must be large + * enough. No length check is performed. + * + * Returns: + * Nothing + */ +PNMI_STATIC void CopyTrapQueue( +SK_AC *pAC, /* Pointer to adapter context */ +char *pDstBuf) /* Buffer to which the queued traps will be copied */ +{ + unsigned int BufPad = pAC->Pnmi.TrapBufPad; + unsigned int Trap = pAC->Pnmi.TrapQueueBeg; + unsigned int End = pAC->Pnmi.TrapQueueEnd; + char *pBuf = &pAC->Pnmi.TrapBuf[0]; + unsigned int Len; + unsigned int DstOff = 0; + + + while (Trap != End) { + + Len = (unsigned int)*(pBuf + Trap); + + /* + * Last byte containing a copy of the length will + * not be copied. + */ + *(pDstBuf + DstOff) = (char)(Len - 1); + SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); + DstOff += Len - 1; + + Trap += Len; + if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { + + Trap = BufPad; + } + } +} + +/***************************************************************************** + * + * GetTrapQueueLen - Get the length of the trap buffer + * + * Description: + * Evaluates the number of currently stored traps and the needed + * buffer size to retrieve them. + * + * Returns: + * Nothing + */ +PNMI_STATIC void GetTrapQueueLen( +SK_AC *pAC, /* Pointer to adapter context */ +unsigned int *pLen, /* Length in Bytes of all queued traps */ +unsigned int *pEntries) /* Returns number of trapes stored in queue */ +{ + unsigned int BufPad = pAC->Pnmi.TrapBufPad; + unsigned int Trap = pAC->Pnmi.TrapQueueBeg; + unsigned int End = pAC->Pnmi.TrapQueueEnd; + char *pBuf = &pAC->Pnmi.TrapBuf[0]; + unsigned int Len; + unsigned int Entries = 0; + unsigned int TotalLen = 0; + + + while (Trap != End) { + + Len = (unsigned int)*(pBuf + Trap); + TotalLen += Len - 1; + Entries ++; + + Trap += Len; + if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { + + Trap = BufPad; + } + } + + *pEntries = Entries; + *pLen = TotalLen; +} + +/***************************************************************************** + * + * QueueSimpleTrap - Store a simple trap to the trap buffer + * + * Description: + * A simple trap is a trap with now additional data. It consists + * simply of a trap code. + * + * Returns: + * Nothing + */ +PNMI_STATIC void QueueSimpleTrap( +SK_AC *pAC, /* Pointer to adapter context */ +SK_U32 TrapId) /* Type of sensor trap */ +{ + GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); +} + +/***************************************************************************** + * + * QueueSensorTrap - Stores a sensor trap in the trap buffer + * + * Description: + * Gets an entry in the trap buffer and fills it with sensor related + * data. + * + * Returns: + * Nothing + */ +PNMI_STATIC void QueueSensorTrap( +SK_AC *pAC, /* Pointer to adapter context */ +SK_U32 TrapId, /* Type of sensor trap */ +unsigned int SensorIndex) /* Index of sensor which caused the trap */ +{ + char *pBuf; + unsigned int Offset; + unsigned int DescrLen; + SK_U32 Val32; + + + /* Get trap buffer entry */ + DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); + pBuf = GetTrapEntry(pAC, TrapId, + SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); + Offset = SK_PNMI_TRAP_SIMPLE_LEN; + + /* Store additionally sensor trap related data */ + Val32 = OID_SKGE_SENSOR_INDEX; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + *(pBuf + Offset + 4) = 4; + Val32 = (SK_U32)SensorIndex; + SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); + Offset += 9; + + Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + *(pBuf + Offset + 4) = (char)DescrLen; + SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, + DescrLen); + Offset += DescrLen + 5; + + Val32 = OID_SKGE_SENSOR_TYPE; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + *(pBuf + Offset + 4) = 1; + *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; + Offset += 6; + + Val32 = OID_SKGE_SENSOR_VALUE; + SK_PNMI_STORE_U32(pBuf + Offset, Val32); + *(pBuf + Offset + 4) = 4; + Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; + SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); +} + +/***************************************************************************** + * + * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer + * + * Description: + * Nothing further to explain. + * + * Returns: + * Nothing + */ +PNMI_STATIC void QueueRlmtNewMacTrap( +SK_AC *pAC, /* Pointer to adapter context */ +unsigned int ActiveMac) /* Index (0..n) of the currently active port */ +{ + char *pBuf; + SK_U32 Val32; + + + pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, + SK_PNMI_TRAP_RLMT_CHANGE_LEN); + + Val32 = OID_SKGE_RLMT_PORT_ACTIVE; + SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); + *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; + *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; +} + +/***************************************************************************** + * + * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer + * + * Description: + * Nothing further to explain. + * + * Returns: + * Nothing + */ +PNMI_STATIC void QueueRlmtPortTrap( +SK_AC *pAC, /* Pointer to adapter context */ +SK_U32 TrapId, /* Type of RLMT port trap */ +unsigned int PortIndex) /* Index of the port, which changed its state */ +{ + char *pBuf; + SK_U32 Val32; + + + pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); + + Val32 = OID_SKGE_RLMT_PORT_INDEX; + SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); + *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; + *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; +} + +/***************************************************************************** + * + * CopyMac - Copies a MAC address + * + * Description: + * Nothing further to explain. + * + * Returns: + * Nothing + */ +PNMI_STATIC void CopyMac( +char *pDst, /* Pointer to destination buffer */ +SK_MAC_ADDR *pMac) /* Pointer of Source */ +{ + int i; + + + for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { + + *(pDst + i) = pMac->a[i]; + } +} + + +#ifdef SK_POWER_MGMT +/***************************************************************************** + * + * PowerManagement - OID handler function of PowerManagement OIDs + * + * Description: + * The code is simple. No description necessary. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ + +PNMI_STATIC int PowerManagement( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +{ + + SK_U32 RetCode = SK_PNMI_ERR_GENERAL; + + /* + * Check instance. We only handle single instance variables + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* + * Perform action + */ + if (Action == SK_PNMI_GET) { + + /* + * Check length + */ + switch (Id) { + + case OID_PNP_CAPABILITIES: + if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { + + *pLen = sizeof(SK_PNP_CAPABILITIES); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_PNP_QUERY_POWER: + case OID_PNP_ENABLE_WAKE_UP: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_PNP_SET_POWER: + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, + SK_PNMI_ERR040MSG); + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Get value + */ + switch (Id) { + + case OID_PNP_CAPABILITIES: + RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); + break; + + case OID_PNP_QUERY_POWER: + /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests + the miniport to indicate whether it can transition its NIC + to the low-power state. + A miniport driver must always return NDIS_STATUS_SUCCESS + to a query of OID_PNP_QUERY_POWER. */ + RetCode = SK_PNMI_ERR_OK; + break; + + /* NDIS handles these OIDs as write-only. + * So in case of get action the buffer with written length = 0 + * is returned + */ + case OID_PNP_SET_POWER: + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + *pLen = 0; + RetCode = SK_PNMI_ERR_OK; + break; + + case OID_PNP_ENABLE_WAKE_UP: + RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); + break; + + default: + RetCode = SK_PNMI_ERR_GENERAL; + break; + } + + return (RetCode); + } + + /* + * From here SET or PRESET action. Check if the passed + * buffer length is plausible. + */ + switch (Id) { + case OID_PNP_SET_POWER: + case OID_PNP_ENABLE_WAKE_UP: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + if (*pLen != sizeof(SK_U32)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + break; + + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { + + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_READ_ONLY); + } + + /* + * Perform preset or set + */ + + /* POWER module does not support PRESET action */ + if (Action == SK_PNMI_PRESET) { + return (SK_PNMI_ERR_OK); + } + + switch (Id) { + case OID_PNP_SET_POWER: + RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); + break; + + case OID_PNP_ADD_WAKE_UP_PATTERN: + RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); + break; + + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); + break; + + case OID_PNP_ENABLE_WAKE_UP: + RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); + break; + + default: + RetCode = SK_PNMI_ERR_GENERAL; + } + + return (RetCode); +} +#endif /* SK_POWER_MGMT */ + + +/***************************************************************************** + * + * Vct - OID handler function of OIDs + * + * Description: + * The code is simple. No description necessary. + * + * Returns: + * SK_PNMI_ERR_OK The request was performed successfully. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter). + * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. + * + */ + +PNMI_STATIC int Vct( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* Get/PreSet/Set action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer to which the mgmt data will be copied */ +unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ +{ + SK_GEPORT *pPrt; + SK_PNMI_VCT *pVctBackupData; + SK_U32 LogPortMax; + SK_U32 PhysPortMax; + SK_U32 PhysPortIndex; + SK_U32 Limit; + SK_U32 Offset; + SK_BOOL Link; + SK_U32 RetCode = SK_PNMI_ERR_GENERAL; + int i; + SK_EVPARA Para; + SK_U32 CableLength; + + /* + * Calculate the port indexes from the instance. + */ + PhysPortMax = pAC->GIni.GIMacsFound; + LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); + + /* Dual net mode? */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + LogPortMax--; + } + + if ((Instance != (SK_U32) (-1))) { + /* Check instance range. */ + if ((Instance < 2) || (Instance > LogPortMax)) { + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + PhysPortIndex = NetIndex; + } + else { + PhysPortIndex = Instance - 2; + } + Limit = PhysPortIndex + 1; + } + else { /* + * Instance == (SK_U32) (-1), get all Instances of that OID. + * + * Not implemented yet. May be used in future releases. + */ + PhysPortIndex = 0; + Limit = PhysPortMax; + } + + pPrt = &pAC->GIni.GP[PhysPortIndex]; + if (pPrt->PHWLinkUp) { + Link = SK_TRUE; + } + else { + Link = SK_FALSE; + } + + /* + * Check MAC type. + */ + if (pPrt->PhyType != SK_PHY_MARV_COPPER) { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* Initialize backup data pointer. */ + pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; + + /* + * Check action type. + */ + if (Action == SK_PNMI_GET) { + /* + * Check length. + */ + switch (Id) { + + case OID_SKGE_VCT_GET: + if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { + *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_SKGE_VCT_STATUS: + if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { + *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Get value. + */ + Offset = 0; + for (; PhysPortIndex < Limit; PhysPortIndex++) { + switch (Id) { + + case OID_SKGE_VCT_GET: + if ((Link == SK_FALSE) && + (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { + RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); + if (RetCode == 0) { + pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; + pAC->Pnmi.VctStatus[PhysPortIndex] |= + (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); + + /* Copy results for later use to PNMI struct. */ + for (i = 0; i < 4; i++) { + if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { + if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { + pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; + } + } + if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { + CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); + } + else { + CableLength = 0; + } + pVctBackupData->PMdiPairLen[i] = CableLength; + pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; + } + + Para.Para32[0] = PhysPortIndex; + Para.Para32[1] = -1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); + SkEventDispatcher(pAC, IoC); + } + else { + ; /* VCT test is running. */ + } + } + + /* Get all results. */ + CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); + Offset += sizeof(SK_U8); + *(pBuf + Offset) = pPrt->PCableLen; + Offset += sizeof(SK_U8); + for (i = 0; i < 4; i++) { + SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); + Offset += sizeof(SK_U32); + } + for (i = 0; i < 4; i++) { + *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; + Offset += sizeof(SK_U8); + } + + RetCode = SK_PNMI_ERR_OK; + break; + + case OID_SKGE_VCT_STATUS: + CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); + Offset += sizeof(SK_U8); + RetCode = SK_PNMI_ERR_OK; + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } /* for */ + *pLen = Offset; + return (RetCode); + + } /* if SK_PNMI_GET */ + + /* + * From here SET or PRESET action. Check if the passed + * buffer length is plausible. + */ + + /* + * Check length. + */ + switch (Id) { + case OID_SKGE_VCT_SET: + if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { + *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + /* + * Perform preset or set. + */ + + /* VCT does not support PRESET action. */ + if (Action == SK_PNMI_PRESET) { + return (SK_PNMI_ERR_OK); + } + + Offset = 0; + for (; PhysPortIndex < Limit; PhysPortIndex++) { + switch (Id) { + case OID_SKGE_VCT_SET: /* Start VCT test. */ + if (Link == SK_FALSE) { + SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); + + RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); + if (RetCode == 0) { /* RetCode: 0 => Start! */ + pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; + pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; + pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; + + /* + * Start VCT timer counter. + */ + SK_MEMSET((char *) &Para, 0, sizeof(Para)); + Para.Para32[0] = PhysPortIndex; + Para.Para32[1] = -1; + SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, + 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); + SK_PNMI_STORE_U32((pBuf + Offset), RetCode); + RetCode = SK_PNMI_ERR_OK; + } + else { /* RetCode: 2 => Running! */ + SK_PNMI_STORE_U32((pBuf + Offset), RetCode); + RetCode = SK_PNMI_ERR_OK; + } + } + else { /* RetCode: 4 => Link! */ + RetCode = 4; + SK_PNMI_STORE_U32((pBuf + Offset), RetCode); + RetCode = SK_PNMI_ERR_OK; + } + Offset += sizeof(SK_U32); + break; + + default: + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } /* for */ + *pLen = Offset; + return (RetCode); + +} /* Vct */ + + +PNMI_STATIC void CheckVctStatus( +SK_AC *pAC, +SK_IOC IoC, +char *pBuf, +SK_U32 Offset, +SK_U32 PhysPortIndex) +{ + SK_GEPORT *pPrt; + SK_PNMI_VCT *pVctData; + SK_U32 RetCode; + SK_U8 LinkSpeedUsed; + + pPrt = &pAC->GIni.GP[PhysPortIndex]; + + pVctData = (SK_PNMI_VCT *) (pBuf + Offset); + pVctData->VctStatus = SK_PNMI_VCT_NONE; + + if (!pPrt->PHWLinkUp) { + + /* Was a VCT test ever made before? */ + if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { + if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { + pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; + } + else { + pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; + } + } + + /* Check VCT test status. */ + RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); + if (RetCode == 2) { /* VCT test is running. */ + pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; + } + else { /* VCT data was copied to pAC here. Check PENDING state. */ + if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { + pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; + } + } + + if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ + pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; + } + } + else { + + /* Was a VCT test ever made before? */ + if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { + pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; + pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; + } + + /* DSP only valid in 100/1000 modes. */ + LinkSpeedUsed = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; + if (LinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { + pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; + } + } + +} /* CheckVctStatus */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c new file mode 100644 index 0000000000..e5a4f7ec10 --- /dev/null +++ b/drivers/net/sk98lin/skgesirq.c @@ -0,0 +1,2417 @@ +/****************************************************************************** + * + * Name: skgesirq.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.83 $ + * Date: $Date: 2003/02/05 15:10:59 $ + * Purpose: Special IRQ module + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skgesirq.c,v $ + * Revision 1.83 2003/02/05 15:10:59 rschmidt + * Fixed setting of PLinkSpeedUsed in SkHWLinkUp() when + * auto-negotiation is disabled. + * Editorial changes. + * + * Revision 1.82 2003/01/29 13:34:33 rschmidt + * Added some typecasts to avoid compiler warnings. + * + * Revision 1.81 2002/12/05 10:49:51 rschmidt + * Fixed missing Link Down Event for fiber (Bug Id #10768) + * Added reading of cable length when link is up + * Removed testing of unused error bits in PHY ISR + * Editorial changes. + * + * Revision 1.80 2002/11/12 17:15:21 rschmidt + * Replaced SkPnmiGetVar() by ...MacStatistic() in SkMacParity(). + * Editorial changes. + * + * Revision 1.79 2002/10/14 15:14:51 rschmidt + * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in + * SkMacParity() depending on GIChipRev (HW-Bug #8). + * Added error messages for GPHY Auto-Negotiation Error and + * FIFO Overflow/Underrun in SkPhyIsrGmac(). + * Editorial changes. + * + * Revision 1.78 2002/10/10 15:54:29 mkarl + * changes for PLinkSpeedUsed + * + * Revision 1.77 2002/09/12 08:58:51 rwahl + * Retrieve counters needed for XMAC errata workarounds directly because + * PNMI returns corrected counter values (e.g. #10620). + * + * Revision 1.76 2002/08/16 15:21:54 rschmidt + * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. + * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. + * Editorial changes. + * + * Revision 1.75 2002/08/12 13:50:47 rschmidt + * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in + * SkMacParity() by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE (HW-Bug #8). + * Added clearing of IS_IRQ_TIST_OV and IS_IRQ_SENSOR in SkGeHwErr(). + * Corrected handling of Link Up and Auto-Negotiation Over for GPHY. + * in SkGePortCheckUpGmac(). + * Editorial changes. + * + * Revision 1.74 2002/08/08 16:17:04 rschmidt + * Added PhyType check for SK_HWEV_SET_ROLE event (copper only) + * Changed Link Up check reading PHY Specific Status (YUKON) + * Editorial changes + * + * Revision 1.73 2002/07/15 18:36:53 rwahl + * Editorial changes. + * + * Revision 1.72 2002/07/15 15:46:26 rschmidt + * Added new event: SK_HWEV_SET_SPEED + * Editorial changes + * + * Revision 1.71 2002/06/10 09:34:19 rschmidt + * Editorial changes + * + * Revision 1.70 2002/06/05 08:29:18 rschmidt + * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). + * Editorial changes. + * + * Revision 1.69 2002/04/25 13:03:49 rschmidt + * Changes for handling YUKON. + * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. + * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), + * SkMacIrqDisable(). + * Added handling for GMAC FIFO in SkMacParity(). + * Replaced all SkXm...() functions with SkMac...() to handle also + * YUKON's GMAC. + * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced + * by functions SkXmPhyRead(), SkXmPhyWrite(). + * Disabling all PHY interrupts moved to SkMacIrqDisable(). + * Added handling for GPHY IRQ in SkGeSirqIsr(). + * Removed status parameter from MAC IRQ handler SkMacIrq(). + * Added SkGePortCheckUpGmac(), SkPhyIsrGmac() for GMAC. + * Editorial changes + * + * Revision 1.68 2002/02/26 15:24:53 rwahl + * Fix: no link with manual configuration (#10673). The previous fix for + * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to + * misconfigured port. It should not occur for the other RLMT modes. + * + * Revision 1.67 2001/11/20 09:19:58 rwahl + * Reworked bugfix #10639 (no dependency to RLMT mode). + * + * Revision 1.66 2001/10/26 07:52:53 afischer + * Port switching bug in `check local link` mode + * + * Revision 1.65 2001/02/23 13:41:51 gklug + * fix: PHYS2INST should be used correctly for Dual Net operation + * chg: do no longer work with older PNMI + * + * Revision 1.64 2001/02/15 11:27:04 rassmann + * Working with RLMT v1 if SK_MAX_NETS undefined. + * + * Revision 1.63 2001/02/06 10:44:23 mkunz + * - NetIndex added to interface functions of pnmi V4 with dual net support + * + * Revision 1.62 2001/01/31 15:31:41 gklug + * fix: problem with autosensing an SR8800 switch + * + * Revision 1.61 2000/11/09 11:30:09 rassmann + * WA: Waiting after releasing reset until BCom chip is accessible. + * + * Revision 1.60 2000/10/18 12:37:48 cgoos + * Reinserted the comment for version 1.56. + * + * Revision 1.59 2000/10/18 12:22:20 cgoos + * Added workaround for half duplex hangup. + * + * Revision 1.58 2000/09/28 13:06:04 gklug + * fix: BCom may NOT be touched if XMAC is in RESET state + * + * Revision 1.57 2000/09/08 12:38:39 cgoos + * Added forgotten variable declaration. + * + * Revision 1.56 2000/09/08 08:12:13 cgoos + * Changed handling of parity errors in SkGeHwErr (correct reset of error). + * + * Revision 1.55 2000/06/19 08:36:25 cgoos + * Changed comment. + * + * Revision 1.54 2000/05/22 08:45:57 malthoff + * Fix: #10523 is valid for all BCom PHYs. + * + * Revision 1.53 2000/05/19 10:20:30 cgoos + * Removed Solaris debug output code. + * + * Revision 1.52 2000/05/19 10:19:37 cgoos + * Added PHY state check in HWLinkDown. + * Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr. + * + * Revision 1.51 2000/05/18 05:56:20 cgoos + * Fixed typo. + * + * Revision 1.50 2000/05/17 12:49:49 malthoff + * Fixes BCom link bugs (#10523). + * + * Revision 1.49 1999/12/17 11:02:50 gklug + * fix: read PHY_STAT of Broadcom chip more often to assure good status + * + * Revision 1.48 1999/12/06 10:01:17 cgoos + * Added SET function for Role. + * + * Revision 1.47 1999/11/22 13:34:24 cgoos + * Changed license header to GPL. + * + * Revision 1.46 1999/09/16 10:30:07 cgoos + * Removed debugging output statement from Linux. + * + * Revision 1.45 1999/09/16 07:32:55 cgoos + * Fixed dual-port copperfield bug (PHY_READ from resetted port). + * Removed some unused variables. + * + * Revision 1.44 1999/08/03 15:25:04 cgoos + * Removed workaround for disabled interrupts in half duplex mode. + * + * Revision 1.43 1999/08/03 14:27:58 cgoos + * Removed SENSE mode code from SkGePortCheckUpBcom. + * + * Revision 1.42 1999/07/26 09:16:54 cgoos + * Added some typecasts to avoid compiler warnings. + * + * Revision 1.41 1999/05/19 07:28:59 cgoos + * Changes for 1000Base-T. + * + * Revision 1.40 1999/04/08 13:59:39 gklug + * fix: problem with 3Com switches endless RESTARTs + * + * Revision 1.39 1999/03/08 10:10:52 gklug + * fix: AutoSensing did switch to next mode even if LiPa indicated offline + * + * Revision 1.38 1999/03/08 09:49:03 gklug + * fix: Bug using pAC instead of IoC, causing AIX problems + * fix: change compare for Linux compiler bug workaround + * + * Revision 1.37 1999/01/28 14:51:33 gklug + * fix: monitor for autosensing and extra RESETS the RX on wire counters + * + * Revision 1.36 1999/01/22 09:19:55 gklug + * fix: Init DupMode and InitPauseMd are now called in RxTxEnable + * + * Revision 1.35 1998/12/11 15:22:59 gklug + * chg: autosensing: check for receive if manual mode was guessed + * chg: simplified workaround for XMAC errata + * chg: wait additional 100 ms before link goes up. + * chg: autoneg timeout to 600 ms + * chg: restart autoneg even if configured to autonegotiation + * + * Revision 1.34 1998/12/10 10:33:14 gklug + * add: more debug messages + * fix: do a new InitPhy if link went down (AutoSensing problem) + * chg: Check for zero shorts if link is NOT up + * chg: reset Port if link goes down + * chg: wait additional 100 ms when link comes up to check shorts + * fix: dummy read extended autoneg status to prevent link going down immediately + * + * Revision 1.33 1998/12/07 12:18:29 gklug + * add: refinement of autosense mode: take into account the autoneg cap of LiPa + * + * Revision 1.32 1998/12/07 07:11:21 gklug + * fix: compiler warning + * + * Revision 1.31 1998/12/02 09:29:05 gklug + * fix: WA XMAC Errata: FCSCt check was not correct. + * fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks. + * fix: Clear Stat : now clears the Prev counters of all known Ports + * + * Revision 1.30 1998/12/01 10:54:15 gklug + * dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too. + * + * Revision 1.29 1998/12/01 10:01:53 gklug + * fix: if MAC IRQ occurs during port down, this will be handled correctly + * + * Revision 1.28 1998/11/26 16:22:11 gklug + * fix: bug in autosense if manual modes are used + * + * Revision 1.27 1998/11/26 15:50:06 gklug + * fix: PNMI needs to set PLinkModeConf + * + * Revision 1.26 1998/11/26 14:51:58 gklug + * add: AutoSensing functionalty + * + * Revision 1.25 1998/11/26 07:34:37 gklug + * fix: Init PrevShorts when restarting port due to Link connection + * + * Revision 1.24 1998/11/25 10:57:32 gklug + * fix: remove unreferenced local vars + * + * Revision 1.23 1998/11/25 08:26:40 gklug + * fix: don't do a RESET on a starting or stopping port + * + * Revision 1.22 1998/11/24 13:29:44 gklug + * add: Workaround for MAC parity errata + * + * Revision 1.21 1998/11/18 15:31:06 gklug + * fix: lint bugs + * + * Revision 1.20 1998/11/18 12:58:54 gklug + * fix: use PNMI query instead of hardware access + * + * Revision 1.19 1998/11/18 12:54:55 gklug + * chg: add new workaround for XMAC Errata + * add: short event counter monitoring on active link too + * + * Revision 1.18 1998/11/13 14:27:41 malthoff + * Bug Fix: Packet Arbiter Timeout was not cleared correctly + * for timeout on TX1 and TX2. + * + * Revision 1.17 1998/11/04 07:01:59 cgoos + * Moved HW link poll sequence. + * Added call to SkXmRxTxEnable. + * + * Revision 1.16 1998/11/03 13:46:03 gklug + * add: functionality of SET_LMODE and SET_FLOW_MODE + * fix: send RLMT LinkDown event when Port stop is given with LinkUp + * + * Revision 1.15 1998/11/03 12:56:47 gklug + * fix: Needs more events + * + * Revision 1.14 1998/10/30 07:36:35 gklug + * rmv: unnecessary code + * + * Revision 1.13 1998/10/29 15:21:57 gklug + * add: Poll link feature for activating HW link + * fix: Deactivate HWLink when Port STOP is given + * + * Revision 1.12 1998/10/28 07:38:57 cgoos + * Checking link status at begin of SkHWLinkUp. + * + * Revision 1.11 1998/10/22 09:46:50 gklug + * fix SysKonnectFileId typo + * + * Revision 1.10 1998/10/14 13:57:47 gklug + * add: Port start/stop event + * + * Revision 1.9 1998/10/14 05:48:29 cgoos + * Added definition for Para. + * + * Revision 1.8 1998/10/14 05:40:09 gklug + * add: Hardware Linkup signal used + * + * Revision 1.7 1998/10/09 06:50:20 malthoff + * Remove ID_sccs by SysKonnectFileId. + * + * Revision 1.6 1998/10/08 09:11:49 gklug + * add: clear IRQ commands + * + * Revision 1.5 1998/10/02 14:27:35 cgoos + * Fixed some typos and wrong event names. + * + * Revision 1.4 1998/10/02 06:24:17 gklug + * add: HW error function + * fix: OUT macros + * + * Revision 1.3 1998/10/01 07:03:00 gklug + * add: ISR for the usual interrupt source register + * + * Revision 1.2 1998/09/03 13:50:33 gklug + * add: function prototypes + * + * Revision 1.1 1998/08/27 11:50:21 gklug + * initial revision + * + * + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +/* + * Special Interrupt handler + * + * The following abstract should show how this module is included + * in the driver path: + * + * In the ISR of the driver the bits for frame transmission complete and + * for receive complete are checked and handled by the driver itself. + * The bits of the slow path mask are checked after that and then the + * entry into the so-called "slow path" is prepared. It is an implementors + * decision whether this is executed directly or just scheduled by + * disabling the mask. In the interrupt service routine some events may be + * generated, so it would be a good idea to call the EventDispatcher + * right after this ISR. + * + * The Interrupt source register of the adapter is NOT read by this module. + * SO if the drivers implementor needs a while loop around the + * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for + * each loop entered. + * + * However, the MAC Interrupt status registers are read in a while loop. + * + */ + +static const char SysKonnectFileId[] = + "$Id: skgesirq.c,v 1.83 2003/02/05 15:10:59 rschmidt Exp $" ; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/skgepnmi.h" /* PNMI Definitions */ +#include "h/skrlmt.h" /* RLMT Definitions */ +#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */ + +/* local function prototypes */ +static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int); +static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int); +static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int); +static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); +static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); +#ifdef OTHER_PHY +static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int); +static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int); +static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); +#endif /* OTHER_PHY */ + +/* + * array of Rx counter from XMAC which are checked + * in AutoSense mode to check whether a link is not able to auto-negotiate. + */ +static const SK_U16 SkGeRxRegs[]= { + XM_RXF_64B, + XM_RXF_127B, + XM_RXF_255B, + XM_RXF_511B, + XM_RXF_1023B, + XM_RXF_MAX_SZ +} ; + +#ifdef __C2MAN__ +/* + * Special IRQ function + * + * General Description: + * + */ +intro() +{} +#endif + +/* Define return codes of SkGePortCheckUp and CheckShort */ +#define SK_HW_PS_NONE 0 /* No action needed */ +#define SK_HW_PS_RESTART 1 /* Restart needed */ +#define SK_HW_PS_LINK 2 /* Link Up actions needed */ + +/****************************************************************************** + * + * SkHWInitDefSense() - Default Autosensing mode initialization + * + * Description: sets the PLinkMode for HWInit + * + * Returns: N/A + */ +static void SkHWInitDefSense( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + pPrt = &pAC->GIni.GP[Port]; + + pPrt->PAutoNegTimeOut = 0; + + if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + pPrt->PLinkMode = pPrt->PLinkModeConf; + return; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("AutoSensing: First mode %d on Port %d\n", + (int)SK_LMODE_AUTOFULL, Port)); + + pPrt->PLinkMode = SK_LMODE_AUTOFULL; + + return; +} /* SkHWInitDefSense */ + + +/****************************************************************************** + * + * SkHWSenseGetNext() - Get Next Autosensing Mode + * + * Description: gets the appropriate next mode + * + * Note: + * + */ +SK_U8 SkHWSenseGetNext( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + pPrt = &pAC->GIni.GP[Port]; + + pPrt->PAutoNegTimeOut = 0; + + if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + /* Leave all as configured */ + return(pPrt->PLinkModeConf); + } + + if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) { + /* Return next mode AUTOBOTH */ + return(SK_LMODE_AUTOBOTH); + } + + /* Return default autofull */ + return(SK_LMODE_AUTOFULL); +} /* SkHWSenseGetNext */ + + +/****************************************************************************** + * + * SkHWSenseSetNext() - Autosensing Set next mode + * + * Description: sets the appropriate next mode + * + * Returns: N/A + */ +void SkHWSenseSetNext( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U8 NewMode) /* New Mode to be written in sense mode */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + pPrt = &pAC->GIni.GP[Port]; + + pPrt->PAutoNegTimeOut = 0; + + if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + return; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("AutoSensing: next mode %d on Port %d\n", + (int)NewMode, Port)); + + pPrt->PLinkMode = NewMode; + + return; +} /* SkHWSenseSetNext */ + + +/****************************************************************************** + * + * SkHWLinkDown() - Link Down handling + * + * Description: handles the hardware link down signal + * + * Returns: N/A + */ +void SkHWLinkDown( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + pPrt = &pAC->GIni.GP[Port]; + + /* Disable all MAC interrupts */ + SkMacIrqDisable(pAC, IoC, Port); + + /* Disable Receiver and Transmitter */ + SkMacRxTxDisable(pAC, IoC, Port); + + /* Init default sense mode */ + SkHWInitDefSense(pAC, IoC, Port); + + if (!pPrt->PHWLinkUp) { + return; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link down Port %d\n", Port)); + + /* Set Link to DOWN */ + pPrt->PHWLinkUp = SK_FALSE; + + /* Reset Port stati */ + pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED; + + /* Re-init Phy especially when the AutoSense default is set now */ + SkMacInitPhy(pAC, IoC, Port, SK_FALSE); + + /* GP0: used for workaround of Rev. C Errata 2 */ + + /* Do NOT signal to RLMT */ + + /* Do NOT start the timer here */ +} /* SkHWLinkDown */ + + +/****************************************************************************** + * + * SkHWLinkUp() - Link Up handling + * + * Description: handles the hardware link up signal + * + * Returns: N/A + */ +void SkHWLinkUp( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PHWLinkUp) { + /* We do NOT need to proceed on active link */ + return; + } + + pPrt->PHWLinkUp = SK_TRUE; + pPrt->PAutoNegFail = SK_FALSE; + pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + + if (pPrt->PLinkMode != SK_LMODE_AUTOHALF && + pPrt->PLinkMode != SK_LMODE_AUTOFULL && + pPrt->PLinkMode != SK_LMODE_AUTOBOTH) { + /* Link is up and no Auto-negotiation should be done */ + + /* Link speed should be the configured one */ + switch (pPrt->PLinkSpeed) { + case SK_LSPEED_AUTO: + /* default is 1000 Mbps */ + case SK_LSPEED_1000MBPS: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + break; + case SK_LSPEED_100MBPS: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; + break; + case SK_LSPEED_10MBPS: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; + break; + } + + /* Set Link Mode Status */ + if (pPrt->PLinkMode == SK_LMODE_FULL) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; + } + else { + pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF; + } + + /* No flow control without auto-negotiation */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + + /* enable Rx/Tx */ + SkMacRxTxEnable(pAC, IoC, Port); + } +} /* SkHWLinkUp */ + + +/****************************************************************************** + * + * SkMacParity() - MAC parity workaround + * + * Description: handles MAC parity errors correctly + * + * Returns: N/A + */ +static void SkMacParity( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index of the port failed */ +{ + SK_EVPARA Para; + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_U32 TxMax; /* TxMax Counter */ + + pPrt = &pAC->GIni.GP[Port]; + + /* Clear IRQ Tx Parity Error */ + if (pAC->GIni.GIGenesis) { + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); + } + else { + /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), + (SK_U8)((pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); + } + + if (pPrt->PCheckPar) { + if (Port == MAC_1) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); + } + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = Port; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + + return; + } + + /* Check whether frames with a size of 1k were sent */ + if (pAC->GIni.GIGenesis) { + /* Snap statistic counters */ + (void)SkXmUpdateStats(pAC, IoC, Port); + + (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); + } + else { + (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); + } + + if (TxMax > 0) { + /* From now on check the parity */ + pPrt->PCheckPar = SK_TRUE; + } +} /* SkMacParity */ + + +/****************************************************************************** + * + * SkGeHwErr() - Hardware Error service routine + * + * Description: handles all HW Error interrupts + * + * Returns: N/A + */ +static void SkGeHwErr( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +SK_U32 HwStatus) /* Interrupt status word */ +{ + SK_EVPARA Para; + SK_U16 Word; + + if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { + /* PCI Errors occured */ + if ((HwStatus & IS_IRQ_STAT) != 0) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); + } + + /* Reset all bits in the PCI STATUS register */ + SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + } + + if (pAC->GIni.GIGenesis) { + if ((HwStatus & IS_NO_STAT_M1) != 0) { + /* Ignore it */ + /* This situation is also indicated in the descriptor */ + SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); + } + + if ((HwStatus & IS_NO_STAT_M2) != 0) { + /* Ignore it */ + /* This situation is also indicated in the descriptor */ + SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); + } + + if ((HwStatus & IS_NO_TIST_M1) != 0) { + /* Ignore it */ + /* This situation is also indicated in the descriptor */ + SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); + } + + if ((HwStatus & IS_NO_TIST_M2) != 0) { + /* Ignore it */ + /* This situation is also indicated in the descriptor */ + SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); + } + } + else { /* YUKON */ + /* This is necessary only for Rx timing measurements */ + if ((HwStatus & IS_IRQ_TIST_OV) != 0) { + /* Clear Time Stamp Timer IRQ */ + SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); + } + + if ((HwStatus & IS_IRQ_SENSOR) != 0) { + /* Clear I2C IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + } + } + + if ((HwStatus & IS_RAM_RD_PAR) != 0) { + SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + } + + if ((HwStatus & IS_RAM_WR_PAR) != 0) { + SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + } + + if ((HwStatus & IS_M1_PAR_ERR) != 0) { + SkMacParity(pAC, IoC, MAC_1); + } + + if ((HwStatus & IS_M2_PAR_ERR) != 0) { + SkMacParity(pAC, IoC, MAC_2); + } + + if ((HwStatus & IS_R1_PAR_ERR) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); + + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); + Para.Para64 = MAC_1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((HwStatus & IS_R2_PAR_ERR) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); + + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); + Para.Para64 = MAC_2; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_2; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } +} /* SkGeHwErr */ + + +/****************************************************************************** + * + * SkGeSirqIsr() - Special Interrupt Service Routine + * + * Description: handles all non data transfer specific interrupts (slow path) + * + * Returns: N/A + */ +void SkGeSirqIsr( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +SK_U32 Istatus) /* Interrupt status word */ +{ + SK_EVPARA Para; + SK_U32 RegVal32; /* Read register value */ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + unsigned Len; + SK_U64 Octets; + SK_U16 PhyInt; + SK_U16 PhyIMsk; + int i; + + if ((Istatus & IS_HW_ERR) != 0) { + /* read the HW Error Interrupt source */ + SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); + + SkGeHwErr(pAC, IoC, RegVal32); + } + + /* + * Packet Timeout interrupts + */ + /* Check whether MACs are correctly initialized */ + if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && + pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { + /* MAC 1 was not initialized but Packet timeout occured */ + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, + SKERR_SIRQ_E004MSG); + } + + if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && + pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { + /* MAC 2 was not initialized but Packet timeout occured */ + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, + SKERR_SIRQ_E005MSG); + } + + if ((Istatus & IS_PA_TO_RX1) != 0) { + /* Means network is filling us up */ + SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, + SKERR_SIRQ_E002MSG); + SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); + } + + if ((Istatus & IS_PA_TO_RX2) != 0) { + /* Means network is filling us up */ + SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, + SKERR_SIRQ_E003MSG); + SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); + } + + if ((Istatus & IS_PA_TO_TX1) != 0) { + + pPrt = &pAC->GIni.GP[0]; + + /* May be a normal situation in a server with a slow network */ + SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); + + /* + * workaround: if in half duplex mode, check for Tx hangup. + * Read number of TX'ed bytes, wait for 10 ms, then compare + * the number with current value. If nothing changed, we assume + * that Tx is hanging and do a FIFO flush (see event routine). + */ + if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && + !pPrt->HalfDupTimerActive) { + /* + * many more pack. arb. timeouts may come in between, + * we ignore those + */ + pPrt->HalfDupTimerActive = SK_TRUE; + + Len = sizeof(SK_U64); + SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, + &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0), + pAC->Rlmt.Port[0].Net->NetNumber); + + pPrt->LastOctets = Octets; + + Para.Para32[0] = 0; + SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, + SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + } + } + + if ((Istatus & IS_PA_TO_TX2) != 0) { + + pPrt = &pAC->GIni.GP[1]; + + /* May be a normal situation in a server with a slow network */ + SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); + + /* workaround: see above */ + if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && + !pPrt->HalfDupTimerActive) { + pPrt->HalfDupTimerActive = SK_TRUE; + + Len = sizeof(SK_U64); + SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, + &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1), + pAC->Rlmt.Port[1].Net->NetNumber); + + pPrt->LastOctets = Octets; + + Para.Para32[0] = 1; + SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, + SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + } + } + + /* Check interrupts of the particular queues */ + if ((Istatus & IS_R1_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, + SKERR_SIRQ_E006MSG); + Para.Para64 = MAC_1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((Istatus & IS_R2_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, + SKERR_SIRQ_E007MSG); + Para.Para64 = MAC_2; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_2; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((Istatus & IS_XS1_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, + SKERR_SIRQ_E008MSG); + Para.Para64 = MAC_1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((Istatus & IS_XA1_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, + SKERR_SIRQ_E009MSG); + Para.Para64 = MAC_1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((Istatus & IS_XS2_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, + SKERR_SIRQ_E010MSG); + Para.Para64 = MAC_2; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_2; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((Istatus & IS_XA2_C) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, + SKERR_SIRQ_E011MSG); + Para.Para64 = MAC_2; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_2; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + /* External reg interrupt */ + if ((Istatus & IS_EXT_REG) != 0) { + /* Test IRQs from PHY */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + pPrt = &pAC->GIni.GP[i]; + + if (pPrt->PState == SK_PRT_RESET) { + continue; + } + + switch (pPrt->PhyType) { + + case SK_PHY_XMAC: + break; + + case SK_PHY_BCOM: + SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); + SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_MASK, &PhyIMsk); + + if ((PhyInt & ~PhyIMsk) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d Bcom Int: 0x%04X Mask: 0x%04X\n", + i, PhyInt, PhyIMsk)); + SkPhyIsrBcom(pAC, IoC, i, PhyInt); + } + break; + + case SK_PHY_MARV_COPPER: + case SK_PHY_MARV_FIBER: + SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); + SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_MASK, &PhyIMsk); + + if ((PhyInt & PhyIMsk) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d Marv Int: 0x%04X Mask: 0x%04X\n", + i, PhyInt, PhyIMsk)); + SkPhyIsrGmac(pAC, IoC, i, PhyInt); + } + break; + +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); + SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_ENAB, &PhyIMsk); + + if ((PhyInt & PhyIMsk) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d Lone Int: %x Mask: %x\n", + i, PhyInt, PhyIMsk)); + SkPhyIsrLone(pAC, IoC, i, PhyInt); + } + break; + case SK_PHY_NAT: + /* todo: National */ + break; +#endif /* OTHER_PHY */ + } + } + } + + /* I2C Ready interrupt */ + if ((Istatus & IS_I2C_READY) != 0) { + SkI2cIsr(pAC, IoC); + } + + if ((Istatus & IS_LNK_SYNC_M1) != 0) { + /* + * We do NOT need the Link Sync interrupt, because it shows + * us only a link going down. + */ + /* clear interrupt */ + SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); + } + + /* Check MAC after link sync counter */ + if ((Istatus & IS_MAC1) != 0) { + /* IRQ from MAC 1 */ + SkMacIrq(pAC, IoC, MAC_1); + } + + if ((Istatus & IS_LNK_SYNC_M2) != 0) { + /* + * We do NOT need the Link Sync interrupt, because it shows + * us only a link going down. + */ + /* clear interrupt */ + SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); + } + + /* Check MAC after link sync counter */ + if ((Istatus & IS_MAC2) != 0) { + /* IRQ from MAC 2 */ + SkMacIrq(pAC, IoC, MAC_2); + } + + /* Timer interrupt (served last) */ + if ((Istatus & IS_TIMINT) != 0) { + SkHwtIsr(pAC, IoC); + } +} /* SkGeSirqIsr */ + + +/****************************************************************************** + * + * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + */ +static int SkGePortCheckShorts( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + SK_U32 Shorts; /* Short Event Counter */ + SK_U32 CheckShorts; /* Check value for Short Event Counter */ + SK_U64 RxCts; /* Rx Counter (packets on network) */ + SK_U32 RxTmp; /* Rx temp. Counter */ + SK_U32 FcsErrCts; /* FCS Error Counter */ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Rtv; /* Return value */ + int i; + + pPrt = &pAC->GIni.GP[Port]; + + /* Default: no action */ + Rtv = SK_HW_PS_NONE; + + (void)SkXmUpdateStats(pAC, IoC, Port); + + /* Extra precaution: check for short Event counter */ + (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); + + /* + * Read Rx counter (packets seen on the network and not necessarily + * really received. + */ + RxCts = 0; + + for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { + (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); + RxCts += (SK_U64)RxTmp; + } + + /* On default: check shorts against zero */ + CheckShorts = 0; + + /* Extra precaution on active links */ + if (pPrt->PHWLinkUp) { + /* Reset Link Restart counter */ + pPrt->PLinkResCt = 0; + pPrt->PAutoNegTOCt = 0; + + /* If link is up check for 2 */ + CheckShorts = 2; + + (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); + + if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && + (pPrt->PLinkMode == SK_LMODE_HALF || + pPrt->PLinkMode == SK_LMODE_FULL)) { + /* + * This is autosensing and we are in the fallback + * manual full/half duplex mode. + */ + if (RxCts == pPrt->PPrevRx) { + /* Nothing received, restart link */ + pPrt->PPrevFcs = FcsErrCts; + pPrt->PPrevShorts = Shorts; + + return(SK_HW_PS_RESTART); + } + else { + pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; + } + } + + if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || + (!(FcsErrCts - pPrt->PPrevFcs))) { + /* + * Note: The compare with zero above has to be done the way shown, + * otherwise the Linux driver will have a problem. + */ + /* + * We received a bunch of frames or no CRC error occured on the + * network -> ok. + */ + pPrt->PPrevRx = RxCts; + pPrt->PPrevFcs = FcsErrCts; + pPrt->PPrevShorts = Shorts; + + return(SK_HW_PS_NONE); + } + + pPrt->PPrevFcs = FcsErrCts; + } + + + if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Short Event Count Restart Port %d \n", Port)); + Rtv = SK_HW_PS_RESTART; + } + + pPrt->PPrevShorts = Shorts; + pPrt->PPrevRx = RxCts; + + return(Rtv); +} /* SkGePortCheckShorts */ + + +/****************************************************************************** + * + * SkGePortCheckUp() - Check if the link is up + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUp( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + switch (pAC->GIni.GP[Port].PhyType) { + case SK_PHY_XMAC: + return(SkGePortCheckUpXmac(pAC, IoC, Port)); + case SK_PHY_BCOM: + return(SkGePortCheckUpBcom(pAC, IoC, Port)); + case SK_PHY_MARV_COPPER: + case SK_PHY_MARV_FIBER: + return(SkGePortCheckUpGmac(pAC, IoC, Port)); +#ifdef OTHER_PHY + case SK_PHY_LONE: + return(SkGePortCheckUpLone(pAC, IoC, Port)); + case SK_PHY_NAT: + return(SkGePortCheckUpNat(pAC, IoC, Port)); +#endif /* OTHER_PHY */ + } + return(SK_HW_PS_NONE); +} /* SkGePortCheckUp */ + + +/****************************************************************************** + * + * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpXmac( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + SK_U32 Shorts; /* Short Event Counter */ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Done; + SK_U32 GpReg; /* General Purpose register value */ + SK_U16 Isrc; /* Interrupt source register */ + SK_U16 IsrcSum; /* Interrupt source register sum */ + SK_U16 LpAb; /* Link Partner Ability */ + SK_U16 ResAb; /* Resolved Ability */ + SK_U16 ExtStat; /* Extended Status Register */ + SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ + SK_U8 NextMode; /* Next AutoSensing Mode */ + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PHWLinkUp) { + if (pPrt->PhyType != SK_PHY_XMAC) { + return(SK_HW_PS_NONE); + } + else { + return(SkGePortCheckShorts(pAC, IoC, Port)); + } + } + + IsrcSum = pPrt->PIsave; + pPrt->PIsave = 0; + + /* Now wait for each port's link */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + AutoNeg = SK_FALSE; + } + else { + AutoNeg = SK_TRUE; + } + + if (pPrt->PLinkBroken) { + /* Link was broken */ + XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); + + if ((GpReg & XM_GP_INP_ASS) == 0) { + /* The Link is in sync */ + XM_IN16(IoC, Port, XM_ISRC, &Isrc); + IsrcSum |= Isrc; + SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); + + if ((Isrc & XM_IS_INP_ASS) == 0) { + /* It has been in sync since last time */ + /* Restart the PORT */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link in sync Restart Port %d\n", Port)); + + (void)SkXmUpdateStats(pAC, IoC, Port); + + /* We now need to reinitialize the PrevShorts counter */ + (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); + pPrt->PPrevShorts = Shorts; + + pPrt->PLinkBroken = SK_FALSE; + + /* + * Link Restart Workaround: + * it may be possible that the other Link side + * restarts its link as well an we detect + * another LinkBroken. To prevent this + * happening we check for a maximum number + * of consecutive restart. If those happens, + * we do NOT restart the active link and + * check whether the link is now o.k. + */ + pPrt->PLinkResCt++; + + pPrt->PAutoNegTimeOut = 0; + + if (pPrt->PLinkResCt < SK_MAX_LRESTART) { + return(SK_HW_PS_RESTART); + } + + pPrt->PLinkResCt = 0; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); + } + else { + pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); + + /* Do nothing more if link is broken */ + return(SK_HW_PS_NONE); + } + } + else { + /* Do nothing more if link is broken */ + return(SK_HW_PS_NONE); + } + + } + else { + /* Link was not broken, check if it is */ + XM_IN16(IoC, Port, XM_ISRC, &Isrc); + IsrcSum |= Isrc; + if ((Isrc & XM_IS_INP_ASS) != 0) { + XM_IN16(IoC, Port, XM_ISRC, &Isrc); + IsrcSum |= Isrc; + if ((Isrc & XM_IS_INP_ASS) != 0) { + XM_IN16(IoC, Port, XM_ISRC, &Isrc); + IsrcSum |= Isrc; + if ((Isrc & XM_IS_INP_ASS) != 0) { + pPrt->PLinkBroken = SK_TRUE; + /* Re-Init Link partner Autoneg flag */ + pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link broken Port %d\n", Port)); + + /* Cable removed-> reinit sense mode */ + SkHWInitDefSense(pAC, IoC, Port); + + return(SK_HW_PS_RESTART); + } + } + } + else { + SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); + if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { + return(SK_HW_PS_RESTART); + } + } + } + + /* + * here we usually can check whether the link is in sync and + * auto-negotiation is done. + */ + XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); + XM_IN16(IoC, Port, XM_ISRC, &Isrc); + IsrcSum |= Isrc; + + SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); + + if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { + if ((GpReg & XM_GP_INP_ASS) == 0) { + /* Save Auto-negotiation Done interrupt only if link is in sync */ + pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); + } +#ifdef DEBUG + if ((pPrt->PIsave & XM_IS_AND) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done rescheduled Port %d\n", Port)); + } +#endif /* DEBUG */ + return(SK_HW_PS_NONE); + } + + if (AutoNeg) { + if ((IsrcSum & XM_IS_AND) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { + /* Get PHY parameters, for debugging only */ + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", + Port, LpAb, ResAb)); + + /* Try next possible mode */ + NextMode = SkHWSenseGetNext(pAC, IoC, Port); + SkHWLinkDown(pAC, IoC, Port); + if (Done == SK_AND_DUP_CAP) { + /* GoTo next mode */ + SkHWSenseSetNext(pAC, IoC, Port, NextMode); + } + + return(SK_HW_PS_RESTART); + } + /* + * Dummy Read extended status to prevent extra link down/ups + * (clear Page Received bit if set) + */ + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); + } + + /* AutoNeg not done, but HW link is up. Check for timeouts */ + pPrt->PAutoNegTimeOut++; + if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { + /* Increase the Timeout counter */ + pPrt->PAutoNegTOCt++; + + /* Timeout occured */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("AutoNeg timeout Port %d\n", Port)); + if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { + /* Set Link manually up */ + SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Set manual full duplex Port %d\n", Port)); + } + + if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg == SK_LIPA_AUTO && + pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { + /* + * This is rather complicated. + * we need to check here whether the LIPA_AUTO + * we saw before is false alert. We saw at one + * switch ( SR8800) that on boot time it sends + * just one auto-neg packet and does no further + * auto-negotiation. + * Solution: we restart the autosensing after + * a few timeouts. + */ + pPrt->PAutoNegTOCt = 0; + pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; + SkHWInitDefSense(pAC, IoC, Port); + } + + /* Do the restart */ + return(SK_HW_PS_RESTART); + } + } + else { + /* Link is up and we don't need more */ +#ifdef DEBUG + if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("ERROR: Lipa auto detected on port %d\n", Port)); + } +#endif /* DEBUG */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link sync(GP), Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + + /* + * Link sync (GP) and so assume a good connection. But if not received + * a bunch of frames received in a time slot (maybe broken tx cable) + * the port is restart. + */ + return(SK_HW_PS_LINK); + } + + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpXmac */ + + +/****************************************************************************** + * + * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpBcom( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Done; + SK_U16 Isrc; /* Interrupt source register */ + SK_U16 PhyStat; /* Phy Status Register */ + SK_U16 ResAb; /* Master/Slave resolution */ + SK_U16 Ctrl; /* Broadcom control flags */ +#ifdef DEBUG + SK_U16 LpAb; + SK_U16 ExtStat; +#endif /* DEBUG */ + SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ + + pPrt = &pAC->GIni.GP[Port]; + + /* Check for No HCD Link events (#10523) */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); + +#ifdef xDEBUG + if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) == + (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { + + SK_U32 Stat1, Stat2, Stat3; + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "CheckUp1 - Stat: %x, Mask: %x", + (void *)Isrc, + (void *)Stat1); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); + Stat1 = Stat1 << 16 | Stat2; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); + Stat2 = Stat2 << 16 | Stat3; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "Ctrl/Stat: %x, AN Adv/LP: %x", + (void *)Stat1, + (void *)Stat2); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); + Stat1 = Stat1 << 16 | Stat2; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); + Stat2 = Stat2 << 16 | Stat3; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", + (void *)Stat1, + (void *)Stat2); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); + Stat1 = Stat1 << 16 | Stat2; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); + Stat2 = Stat2 << 16 | Stat3; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", + (void *)Stat1, + (void *)Stat2); + } +#endif /* DEBUG */ + + if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { + /* + * Workaround BCom Errata: + * enable and disable loopback mode if "NO HCD" occurs. + */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, + (SK_U16)(Ctrl | PHY_CT_LOOP)); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, + (SK_U16)(Ctrl & ~PHY_CT_LOOP)); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("No HCD Link event, Port %d\n", Port)); +#ifdef xDEBUG + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "No HCD link event, port %d.", + (void *)Port, + (void *)NULL); +#endif /* DEBUG */ + } + + /* Not obsolete: link status bit is latched to 0 and autoclearing! */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); + + if (pPrt->PHWLinkUp) { + return(SK_HW_PS_NONE); + } + +#ifdef xDEBUG + { + SK_U32 Stat1, Stat2, Stat3; + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "CheckUp1a - Stat: %x, Mask: %x", + (void *)Isrc, + (void *)Stat1); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); + Stat1 = Stat1 << 16 | PhyStat; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); + Stat2 = Stat2 << 16 | Stat3; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "Ctrl/Stat: %x, AN Adv/LP: %x", + (void *)Stat1, + (void *)Stat2); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); + Stat1 = Stat1 << 16 | Stat2; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); + Stat2 = Stat2 << 16 | ResAb; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", + (void *)Stat1, + (void *)Stat2); + + Stat1 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); + Stat1 = Stat1 << 16 | Stat2; + Stat2 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); + Stat3 = 0; + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); + Stat2 = Stat2 << 16 | Stat3; + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", + (void *)Stat1, + (void *)Stat2); + } +#endif /* DEBUG */ + + /* Now wait for each port's link */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + AutoNeg = SK_FALSE; + } + else { + AutoNeg = SK_TRUE; + } + + /* + * Here we usually can check whether the link is in sync and + * auto-negotiation is done. + */ + + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); + + SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); + + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); + + if ((ResAb & PHY_B_1000S_MSF) != 0) { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Master/Slave Fault port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + + return(SK_HW_PS_RESTART); + } + + if ((PhyStat & PHY_ST_LSYNC) == 0) { + return(SK_HW_PS_NONE); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); + + if (AutoNeg) { + if ((PhyStat & PHY_ST_AN_OVER) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { +#ifdef DEBUG + /* Get PHY parameters, for debugging only */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", + Port, LpAb, ExtStat)); +#endif /* DEBUG */ + return(SK_HW_PS_RESTART); + } + else { +#ifdef xDEBUG + /* Dummy read ISR to prevent extra link downs/ups */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); + + if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "CheckUp2 - Stat: %x", + (void *)ExtStat, + (void *)NULL); + } +#endif /* DEBUG */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); + } + } + } + else { /* !AutoNeg */ + /* Link is up and we don't need more. */ +#ifdef DEBUG + if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("ERROR: Lipa auto detected on port %d\n", Port)); + } +#endif /* DEBUG */ + +#ifdef xDEBUG + /* Dummy read ISR to prevent extra link downs/ups */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); + + if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { + CMSMPrintString( + pAC->pConfigTable, + MSG_TYPE_RUNTIME_INFO, + "CheckUp3 - Stat: %x", + (void *)ExtStat, + (void *)NULL); + } +#endif /* DEBUG */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link sync(GP), Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + return(SK_HW_PS_LINK); + } + + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpBcom */ + + +/****************************************************************************** + * + * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpGmac( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Done; + SK_U16 Isrc; /* Interrupt source */ + SK_U16 PhyStat; /* Phy Status */ + SK_U16 PhySpecStat;/* Phy Specific Status */ + SK_U16 ResAb; /* Master/Slave resolution */ + SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ + + pPrt = &pAC->GIni.GP[Port]; + + /* Read PHY Interrupt Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &Isrc); + + if ((Isrc & PHY_M_IS_AN_COMPL) != 0) { + /* TBD */ + } + + if ((Isrc & PHY_M_IS_DOWNSH_DET) != 0) { + /* TBD */ + } + + if (pPrt->PHWLinkUp) { + return(SK_HW_PS_NONE); + } + + /* Now wait for each port's link */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + AutoNeg = SK_FALSE; + } + else { + AutoNeg = SK_TRUE; + } + + /* Read PHY Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); + + SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); + + if ((ResAb & PHY_B_1000S_MSF) != 0) { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Master/Slave Fault port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + + return(SK_HW_PS_RESTART); + } + + /* Read PHY Specific Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg: %d, PhySpecStat: 0x%04x\n", AutoNeg, PhySpecStat)); + + if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { + return(SK_HW_PS_NONE); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; + + pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); + + if (AutoNeg) { + /* Auto-Negotiation Over ? */ + if ((PhyStat & PHY_ST_AN_OVER) != 0) { + + SkHWLinkUp(pAC, IoC, Port); + + Done = SkMacAutoNegDone(pAC, IoC, Port); + + if (Done != SK_AND_OK) { + return(SK_HW_PS_RESTART); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); + } + } + else { /* !AutoNeg */ + /* Link is up and we don't need more */ +#ifdef DEBUG + if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("ERROR: Lipa auto detected on port %d\n", Port)); + } +#endif /* DEBUG */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link sync, Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + + return(SK_HW_PS_LINK); + } + + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpGmac */ + + +#ifdef OTHER_PHY +/****************************************************************************** + * + * SkGePortCheckUpLone() - Check if the link is up on Level One PHY + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpLone( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Done; + SK_U16 Isrc; /* Interrupt source register */ + SK_U16 LpAb; /* Link Partner Ability */ + SK_U16 ExtStat; /* Extended Status Register */ + SK_U16 PhyStat; /* Phy Status Register */ + SK_U16 StatSum; + SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ + SK_U8 NextMode; /* Next AutoSensing Mode */ + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PHWLinkUp) { + return(SK_HW_PS_NONE); + } + + StatSum = pPrt->PIsave; + pPrt->PIsave = 0; + + /* Now wait for each ports link */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + AutoNeg = SK_FALSE; + } + else { + AutoNeg = SK_TRUE; + } + + /* + * here we usually can check whether the link is in sync and + * auto-negotiation is done. + */ + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); + StatSum |= PhyStat; + + SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); + + if ((PhyStat & PHY_ST_LSYNC) == 0) { + /* Save Auto-negotiation Done bit */ + pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); +#ifdef DEBUG + if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done rescheduled Port %d\n", Port)); + } +#endif /* DEBUG */ + return(SK_HW_PS_NONE); + } + + if (AutoNeg) { + if ((StatSum & PHY_ST_AN_OVER) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { + /* Get PHY parameters, for debugging only */ + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", + Port, LpAb, ExtStat)); + + /* Try next possible mode */ + NextMode = SkHWSenseGetNext(pAC, IoC, Port); + SkHWLinkDown(pAC, IoC, Port); + if (Done == SK_AND_DUP_CAP) { + /* GoTo next mode */ + SkHWSenseSetNext(pAC, IoC, Port, NextMode); + } + + return(SK_HW_PS_RESTART); + + } + else { + /* + * Dummy Read interrupt status to prevent + * extra link down/ups + */ + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); + } + } + + /* AutoNeg not done, but HW link is up. Check for timeouts */ + pPrt->PAutoNegTimeOut++; + if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { + /* Timeout occured */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("AutoNeg timeout Port %d\n", Port)); + if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { + /* Set Link manually up */ + SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Set manual full duplex Port %d\n", Port)); + } + + /* Do the restart */ + return(SK_HW_PS_RESTART); + } + } + else { + /* Link is up and we don't need more */ +#ifdef DEBUG + if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("ERROR: Lipa auto detected on port %d\n", Port)); + } +#endif /* DEBUG */ + + /* + * Dummy Read interrupt status to prevent + * extra link down/ups + */ + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link sync(GP), Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + return(SK_HW_PS_LINK); + } + + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpLone */ + + +/****************************************************************************** + * + * SkGePortCheckUpNat() - Check if the link is up on National PHY + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpNat( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO Context */ +int Port) /* Which port should be checked */ +{ + /* todo: National */ + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpNat */ +#endif /* OTHER_PHY */ + + +/****************************************************************************** + * + * SkGeSirqEvent() - Event Service Routine + * + * Description: + * + * Notes: + */ +int SkGeSirqEvent( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* Io Context */ +SK_U32 Event, /* Module specific Event */ +SK_EVPARA Para) /* Event specific Parameter */ +{ + SK_U64 Octets; + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_U32 Port; + SK_U32 Time; + unsigned Len; + int PortStat; + SK_U8 Val8; + + Port = Para.Para32[0]; + pPrt = &pAC->GIni.GP[Port]; + + switch (Event) { + case SK_HWEV_WATIM: + /* Check whether port came up */ + PortStat = SkGePortCheckUp(pAC, IoC, Port); + + switch (PortStat) { + case SK_HW_PS_RESTART: + if (pPrt->PHWLinkUp) { + /* + * Set Link to down. + */ + SkHWLinkDown(pAC, IoC, Port); + + /* + * Signal directly to RLMT to ensure correct + * sequence of SWITCH and RESET event. + */ + SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); + } + + /* Restart needed */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); + break; + + case SK_HW_PS_LINK: + /* Signal to RLMT */ + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); + break; + + } + + /* Start again the check Timer */ + if (pPrt->PHWLinkUp) { + Time = SK_WA_ACT_TIME; + } + else { + Time = SK_WA_INA_TIME; + } + + /* Todo: still needed for non-XMAC PHYs??? */ + /* Start workaround Errata #2 timer */ + SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Time, + SKGE_HWAC, SK_HWEV_WATIM, Para); + break; + + case SK_HWEV_PORT_START: + if (pPrt->PHWLinkUp) { + /* + * Signal directly to RLMT to ensure correct + * sequence of SWITCH and RESET event. + */ + SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); + } + + SkHWLinkDown(pAC, IoC, Port); + + /* Schedule Port RESET */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); + + /* Start workaround Errata #2 timer */ + SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, + SKGE_HWAC, SK_HWEV_WATIM, Para); + break; + + case SK_HWEV_PORT_STOP: + if (pPrt->PHWLinkUp) { + /* + * Signal directly to RLMT to ensure correct + * sequence of SWITCH and RESET event. + */ + SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); + } + + /* Stop Workaround Timer */ + SkTimerStop(pAC, IoC, &pPrt->PWaTimer); + + SkHWLinkDown(pAC, IoC, Port); + break; + + case SK_HWEV_UPDATE_STAT: + /* We do NOT need to update any statistics */ + break; + + case SK_HWEV_CLEAR_STAT: + /* We do NOT need to clear any statistics */ + for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { + pPrt->PPrevRx = 0; + pPrt->PPrevFcs = 0; + pPrt->PPrevShorts = 0; + } + break; + + case SK_HWEV_SET_LMODE: + Val8 = (SK_U8)Para.Para32[1]; + if (pPrt->PLinkModeConf != Val8) { + /* Set New link mode */ + pPrt->PLinkModeConf = Val8; + + /* Restart Port */ + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); + } + break; + + case SK_HWEV_SET_FLOWMODE: + Val8 = (SK_U8)Para.Para32[1]; + if (pPrt->PFlowCtrlMode != Val8) { + /* Set New Flow Control mode */ + pPrt->PFlowCtrlMode = Val8; + + /* Restart Port */ + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); + } + break; + + case SK_HWEV_SET_ROLE: + /* not possible for fiber */ + if (!pAC->GIni.GICopperType) { + break; + } + Val8 = (SK_U8)Para.Para32[1]; + if (pPrt->PMSMode != Val8) { + /* Set New link mode */ + pPrt->PMSMode = Val8; + + /* Restart Port */ + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); + } + break; + + case SK_HWEV_SET_SPEED: + if (pPrt->PhyType != SK_PHY_MARV_COPPER) { + break; + } + Val8 = (SK_U8)Para.Para32[1]; + if (pPrt->PLinkSpeed != Val8) { + /* Set New Speed parameter */ + pPrt->PLinkSpeed = Val8; + + /* Restart Port */ + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); + } + break; + + case SK_HWEV_HALFDUP_CHK: + /* + * half duplex hangup workaround. + * See packet arbiter timeout interrupt for description + */ + pPrt->HalfDupTimerActive = SK_FALSE; + if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { + + Len = sizeof(SK_U64); + SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, + &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), + pAC->Rlmt.Port[Port].Net->NetNumber); + + if (pPrt->LastOctets == Octets) { + /* Tx hanging, a FIFO flush restarts it */ + SkMacFlushTxFifo(pAC, IoC, Port); + } + } + break; + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); + break; + } + + return(0); +} /* SkGeSirqEvent */ + + +/****************************************************************************** + * + * SkPhyIsrBcom() - PHY interrupt service routine + * + * Description: handles all interrupts from BCom PHY + * + * Returns: N/A + */ +static void SkPhyIsrBcom( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* Io Context */ +int Port, /* Port Num = PHY Num */ +SK_U16 IStatus) /* Interrupt Status */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_EVPARA Para; + + pPrt = &pAC->GIni.GP[Port]; + + if ((IStatus & PHY_B_IS_PSE) != 0) { + /* Incorrectable pair swap error */ + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022, + SKERR_SIRQ_E022MSG); + } + + if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { + Para.Para32[0] = (SK_U32)Port; + + SkHWLinkDown(pAC, IoC, Port); + + /* Signal to RLMT */ + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + + /* Start workaround Errata #2 timer */ + SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, + SKGE_HWAC, SK_HWEV_WATIM, Para); + } + +} /* SkPhyIsrBcom */ + + +/****************************************************************************** + * + * SkPhyIsrGmac() - PHY interrupt service routine + * + * Description: handles all interrupts from Marvell PHY + * + * Returns: N/A + */ +static void SkPhyIsrGmac( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* Io Context */ +int Port, /* Port Num = PHY Num */ +SK_U16 IStatus) /* Interrupt Status */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_EVPARA Para; + + pPrt = &pAC->GIni.GP[Port]; + + if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { + Para.Para32[0] = (SK_U32)Port; + + SkHWLinkDown(pAC, IoC, Port); + + /* Signal to RLMT */ + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + + if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { + /* Auto-Negotiation Error */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); + } + + if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) { + /* TBD */ + } + + if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { + /* FIFO Overflow/Underrun Error */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); + } +} /* SkPhyIsrGmac */ + + +#ifdef OTHER_PHY +/****************************************************************************** + * + * SkPhyIsrLone() - PHY interrupt service routine + * + * Description: handles all interrupts from LONE PHY + * + * Returns: N/A + */ +static void SkPhyIsrLone( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* Io Context */ +int Port, /* Port Num = PHY Num */ +SK_U16 IStatus) /* Interrupt Status */ +{ + SK_EVPARA Para; + + if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { + SkHWLinkDown(pAC, IoC, Port); + + /* Signal to RLMT */ + Para.Para32[0] = (SK_U32)Port; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + +} /* SkPhyIsrLone */ +#endif /* OTHER_PHY */ + +#endif /* CONFIG_SK98 */ + +/* End of File */ diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c new file mode 100644 index 0000000000..2ab635a229 --- /dev/null +++ b/drivers/net/sk98lin/ski2c.c @@ -0,0 +1,1505 @@ +/****************************************************************************** + * + * Name: ski2c.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.57 $ + * Date: $Date: 2003/01/28 09:17:38 $ + * Purpose: Functions to access Voltage and Temperature Sensor + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: ski2c.c,v $ + * Revision 1.57 2003/01/28 09:17:38 rschmidt + * Fixed handling for sensors on YUKON Fiber. + * Editorial changes. + * + * Revision 1.56 2002/12/19 14:20:41 rschmidt + * Added debugging code in SkI2cWait(). + * Replaced all I2C-write operations with function SkI2cWrite(). + * Fixed compiler warning because of uninitialized 'Time' in SkI2cEvent(). + * Editorial changes. + * + * Revision 1.55 2002/10/15 07:23:55 rschmidt + * Added setting of the GIYukon32Bit bool variable to distinguish + * 32-bit adapters. + * Editorial changes (TWSI). + * + * Revision 1.54 2002/08/13 09:05:06 rschmidt + * Added new thresholds if VAUX is not available (GIVauxAvail). + * Merged defines for PHY PLL 3V3 voltage (A and B). + * Editorial changes. + * + * Revision 1.53 2002/08/08 11:04:53 rwahl + * Added missing comment for revision 1.51 + * + * Revision 1.52 2002/08/08 10:09:02 jschmalz + * Sensor init state caused wrong error log entry + * + * Revision 1.51 2002/08/06 09:43:03 jschmalz + * Extensions and changes for Yukon + * + * Revision 1.50 2002/08/02 12:09:22 rschmidt + * Added support for YUKON sensors. + * Editorial changes. + * + * Revision 1.49 2002/07/30 11:07:52 rschmidt + * Replaced MaxSens init by update for Copper in SkI2cInit1(), + * because it was already initialized in SkI2cInit0(). + * Editorial changes. + * + * Revision 1.48 2001/08/16 12:44:33 afischer + * LM80 sensor init values corrected + * + * Revision 1.47 2001/04/05 11:38:09 rassmann + * Set SenState to idle in SkI2cWaitIrq(). + * Changed error message in SkI2cWaitIrq(). + * + * Revision 1.46 2001/04/02 14:03:35 rassmann + * Changed pAC to IoC in SK_IN32(). + * + * Revision 1.45 2001/03/21 12:12:49 rassmann + * Resetting I2C_READY interrupt in SkI2cInit1(). + * + * Revision 1.44 2000/08/07 15:49:03 gklug + * Fix: SK_INFAST only in NetWare driver. + * + * Revision 1.43 2000/08/03 14:28:17 rassmann + * Added function to wait for I2C being ready before resetting the board. + * Replaced one duplicate "out of range" message with correct one. + * + * Revision 1.42 1999/11/22 13:35:12 cgoos + * Changed license header to GPL. + * + * Revision 1.41 1999/09/14 14:11:30 malthoff + * The 1000BT Dual Link adapter has got only one Fan. + * The second Fan has been removed. + * + * Revision 1.40 1999/05/27 13:37:27 malthoff + * Set divisor of 1 for fan count calculation. + * + * Revision 1.39 1999/05/20 14:54:43 malthoff + * I2c.DummyReads is not used in Diagnostics. + * + * Revision 1.38 1999/05/20 09:20:56 cgoos + * Changes for 1000Base-T (up to 9 sensors and fans). + * + * Revision 1.37 1999/03/25 15:11:36 gklug + * fix: reset error flag if sensor reads correct value + * + * Revision 1.36 1999/01/07 14:11:16 gklug + * fix: break added + * + * Revision 1.35 1999/01/05 15:31:49 gklug + * fix: CLEAR STAT command is now added correctly + * + * Revision 1.34 1998/12/01 13:45:16 gklug + * fix: introduced Init level, because we don't need reinits + * + * Revision 1.33 1998/11/09 14:54:25 malthoff + * Modify I2C Transfer Timeout handling for Diagnostics. + * + * Revision 1.32 1998/11/03 06:54:35 gklug + * fix: Need dummy reads at the beginning to init sensors + * + * Revision 1.31 1998/11/03 06:42:42 gklug + * fix: select correctVIO range only if between warning levels + * + * Revision 1.30 1998/11/02 07:36:53 gklug + * fix: Error should not include WARNING message + * + * Revision 1.29 1998/10/30 15:07:43 malthoff + * Disable 'I2C does not compelete' error log for diagnostics. + * + * Revision 1.28 1998/10/22 09:48:11 gklug + * fix: SysKonnectFileId typo + * + * Revision 1.27 1998/10/20 09:59:46 gklug + * add: parameter to SkOsGetTime + * + * Revision 1.26 1998/10/09 06:10:59 malthoff + * Remove ID_sccs by SysKonnectFileId. + * + * Revision 1.25 1998/09/08 12:40:26 gklug + * fix: syntax error in if clause + * + * Revision 1.24 1998/09/08 12:19:42 gklug + * chg: INIT Level checking + * + * Revision 1.23 1998/09/08 07:37:20 gklug + * fix: log error if PCI_IO voltage sensor could not be initialized + * + * Revision 1.22 1998/09/04 08:30:03 malthoff + * Bugfixes during SK_DIAG testing: + * - correct NS2BCLK() macro + * - correct SkI2cSndDev() + * - correct SkI2cWait() loop waiting for an event + * + * Revision 1.21 1998/08/27 14:46:01 gklug + * chg: if-then-else replaced by switch + * + * Revision 1.20 1998/08/27 14:40:07 gklug + * test: integral types + * + * Revision 1.19 1998/08/25 07:51:54 gklug + * fix: typos for compiling + * + * Revision 1.18 1998/08/25 06:12:24 gklug + * add: count errors and warnings + * fix: check not the sensor state but the ErrFlag! + * + * Revision 1.17 1998/08/25 05:56:48 gklug + * add: CheckSensor function + * + * Revision 1.16 1998/08/20 11:41:10 gklug + * chg: omit STRCPY macro by using char * as Sensor Description + * + * Revision 1.15 1998/08/20 11:37:35 gklug + * chg: change Ioc to IoC + * + * Revision 1.14 1998/08/20 11:32:52 gklug + * fix: Para compile error + * + * Revision 1.13 1998/08/20 11:27:41 gklug + * fix: Compile bugs with new awrning constants + * + * Revision 1.12 1998/08/20 08:53:05 gklug + * fix: compiler errors + * add: Threshold values + * + * Revision 1.11 1998/08/19 12:39:22 malthoff + * Compiler Fix: Some names have changed. + * + * Revision 1.10 1998/08/19 12:20:56 gklug + * fix: remove struct from C files (see CCC) + * + * Revision 1.9 1998/08/19 06:28:46 malthoff + * SkOsGetTime returns SK_U64 now. + * + * Revision 1.8 1998/08/17 13:53:33 gklug + * fix: Parameter of event function and its result + * + * Revision 1.7 1998/08/17 07:02:15 malthoff + * Modify the functions for accessing the I2C SW Registers. + * Modify SkI2cWait(). + * Put Lm80RcvReg into sklm80.c + * Remove Compiler Errors. + * + * Revision 1.6 1998/08/14 07:13:20 malthoff + * remove pAc with pAC + * remove smc with pAC + * change names to new convention + * + * Revision 1.5 1998/08/14 06:24:49 gklug + * add: init level 1 and 2 + * + * Revision 1.4 1998/08/12 14:31:12 gklug + * add: error log for unknown event + * + * Revision 1.3 1998/08/12 13:37:04 gklug + * add: Init 0 function + * + * Revision 1.2 1998/08/11 07:27:15 gklug + * add: functions of the interface + * adapt rest of source to C coding Conventions + * rmv: unnecessary code taken from Mona Lisa + * + * Revision 1.1 1998/06/19 14:28:43 malthoff + * Created. Sources taken from ML Projekt. + * Sources have to be reworked for GE. + * + * + ******************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +/* + * I2C Protocol + */ +static const char SysKonnectFileId[] = + "$Id: ski2c.c,v 1.57 2003/01/28 09:17:38 rschmidt Exp $"; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/lm80.h" +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef __C2MAN__ +/* + I2C protocol implementation. + + General Description: + + The I2C protocol is used for the temperature sensors and for + the serial EEPROM which hold the configuration. + + This file covers functions that allow to read write and do + some bulk requests a specified I2C address. + + The Genesis has 2 I2C buses. One for the EEPROM which holds + the VPD Data and one for temperature and voltage sensor. + The following picture shows the I2C buses, I2C devices and + their control registers. + + Note: The VPD functions are in skvpd.c +. +. PCI Config I2C Bus for VPD Data: +. +. +------------+ +. | VPD EEPROM | +. +------------+ +. | +. | <-- I2C +. | +. +-----------+-----------+ +. | | +. +-----------------+ +-----------------+ +. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | +. +-----------------+ +-----------------+ +. +. +. I2C Bus for LM80 sensor: +. +. +-----------------+ +. | Temperature and | +. | Voltage Sensor | +. | LM80 | +. +-----------------+ +. | +. | +. I2C --> | +. | +. +----+ +. +-------------->| OR |<--+ +. | +----+ | +. +------+------+ | +. | | | +. +--------+ +--------+ +----------+ +. | B2_I2C | | B2_I2C | | B2_I2C | +. | _CTRL | | _DATA | | _SW | +. +--------+ +--------+ +----------+ +. + The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL + and B2_I2C_DATA registers. + For driver software it is recommended to use the I2C control and + data register, because I2C bus timing is done by the ASIC and + an interrupt may be received when the I2C request is completed. + + Clock Rate Timing: MIN MAX generated by + VPD EEPROM: 50 kHz 100 kHz HW + LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW + LM80 over B2_I2C_SW register 0 400 kHz SW + + Note: The clock generated by the hardware is dependend on the + PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD + clock is 50 kHz. + */ +intro() +{} +#endif + +#ifdef SK_DIAG +/* + * I2C Fast Mode timing values used by the LM80. + * If new devices are added to the I2C bus the timing values have to be checked. + */ +#ifndef I2C_SLOW_TIMING +#define T_CLK_LOW 1300L /* clock low time in ns */ +#define T_CLK_HIGH 600L /* clock high time in ns */ +#define T_DATA_IN_SETUP 100L /* data in Set-up Time */ +#define T_START_HOLD 600L /* start condition hold time */ +#define T_START_SETUP 600L /* start condition Set-up time */ +#define T_STOP_SETUP 600L /* stop condition Set-up time */ +#define T_BUS_IDLE 1300L /* time the bus must free after Tx */ +#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ +#else /* I2C_SLOW_TIMING */ +/* I2C Standard Mode Timing */ +#define T_CLK_LOW 4700L /* clock low time in ns */ +#define T_CLK_HIGH 4000L /* clock high time in ns */ +#define T_DATA_IN_SETUP 250L /* data in Set-up Time */ +#define T_START_HOLD 4000L /* start condition hold time */ +#define T_START_SETUP 4700L /* start condition Set-up time */ +#define T_STOP_SETUP 4000L /* stop condition Set-up time */ +#define T_BUS_IDLE 4700L /* time the bus must free after Tx */ +#endif /* !I2C_SLOW_TIMING */ + +#define NS2BCLK(x) (((x)*125)/10000) + +/* + * I2C Wire Operations + * + * About I2C_CLK_LOW(): + * + * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting + * clock to low, to prevent the ASIC and the I2C data client from driving the + * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client + * send an 'ACK'). See also Concentrator Bugreport No. 10192. + */ +#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) +#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) +#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) +#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) +#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) +#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) +#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) + +#define NS2CLKT(x) ((x*125L)/10000) + +/*--------------- I2C Interface Register Functions --------------- */ + +/* + * sending one bit + */ +void SkI2cSndBit( +SK_IOC IoC, /* I/O Context */ +SK_U8 Bit) /* Bit to send */ +{ + I2C_DATA_OUT(IoC); + if (Bit) { + I2C_DATA_HIGH(IoC); + } + else { + I2C_DATA_LOW(IoC); + } + SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); + I2C_CLK_HIGH(IoC); + SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); + I2C_CLK_LOW(IoC); +} /* SkI2cSndBit*/ + + +/* + * Signal a start to the I2C Bus. + * + * A start is signaled when data goes to low in a high clock cycle. + * + * Ends with Clock Low. + * + * Status: not tested + */ +void SkI2cStart( +SK_IOC IoC) /* I/O Context */ +{ + /* Init data and Clock to output lines */ + /* Set Data high */ + I2C_DATA_OUT(IoC); + I2C_DATA_HIGH(IoC); + /* Set Clock high */ + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); + + /* Set Data Low */ + I2C_DATA_LOW(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); + + /* Clock low without Data to Input */ + I2C_START_COND(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); +} /* SkI2cStart */ + + +void SkI2cStop( +SK_IOC IoC) /* I/O Context */ +{ + /* Init data and Clock to output lines */ + /* Set Data low */ + I2C_DATA_OUT(IoC); + I2C_DATA_LOW(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); + + /* Set Clock high */ + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); + + /* + * Set Data High: Do it by setting the Data Line to Input. + * Because of a pull up resistor the Data Line + * floods to high. + */ + I2C_DATA_IN(IoC); + + /* + * When I2C activity is stopped + * o DATA should be set to input and + * o CLOCK should be set to high! + */ + SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); +} /* SkI2cStop */ + + +/* + * Receive just one bit via the I2C bus. + * + * Note: Clock must be set to LOW before calling this function. + * + * Returns The received bit. + */ +int SkI2cRcvBit( +SK_IOC IoC) /* I/O Context */ +{ + int Bit; + SK_U8 I2cSwCtrl; + + /* Init data as input line */ + I2C_DATA_IN(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); + + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); + + SK_I2C_GET_SW(IoC, &I2cSwCtrl); + + Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; + + I2C_CLK_LOW(IoC); + SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); + + return(Bit); +} /* SkI2cRcvBit */ + + +/* + * Receive an ACK. + * + * returns 0 If acknowledged + * 1 in case of an error + */ +int SkI2cRcvAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + */ + return(SkI2cRcvBit(IoC) != 0); +} /* SkI2cRcvAck */ + + +/* + * Send an NACK. + */ +void SkI2cSndNAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + */ + SkI2cSndBit(IoC, 1); +} /* SkI2cSndNAck */ + + +/* + * Send an ACK. + */ +void SkI2cSndAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + * + */ + SkI2cSndBit(IoC, 0); +} /* SkI2cSndAck */ + + +/* + * Send one byte to the I2C device and wait for ACK. + * + * Return acknowleged status. + */ +int SkI2cSndByte( +SK_IOC IoC, /* I/O Context */ +int Byte) /* byte to send */ +{ + int i; + + for (i = 0; i < 8; i++) { + if (Byte & (1<<(7-i))) { + SkI2cSndBit(IoC, 1); + } + else { + SkI2cSndBit(IoC, 0); + } + } + + return(SkI2cRcvAck(IoC)); +} /* SkI2cSndByte */ + + +/* + * Receive one byte and ack it. + * + * Return byte. + */ +int SkI2cRcvByte( +SK_IOC IoC, /* I/O Context */ +int Last) /* Last Byte Flag */ +{ + int i; + int Byte = 0; + + for (i = 0; i < 8; i++) { + Byte <<= 1; + Byte |= SkI2cRcvBit(IoC); + } + + if (Last) { + SkI2cSndNAck(IoC); + } + else { + SkI2cSndAck(IoC); + } + + return(Byte); +} /* SkI2cRcvByte */ + + +/* + * Start dialog and send device address + * + * Return 0 if acknowleged, 1 in case of an error + */ +int SkI2cSndDev( +SK_IOC IoC, /* I/O Context */ +int Addr, /* Device Address */ +int Rw) /* Read / Write Flag */ +{ + SkI2cStart(IoC); + Rw = ~Rw; + Rw &= I2C_WRITE; + return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); +} /* SkI2cSndDev */ + +#endif /* SK_DIAG */ + +/*----------------- I2C CTRL Register Functions ----------*/ + +/* + * waits for a completion of an I2C transfer + * + * returns 0: success, transfer completes + * 1: error, transfer does not complete, I2C transfer + * killed, wait loop terminated. + */ +int SkI2cWait( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ +{ + SK_U64 StartTime; + SK_U64 CurrentTime; + SK_U32 I2cCtrl; + + StartTime = SkOsGetTime(pAC); + + do { + CurrentTime = SkOsGetTime(pAC); + + if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { + + SK_I2C_STOP(IoC); +#ifndef SK_DIAG + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); +#endif /* !SK_DIAG */ + return(1); + } + + SK_I2C_GET_CTL(IoC, &I2cCtrl); + +#ifdef xYUKON_DBG + printf("StartTime=%lu, CurrentTime=%lu\n", + StartTime, CurrentTime); + if (kbhit()) { + return(1); + } +#endif /* YUKON_DBG */ + + } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); + + return(0); +} /* SkI2cWait */ + + +/* + * waits for a completion of an I2C transfer + * + * Returns + * Nothing + */ +void SkI2cWaitIrq( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + SK_SENSOR *pSen; + SK_U64 StartTime; + SK_U32 IrqSrc; + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + + if (pSen->SenState == SK_SEN_IDLE) { + return; + } + + StartTime = SkOsGetTime(pAC); + do { + if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { + SK_I2C_STOP(IoC); +#ifndef SK_DIAG + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); +#endif /* !SK_DIAG */ + return; + } + SK_IN32(IoC, B0_ISRC, &IrqSrc); + } while ((IrqSrc & IS_I2C_READY) == 0); + + pSen->SenState = SK_SEN_IDLE; + return; +} /* SkI2cWaitIrq */ + +/* + * writes a single byte or 4 bytes into the I2C device + * + * returns 0: success + * 1: error + */ +int SkI2cWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 I2cData, /* I2C Data to write */ +int I2cDev, /* I2C Device Address */ +int I2cReg, /* I2C Device Register Address */ +int I2cBurst) /* I2C Burst Flag */ +{ + SK_OUT32(IoC, B2_I2C_DATA, I2cData); + SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cReg, I2cBurst); + + return(SkI2cWait(pAC, IoC, I2C_WRITE)); +} /* SkI2cWrite*/ + + +#ifdef SK_DIAG + +/* + * reads a single byte or 4 bytes from the I2C device + * + * returns the word read + */ +SK_U32 SkI2cRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int I2cDev, /* I2C Device Address */ +int I2cReg, /* I2C Device Register Address */ +int I2cBurst) /* I2C Burst Flag */ +{ + SK_U32 Data; + + SK_OUT32(IoC, B2_I2C_DATA, 0); + SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cReg, I2cBurst); + + if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { + w_print("%s\n", SKERR_I2C_E002MSG); + } + + SK_IN32(IoC, B2_I2C_DATA, &Data); + return(Data); +} /* SkI2cRead */ + +#endif /* SK_DIAG */ + + +/* + * read a sensor's value + * + * This function reads a sensor's value from the I2C sensor chip. The sensor + * is defined by its index into the sensors database in the struct pAC points + * to. + * Returns + * 1 if the read is completed + * 0 if the read must be continued (I2C Bus still allocated) + */ +int SkI2cReadSensor( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_SENSOR *pSen) /* Sensor to be read */ +{ + if (pSen->SenRead != NULL) { + return((*pSen->SenRead)(pAC, IoC, pSen)); + } + else + return(0); /* no success */ +} /* SkI2cReadSensor*/ + +/* + * Do the Init state 0 initialization + */ +static int SkI2cInit0( +SK_AC *pAC) /* Adapter Context */ +{ + int i; + + /* Begin with first sensor */ + pAC->I2c.CurrSens = 0; + + /* Begin with timeout control for state machine */ + pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; + + /* Set sensor number to zero */ + pAC->I2c.MaxSens = 0; + +#ifndef SK_DIAG + /* Initialize Number of Dummy Reads */ + pAC->I2c.DummyReads = SK_MAX_SENSORS; +#endif + + for (i = 0; i < SK_MAX_SENSORS; i++) { + pAC->I2c.SenTable[i].SenDesc = "unknown"; + pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN; + pAC->I2c.SenTable[i].SenThreErrHigh = 0; + pAC->I2c.SenTable[i].SenThreErrLow = 0; + pAC->I2c.SenTable[i].SenThreWarnHigh = 0; + pAC->I2c.SenTable[i].SenThreWarnLow = 0; + pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; + pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE; + pAC->I2c.SenTable[i].SenValue = 0; + pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT; + pAC->I2c.SenTable[i].SenErrCts = 0; + pAC->I2c.SenTable[i].SenBegErrTS = 0; + pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; + pAC->I2c.SenTable[i].SenRead = NULL; + pAC->I2c.SenTable[i].SenDev = 0; + } + + /* Now we are "INIT data"ed */ + pAC->I2c.InitLevel = SK_INIT_DATA; + return(0); +} /* SkI2cInit0*/ + + +/* + * Do the init state 1 initialization + * + * initialize the following register of the LM80: + * Configuration register: + * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT + * + * Interrupt Mask Register 1: + * - all interrupts are Disabled (0xff) + * + * Interrupt Mask Register 2: + * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. + * + * Fan Divisor/RST_OUT register: + * - Divisors set to 1 (bits 00), all others 0s. + * + * OS# Configuration/Temperature resolution Register: + * - all 0s + * + */ +static int SkI2cInit1( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + int i; + SK_U8 I2cSwCtrl; + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + + if (pAC->I2c.InitLevel != SK_INIT_DATA) { + /* ReInit not needed in I2C module */ + return(0); + } + + /* Set the Direction of I2C-Data Pin to IN */ + SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); + /* Check for 32-Bit Yukon with Low at I2C-Data Pin */ + SK_I2C_GET_SW(IoC, &I2cSwCtrl); + + if ((I2cSwCtrl & I2C_DATA) == 0) { + /* this is a 32-Bit board */ + pAC->GIni.GIYukon32Bit = SK_TRUE; + return(0); + } + + /* Check for 64 Bit Yukon without sensors */ + if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_CFG, 0) != 0) { + return(0); + } + + (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_1, 0); + + (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_2, 0); + + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_FAN_CTRL, 0); + + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_TEMP_CTRL, 0); + + (void)SkI2cWrite(pAC, IoC, LM80_CFG_START, LM80_ADDR, LM80_CFG, 0); + + /* + * MaxSens has to be updated here, because PhyType is not + * set when performing Init Level 0 + */ + pAC->I2c.MaxSens = 5; + + pPrt = &pAC->GIni.GP[0]; + + if (pAC->GIni.GIGenesis) { + if (pPrt->PhyType == SK_PHY_BCOM) { + if (pAC->GIni.GIMacsFound == 1) { + pAC->I2c.MaxSens += 1; + } + else { + pAC->I2c.MaxSens += 3; + } + } + } + else { + pAC->I2c.MaxSens += 3; + } + + for (i = 0; i < pAC->I2c.MaxSens; i++) { + switch (i) { + case 0: + pAC->I2c.SenTable[i].SenDesc = "Temperature"; + pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN; + break; + case 1: + pAC->I2c.SenTable[i].SenDesc = "Voltage PCI"; + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN; + break; + case 2: + pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO"; + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN; + pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO; + break; + case 3: + pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC"; + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN; + break; + case 4: + if (pAC->GIni.GIGenesis) { + if (pPrt->PhyType == SK_PHY_BCOM) { + pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL"; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + } + else { + pAC->I2c.SenTable[i].SenDesc = "Voltage PMA"; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + } + } + else { + pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX"; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; + if (pAC->GIni.GIVauxAvail) { + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; + } + else { + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR; + } + } + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN; + break; + case 5: + if (pAC->GIni.GIGenesis) { + pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; + } + else { + pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC-Co 1V5"; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; + } + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN; + break; + case 6: + if (pAC->GIni.GIGenesis) { + pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL"; + } + else { + pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3"; + } + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN; + break; + case 7: + if (pAC->GIni.GIGenesis) { + pAC->I2c.SenTable[i].SenDesc = "Speed Fan"; + pAC->I2c.SenTable[i].SenType = SK_SEN_FAN; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; + } + else { + pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; + pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; + pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; + pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; + pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; + pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; + pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN; + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, + SKERR_I2C_E001, SKERR_I2C_E001MSG); + break; + } + + pAC->I2c.SenTable[i].SenValue = 0; + pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; + pAC->I2c.SenTable[i].SenErrCts = 0; + pAC->I2c.SenTable[i].SenBegErrTS = 0; + pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; + pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor; + pAC->I2c.SenTable[i].SenDev = LM80_ADDR; + } + +#ifndef SK_DIAG + pAC->I2c.DummyReads = pAC->I2c.MaxSens; +#endif /* !SK_DIAG */ + + /* Clear I2C IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + + /* Now we are I/O initialized */ + pAC->I2c.InitLevel = SK_INIT_IO; + return(0); +} /* SkI2cInit1 */ + + +/* + * Init level 2: Start first sensor read. + */ +static int SkI2cInit2( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + int ReadComplete; + SK_SENSOR *pSen; + + if (pAC->I2c.InitLevel != SK_INIT_IO) { + /* ReInit not needed in I2C module */ + /* Init0 and Init2 not permitted */ + return(0); + } + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); + } + + /* Now we are correctly initialized */ + pAC->I2c.InitLevel = SK_INIT_RUN; + + return(0); +} /* SkI2cInit2*/ + + +/* + * Initialize I2C devices + * + * Get the first voltage value and discard it. + * Go into temperature read mode. A default pointer is not set. + * + * The things to be done depend on the init level in the parameter list: + * Level 0: + * Initialize only the data structures. Do NOT access hardware. + * Level 1: + * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. + * Level 2: + * Everything is possible. Interrupts may be used from now on. + * + * return: + * 0 = success + * other = error. + */ +int SkI2cInit( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ +int Level) /* Init Level */ +{ + + switch (Level) { + case SK_INIT_DATA: + return(SkI2cInit0(pAC)); + case SK_INIT_IO: + return(SkI2cInit1(pAC, IoC)); + case SK_INIT_RUN: + return(SkI2cInit2(pAC, IoC)); + default: + break; + } + + return(0); +} /* SkI2cInit */ + + +#ifndef SK_DIAG + +/* + * Interrupt service function for the I2C Interface + * + * Clears the Interrupt source + * + * Reads the register and check it for sending a trap. + * + * Starts the timer if necessary. + */ +void SkI2cIsr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + SK_EVPARA Para; + + /* Clear I2C IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); +} /* SkI2cIsr */ + + +/* + * Check this sensors Value against the threshold and send events. + */ +static void SkI2cCheckSensor( +SK_AC *pAC, /* Adapter Context */ +SK_SENSOR *pSen) +{ + SK_EVPARA ParaLocal; + SK_BOOL TooHigh; /* Is sensor too high? */ + SK_BOOL TooLow; /* Is sensor too low? */ + SK_U64 CurrTime; /* Current Time */ + SK_BOOL DoTrapSend; /* We need to send a trap */ + SK_BOOL DoErrLog; /* We need to log the error */ + SK_BOOL IsError; /* We need to log the error */ + + /* Check Dummy Reads first */ + if (pAC->I2c.DummyReads > 0) { + pAC->I2c.DummyReads--; + return; + } + + /* Get the current time */ + CurrTime = SkOsGetTime(pAC); + + /* Set para to the most useful setting: The current sensor. */ + ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; + + /* Check the Value against the thresholds. First: Error Thresholds */ + TooHigh = (pSen->SenValue > pSen->SenThreErrHigh); + TooLow = (pSen->SenValue < pSen->SenThreErrLow); + + IsError = SK_FALSE; + if (TooHigh || TooLow) { + /* Error condition is satisfied */ + DoTrapSend = SK_TRUE; + DoErrLog = SK_TRUE; + + /* Now error condition is satisfied */ + IsError = SK_TRUE; + + if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { + /* This state is the former one */ + + /* So check first whether we have to send a trap */ + if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > + CurrTime) { + /* + * Do NOT send the Trap. The hold back time + * has to run out first. + */ + DoTrapSend = SK_FALSE; + } + + /* Check now whether we have to log an Error */ + if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > + CurrTime) { + /* + * Do NOT log the error. The hold back time + * has to run out first. + */ + DoErrLog = SK_FALSE; + } + } + else { + /* We came from a different state -> Set Begin Time Stamp */ + pSen->SenBegErrTS = CurrTime; + pSen->SenErrFlag = SK_SEN_ERR_ERR; + } + + if (DoTrapSend) { + /* Set current Time */ + pSen->SenLastErrTrapTS = CurrTime; + pSen->SenErrCts++; + + /* Queue PNMI Event */ + SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? + SK_PNMI_EVT_SEN_ERR_UPP : + SK_PNMI_EVT_SEN_ERR_LOW), + ParaLocal); + } + + if (DoErrLog) { + /* Set current Time */ + pSen->SenLastErrLogTS = CurrTime; + + if (pSen->SenType == SK_SEN_TEMP) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, + SKERR_I2C_E011MSG); + } else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, + SKERR_I2C_E012MSG); + } else + { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, + SKERR_I2C_E015MSG); + } + } + } + + /* Check the Value against the thresholds */ + /* 2nd: Warning thresholds */ + TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh); + TooLow = (pSen->SenValue < pSen->SenThreWarnLow); + + if (!IsError && (TooHigh || TooLow)) { + /* Error condition is satisfied */ + DoTrapSend = SK_TRUE; + DoErrLog = SK_TRUE; + + if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { + /* This state is the former one */ + + /* So check first whether we have to send a trap */ + if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > + CurrTime) { + /* + * Do NOT send the Trap. The hold back time + * has to run out first. + */ + DoTrapSend = SK_FALSE; + } + + /* Check now whether we have to log an Error */ + if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > + CurrTime) { + /* + * Do NOT log the error. The hold back time + * has to run out first. + */ + DoErrLog = SK_FALSE; + } + } + else { + /* We came from a different state -> Set Begin Time Stamp */ + pSen->SenBegWarnTS = CurrTime; + pSen->SenErrFlag = SK_SEN_ERR_WARN; + } + + if (DoTrapSend) { + /* Set current Time */ + pSen->SenLastWarnTrapTS = CurrTime; + pSen->SenWarnCts++; + + /* Queue PNMI Event */ + SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? + SK_PNMI_EVT_SEN_WAR_UPP : + SK_PNMI_EVT_SEN_WAR_LOW), + ParaLocal); + } + + if (DoErrLog) { + /* Set current Time */ + pSen->SenLastWarnLogTS = CurrTime; + + if (pSen->SenType == SK_SEN_TEMP) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, + SKERR_I2C_E009MSG); + } else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, + SKERR_I2C_E010MSG); + } else + { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, + SKERR_I2C_E014MSG); + } + } + } + + /* Check for NO error at all */ + if (!IsError && !TooHigh && !TooLow) { + /* Set o.k. Status if no error and no warning condition */ + pSen->SenErrFlag = SK_SEN_ERR_OK; + } + + /* End of check against the thresholds */ + + /* Bug fix AF: 16.Aug.2001: Correct the init base + * of LM80 sensor. + */ + if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { + + pSen->SenInit = SK_SEN_DYN_INIT_NONE; + + if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { + /* 5V PCI-IO Voltage */ + pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; + } + else { + /* 3.3V PCI-IO Voltage */ + pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; + pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; + } + } + +#if 0 + /* Dynamic thresholds also for VAUX of LM80 sensor */ + if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { + + pSen->SenInit = SK_SEN_DYN_INIT_NONE; + + /* 3.3V VAUX Voltage */ + if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { + pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; + } + /* 0V VAUX Voltage */ + else { + pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; + pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; + } + } + + /* + * Check initialization state: + * The VIO Thresholds need adaption + */ + if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && + pSen->SenValue > SK_SEN_WARNLOW2C && + pSen->SenValue < SK_SEN_WARNHIGH2) { + pSen->SenThreErrLow = SK_SEN_ERRLOW2C; + pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; + pSen->SenInit = SK_TRUE; + } + + if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && + pSen->SenValue > SK_SEN_WARNLOW2 && + pSen->SenValue < SK_SEN_WARNHIGH2C) { + pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; + pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; + pSen->SenInit = SK_TRUE; + } +#endif + + if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); + } +} /* SkI2cCheckSensor*/ + + +/* + * The only Event to be served is the timeout event + * + */ +int SkI2cEvent( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Event, /* Module specific Event */ +SK_EVPARA Para) /* Event specific Parameter */ +{ + int ReadComplete; + SK_SENSOR *pSen; + SK_U32 Time; + SK_EVPARA ParaLocal; + int i; + + /* New case: no sensors */ + if (pAC->I2c.MaxSens == 0) { + return(0); + } + + switch (Event) { + case SK_I2CEV_IRQ: + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + /* Check sensor against defined thresholds */ + SkI2cCheckSensor (pAC, pSen); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + else { + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + break; + case SK_I2CEV_TIM: + if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { + + ParaLocal.Para64 = (SK_U64)0; + SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + /* Check sensor against defined thresholds */ + SkI2cCheckSensor (pAC, pSen); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + } + else { + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + pSen->SenErrFlag = SK_SEN_ERR_FAULTY; + SK_I2C_STOP(IoC); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + break; + case SK_I2CEV_CLEAR: + for (i = 0; i < SK_MAX_SENSORS; i++) { + pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; + pAC->I2c.SenTable[i].SenErrCts = 0; + pAC->I2c.SenTable[i].SenWarnCts = 0; + pAC->I2c.SenTable[i].SenBegErrTS = 0; + pAC->I2c.SenTable[i].SenBegWarnTS = 0; + pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0; + pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0; + pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0; + pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0; + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); + } + + return(0); +} /* SkI2cEvent*/ + +#endif /* !SK_DIAG */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c new file mode 100644 index 0000000000..687572b1d2 --- /dev/null +++ b/drivers/net/sk98lin/sklm80.c @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * Name: sklm80.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.20 $ + * Date: $Date: 2002/08/13 09:16:27 $ + * Purpose: Funktions to access Voltage and Temperature Sensor (LM80) + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sklm80.c,v $ + * Revision 1.20 2002/08/13 09:16:27 rschmidt + * Changed return value for SkLm80ReadSensor() back to 'int' + * Editorial changes + * + * Revision 1.19 2002/08/06 09:43:31 jschmalz + * Extensions and changes for Yukon + * + * Revision 1.18 2002/08/02 12:26:57 rschmidt + * Editorial changes + * + * Revision 1.17 1999/11/22 13:35:51 cgoos + * Changed license header to GPL. + * + * Revision 1.16 1999/05/27 14:05:47 malthoff + * Fans: Set SenVal to 0 if the fan value is 0 or 0xff. Both values + * are outside the limits (0: div zero error, 0xff: value not in + * range, assume 0). + * + * Revision 1.15 1999/05/27 13:38:51 malthoff + * Pervent from Division by zero errors. + * + * Revision 1.14 1999/05/20 09:20:01 cgoos + * Changes for 1000Base-T (Fan sensors). + * + * Revision 1.13 1998/10/22 09:48:14 gklug + * fix: SysKonnectFileId typo + * + * Revision 1.12 1998/10/09 06:12:06 malthoff + * Remove ID_sccs by SysKonnectFileId. + * + * Revision 1.11 1998/09/04 08:33:48 malthoff + * bug fix: SenState = SK_SEN_IDLE when + * leaving SK_SEN_VALEXT state + * + * Revision 1.10 1998/08/20 12:02:10 gklug + * fix: compiler warnings type mismatch + * + * Revision 1.9 1998/08/20 11:37:38 gklug + * chg: change Ioc to IoC + * + * Revision 1.8 1998/08/19 12:20:58 gklug + * fix: remove struct from C files (see CCC) + * + * Revision 1.7 1998/08/17 07:04:57 malthoff + * Take SkLm80RcvReg() function from ski2c.c. + * Add IoC parameter to BREAK_OR_WAIT() macro. + * + * Revision 1.6 1998/08/14 07:11:28 malthoff + * remove pAc with pAC. + * + * Revision 1.5 1998/08/14 06:46:55 gklug + * fix: temperature can get negative + * + * Revision 1.4 1998/08/13 08:27:04 gklug + * add: temperature reading now o.k. + * fix: pSen declaration, SK_ERR_LOG call, ADDR macro + * + * Revision 1.3 1998/08/13 07:28:21 gklug + * fix: pSen was wrong initialized + * add: correct conversion for voltage readings + * + * Revision 1.2 1998/08/11 07:52:14 gklug + * add: Lm80 read sensor function + * + * Revision 1.1 1998/07/17 09:57:12 gklug + * initial version + * + * + * + ******************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +/* + LM80 functions +*/ +static const char SysKonnectFileId[] = + "$Id: sklm80.c,v 1.20 2002/08/13 09:16:27 rschmidt Exp $" ; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/lm80.h" +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef SK_DIAG +#define BREAK_OR_WAIT(pAC,IoC,Event) SkI2cWait(pAC,IoC,Event) +#else /* nSK_DIAG */ +#define BREAK_OR_WAIT(pAC,IoC,Event) break +#endif /* nSK_DIAG */ + +#ifdef SK_DIAG +/* + * read the register 'Reg' from the device 'Dev' + * + * return read error -1 + * success the read value + */ +int SkLm80RcvReg( +SK_IOC IoC, /* Adapter Context */ +int Dev, /* I2C device address */ +int Reg) /* register to read */ +{ + int Val = 0; + int TempExt; + + /* Signal device number */ + if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) { + return(-1); + } + + if (SkI2cSndByte(IoC, Reg)) { + return(-1); + } + + /* repeat start */ + if (SkI2cSndDev(IoC, Dev, I2C_READ)) { + return(-1); + } + + switch (Reg) { + case LM80_TEMP_IN: + Val = (int)SkI2cRcvByte(IoC, 1); + + /* First: correct the value: it might be negative */ + if ((Val & 0x80) != 0) { + /* Value is negative */ + Val = Val - 256; + } + Val = Val * SK_LM80_TEMP_LSB; + SkI2cStop(IoC); + + TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL); + + if (Val > 0) { + Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); + } + else { + Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); + } + return(Val); + break; + case LM80_VT0_IN: + case LM80_VT1_IN: + case LM80_VT2_IN: + case LM80_VT3_IN: + Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB; + break; + + default: + Val = (int)SkI2cRcvByte(IoC, 1); + break; + } + + SkI2cStop(IoC); + return(Val); +} +#endif /* SK_DIAG */ + +/* + * read a sensors value (LM80 specific) + * + * This function reads a sensors value from the I2C sensor chip LM80. + * The sensor is defined by its index into the sensors database in the struct + * pAC points to. + * + * Returns 1 if the read is completed + * 0 if the read must be continued (I2C Bus still allocated) + */ +int SkLm80ReadSensor( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context needed in level 1 and 2 */ +SK_SENSOR *pSen) /* Sensor to be read */ +{ + SK_I32 Value; + + switch (pSen->SenState) { + case SK_SEN_IDLE: + /* Send address to ADDR register */ + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, pSen->SenReg, 0); + + pSen->SenState = SK_SEN_VALUE ; + BREAK_OR_WAIT(pAC, IoC, I2C_READ); + + case SK_SEN_VALUE: + /* Read value from data register */ + SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); + + Value &= 0xff; /* only least significant byte is valid */ + + /* Do NOT check the Value against the thresholds */ + /* Checking is done in the calling instance */ + + if (pSen->SenType == SK_SEN_VOLT) { + /* Voltage sensor */ + pSen->SenValue = Value * SK_LM80_VT_LSB; + pSen->SenState = SK_SEN_IDLE ; + return(1); + } + + if (pSen->SenType == SK_SEN_FAN) { + if (Value != 0 && Value != 0xff) { + /* Fan speed counter */ + pSen->SenValue = SK_LM80_FAN_FAKTOR/Value; + } + else { + /* Indicate Fan error */ + pSen->SenValue = 0; + } + pSen->SenState = SK_SEN_IDLE ; + return(1); + } + + /* First: correct the value: it might be negative */ + if ((Value & 0x80) != 0) { + /* Value is negative */ + Value = Value - 256; + } + + /* We have a temperature sensor and need to get the signed extension. + * For now we get the extension from the last reading, so in the normal + * case we won't see flickering temperatures. + */ + pSen->SenValue = (Value * SK_LM80_TEMP_LSB) + + (pSen->SenValue % SK_LM80_TEMP_LSB); + + /* Send address to ADDR register */ + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, LM80_TEMP_CTRL, 0); + + pSen->SenState = SK_SEN_VALEXT ; + BREAK_OR_WAIT(pAC, IoC, I2C_READ); + + case SK_SEN_VALEXT: + /* Read value from data register */ + SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); + Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */ + + /* cut the LSB bit */ + pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) * + SK_LM80_TEMP_LSB); + + if (pSen->SenValue < 0) { + /* Value negative: The bit value must be subtracted */ + pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB); + } + else { + /* Value positive: The bit value must be added */ + pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB); + } + + pSen->SenState = SK_SEN_IDLE ; + return(1); + + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); + return(1); + } + + /* Not completed */ + return(0); +} + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c new file mode 100644 index 0000000000..4e340730e5 --- /dev/null +++ b/drivers/net/sk98lin/skproc.c @@ -0,0 +1,515 @@ +/****************************************************************************** + * + * Name: skproc.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.4 $ + * Date: $Date: 2003/02/25 14:16:37 $ + * Purpose: Funktions to display statictic data + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Created 22-Nov-2000 + * Author: Mirko Lindner (mlindner@syskonnect.de) + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ +/****************************************************************************** + * + * History: + * + * $Log: skproc.c,v $ + * Revision 1.4 2003/02/25 14:16:37 mlindner + * Fix: Copyright statement + * + * Revision 1.3 2002/10/02 12:59:51 mlindner + * Add: Support for Yukon + * Add: Speed check and setup + * Add: Merge source for kernel 2.2.x and 2.4.x + * Add: Read sensor names directly from VPD + * Fix: Volt values + * + * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner + * Fix: Editorial changes + * + * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner + * Fix: Return value of proc_read + * + * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner + * New ProcFs entries + * + * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner + * Add: New ProcFs entries + * Fix: Counter Errors (Jumbo == to long errors) + * Fix: Kernel error compilation + * Fix: too short counters + * + * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner + * Add: More error messages + * + * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner + * fix: ProcFS owner protection + * + * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner + * chg: 2.4 requirements for procfs + * + * Revision 1.1 2001/01/22 14:15:31 mlindner + * added ProcFs functionality + * Dual Net functionality integrated + * Rlmt networks added + * + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIALX 32 /* 0x */ +#define LARGE 64 + +extern SK_AC *pACList; +extern struct net_device *SkGeRootDev; + +extern char * SkNumber( + char * str, + long long num, + int base, + int size, + int precision, + int type); + + +/***************************************************************************** + * + * proc_read - print "summaries" entry + * + * Description: + * This function fills the proc entry with statistic data about + * the ethernet device. + * + * + * Returns: buffer with statistic data + * + */ +int proc_read(char *buffer, +char **buffer_location, +off_t offset, +int buffer_length, +int *eof, +void *data) +{ + int len = 0; + int t; + int i; + DEV_NET *pNet; + SK_AC *pAC; + char test_buf[100]; + char sens_msg[50]; + unsigned long Flags; + unsigned int Size; + struct SK_NET_DEVICE *next; + struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; + + SK_PNMI_STRUCT_DATA *pPnmiStruct; + SK_PNMI_STAT *pPnmiStat; + struct proc_dir_entry *file = (struct proc_dir_entry*) data; + + while (SkgeProcDev) { + pNet = (DEV_NET*) SkgeProcDev->priv; + pAC = pNet->pAC; + next = pAC->Next; + pPnmiStruct = &pAC->PnmiStruct; + /* NetIndex in GetStruct is now required, zero is only dummy */ + + for (t=pAC->GIni.GIMacsFound; t > 0; t--) { + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1) + t--; + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + Size = SK_PNMI_STRUCT_SIZE; + SkPnmiGetStruct(pAC, pAC->IoBase, + pPnmiStruct, &Size, t-1); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + if (strcmp(pAC->dev[t-1]->name, file->name) == 0) { + pPnmiStat = &pPnmiStruct->Stat[0]; + len = sprintf(buffer, + "\nDetailed statistic for device %s\n", + pAC->dev[t-1]->name); + len += sprintf(buffer + len, + "=======================================\n"); + + /* Board statistics */ + len += sprintf(buffer + len, + "\nBoard statistics\n\n"); + len += sprintf(buffer + len, + "Active Port %c\n", + 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. + Net[t-1].PrefPort]->PortNumber); + len += sprintf(buffer + len, + "Preferred Port %c\n", + 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. + Net[t-1].PrefPort]->PortNumber); + + len += sprintf(buffer + len, + "Bus speed (MHz) %d\n", + pPnmiStruct->BusSpeed); + + len += sprintf(buffer + len, + "Bus width (Bit) %d\n", + pPnmiStruct->BusWidth); + len += sprintf(buffer + len, + "Hardware revision v%d.%d\n", + (pAC->GIni.GIPciHwRev >> 4) & 0x0F, + pAC->GIni.GIPciHwRev & 0x0F); + + /* Print sensor informations */ + for (i=0; i < pAC->I2c.MaxSens; i ++) { + /* Check type */ + switch (pAC->I2c.SenTable[i].SenType) { + case 1: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (C)"); + len += sprintf(buffer + len, + "%-25s %d.%02d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue / 10, + pAC->I2c.SenTable[i].SenValue % 10); + + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (F)"); + len += sprintf(buffer + len, + "%-25s %d.%02d\n", + sens_msg, + ((((pAC->I2c.SenTable[i].SenValue) + *10)*9)/5 + 3200)/100, + ((((pAC->I2c.SenTable[i].SenValue) + *10)*9)/5 + 3200) % 10); + break; + case 2: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (V)"); + len += sprintf(buffer + len, + "%-25s %d.%03d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue / 1000, + pAC->I2c.SenTable[i].SenValue % 1000); + break; + case 3: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (rpm)"); + len += sprintf(buffer + len, + "%-25s %d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue); + break; + default: + break; + } + } + + /*Receive statistics */ + len += sprintf(buffer + len, + "\nReceive statistics\n\n"); + + len += sprintf(buffer + len, + "Received bytes %s\n", + SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Received packets %s\n", + SkNumber(test_buf, pPnmiStat->StatRxOkCts, + 10,0,-1,0)); +#if 0 + if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && + pAC->HWRevision < 12) { + pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - + pPnmiStat->StatRxShortsCts; + pPnmiStat->StatRxShortsCts = 0; + } +#endif + if (pNet->Mtu > 1500) + pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - + pPnmiStat->StatRxTooLongCts; + + len += sprintf(buffer + len, + "Receive errors %s\n", + SkNumber(test_buf, pPnmiStruct->InErrorsCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Receive drops %s\n", + SkNumber(test_buf, pPnmiStruct->RxNoBufCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Received multicast %s\n", + SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Receive error types\n"); + len += sprintf(buffer + len, + " length %s\n", + SkNumber(test_buf, pPnmiStat->StatRxRuntCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " buffer overflow %s\n", + SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " bad crc %s\n", + SkNumber(test_buf, pPnmiStat->StatRxFcsCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " framing %s\n", + SkNumber(test_buf, pPnmiStat->StatRxFramingCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " missed frames %s\n", + SkNumber(test_buf, pPnmiStat->StatRxMissedCts, + 10, 0, -1, 0)); + + if (pNet->Mtu > 1500) + pPnmiStat->StatRxTooLongCts = 0; + + len += sprintf(buffer + len, + " too long %s\n", + SkNumber(test_buf, pPnmiStat->StatRxTooLongCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " carrier extension %s\n", + SkNumber(test_buf, pPnmiStat->StatRxCextCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " too short %s\n", + SkNumber(test_buf, pPnmiStat->StatRxShortsCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " symbol %s\n", + SkNumber(test_buf, pPnmiStat->StatRxSymbolCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " LLC MAC size %s\n", + SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " carrier event %s\n", + SkNumber(test_buf, pPnmiStat->StatRxCarrierCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " jabber %s\n", + SkNumber(test_buf, pPnmiStat->StatRxJabberCts, + 10, 0, -1, 0)); + + + /*Transmit statistics */ + len += sprintf(buffer + len, + "\nTransmit statistics\n\n"); + + len += sprintf(buffer + len, + "Transmited bytes %s\n", + SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Transmited packets %s\n", + SkNumber(test_buf, pPnmiStat->StatTxOkCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Transmit errors %s\n", + SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Transmit dropped %s\n", + SkNumber(test_buf, pPnmiStruct->TxNoBufCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Transmit collisions %s\n", + SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, + 10,0,-1,0)); + len += sprintf(buffer + len, + "Transmit errors types\n"); + len += sprintf(buffer + len, + " excessive collision %ld\n", + pAC->stats.tx_aborted_errors); + len += sprintf(buffer + len, + " carrier %s\n", + SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " fifo underrun %s\n", + SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " heartbeat %s\n", + SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, + 10, 0, -1, 0)); + len += sprintf(buffer + len, + " window %ld\n", + pAC->stats.tx_window_errors); + + } + } + SkgeProcDev = next; + } + if (offset >= len) { + *eof = 1; + return 0; + } + + *buffer_location = buffer + offset; + if (buffer_length >= len - offset) { + *eof = 1; + } + return (min_t(int, buffer_length, len - offset)); +} + + +/***************************************************************************** + * + * SkDoDiv - convert 64bit number + * + * Description: + * This function "converts" a long long number. + * + * Returns: + * remainder of division + */ +static long SkDoDiv (long long Dividend, int Divisor, long long *pErg) +{ + long Rest; + long long Ergebnis; + long Akku; + + + Akku = Dividend >> 32; + + Ergebnis = ((long long) (Akku / Divisor)) << 32; + Rest = Akku % Divisor ; + + Akku = Rest << 16; + Akku |= ((Dividend & 0xFFFF0000) >> 16); + + + Ergebnis += ((long long) (Akku / Divisor)) << 16; + Rest = Akku % Divisor ; + + Akku = Rest << 16; + Akku |= (Dividend & 0xFFFF); + + Ergebnis += (Akku / Divisor); + Rest = Akku % Divisor ; + + *pErg = Ergebnis; + return (Rest); +} + + +#if 0 +#define do_div(n,base) ({ \ +long long __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + +#endif + + +/***************************************************************************** + * + * SkNumber - Print results + * + * Description: + * This function converts a long long number into a string. + * + * Returns: + * number as string + */ +char * SkNumber(char * str, long long num, int base, int size, int precision + ,int type) +{ + char c,sign,tmp[66], *strorg = str; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIALX) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[SkDoDiv(num,base, &num)]; + + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIALX) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + + str[0] = '\0'; + + return strorg; +} + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c new file mode 100644 index 0000000000..c49baed4f0 --- /dev/null +++ b/drivers/net/sk98lin/skqueue.c @@ -0,0 +1,242 @@ +/****************************************************************************** + * + * Name: skqueue.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.18 $ + * Date: $Date: 2002/05/07 14:11:11 $ + * Purpose: Management of an event queue. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skqueue.c,v $ + * Revision 1.18 2002/05/07 14:11:11 rwahl + * Fixed Watcom Precompiler error. + * + * Revision 1.17 2002/03/25 10:06:41 mkunz + * SkIgnoreEvent deleted + * + * Revision 1.16 2002/03/15 10:51:59 mkunz + * Added event classes for link aggregation + * + * Revision 1.15 1999/11/22 13:36:29 cgoos + * Changed license header to GPL. + * + * Revision 1.14 1998/10/15 15:11:35 gklug + * fix: ID_sccs to SysKonnectFileId + * + * Revision 1.13 1998/09/08 08:47:52 gklug + * add: init level handling + * + * Revision 1.12 1998/09/08 07:43:20 gklug + * fix: Sirq Event function name + * + * Revision 1.11 1998/09/08 05:54:34 gklug + * chg: define SK_CSUM is replaced by SK_USE_CSUM + * + * Revision 1.10 1998/09/03 14:14:49 gklug + * add: CSUM and HWAC Eventclass and function. + * + * Revision 1.9 1998/08/19 09:50:50 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.8 1998/08/17 13:43:11 gklug + * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR + * + * Revision 1.7 1998/08/14 07:09:11 gklug + * fix: chg pAc -> pAC + * + * Revision 1.6 1998/08/11 12:13:14 gklug + * add: return code feature of Event service routines + * add: correct Error log calls + * + * Revision 1.5 1998/08/07 12:53:45 gklug + * fix: first compiled version + * + * Revision 1.4 1998/08/07 09:20:48 gklug + * adapt functions to C coding conventions. + * + * Revision 1.3 1998/08/05 11:29:32 gklug + * rmv: Timer event entry. Timer will queue event directly + * + * Revision 1.2 1998/07/31 11:22:40 gklug + * Initial version + * + * Revision 1.1 1998/07/30 15:14:01 gklug + * Initial version. Adapted from SMT + * + * + * + ******************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +/* + Event queue and dispatcher +*/ +static const char SysKonnectFileId[] = + "$Header: /usr56/projects/ge/schedule/skqueue.c,v 1.18 2002/05/07 14:11:11 rwahl Exp $" ; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/skqueue.h" /* Queue Definitions */ +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef __C2MAN__ +/* + Event queue management. + + General Description: + + */ +intro() +{} +#endif + +#define PRINTF(a,b,c) + +/* + * init event queue management + * + * Must be called during init level 0. + */ +void SkEventInit( +SK_AC *pAC, /* Adapter context */ +SK_IOC Ioc, /* IO context */ +int Level) /* Init level */ +{ + switch (Level) { + case SK_INIT_DATA: + pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue ; + break; + default: + break; + } +} + +/* + * add event to queue + */ +void SkEventQueue( +SK_AC *pAC, /* Adapters context */ +SK_U32 Class, /* Event Class */ +SK_U32 Event, /* Event to be queued */ +SK_EVPARA Para) /* Event parameter */ +{ + pAC->Event.EvPut->Class = Class ; + pAC->Event.EvPut->Event = Event ; + pAC->Event.EvPut->Para = Para ; + if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) + pAC->Event.EvPut = pAC->Event.EvQueue ; + + if (pAC->Event.EvPut == pAC->Event.EvGet) { + SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG) ; + } +} + +/* + * event dispatcher + * while event queue is not empty + * get event from queue + * send command to state machine + * end + * return error reported by individual Event function + * 0 if no error occured. + */ +int SkEventDispatcher( +SK_AC *pAC, /* Adapters Context */ +SK_IOC Ioc) /* Io context */ +{ + SK_EVENTELEM *pEv ; /* pointer into queue */ + SK_U32 Class ; + int Rtv ; + + pEv = pAC->Event.EvGet ; + PRINTF("dispatch get %x put %x\n",pEv,pAC->Event.ev_put) ; + while (pEv != pAC->Event.EvPut) { + PRINTF("dispatch Class %d Event %d\n",pEv->Class,pEv->Event) ; + switch(Class = pEv->Class) { +#ifndef SK_USE_LAC_EV + case SKGE_RLMT : /* RLMT Event */ + Rtv = SkRlmtEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; + case SKGE_I2C : /* I2C Event */ + Rtv = SkI2cEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; + case SKGE_PNMI : + Rtv = SkPnmiEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#endif /* SK_USE_LAC_EV */ + case SKGE_DRV : /* Driver Event */ + Rtv = SkDrvEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#ifndef SK_USE_SW_TIMER + case SKGE_HWAC : + Rtv = SkGeSirqEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#else /* !SK_USE_SW_TIMER */ + case SKGE_SWT : + Rtv = SkSwtEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#endif /* !SK_USE_SW_TIMER */ +#ifdef SK_USE_LAC_EV + case SKGE_LACP : + Rtv = SkLacpEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; + case SKGE_RSF : + Rtv = SkRsfEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; + case SKGE_MARKER : + Rtv = SkMarkerEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; + case SKGE_FD : + Rtv = SkFdEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#endif /* SK_USE_LAC_EV */ +#ifdef SK_USE_CSUM + case SKGE_CSUM : + Rtv = SkCsEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#endif /* SK_USE_CSUM */ + default : + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, + SKERR_Q_E002MSG) ; + Rtv = 0; + } + + if (Rtv != 0) { + return(Rtv) ; + } + + if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) + pEv = pAC->Event.EvQueue ; + + /* Renew get: it is used in queue_events to detect overruns */ + pAC->Event.EvGet = pEv; + } + + return(0) ; +} + +#endif /* CONFIG_SK98 */ + +/* End of file */ diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c new file mode 100644 index 0000000000..f8a3b41f0f --- /dev/null +++ b/drivers/net/sk98lin/skrlmt.c @@ -0,0 +1,3508 @@ +/****************************************************************************** + * + * Name: skrlmt.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.68 $ + * Date: $Date: 2003/01/31 15:26:56 $ + * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2001 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skrlmt.c,v $ + * Revision 1.68 2003/01/31 15:26:56 rschmidt + * Added init for local variables in RlmtInit(). + * + * Revision 1.67 2003/01/31 14:12:41 mkunz + * single port adapter runs now with two identical MAC addresses + * + * Revision 1.66 2002/09/23 15:14:19 rwahl + * - Reset broadcast timestamp on link down. + * - Editorial corrections. + * + * Revision 1.65 2002/07/22 14:29:48 rwahl + * - Removed BRK statement from debug check. + * + * Revision 1.64 2001/11/28 19:36:14 rwahl + * - RLMT Packets sent to an invalid MAC address in CLP/CLPSS mode + * (#10650). + * - Reworked fix for port switching in CLS mode (#10639) + * (no dependency to RLMT module). + * - Enabled dbg output for entry/exit of event functions. + * - Editorial changes. + * + * Revision 1.63 2001/10/26 07:53:18 afischer + * Port switching bug in `check local link` mode + * + * Revision 1.62 2001/07/03 12:16:30 mkunz + * New Flag ChgBcPrio (Change priority of last broadcast received) + * + * Revision 1.61 2001/03/14 12:52:08 rassmann + * Fixed reporting of active port up/down to PNMI. + * + * Revision 1.60 2001/02/21 16:02:25 gklug + * fix: when RLMT starts set Active Port for PNMI + * + * Revision 1.59 2001/02/16 14:38:19 rassmann + * Initializing some pointers earlier in the init phase. + * Rx Mbufs are freed if the net which they belong to is stopped. + * + * Revision 1.58 2001/02/14 14:06:31 rassmann + * Editorial changes. + * + * Revision 1.57 2001/02/05 14:25:26 rassmann + * Prepared RLMT for transparent operation. + * + * Revision 1.56 2001/01/30 10:29:09 rassmann + * Not checking switching befor RlmtStart. + * Editorial changes. + * + * Revision 1.55 2001/01/22 13:41:38 rassmann + * Supporting two nets on dual-port adapters. + * + * Revision 1.54 2000/11/30 13:25:07 rassmann + * Setting SK_TICK_INCR to 1 by default. + * + * Revision 1.53 2000/11/30 10:48:07 cgoos + * Changed definition of SK_RLMT_BC_DELTA. + * + * Revision 1.52 2000/11/27 12:50:03 rassmann + * Checking ports after receiving broadcasts. + * + * Revision 1.51 2000/11/17 08:58:00 rassmann + * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. + * + * Revision 1.50 2000/11/09 12:24:34 rassmann + * Indicating that segmentation check is not running anymore after + * SkRlmtCheckSeg(). + * Restarting segmentation timer after segmentation log. + * Editorial changes. + * + * Revision 1.49 1999/11/22 13:38:02 cgoos + * Changed license header to GPL. + * Added initialization to some variables to avoid compiler warnings. + * + * Revision 1.48 1999/10/04 14:01:17 rassmann + * Corrected reaction to reception of BPDU frames (#10441). + * + * Revision 1.47 1999/07/20 12:53:36 rassmann + * Fixed documentation errors for lookahead macros. + * + * Revision 1.46 1999/05/28 13:29:16 rassmann + * Replaced C++-style comment. + * + * Revision 1.45 1999/05/28 13:28:08 rassmann + * Corrected syntax error (xxx). + * + * Revision 1.44 1999/05/28 11:15:54 rassmann + * Changed behaviour to reflect Design Spec v1.2. + * Controlling Link LED(s). + * Introduced RLMT Packet Version field in RLMT Packet. + * Newstyle lookahead macros (checking meta-information before looking at + * the packet). + * + * Revision 1.43 1999/01/28 13:12:43 rassmann + * Corrected Lookahead (bug introduced in previous Rev.). + * + * Revision 1.42 1999/01/28 12:50:41 rassmann + * Not using broadcast time stamps in CheckLinkState mode. + * + * Revision 1.41 1999/01/27 14:13:02 rassmann + * Monitoring broadcast traffic. + * Switching more reliably and not too early if switch is + * configured for spanning tree. + * + * Revision 1.40 1999/01/22 13:17:30 rassmann + * Informing PNMI of NET_UP. + * Clearing RLMT multicast addresses before setting them for the first time. + * Reporting segmentation earlier, setting a "quiet time" + * after a report. + * + * Revision 1.39 1998/12/10 15:29:53 rassmann + * Corrected SuspectStatus in SkRlmtBuildCheckChain(). + * Corrected CHECK_SEG mode. + * + * Revision 1.38 1998/12/08 13:11:23 rassmann + * Stopping SegTimer at RlmtStop. + * + * Revision 1.37 1998/12/07 16:51:42 rassmann + * Corrected comments. + * + * Revision 1.36 1998/12/04 10:58:56 rassmann + * Setting next pointer to NULL when receiving. + * + * Revision 1.35 1998/12/03 16:12:42 rassmann + * Ignoring/correcting illegal PrefPort values. + * + * Revision 1.34 1998/12/01 11:45:35 rassmann + * Code cleanup. + * + * Revision 1.33 1998/12/01 10:29:32 rassmann + * Starting standby ports before getting the net up. + * Checking if a port is started when the link comes up. + * + * Revision 1.32 1998/11/30 16:19:50 rassmann + * New default for PortNoRx. + * + * Revision 1.31 1998/11/27 19:17:13 rassmann + * Corrected handling of LINK_DOWN coming shortly after LINK_UP. + * + * Revision 1.30 1998/11/24 12:37:31 rassmann + * Implemented segmentation check. + * + * Revision 1.29 1998/11/18 13:04:32 rassmann + * Secured PortUpTimer event. + * Waiting longer before starting standby port(s). + * + * Revision 1.28 1998/11/17 13:43:04 rassmann + * Handling (logical) tx failure. + * Sending packet on logical address after PORT_SWITCH. + * + * Revision 1.27 1998/11/13 17:09:50 rassmann + * Secured some events against being called in wrong state. + * + * Revision 1.26 1998/11/13 16:56:54 rassmann + * Added macro version of SkRlmtLookaheadPacket. + * + * Revision 1.25 1998/11/06 18:06:04 rassmann + * Corrected timing when RLMT checks fail. + * Clearing tx counter earlier in periodical checks. + * + * Revision 1.24 1998/11/05 10:37:27 rassmann + * Checking destination address in Lookahead. + * + * Revision 1.23 1998/11/03 13:53:49 rassmann + * RLMT should switch now (at least in mode 3). + * + * Revision 1.22 1998/10/29 14:34:49 rassmann + * Clearing SK_RLMT struct at startup. + * Initializing PortsUp during SK_RLMT_START. + * + * Revision 1.21 1998/10/28 11:30:17 rassmann + * Default mode is now SK_RLMT_CHECK_LOC_LINK. + * + * Revision 1.20 1998/10/26 16:02:03 rassmann + * Ignoring LINK_DOWN for links that are down. + * + * Revision 1.19 1998/10/22 15:54:01 rassmann + * Corrected EtherLen. + * Starting Link Check when second port comes up. + * + * Revision 1.18 1998/10/22 11:39:50 rassmann + * Corrected signed/unsigned mismatches. + * Corrected receive list handling and address recognition. + * + * Revision 1.17 1998/10/19 17:01:20 rassmann + * More detailed checking of received packets. + * + * Revision 1.16 1998/10/15 15:16:34 rassmann + * Finished Spanning Tree checking. + * Checked with lint. + * + * Revision 1.15 1998/09/24 19:16:07 rassmann + * Code cleanup. + * Introduced Timer for PORT_DOWN due to no RX. + * + * Revision 1.14 1998/09/18 20:27:14 rassmann + * Added address override. + * + * Revision 1.13 1998/09/16 11:31:48 rassmann + * Including skdrv1st.h again. :( + * + * Revision 1.12 1998/09/16 11:09:50 rassmann + * Syntax corrections. + * + * Revision 1.11 1998/09/15 12:32:03 rassmann + * Syntax correction. + * + * Revision 1.10 1998/09/15 11:28:49 rassmann + * Syntax corrections. + * + * Revision 1.9 1998/09/14 17:07:37 rassmann + * Added code for port checking via LAN. + * Changed Mbuf definition. + * + * Revision 1.8 1998/09/07 11:14:14 rassmann + * Syntax corrections. + * + * Revision 1.7 1998/09/07 09:06:07 rassmann + * Syntax corrections. + * + * Revision 1.6 1998/09/04 19:41:33 rassmann + * Syntax corrections. + * Started entering code for checking local links. + * + * Revision 1.5 1998/09/04 12:14:27 rassmann + * Interface cleanup. + * + * Revision 1.4 1998/09/02 16:55:28 rassmann + * Updated to reflect new DRV/HWAC/RLMT interface. + * + * Revision 1.3 1998/08/27 14:29:03 rassmann + * Code cleanup. + * + * Revision 1.2 1998/08/27 14:26:24 rassmann + * Updated interface. + * + * Revision 1.1 1998/08/21 08:26:49 rassmann + * First public version. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Description: + * + * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters. + * It is mainly intended for adapters with more than one link. + * For such adapters, this module realizes Redundant Link ManagemenT (RLMT). + * + * Include File Hierarchy: + * + * "skdrv1st.h" + * "skdrv2nd.h" + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#ifndef lint +static const char SysKonnectFileId[] = + "@(#) $Id: skrlmt.c,v 1.68 2003/01/31 15:26:56 rschmidt Exp $ (C) SysKonnect."; +#endif /* !defined(lint) */ + +#define __SKRLMT_C + +#ifdef __cplusplus +#error C++ is not yet supported. +extern "C" { +#endif /* cplusplus */ + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/* defines ********************************************************************/ + +#ifndef SK_HWAC_LINK_LED +#define SK_HWAC_LINK_LED(a,b,c,d) +#endif /* !defined(SK_HWAC_LINK_LED) */ + +#ifndef DEBUG +#define RLMT_STATIC static +#else /* DEBUG */ +#define RLMT_STATIC + +#ifndef SK_LITTLE_ENDIAN +/* First 32 bits */ +#define OFFS_LO32 1 + +/* Second 32 bits */ +#define OFFS_HI32 0 +#else /* SK_LITTLE_ENDIAN */ +/* First 32 bits */ +#define OFFS_LO32 0 + +/* Second 32 bits */ +#define OFFS_HI32 1 +#endif /* SK_LITTLE_ENDIAN */ + +#endif /* DEBUG */ + +/* ----- Private timeout values ----- */ + +#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */ +#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */ +#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */ +#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */ +#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */ +#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */ + +/* Assume tick counter increment is 1 - may be set OS-dependent. */ +#ifndef SK_TICK_INCR +#define SK_TICK_INCR SK_CONSTU64(1) +#endif /* !defined(SK_TICK_INCR) */ + +/* + * Amount that a time stamp must be later to be recognized as "substantially + * later". This is about 1/128 sec, but above 1 tick counter increment. + */ +#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \ + (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR)) + +/* ----- Private RLMT defaults ----- */ + +#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */ +#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */ + +/* ----- Private RLMT checking states ----- */ + +#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */ +#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */ +#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */ +#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */ + +/* ----- Private PORT checking states ----- */ + +#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */ +#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */ + +/* ----- Private PORT events ----- */ + +/* Note: Update simulation when changing these. */ +#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */ +#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */ +#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */ +#define SK_RLMT_PORTDOWN 1103 /* Port went down. */ +#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */ + +/* ----- Private RLMT events ----- */ + +/* Note: Update simulation when changing these. */ +#define SK_RLMT_TIM 2100 /* RLMT timeout. */ +#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */ + +#define TO_SHORTEN(tim) ((tim) / 2) + +/* Error numbers and messages. */ +#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0) +#define SKERR_RLMT_E001_MSG "No Packet." +#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1) +#define SKERR_RLMT_E002_MSG "Short Packet." +#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1) +#define SKERR_RLMT_E003_MSG "Unknown RLMT event." +#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1) +#define SKERR_RLMT_E004_MSG "PortsUp incorrect." +#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1) +#define SKERR_RLMT_E005_MSG \ + "Net seems to be segmented (different root bridges are reported on the ports)." +#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1) +#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected." +#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1) +#define SKERR_RLMT_E007_MSG "LinksUp incorrect." +#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1) +#define SKERR_RLMT_E008_MSG "Port not started but link came up." +#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1) +#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port." +#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1) +#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port." + +/* LLC field values. */ +#define LLC_COMMAND_RESPONSE_BIT 1 +#define LLC_TEST_COMMAND 0xE3 +#define LLC_UI 0x03 + +/* RLMT Packet fields. */ +#define SK_RLMT_DSAP 0 +#define SK_RLMT_SSAP 0 +#define SK_RLMT_CTRL (LLC_TEST_COMMAND) +#define SK_RLMT_INDICATOR0 0x53 /* S */ +#define SK_RLMT_INDICATOR1 0x4B /* K */ +#define SK_RLMT_INDICATOR2 0x2D /* - */ +#define SK_RLMT_INDICATOR3 0x52 /* R */ +#define SK_RLMT_INDICATOR4 0x4C /* L */ +#define SK_RLMT_INDICATOR5 0x4D /* M */ +#define SK_RLMT_INDICATOR6 0x54 /* T */ +#define SK_RLMT_PACKET_VERSION 0 + +/* RLMT SPT Flag values. */ +#define SK_RLMT_SPT_FLAG_CHANGE 0x01 +#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80 + +/* RLMT SPT Packet fields. */ +#define SK_RLMT_SPT_DSAP 0x42 +#define SK_RLMT_SPT_SSAP 0x42 +#define SK_RLMT_SPT_CTRL (LLC_UI) +#define SK_RLMT_SPT_PROTOCOL_ID0 0x00 +#define SK_RLMT_SPT_PROTOCOL_ID1 0x00 +#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00 +#define SK_RLMT_SPT_BPDU_TYPE 0x00 +#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */ +#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */ +#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */ + +/* Remaining 6 bytes will be the current port address. */ +#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00 +#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00 +#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00 +#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00 +#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */ +#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */ + +/* Remaining 6 bytes will be the current port address. */ +#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */ +#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */ +#define SK_RLMT_SPT_MSG_AGE0 0x00 +#define SK_RLMT_SPT_MSG_AGE1 0x00 +#define SK_RLMT_SPT_MAX_AGE0 0x00 +#define SK_RLMT_SPT_MAX_AGE1 0xFF +#define SK_RLMT_SPT_HELLO_TIME0 0x00 +#define SK_RLMT_SPT_HELLO_TIME1 0xFF +#define SK_RLMT_SPT_FWD_DELAY0 0x00 +#define SK_RLMT_SPT_FWD_DELAY1 0x40 + +/* Size defines. */ +#define SK_RLMT_MIN_PACKET_SIZE 34 +#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE) +#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ + SK_RLMT_MIN_PACKET_SIZE) + +/* ----- RLMT packet types ----- */ +#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */ +#define SK_PACKET_ALIVE 2 /* Alive packet to port. */ +#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */ +#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */ + +#ifdef SK_LITTLE_ENDIAN +#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ + SK_U8 *_Addr = (SK_U8*)(Addr); \ + SK_U16 _Val = (SK_U16)(Val); \ + *_Addr++ = (SK_U8)(_Val >> 8); \ + *_Addr = (SK_U8)(_Val & 0xFF); \ +} +#endif /* SK_LITTLE_ENDIAN */ + +#ifdef SK_BIG_ENDIAN +#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val)) +#endif /* SK_BIG_ENDIAN */ + +#define AUTONEG_FAILED SK_FALSE +#define AUTONEG_SUCCESS SK_TRUE + + +/* typedefs *******************************************************************/ + +/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */ +typedef struct s_RlmtPacket { + SK_U8 DstAddr[SK_MAC_ADDR_LEN]; + SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; + SK_U8 TypeLen[2]; + SK_U8 DSap; + SK_U8 SSap; + SK_U8 Ctrl; + SK_U8 Indicator[7]; + SK_U8 RlmtPacketType[2]; + SK_U8 Align1[2]; + SK_U8 Random[4]; /* Random value of requesting(!) station. */ + SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ + SK_U8 Data[SK_PACKET_DATA_LEN]; +} SK_RLMT_PACKET; + +typedef struct s_SpTreeRlmtPacket { + SK_U8 DstAddr[SK_MAC_ADDR_LEN]; + SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; + SK_U8 TypeLen[2]; + SK_U8 DSap; + SK_U8 SSap; + SK_U8 Ctrl; + SK_U8 ProtocolId[2]; + SK_U8 ProtocolVersionId; + SK_U8 BpduType; + SK_U8 Flags; + SK_U8 RootId[8]; + SK_U8 RootPathCost[4]; + SK_U8 BridgeId[8]; + SK_U8 PortId[2]; + SK_U8 MessageAge[2]; + SK_U8 MaxAge[2]; + SK_U8 HelloTime[2]; + SK_U8 ForwardDelay[2]; +} SK_SPTREE_PACKET; + +/* global variables ***********************************************************/ + +SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; +SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; +SK_MAC_ADDR BcAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + +/* local variables ************************************************************/ + +/* None. */ + +/* functions ******************************************************************/ + +RLMT_STATIC void SkRlmtCheckSwitch( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 NetIdx); +RLMT_STATIC void SkRlmtCheckSeg( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 NetIdx); +RLMT_STATIC void SkRlmtEvtSetNets( + SK_AC *pAC, + SK_IOC IoC, + SK_EVPARA Para); + +/****************************************************************************** + * + * SkRlmtInit - initialize data, set state to init + * + * Description: + * + * SK_INIT_DATA + * ============ + * + * This routine initializes all RLMT-related variables to a known state. + * The initial state is SK_RLMT_RS_INIT. + * All ports are initialized to SK_RLMT_PS_INIT. + * + * + * SK_INIT_IO + * ========== + * + * Nothing. + * + * + * SK_INIT_RUN + * =========== + * + * Determine the adapter's random value. + * Set the hw registers, the "logical MAC address", the + * RLMT multicast address, and eventually the BPDU multicast address. + * + * Context: + * init, pageable + * + * Returns: + * Nothing. + */ +void SkRlmtInit( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Level) /* Initialization Level */ +{ + SK_U32 i, j; + SK_U64 Random; + SK_EVPARA Para; + SK_MAC_ADDR VirtualMacAddress; + SK_MAC_ADDR PhysicalAMacAddress; + SK_BOOL VirtualMacAddressSet; + SK_BOOL PhysicalAMacAddressSet; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, + ("RLMT Init level %d.\n", Level)) + + switch (Level) { + case SK_INIT_DATA: /* Initialize data structures. */ + SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); + + for (i = 0; i < SK_MAX_MACS; i++) { + pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; + pAC->Rlmt.Port[i].LinkDown = SK_TRUE; + pAC->Rlmt.Port[i].PortDown = SK_TRUE; + pAC->Rlmt.Port[i].PortStarted = SK_FALSE; + pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; + pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; + pAC->Rlmt.Port[i].PortNumber = i; + pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; + pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; + } + + pAC->Rlmt.NumNets = 1; + for (i = 0; i < SK_MAX_NETS; i++) { + pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; + pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; + pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; + pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ + /* Just assuming. */ + pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; + pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; + pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; + pAC->Rlmt.Net[i].NetNumber = i; + } + + pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; + pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1]; +#if SK_MAX_NETS > 1 + pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1]; +#endif /* SK_MAX_NETS > 1 */ + break; + + case SK_INIT_IO: /* GIMacsFound first available here. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, + ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) + + pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; + + /* Initialize HW registers? */ + if (pAC->GIni.GIMacsFound == 1) { + Para.Para32[0] = SK_RLMT_MODE_CLS; + Para.Para32[1] = 0; + (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); + } + break; + + case SK_INIT_RUN: + /* Ensure RLMT is set to one net. */ + if (pAC->Rlmt.NumNets > 1) { + Para.Para32[0] = 1; + Para.Para32[1] = -1; + SkRlmtEvtSetNets(pAC, IoC, Para); + } + + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + Random = SkOsGetTime(pAC); + *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random; + + for (j = 0; j < 4; j++) { + pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort-> + CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j]; + } + + (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); + + /* Add RLMT MC address. */ + (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); + + if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) { + /* Add BPDU MC address. */ + (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT); + } + + (void)SkAddrMcUpdate(pAC, IoC, i); + } + + VirtualMacAddressSet = SK_FALSE; + /* Read virtual MAC address from Control Register File. */ + for (j = 0; j < SK_MAC_ADDR_LEN; j++) { + + SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); + VirtualMacAddressSet |= VirtualMacAddress.a[j]; + } + + PhysicalAMacAddressSet = SK_FALSE; + /* Read physical MAC address for MAC A from Control Register File. */ + for (j = 0; j < SK_MAC_ADDR_LEN; j++) { + + SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); + PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; + } + + /* check if the two mac addresses contain reasonable values */ + if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { + + pAC->Rlmt.RlmtOff = SK_TRUE; + } + + /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD + and the RLMT_LOOKAHEAD macros */ + else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { + + pAC->Rlmt.RlmtOff = SK_TRUE; + } + else { + pAC->Rlmt.RlmtOff = SK_FALSE; + } + break; + + default: /* error */ + break; + } + return; +} /* SkRlmtInit */ + + +/****************************************************************************** + * + * SkRlmtBuildCheckChain - build the check chain + * + * Description: + * This routine builds the local check chain: + * - Each port that is up checks the next port. + * - The last port that is up checks the first port that is up. + * + * Notes: + * - Currently only local ports are considered when building the chain. + * - Currently the SuspectState is just reset; + * it would be better to save it ... + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtBuildCheckChain( +SK_AC *pAC, /* Adapter Context */ +SK_U32 NetIdx) /* Net Number */ +{ + SK_U32 i; + SK_U32 NumMacsUp; + SK_RLMT_PORT * FirstMacUp; + SK_RLMT_PORT * PrevMacUp; + + FirstMacUp = NULL; + PrevMacUp = NULL; + + if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { + for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { + pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; + } + return; /* Done. */ + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SkRlmtBuildCheckChain.\n")) + + NumMacsUp = 0; + + for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { + pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; + pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; + pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &= + ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX); + + /* + * If more than two links are detected we should consider + * checking at least two other ports: + * 1. the next port that is not LinkDown and + * 2. the next port that is not PortDown. + */ + if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { + if (NumMacsUp == 0) { + FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; + } + else { + PrevMacUp->PortCheck[ + pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = + pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; + PrevMacUp->PortCheck[ + PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; + PrevMacUp->PortsChecked++; + } + PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; + NumMacsUp++; + } + } + + if (NumMacsUp > 1) { + PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = + FirstMacUp->AddrPort->CurrentMacAddress; + PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = + SK_FALSE; + PrevMacUp->PortsChecked++; + } + +#ifdef DEBUG + for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Port %d checks %d other ports: %2X.\n", i, + pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, + pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) + } +#endif /* DEBUG */ + + return; +} /* SkRlmtBuildCheckChain */ + + +/****************************************************************************** + * + * SkRlmtBuildPacket - build an RLMT packet + * + * Description: + * This routine sets up an RLMT packet. + * + * Context: + * runtime, pageable? + * + * Returns: + * NULL or pointer to RLMT mbuf + */ +RLMT_STATIC SK_MBUF *SkRlmtBuildPacket( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber, /* Sending port */ +SK_U16 PacketType, /* RLMT packet type */ +SK_MAC_ADDR *SrcAddr, /* Source address */ +SK_MAC_ADDR *DestAddr) /* Destination address */ +{ + int i; + SK_U16 Length; + SK_MBUF *pMb; + SK_RLMT_PACKET *pPacket; + +#ifdef DEBUG + SK_U8 CheckSrc = 0; + SK_U8 CheckDest = 0; + + for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { + CheckSrc |= SrcAddr->a[i]; + CheckDest |= DestAddr->a[i]; + } + + if ((CheckSrc == 0) || (CheckDest == 0)) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, + ("SkRlmtBuildPacket: Invalid %s%saddr.\n", + (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) + } +#endif + + if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) { + pPacket = (SK_RLMT_PACKET*)pMb->pData; + for (i = 0; i < SK_MAC_ADDR_LEN; i++) { + pPacket->DstAddr[i] = DestAddr->a[i]; + pPacket->SrcAddr[i] = SrcAddr->a[i]; + } + pPacket->DSap = SK_RLMT_DSAP; + pPacket->SSap = SK_RLMT_SSAP; + pPacket->Ctrl = SK_RLMT_CTRL; + pPacket->Indicator[0] = SK_RLMT_INDICATOR0; + pPacket->Indicator[1] = SK_RLMT_INDICATOR1; + pPacket->Indicator[2] = SK_RLMT_INDICATOR2; + pPacket->Indicator[3] = SK_RLMT_INDICATOR3; + pPacket->Indicator[4] = SK_RLMT_INDICATOR4; + pPacket->Indicator[5] = SK_RLMT_INDICATOR5; + pPacket->Indicator[6] = SK_RLMT_INDICATOR6; + + SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]); + + for (i = 0; i < 4; i++) { + pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; + } + + SK_U16_TO_NETWORK_ORDER( + SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); + + for (i = 0; i < SK_PACKET_DATA_LEN; i++) { + pPacket->Data[i] = 0x00; + } + + Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ + pMb->Length = Length; + pMb->PortIdx = PortNumber; + Length -= 14; + SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); + + if (PacketType == SK_PACKET_ALIVE) { + pAC->Rlmt.Port[PortNumber].TxHelloCts++; + } + } + + return (pMb); +} /* SkRlmtBuildPacket */ + + +/****************************************************************************** + * + * SkRlmtBuildSpanningTreePacket - build spanning tree check packet + * + * Description: + * This routine sets up a BPDU packet for spanning tree check. + * + * Context: + * runtime, pageable? + * + * Returns: + * NULL or pointer to RLMT mbuf + */ +RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber) /* Sending port */ +{ + unsigned i; + SK_U16 Length; + SK_MBUF *pMb; + SK_SPTREE_PACKET *pSPacket; + + if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != + NULL) { + pSPacket = (SK_SPTREE_PACKET*)pMb->pData; + for (i = 0; i < SK_MAC_ADDR_LEN; i++) { + pSPacket->DstAddr[i] = BridgeMcAddr.a[i]; + pSPacket->SrcAddr[i] = + pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; + } + pSPacket->DSap = SK_RLMT_SPT_DSAP; + pSPacket->SSap = SK_RLMT_SPT_SSAP; + pSPacket->Ctrl = SK_RLMT_SPT_CTRL; + + pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0; + pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1; + pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID; + pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE; + pSPacket->Flags = SK_RLMT_SPT_FLAGS; + pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0; + pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1; + pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0; + pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1; + pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2; + pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3; + pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0; + pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1; + + /* + * Use logical MAC address as bridge ID and filter these packets + * on receive. + */ + for (i = 0; i < SK_MAC_ADDR_LEN; i++) { + pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] = + pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. + CurrentMacAddress.a[i]; + } + pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0; + pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1; + pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0; + pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1; + pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0; + pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1; + pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0; + pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1; + pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0; + pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1; + + Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ + pMb->Length = Length; + pMb->PortIdx = PortNumber; + Length -= 14; + SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); + + pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++; + } + + return (pMb); +} /* SkRlmtBuildSpanningTreePacket */ + + +/****************************************************************************** + * + * SkRlmtSend - build and send check packets + * + * Description: + * Depending on the RLMT state and the checking state, several packets + * are sent through the indicated port. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing. + */ +RLMT_STATIC void SkRlmtSend( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber) /* Sending port */ +{ + unsigned j; + SK_EVPARA Para; + SK_RLMT_PORT *pRPort; + + pRPort = &pAC->Rlmt.Port[PortNumber]; + if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { + if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) { + /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */ + if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, + SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, + &SkRlmtMcAddr)) != NULL) { + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + } + else { + /* + * Send a directed RLMT packet to all ports that are + * checked by the indicated port. + */ + for (j = 0; j < pRPort->PortsChecked; j++) { + if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, + SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, + &pRPort->PortCheck[j].CheckAddr)) != NULL) { + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + } + } + } + + if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && + (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) { + /* + * Send a BPDU packet to make a connected switch tell us + * the correct root bridge. + */ + if ((Para.pParaPtr = + SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) { + pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG; + pRPort->RootIdSet = SK_FALSE; + + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, + ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) + } + } + return; +} /* SkRlmtSend */ + + +/****************************************************************************** + * + * SkRlmtPortReceives - check if port is (going) down and bring it up + * + * Description: + * This routine checks if a port who received a non-BPDU packet + * needs to go up or needs to be stopped going down. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing. + */ +RLMT_STATIC void SkRlmtPortReceives( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber) /* Port to check */ +{ + SK_RLMT_PORT *pRPort; + SK_EVPARA Para; + + pRPort = &pAC->Rlmt.Port[PortNumber]; + pRPort->PortNoRx = SK_FALSE; + + if ((pRPort->PortState == SK_RLMT_PS_DOWN) && + !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { + /* + * Port is marked down (rx), but received a non-BPDU packet. + * Bring it up. + */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Received on PortDown.\n")) + + pRPort->PortState = SK_RLMT_PS_GOING_UP; + pRPort->GuTimeStamp = SkOsGetTime(pAC); + Para.Para32[0] = PortNumber; + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, + SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); + pRPort->CheckingState &= ~SK_RLMT_PCS_RX; + /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + } /* PortDown && !SuspectTx */ + else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Stop bringing port down.\n")) + SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); + pRPort->CheckingState &= ~SK_RLMT_PCS_RX; + /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + } /* PortGoingDown */ + + return; +} /* SkRlmtPortReceives */ + + +/****************************************************************************** + * + * SkRlmtPacketReceive - receive a packet for closer examination + * + * Description: + * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing. + */ +RLMT_STATIC void SkRlmtPacketReceive( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_MBUF *pMb) /* Received packet */ +{ +#ifdef xDEBUG + extern void DumpData(char *p, int size); +#endif /* DEBUG */ + int i; + unsigned j; + SK_U16 PacketType; + SK_U32 PortNumber; + SK_ADDR_PORT *pAPort; + SK_RLMT_PORT *pRPort; + SK_RLMT_PACKET *pRPacket; + SK_SPTREE_PACKET *pSPacket; + SK_EVPARA Para; + + PortNumber = pMb->PortIdx; + pAPort = &pAC->Addr.Port[PortNumber]; + pRPort = &pAC->Rlmt.Port[PortNumber]; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) + + pRPacket = (SK_RLMT_PACKET*)pMb->pData; + pSPacket = (SK_SPTREE_PACKET*)pRPacket; + +#ifdef xDEBUG + DumpData((char *)pRPacket, 32); +#endif /* DEBUG */ + + if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { + SkRlmtPortReceives(pAC, IoC, PortNumber); + } + + /* Check destination address. */ + + if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && + !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && + !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { + + /* Not sent to current MAC or registered MC address => Trash it. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Not for me.\n")) + + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + return; + } + else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { + + /* + * Was sent by same port (may happen during port switching + * or in case of duplicate MAC addresses). + */ + + /* + * Check for duplicate address here: + * If Packet.Random != My.Random => DupAddr. + */ + for (i = 3; i >= 0; i--) { + if (pRPort->Random[i] != pRPacket->Random[i]) { + break; + } + } + + /* + * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply + * packets (they have the LLC_COMMAND_RESPONSE_BIT set in + * pRPacket->SSap). + */ + if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && + pRPacket->Ctrl == SK_RLMT_CTRL && + pRPacket->SSap == SK_RLMT_SSAP && + pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && + pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && + pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && + pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && + pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && + pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && + pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) + + /* Error Log entry. */ + SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); + } + else { + /* Simply trash it. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Sent by me.\n")) + } + + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + return; + } + + /* Check SuspectTx entries. */ + if (pRPort->PortsSuspect > 0) { + for (j = 0; j < pRPort->PortsChecked; j++) { + if (pRPort->PortCheck[j].SuspectTx && + SK_ADDR_EQUAL( + pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { + pRPort->PortCheck[j].SuspectTx = SK_FALSE; + pRPort->PortsSuspect--; + break; + } + } + } + + /* Determine type of packet. */ + if (pRPacket->DSap == SK_RLMT_DSAP && + pRPacket->Ctrl == SK_RLMT_CTRL && + (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && + pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && + pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && + pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && + pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && + pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && + pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && + pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { + + /* It's an RLMT packet. */ + PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | + pRPacket->RlmtPacketType[1]); + + switch (PacketType) { + case SK_PACKET_ANNOUNCE: /* Not yet used. */ +#if 0 + /* Build the check chain. */ + SkRlmtBuildCheckChain(pAC); +#endif /* 0 */ + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Announce.\n")) + + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + break; + + case SK_PACKET_ALIVE: + if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Alive Reply.\n")) + + if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || + SK_ADDR_EQUAL( + pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { + /* Obviously we could send something. */ + if (pRPort->CheckingState & SK_RLMT_PCS_TX) { + pRPort->CheckingState &= ~SK_RLMT_PCS_TX; + SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); + } + + if ((pRPort->PortState == SK_RLMT_PS_DOWN) && + !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { + pRPort->PortState = SK_RLMT_PS_GOING_UP; + pRPort->GuTimeStamp = SkOsGetTime(pAC); + + SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); + + Para.Para32[0] = PortNumber; + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->UpTimer, + SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, + SK_RLMT_PORTUP_TIM, Para); + } + } + + /* Mark sending port as alive? */ + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + } + else { /* Alive Request Packet. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Alive Request.\n")) + + pRPort->RxHelloCts++; + + /* Answer. */ + for (i = 0; i < SK_MAC_ADDR_LEN; i++) { + pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; + pRPacket->SrcAddr[i] = + pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; + } + pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; + + Para.pParaPtr = pMb; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + break; + + case SK_PACKET_CHECK_TX: + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Check your tx line.\n")) + + /* A port checking us requests us to check our tx line. */ + pRPort->CheckingState |= SK_RLMT_PCS_TX; + + /* Start PortDownTx timer. */ + Para.Para32[0] = PortNumber; + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, + SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, + SK_RLMT_PORTDOWN_TX_TIM, Para); + + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + + if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, + SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, + &SkRlmtMcAddr)) != NULL) { + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + break; + + case SK_PACKET_ADDR_CHANGED: + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Address Change.\n")) + + /* Build the check chain. */ + SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + break; + + default: + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) + + /* RA;:;: ??? */ + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + } + } + else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && + pSPacket->Ctrl == SK_RLMT_SPT_CTRL && + (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: BPDU Packet.\n")) + + /* Spanning Tree packet. */ + pRPort->RxSpHelloCts++; + + if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. + Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { + /* + * Check segmentation if a new root bridge is set and + * the segmentation check is not currently running. + */ + if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && + (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && + (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) + != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & + SK_RLMT_RCS_SEG) == 0) { + pAC->Rlmt.Port[PortNumber].Net->CheckingState |= + SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; + } + + /* Store tree view of this port. */ + for (i = 0; i < 8; i++) { + pRPort->Root.Id[i] = pSPacket->RootId[i]; + } + pRPort->RootIdSet = SK_TRUE; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, + ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", + PortNumber, + pRPort->Root.Id[0], pRPort->Root.Id[1], + pRPort->Root.Id[2], pRPort->Root.Id[3], + pRPort->Root.Id[4], pRPort->Root.Id[5], + pRPort->Root.Id[6], pRPort->Root.Id[7])) + } + + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & + SK_RLMT_RCS_REPORT_SEG) != 0) { + SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); + } + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, + ("SkRlmtPacketReceive: Unknown Packet Type.\n")) + + /* Unknown packet. */ + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + } + return; +} /* SkRlmtPacketReceive */ + + +/****************************************************************************** + * + * SkRlmtCheckPort - check if a port works + * + * Description: + * This routine checks if a port whose link is up received something + * and if it seems to transmit successfully. + * + * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp + * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg + * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg + * + * if (Rx - RxBpdu == 0) { # No rx. + * if (state == PsUp) { + * PortCheckingState |= ChkRx + * } + * if (ModeCheckSeg && (Timeout == + * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { + * RlmtCheckingState |= ChkSeg) + * PortCheckingState |= ChkSeg + * } + * NewTimeout = TO_SHORTEN(Timeout) + * if (NewTimeout < RLMT_MIN_TIMEOUT) { + * NewTimeout = RLMT_MIN_TIMEOUT + * PortState = PsDown + * ... + * } + * } + * else { # something was received + * # Set counter to 0 at LinkDown? + * # No - rx may be reported after LinkDown ??? + * PortCheckingState &= ~ChkRx + * NewTimeout = RLMT_DEFAULT_TIMEOUT + * if (RxAck == 0) { + * possible reasons: + * is my tx line bad? -- + * send RLMT multicast and report + * back internally? (only possible + * between ports on same adapter) + * } + * if (RxChk == 0) { + * possible reasons: + * - tx line of port set to check me + * maybe bad + * - no other port/adapter available or set + * to check me + * - adapter checking me has a longer + * timeout + * ??? anything that can be done here? + * } + * } + * + * Context: + * runtime, pageable? + * + * Returns: + * New timeout value. + */ +RLMT_STATIC SK_U32 SkRlmtCheckPort( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber) /* Port to check */ +{ + unsigned i; + SK_U32 NewTimeout; + SK_RLMT_PORT *pRPort; + SK_EVPARA Para; + + pRPort = &pAC->Rlmt.Port[PortNumber]; + + if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", + PortNumber, pRPort->PacketsPerTimeSlot)) + + /* + * Check segmentation if there was no receive at least twice + * in a row (PortNoRx is already set) and the segmentation + * check is not currently running. + */ + + if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && + (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && + !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { + pAC->Rlmt.Port[PortNumber].Net->CheckingState |= + SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", + pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) + + if (pRPort->PortState != SK_RLMT_PS_DOWN) { + NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); + if (NewTimeout < SK_RLMT_MIN_TO_VAL) { + NewTimeout = SK_RLMT_MIN_TO_VAL; + } + + if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { + Para.Para32[0] = PortNumber; + pRPort->CheckingState |= SK_RLMT_PCS_RX; + + /* + * What shall we do if the port checked by this one receives + * our request frames? What's bad - our rx line or his tx line? + */ + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->DownRxTimer, + SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, + SK_RLMT_PORTDOWN_RX_TIM, Para); + + for (i = 0; i < pRPort->PortsChecked; i++) { + if (pRPort->PortCheck[i].SuspectTx) { + continue; + } + pRPort->PortCheck[i].SuspectTx = SK_TRUE; + pRPort->PortsSuspect++; + if ((Para.pParaPtr = + SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX, + &pAC->Addr.Port[PortNumber].CurrentMacAddress, + &pRPort->PortCheck[i].CheckAddr)) != NULL) { + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + } + } + } + else { /* PortDown -- or all partners suspect. */ + NewTimeout = SK_RLMT_DEF_TO_VAL; + } + pRPort->PortNoRx = SK_TRUE; + } + else { /* A non-BPDU packet was received. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", + PortNumber, + pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, + pRPort->PacketsPerTimeSlot)) + + SkRlmtPortReceives(pAC, IoC, PortNumber); + if (pAC->Rlmt.CheckSwitch) { + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + } + + NewTimeout = SK_RLMT_DEF_TO_VAL; + } + + return (NewTimeout); +} /* SkRlmtCheckPort */ + + +/****************************************************************************** + * + * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) + * + * Description: + * This routine selects the port that received a broadcast frame + * substantially later than all other ports. + * + * Context: + * runtime, pageable? + * + * Returns: + * SK_BOOL + */ +RLMT_STATIC SK_BOOL SkRlmtSelectBcRx( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Active, /* Active port */ +SK_U32 PrefPort, /* Preferred port */ +SK_U32 *pSelect) /* New active port */ +{ + SK_U64 BcTimeStamp; + SK_U32 i; + SK_BOOL PortFound; + + BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ + PortFound = SK_FALSE; + + /* Select port with the latest TimeStamp. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", + i, + pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, + *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), + *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) + + if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { + if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { + BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; + *pSelect = i; + PortFound = SK_TRUE; + } + } + } + + if (PortFound) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Port %d received the last broadcast.\n", *pSelect)) + + /* Look if another port's time stamp is similar. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (i == *pSelect) { + continue; + } + if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && + (pAC->Rlmt.Port[i].BcTimeStamp > + BcTimeStamp - SK_RLMT_BC_DELTA || + pAC->Rlmt.Port[i].BcTimeStamp + + SK_RLMT_BC_DELTA > BcTimeStamp)) { + PortFound = SK_FALSE; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Port %d received a broadcast at a similar time.\n", i)) + break; + } + } + } + +#ifdef DEBUG + if (PortFound) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " + "latest broadcast (%u).\n", + *pSelect, + BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) + } +#endif /* DEBUG */ + + return (PortFound); +} /* SkRlmtSelectBcRx */ + + +/****************************************************************************** + * + * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) + * + * Description: + * This routine selects a good port (it is PortUp && !SuspectRx). + * + * Context: + * runtime, pageable? + * + * Returns: + * SK_BOOL + */ +RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Active, /* Active port */ +SK_U32 PrefPort, /* Preferred port */ +SK_U32 *pSelect) /* New active port */ +{ + SK_U32 i; + SK_BOOL PortFound; + + PortFound = SK_FALSE; + + /* Select first port that is PortUp && !SuspectRx. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (!pAC->Rlmt.Port[i].PortDown && + !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { + *pSelect = i; + if (!pAC->Rlmt.Port[Active].PortDown && + !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { + *pSelect = Active; + } + if (!pAC->Rlmt.Port[PrefPort].PortDown && + !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { + *pSelect = PrefPort; + } + PortFound = SK_TRUE; + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", + *pSelect)) + break; + } + } + return (PortFound); +} /* SkRlmtSelectNotSuspect */ + + +/****************************************************************************** + * + * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) + * + * Description: + * This routine selects a port that is up. + * + * Context: + * runtime, pageable? + * + * Returns: + * SK_BOOL + */ +RLMT_STATIC SK_BOOL SkRlmtSelectUp( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Active, /* Active port */ +SK_U32 PrefPort, /* Preferred port */ +SK_U32 *pSelect, /* New active port */ +SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ +{ + SK_U32 i; + SK_BOOL PortFound; + + PortFound = SK_FALSE; + + /* Select first port that is PortUp. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && + pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { + *pSelect = i; + if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && + pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { + *pSelect = Active; + } + if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && + pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { + *pSelect = PrefPort; + } + PortFound = SK_TRUE; + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) + break; + } + } + return (PortFound); +} /* SkRlmtSelectUp */ + + +/****************************************************************************** + * + * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) + * + * Description: + * This routine selects the port that is going up for the longest time. + * + * Context: + * runtime, pageable? + * + * Returns: + * SK_BOOL + */ +RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Active, /* Active port */ +SK_U32 PrefPort, /* Preferred port */ +SK_U32 *pSelect, /* New active port */ +SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ +{ + SK_U64 GuTimeStamp; + SK_U32 i; + SK_BOOL PortFound; + + GuTimeStamp = 0; + PortFound = SK_FALSE; + + /* Select port that is PortGoingUp for the longest time. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && + pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { + GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; + *pSelect = i; + PortFound = SK_TRUE; + break; + } + } + + if (!PortFound) { + return (SK_FALSE); + } + + for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && + pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && + pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { + GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; + *pSelect = i; + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) + return (SK_TRUE); +} /* SkRlmtSelectGoingUp */ + + +/****************************************************************************** + * + * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) + * + * Description: + * This routine selects a port that is down. + * + * Context: + * runtime, pageable? + * + * Returns: + * SK_BOOL + */ +RLMT_STATIC SK_BOOL SkRlmtSelectDown( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Active, /* Active port */ +SK_U32 PrefPort, /* Preferred port */ +SK_U32 *pSelect, /* New active port */ +SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ +{ + SK_U32 i; + SK_BOOL PortFound; + + PortFound = SK_FALSE; + + /* Select first port that is PortDown. */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && + pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { + *pSelect = i; + if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && + pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { + *pSelect = Active; + } + if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && + pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { + *pSelect = PrefPort; + } + PortFound = SK_TRUE; + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) + break; + } + } + return (PortFound); +} /* SkRlmtSelectDown */ + + +/****************************************************************************** + * + * SkRlmtCheckSwitch - select new active port and switch to it + * + * Description: + * This routine decides which port should be the active one and queues + * port switching if necessary. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing. + */ +RLMT_STATIC void SkRlmtCheckSwitch( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 NetIdx) /* Net index */ +{ + SK_EVPARA Para; + SK_U32 Active; + SK_U32 PrefPort; + SK_U32 i; + SK_BOOL PortFound; + + Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ + PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ + PortFound = SK_FALSE; + pAC->Rlmt.CheckSwitch = SK_FALSE; + +#if 0 /* RW 2001/10/18 - active port becomes always prefered one */ + if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ + /* disable auto-fail back */ + PrefPort = Active; + } +#endif + + if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { + /* Last link went down - shut down the net. */ + pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; + Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; + Para.Para32[1] = NetIdx; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); + + Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. + Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; + Para.Para32[1] = NetIdx; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); + return; + } /* pAC->Rlmt.LinksUp == 0 */ + else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && + pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { + /* First link came up - get the net up. */ + pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; + + /* + * If pAC->Rlmt.ActivePort != Para.Para32[0], + * the DRV switches to the port that came up. + */ + for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { + if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { + if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { + i = Active; + } + if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { + i = PrefPort; + } + PortFound = SK_TRUE; + break; + } + } + + if (PortFound) { + Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; + Para.Para32[1] = NetIdx; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); + + pAC->Rlmt.Net[NetIdx].ActivePort = i; + Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; + Para.Para32[1] = NetIdx; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); + + if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && + (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, + pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, + SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. + CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { + /* + * Send announce packet to RLMT multicast address to force + * switches to learn the new location of the logical MAC address. + */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); + } + + return; + } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ + else { /* Cannot be reached in dual-net mode. */ + Para.Para32[0] = Active; + + /* + * Preselection: + * If RLMT Mode != CheckLinkState + * select port that received a broadcast frame substantially later + * than all other ports + * else select first port that is not SuspectRx + * else select first port that is PortUp + * else select port that is PortGoingUp for the longest time + * else select first port that is PortDown + * else stop. + * + * For the preselected port: + * If ActivePort is equal in quality, select ActivePort. + * + * If PrefPort is equal in quality, select PrefPort. + * + * If ActivePort != SelectedPort, + * If old ActivePort is LinkDown, + * SwitchHard + * else + * SwitchSoft + */ + /* check of ChgBcPrio flag added */ + if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && + (!pAC->Rlmt.Net[0].ChgBcPrio)) { + + if (!PortFound) { + PortFound = SkRlmtSelectBcRx( + pAC, IoC, Active, PrefPort, &Para.Para32[1]); + } + + if (!PortFound) { + PortFound = SkRlmtSelectNotSuspect( + pAC, IoC, Active, PrefPort, &Para.Para32[1]); + } + } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ + + /* with changed priority for last broadcast received */ + if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && + (pAC->Rlmt.Net[0].ChgBcPrio)) { + if (!PortFound) { + PortFound = SkRlmtSelectNotSuspect( + pAC, IoC, Active, PrefPort, &Para.Para32[1]); + } + + if (!PortFound) { + PortFound = SkRlmtSelectBcRx( + pAC, IoC, Active, PrefPort, &Para.Para32[1]); + } + } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ + + if (!PortFound) { + PortFound = SkRlmtSelectUp( + pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); + } + + if (!PortFound) { + PortFound = SkRlmtSelectUp( + pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); + } + + if (!PortFound) { + PortFound = SkRlmtSelectGoingUp( + pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); + } + + if (!PortFound) { + PortFound = SkRlmtSelectGoingUp( + pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); + } + + if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { + if (!PortFound) { + PortFound = SkRlmtSelectDown(pAC, IoC, + Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); + } + + if (!PortFound) { + PortFound = SkRlmtSelectDown(pAC, IoC, + Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); + } + } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ + + if (PortFound) { + + if (Para.Para32[1] != Active) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) + pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; + Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. + Port[Para.Para32[0]]->PortNumber; + Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. + Port[Para.Para32[1]]->PortNumber; + SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); + if (pAC->Rlmt.Port[Active].LinkDown) { + SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); + } + else { + SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); + SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); + } + Para.Para32[1] = NetIdx; + Para.Para32[0] = + pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); + Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. + Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); + if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && + (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], + SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, + &SkRlmtMcAddr)) != NULL) { + /* + * Send announce packet to RLMT multicast address to force + * switches to learn the new location of the logical + * MAC address. + */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ + } /* Para.Para32[1] != Active */ + } /* PortFound */ + else { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); + } + } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ + return; +} /* SkRlmtCheckSwitch */ + + +/****************************************************************************** + * + * SkRlmtCheckSeg - Report if segmentation is detected + * + * Description: + * This routine checks if the ports see different root bridges and reports + * segmentation in such a case. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing. + */ +RLMT_STATIC void SkRlmtCheckSeg( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 NetIdx) /* Net number */ +{ + SK_EVPARA Para; + SK_RLMT_NET *pNet; + SK_U32 i, j; + SK_BOOL Equal; + + pNet = &pAC->Rlmt.Net[NetIdx]; + pNet->RootIdSet = SK_FALSE; + Equal = SK_TRUE; + + for (i = 0; i < pNet->NumPorts; i++) { + if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { + continue; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, + ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, + pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], + pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], + pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], + pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) + + if (!pNet->RootIdSet) { + pNet->Root = pNet->Port[i]->Root; + pNet->RootIdSet = SK_TRUE; + continue; + } + + for (j = 0; j < 8; j ++) { + Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; + if (!Equal) { + break; + } + } + + if (!Equal) { + SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); + Para.Para32[0] = NetIdx; + Para.Para32[1] = (SK_U32)-1; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); + + pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; + + /* 2000-03-06 RA: New. */ + Para.Para32[0] = NetIdx; + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, + SKGE_RLMT, SK_RLMT_SEG_TIM, Para); + break; + } + } /* for (i = 0; i < pNet->NumPorts; i++) */ + + /* 2000-03-06 RA: Moved here. */ + /* Segmentation check not running anymore. */ + pNet->CheckingState &= ~SK_RLMT_RCS_SEG; + +} /* SkRlmtCheckSeg */ + + +/****************************************************************************** + * + * SkRlmtPortStart - initialize port variables and start port + * + * Description: + * This routine initializes a port's variables and issues a PORT_START + * to the HWAC module. This handles retries if the start fails or the + * link eventually goes down. + * + * Context: + * runtime, pageable? + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtPortStart( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 PortNumber) /* Port number */ +{ + SK_EVPARA Para; + + pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; + pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; + pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; + pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; + pAC->Rlmt.Port[PortNumber].CheckingState = 0; + pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; + Para.Para32[0] = PortNumber; + Para.Para32[1] = (SK_U32)-1; + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); +} /* SkRlmtPortStart */ + + +/****************************************************************************** + * + * SkRlmtEvtPortStartTim - PORT_START_TIM + * + * Description: + * This routine handles PORT_START_TIM events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPortStartTim( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ +{ + SK_U32 i; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) + return; + } + + /* + * Used to start non-preferred ports if the preferred one + * does not come up. + * This timeout needs only be set when starting the first + * (preferred) port. + */ + if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { + /* PORT_START failed. */ + for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) { + if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) { + SkRlmtPortStart(pAC, IoC, + pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber); + } + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) +} /* SkRlmtEvtPortStartTim */ + + +/****************************************************************************** + * + * SkRlmtEvtLinkUp - LINK_UP + * + * Description: + * This routine handles LLINK_UP events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtLinkUp( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ +{ + SK_U32 i; + SK_RLMT_PORT *pRPort; + SK_EVPARA Para2; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) + + pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; + if (!pRPort->PortStarted) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_UP Event EMPTY.\n")) + return; + } + + if (!pRPort->LinkDown) { + /* RA;:;: Any better solution? */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_UP Event EMPTY.\n")) + return; + } + + SkTimerStop(pAC, IoC, &pRPort->UpTimer); + SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); + SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); + + /* Do something if timer already fired? */ + + pRPort->LinkDown = SK_FALSE; + pRPort->PortState = SK_RLMT_PS_GOING_UP; + pRPort->GuTimeStamp = SkOsGetTime(pAC); + pRPort->BcTimeStamp = 0; + pRPort->Net->LinksUp++; + if (pRPort->Net->LinksUp == 1) { + SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); + } + else { + SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); + } + + for (i = 0; i < pRPort->Net->NumPorts; i++) { + if (!pRPort->Net->Port[i]->PortStarted) { + SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber); + } + } + + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + + if (pRPort->Net->LinksUp >= 2) { + if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { + /* Build the check chain. */ + SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); + } + } + + /* If the first link comes up, start the periodical RLMT timeout. */ + if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 && + (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) { + Para2.Para32[0] = pRPort->Net->NetNumber; + Para2.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer, + pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2); + } + + Para2 = Para; + Para2.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, + SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); + + /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ + if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && + (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && + (Para2.pParaPtr = + SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, + &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) + ) != NULL) { + /* Send "new" packet to RLMT multicast address. */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); + } + + if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { + if ((Para2.pParaPtr = + SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) { + pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; + pRPort->Net->CheckingState |= + SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; + + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); + + Para.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer, + SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_UP Event END.\n")) +} /* SkRlmtEvtLinkUp */ + + +/****************************************************************************** + * + * SkRlmtEvtPortUpTim - PORT_UP_TIM + * + * Description: + * This routine handles PORT_UP_TIM events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPortUpTim( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ +{ + SK_RLMT_PORT *pRPort; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) + return; + } + + pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; + if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) + return; + } + + pRPort->PortDown = SK_FALSE; + pRPort->PortState = SK_RLMT_PS_UP; + pRPort->Net->PortsUp++; + if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { + if (pAC->Rlmt.NumNets <= 1) { + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + } + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTUP_TIM Event END.\n")) +} /* SkRlmtEvtPortUpTim */ + + +/****************************************************************************** + * + * SkRlmtEvtPortDownTim - PORT_DOWN_* + * + * Description: + * This routine handles PORT_DOWN_* events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPortDownX( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Event, /* Event code */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ +{ + SK_RLMT_PORT *pRPort; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", + Para.Para32[0], Event)) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) + return; + } + + pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; + if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && + !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) + return; + } + + /* Stop port's timers. */ + SkTimerStop(pAC, IoC, &pRPort->UpTimer); + SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); + SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); + + if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) { + pRPort->PortState = SK_RLMT_PS_DOWN; + } + + if (!pRPort->PortDown) { + pRPort->Net->PortsUp--; + pRPort->PortDown = SK_TRUE; + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para); + } + + pRPort->PacketsPerTimeSlot = 0; + /* pRPort->DataPacketsPerTimeSlot = 0; */ + pRPort->BpduPacketsPerTimeSlot = 0; + pRPort->BcTimeStamp = 0; + + /* + * RA;:;: To be checked: + * - actions at RLMT_STOP: We should not switch anymore. + */ + if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { + if (Para.Para32[0] == + pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) { + /* Active Port went down. */ + SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) +} /* SkRlmtEvtPortDownX */ + + +/****************************************************************************** + * + * SkRlmtEvtLinkDown - LINK_DOWN + * + * Description: + * This routine handles LINK_DOWN events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtLinkDown( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ +{ + SK_RLMT_PORT *pRPort; + + pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) + + if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { + pRPort->Net->LinksUp--; + pRPort->LinkDown = SK_TRUE; + pRPort->PortState = SK_RLMT_PS_LINK_DOWN; + SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF); + + if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) { + /* Build the check chain. */ + SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); + } + + /* Ensure that port is marked down. */ + Para.Para32[1] = -1; + (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_LINK_DOWN Event END.\n")) +} /* SkRlmtEvtLinkDown */ + + +/****************************************************************************** + * + * SkRlmtEvtPortAddr - PORT_ADDR + * + * Description: + * This routine handles PORT_ADDR events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPortAddr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ +{ + SK_U32 i, j; + SK_RLMT_PORT *pRPort; + SK_MAC_ADDR *pOldMacAddr; + SK_MAC_ADDR *pNewMacAddr; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) + return; + } + + /* Port's physical MAC address changed. */ + pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress; + pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress; + + /* + * NOTE: This is not scalable for solutions where ports are + * checked remotely. There, we need to send an RLMT + * address change packet - and how do we ensure delivery? + */ + for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { + pRPort = &pAC->Rlmt.Port[i]; + for (j = 0; j < pRPort->PortsChecked; j++) { + if (SK_ADDR_EQUAL( + pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) { + pRPort->PortCheck[j].CheckAddr = *pNewMacAddr; + } + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PORT_ADDR Event END.\n")) +} /* SkRlmtEvtPortAddr */ + + +/****************************************************************************** + * + * SkRlmtEvtStart - START + * + * Description: + * This routine handles START events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtStart( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ + SK_EVPARA Para2; + SK_U32 PortIdx; + SK_U32 PortNumber; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[0])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Event EMPTY.\n")) + return; + } + + if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Event EMPTY.\n")) + return; + } + + if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("All nets should have been started.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Event EMPTY.\n")) + return; + } + + if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >= + pAC->Rlmt.Net[Para.Para32[0]].NumPorts) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG); + + /* Change PrefPort to internal default. */ + Para2.Para32[0] = 0xFFFFFFFF; + Para2.Para32[1] = Para.Para32[0]; + (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2); + } + + PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort; + PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber; + + pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0; + pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0; + pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0; + pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN; + + /* Start preferred port. */ + SkRlmtPortStart(pAC, IoC, PortNumber); + + /* Start Timer (for first port only). */ + Para2.Para32[0] = PortNumber; + Para2.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer, + SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2); + + pAC->Rlmt.NetsStarted++; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_START Event END.\n")) +} /* SkRlmtEvtStart */ + + +/****************************************************************************** + * + * SkRlmtEvtStop - STOP + * + * Description: + * This routine handles STOP events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtStop( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ + SK_EVPARA Para2; + SK_U32 PortNumber; + SK_U32 i; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[0])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Event EMPTY.\n")) + return; + } + + if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Event EMPTY.\n")) + return; + } + + if (pAC->Rlmt.NetsStarted == 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("All nets are stopped.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Event EMPTY.\n")) + return; + } + + /* Stop RLMT timers. */ + SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer); + SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer); + + /* Stop net. */ + pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT; + pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE; + Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL; + Para2.Para32[1] = Para.Para32[0]; /* Net# */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2); + + /* Stop ports. */ + for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { + PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; + if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) { + SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer); + SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer); + SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer); + + pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT; + pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; + pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE; + Para2.Para32[0] = PortNumber; + Para2.Para32[1] = (SK_U32)-1; + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2); + } + } + + pAC->Rlmt.NetsStarted--; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STOP Event END.\n")) +} /* SkRlmtEvtStop */ + + +/****************************************************************************** + * + * SkRlmtEvtTim - TIM + * + * Description: + * This routine handles TIM events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtTim( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ + SK_RLMT_PORT *pRPort; + SK_U32 Timeout; + SK_U32 NewTimeout; + SK_U32 PortNumber; + SK_U32 i; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_TIM Event BEGIN.\n")) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_TIM Event EMPTY.\n")) + return; + } + + if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 || + pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) { + /* Mode changed or all links down: No more link checking. */ + return; + } + +#if 0 + pAC->Rlmt.SwitchCheckCounter--; + if (pAC->Rlmt.SwitchCheckCounter == 0) { + pAC->Rlmt.SwitchCheckCounter; + } +#endif /* 0 */ + + NewTimeout = SK_RLMT_DEF_TO_VAL; + for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { + PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; + pRPort = &pAC->Rlmt.Port[PortNumber]; + if (!pRPort->LinkDown) { + Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber); + if (Timeout < NewTimeout) { + NewTimeout = Timeout; + } + + /* + * These counters should be set to 0 for all ports before the + * first frame is sent in the next loop. + */ + pRPort->PacketsPerTimeSlot = 0; + /* pRPort->DataPacketsPerTimeSlot = 0; */ + pRPort->BpduPacketsPerTimeSlot = 0; + } + } + pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout; + + if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) { + /* + * If checking remote ports, also send packets if + * (LinksUp == 1) && + * this port checks at least one (remote) port. + */ + + /* + * Must be new loop, as SkRlmtCheckPort can request to + * check segmentation when e.g. checking the last port. + */ + for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { + if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) { + SkRlmtSend(pAC, IoC, + pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber); + } + } + } + + SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer, + pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, + Para); + + if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 && + (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) && + (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) { + SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer, + SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); + pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG; + pAC->Rlmt.Net[Para.Para32[0]].CheckingState |= + SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_TIM Event END.\n")) +} /* SkRlmtEvtTim */ + + +/****************************************************************************** + * + * SkRlmtEvtSegTim - SEG_TIM + * + * Description: + * This routine handles SEG_TIM events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtSegTim( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ +#ifdef xDEBUG + int j; +#endif /* DEBUG */ + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SEG_TIM Event BEGIN.\n")) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SEG_TIM Event EMPTY.\n")) + return; + } + +#ifdef xDEBUG + for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) { + SK_ADDR_PORT *pAPort; + SK_U32 k; + SK_U16 *InAddr; + SK_U8 InAddr8[6]; + + InAddr = (SK_U16 *)&InAddr8[0]; + pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort; + for (k = 0; k < pAPort->NextExactMatchRlmt; k++) { + /* Get exact match address k from port j. */ + XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, + XM_EXM(k), InAddr); + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n", + k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, + InAddr8[0], InAddr8[1], InAddr8[2], + InAddr8[3], InAddr8[4], InAddr8[5], + pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], + pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], + pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) + } + } +#endif /* xDEBUG */ + + SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SEG_TIM Event END.\n")) +} /* SkRlmtEvtSegTim */ + + +/****************************************************************************** + * + * SkRlmtEvtPacketRx - PACKET_RECEIVED + * + * Description: + * This routine handles PACKET_RECEIVED events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPacketRx( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_MBUF *pMb */ +{ + SK_MBUF *pMb; + SK_MBUF *pNextMb; + SK_U32 NetNumber; + + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) + + /* Should we ignore frames during port switching? */ + +#ifdef DEBUG + pMb = Para.pParaPtr; + if (pMb == NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) + } + else if (pMb->pNext != NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("More than one mbuf or pMb->pNext not set.\n")) + } +#endif /* DEBUG */ + + for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) { + pNextMb = pMb->pNext; + pMb->pNext = NULL; + + NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber; + if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) { + SkDrvFreeRlmtMbuf(pAC, IoC, pMb); + } + else { + SkRlmtPacketReceive(pAC, IoC, pMb); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PACKET_RECEIVED Event END.\n")) +} /* SkRlmtEvtPacketRx */ + + +/****************************************************************************** + * + * SkRlmtEvtStatsClear - STATS_CLEAR + * + * Description: + * This routine handles STATS_CLEAR events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtStatsClear( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ + SK_U32 i; + SK_RLMT_PORT *pRPort; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[0])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) + return; + } + + /* Clear statistics for logical and physical ports. */ + for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { + pRPort = + &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber]; + pRPort->TxHelloCts = 0; + pRPort->RxHelloCts = 0; + pRPort->TxSpHelloReqCts = 0; + pRPort->RxSpHelloCts = 0; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_CLEAR Event END.\n")) +} /* SkRlmtEvtStatsClear */ + + +/****************************************************************************** + * + * SkRlmtEvtStatsUpdate - STATS_UPDATE + * + * Description: + * This routine handles STATS_UPDATE events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtStatsUpdate( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[0])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) + return; + } + + /* Update statistics - currently always up-to-date. */ + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_STATS_UPDATE Event END.\n")) +} /* SkRlmtEvtStatsUpdate */ + + +/****************************************************************************** + * + * SkRlmtEvtPrefportChange - PREFPORT_CHANGE + * + * Description: + * This routine handles PREFPORT_CHANGE events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtPrefportChange( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) + + if (Para.Para32[1] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[1])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) + return; + } + + /* 0xFFFFFFFF == auto-mode. */ + if (Para.Para32[0] == 0xFFFFFFFF) { + pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT; + } + else { + if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) + return; + } + + pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0]; + } + + pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0]; + + if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { + SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) +} /* SkRlmtEvtPrefportChange */ + + +/****************************************************************************** + * + * SkRlmtEvtSetNets - SET_NETS + * + * Description: + * This routine handles SET_NETS events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtSetNets( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ +{ + int i; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event BEGIN.\n")) + + if (Para.Para32[1] != (SK_U32)-1) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad Parameter.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || + Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad number of nets: %d.\n", Para.Para32[0])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event EMPTY.\n")) + return; + } + + /* Entering and leaving dual mode only allowed while nets are stopped. */ + if (pAC->Rlmt.NetsStarted > 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Changing dual mode only allowed while all nets are stopped.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event EMPTY.\n")) + return; + } + + if (Para.Para32[0] == 1) { + if (pAC->Rlmt.NumNets > 1) { + /* Clear logical MAC addr from second net's active port. */ + (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. + Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL); + pAC->Rlmt.Net[1].NumPorts = 0; + } + + pAC->Rlmt.NumNets = Para.Para32[0]; + for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { + pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; + pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; + pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ + pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; + /* Just assuming. */ + pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; + pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; + pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; + pAC->Rlmt.Net[i].NetNumber = i; + } + + pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0]; + pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; + + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("RLMT: Changed to one net with two ports.\n")) + } + else if (Para.Para32[0] == 2) { + pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; + pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; + pAC->Rlmt.Net[0].NumPorts = + pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; + + pAC->Rlmt.NumNets = Para.Para32[0]; + for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { + pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; + pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; + pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ + pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; + /* Just assuming. */ + pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; + pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; + pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; + + pAC->Rlmt.Net[i].NetNumber = i; + } + + /* Set logical MAC addr on second net's active port. */ + (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. + Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL); + + SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("RLMT: Changed to two nets with one port each.\n")) + } + else { + /* Not implemented for more than two nets. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SetNets not implemented for more than two nets.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event EMPTY.\n")) + return; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_SET_NETS Event END.\n")) +} /* SkRlmtSetNets */ + + +/****************************************************************************** + * + * SkRlmtEvtModeChange - MODE_CHANGE + * + * Description: + * This routine handles MODE_CHANGE events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * Nothing + */ +RLMT_STATIC void SkRlmtEvtModeChange( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ +{ + SK_EVPARA Para2; + SK_U32 i; + SK_U32 PrevRlmtMode; + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) + + if (Para.Para32[1] >= pAC->Rlmt.NumNets) { + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Bad NetNumber %d.\n", Para.Para32[1])) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) + return; + } + + Para.Para32[0] |= SK_RLMT_CHECK_LINK; + + if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) && + Para.Para32[0] != SK_RLMT_MODE_CLS) { + pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Forced RLMT mode to CLS on single port net.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) + return; + } + + /* Update RLMT mode. */ + PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode; + pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0]; + + if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) != + (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { + /* SK_RLMT_CHECK_LOC_LINK bit changed. */ + if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 && + pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 && + pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) { + /* 20001207 RA: Was "PortsUp == 1". */ + Para2.Para32[0] = Para.Para32[1]; + Para2.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer, + pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue, + SKGE_RLMT, SK_RLMT_TIM, Para2); + } + } + + if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) != + (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) { + /* SK_RLMT_CHECK_SEG bit changed. */ + for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) { + (void)SkAddrMcClear(pAC, IoC, + pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, + SK_ADDR_PERMANENT | SK_MC_SW_ONLY); + + /* Add RLMT MC address. */ + (void)SkAddrMcAdd(pAC, IoC, + pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, + &SkRlmtMcAddr, SK_ADDR_PERMANENT); + + if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & + SK_RLMT_CHECK_SEG) != 0) { + /* Add BPDU MC address. */ + (void)SkAddrMcAdd(pAC, IoC, + pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, + &BridgeMcAddr, SK_ADDR_PERMANENT); + + if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { + if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown && + (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( + pAC, IoC, i)) != NULL) { + pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet = + SK_FALSE; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); + } + } + } + (void)SkAddrMcUpdate(pAC, IoC, + pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber); + } /* for ... */ + + if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) { + Para2.Para32[0] = Para.Para32[1]; + Para2.Para32[1] = (SK_U32)-1; + SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer, + SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2); + } + } /* SK_RLMT_CHECK_SEG bit changed. */ + + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("SK_RLMT_MODE_CHANGE Event END.\n")) +} /* SkRlmtEvtModeChange */ + + +/****************************************************************************** + * + * SkRlmtEvent - a PORT- or an RLMT-specific event happened + * + * Description: + * This routine calls subroutines to handle PORT- and RLMT-specific events. + * + * Context: + * runtime, pageable? + * may be called after SK_INIT_IO + * + * Returns: + * 0 + */ +int SkRlmtEvent( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Event, /* Event code */ +SK_EVPARA Para) /* Event-specific parameter */ +{ + switch (Event) { + + /* ----- PORT events ----- */ + + case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ + SkRlmtEvtPortStartTim(pAC, IoC, Para); + break; + case SK_RLMT_LINK_UP: /* From SIRQ. */ + SkRlmtEvtLinkUp(pAC, IoC, Para); + break; + case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ + SkRlmtEvtPortUpTim(pAC, IoC, Para); + break; + case SK_RLMT_PORTDOWN: /* From RLMT. */ + case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */ + case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */ + SkRlmtEvtPortDownX(pAC, IoC, Event, Para); + break; + case SK_RLMT_LINK_DOWN: /* From SIRQ. */ + SkRlmtEvtLinkDown(pAC, IoC, Para); + break; + case SK_RLMT_PORT_ADDR: /* From ADDR. */ + SkRlmtEvtPortAddr(pAC, IoC, Para); + break; + + /* ----- RLMT events ----- */ + + case SK_RLMT_START: /* From DRV. */ + SkRlmtEvtStart(pAC, IoC, Para); + break; + case SK_RLMT_STOP: /* From DRV. */ + SkRlmtEvtStop(pAC, IoC, Para); + break; + case SK_RLMT_TIM: /* From RLMT via TIME. */ + SkRlmtEvtTim(pAC, IoC, Para); + break; + case SK_RLMT_SEG_TIM: + SkRlmtEvtSegTim(pAC, IoC, Para); + break; + case SK_RLMT_PACKET_RECEIVED: /* From DRV. */ + SkRlmtEvtPacketRx(pAC, IoC, Para); + break; + case SK_RLMT_STATS_CLEAR: /* From PNMI. */ + SkRlmtEvtStatsClear(pAC, IoC, Para); + break; + case SK_RLMT_STATS_UPDATE: /* From PNMI. */ + SkRlmtEvtStatsUpdate(pAC, IoC, Para); + break; + case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */ + SkRlmtEvtPrefportChange(pAC, IoC, Para); + break; + case SK_RLMT_MODE_CHANGE: /* From PNMI. */ + SkRlmtEvtModeChange(pAC, IoC, Para); + break; + case SK_RLMT_SET_NETS: /* From DRV. */ + SkRlmtEvtSetNets(pAC, IoC, Para); + break; + + /* ----- Unknown events ----- */ + + default: /* Create error log entry. */ + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, + ("Unknown RLMT Event %d.\n", Event)) + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); + break; + } /* switch() */ + + return (0); +} /* SkRlmtEvent */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c new file mode 100644 index 0000000000..37cd4c9fe1 --- /dev/null +++ b/drivers/net/sk98lin/sktimer.c @@ -0,0 +1,297 @@ +/****************************************************************************** + * + * Name: sktimer.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.12 $ + * Date: $Date: 1999/11/22 13:38:51 $ + * Purpose: High level timer functions. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sktimer.c,v $ + * Revision 1.12 1999/11/22 13:38:51 cgoos + * Changed license header to GPL. + * + * Revision 1.11 1998/12/17 13:24:13 gklug + * fix: restart problem: do NOT destroy timer queue if init 1 is done + * + * Revision 1.10 1998/10/15 15:11:36 gklug + * fix: ID_sccs to SysKonnectFileId + * + * Revision 1.9 1998/09/15 15:15:04 cgoos + * Changed TRUE/FALSE to SK_TRUE/SK_FALSE + * + * Revision 1.8 1998/09/08 08:47:55 gklug + * add: init level handling + * + * Revision 1.7 1998/08/19 09:50:53 gklug + * fix: remove struct keyword from c-code (see CCC) add typedefs + * + * Revision 1.6 1998/08/17 13:43:13 gklug + * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR + * + * Revision 1.5 1998/08/14 07:09:14 gklug + * fix: chg pAc -> pAC + * + * Revision 1.4 1998/08/07 12:53:46 gklug + * fix: first compiled version + * + * Revision 1.3 1998/08/07 09:31:53 gklug + * fix: delta spelling + * + * Revision 1.2 1998/08/07 09:31:02 gklug + * adapt functions to new c coding conventions + * rmv: "fast" handling + * chg: inserting of new timer in queue. + * chg: event queue generation when timer runs out + * + * Revision 1.1 1998/08/05 11:27:55 gklug + * first version: adapted from SMT + * + * + * + * + ******************************************************************************/ + + +#include + +#ifdef CONFIG_SK98 + +/* + Event queue and dispatcher +*/ +static const char SysKonnectFileId[] = + "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ; + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef __C2MAN__ +/* + Event queue management. + + General Description: + + */ +intro() +{} +#endif + + +/* Forward declaration */ +static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); + + +/* + * Inits the software timer + * + * needs to be called during Init level 1. + */ +void SkTimerInit( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc, /* IoContext */ +int Level) /* Init Level */ +{ + switch (Level) { + case SK_INIT_DATA: + pAC->Tim.StQueue = 0 ; + break; + case SK_INIT_IO: + SkHwtInit(pAC,Ioc) ; + SkTimerDone(pAC, Ioc); + break; + default: + break; + } +} + +/* + * Stops a high level timer + * - If a timer is not in the queue the function returns normally, too. + */ +void SkTimerStop( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc, /* IoContext */ +SK_TIMER *pTimer) /* Timer Pointer to be started */ +{ + SK_TIMER **ppTimPrev ; + SK_TIMER *pTm ; + + /* + * remove timer from queue + */ + pTimer->TmActive = SK_FALSE ; + if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { + SkHwtStop(pAC,Ioc) ; + } + for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + ppTimPrev = &pTm->TmNext ) { + if (pTm == pTimer) { + /* + * Timer found in queue + * - dequeue it and + * - correct delta of the next timer + */ + *ppTimPrev = pTm->TmNext ; + + if (pTm->TmNext) { + /* correct delta of next timer in queue */ + pTm->TmNext->TmDelta += pTm->TmDelta ; + } + return ; + } + } +} + +/* + * Start a high level software timer + */ +void SkTimerStart( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc, /* IoContext */ +SK_TIMER *pTimer, /* Timer Pointer to be started */ +SK_U32 Time, /* Time value */ +SK_U32 Class, /* Event Class for this timer */ +SK_U32 Event, /* Event Value for this timer */ +SK_EVPARA Para) /* Event Parameter for this timer */ +{ + SK_TIMER **ppTimPrev ; + SK_TIMER *pTm ; + SK_U32 Delta ; + + Time /= 16 ; /* input is uS, clock ticks are 16uS */ + if (!Time) + Time = 1 ; + + SkTimerStop(pAC,Ioc,pTimer) ; + + pTimer->TmClass = Class ; + pTimer->TmEvent = Event ; + pTimer->TmPara = Para ; + pTimer->TmActive = SK_TRUE ; + + if (!pAC->Tim.StQueue) { + /* First Timer to be started */ + pAC->Tim.StQueue = pTimer ; + pTimer->TmNext = 0 ; + pTimer->TmDelta = Time ; + SkHwtStart(pAC,Ioc,Time) ; + return ; + } + + /* + * timer correction + */ + timer_done(pAC,Ioc,0) ; + + /* + * find position in queue + */ + Delta = 0 ; + for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + ppTimPrev = &pTm->TmNext ) { + if (Delta + pTm->TmDelta > Time) { + /* Position found */ + /* Here the timer needs to be inserted. */ + break ; + } + Delta += pTm->TmDelta ; + } + + /* insert in queue */ + *ppTimPrev = pTimer ; + pTimer->TmNext = pTm ; + pTimer->TmDelta = Time - Delta ; + + if (pTm) { + /* There is a next timer + * -> correct its Delta value. + */ + pTm->TmDelta -= pTimer->TmDelta ; + } + + /* + * start new with first + */ + SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; +} + + +void SkTimerDone( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc) /* IoContext */ +{ + timer_done(pAC,Ioc,1) ; +} + + +static void timer_done( +SK_AC *pAC, /* Adapters context */ +SK_IOC Ioc, /* IoContext */ +int Restart) /* Do we need to restart the Hardware timer ? */ +{ + SK_U32 Delta ; + SK_TIMER *pTm ; + SK_TIMER *pTComp ; /* Timer completed now now */ + SK_TIMER **ppLast ; /* Next field of Last timer to be deq */ + int Done = 0 ; + + Delta = SkHwtRead(pAC,Ioc) ; + ppLast = &pAC->Tim.StQueue ; + pTm = pAC->Tim.StQueue ; + while (pTm && !Done) { + if (Delta >= pTm->TmDelta) { + /* Timer ran out */ + pTm->TmActive = SK_FALSE ; + Delta -= pTm->TmDelta ; + ppLast = &pTm->TmNext ; + pTm = pTm->TmNext ; + } else { + /* We found the first timer that did not run out */ + pTm->TmDelta -= Delta ; + Delta = 0 ; + Done = 1 ; + } + } + *ppLast = 0 ; + /* + * pTm points to the first Timer that did not run out. + * StQueue points to the first Timer that run out. + */ + + for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) { + SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, + pTComp->TmPara) ; + } + + /* Set head of timer queue to the first timer that did not run out */ + pAC->Tim.StQueue = pTm ; + + if (Restart && pAC->Tim.StQueue) { + /* Restart HW timer */ + SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; + } +} + +#endif /* CONFIG_SK98 */ + +/* End of file */ diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c new file mode 100644 index 0000000000..3b81e67df8 --- /dev/null +++ b/drivers/net/sk98lin/skvpd.c @@ -0,0 +1,1329 @@ +/****************************************************************************** + * + * Name: skvpd.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.37 $ + * Date: $Date: 2003/01/13 10:42:45 $ + * Purpose: Shared software to read and write VPD data + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skvpd.c,v $ + * Revision 1.37 2003/01/13 10:42:45 rschmidt + * Replaced check for PCI device Id from YUKON with GENESIS + * to set the VPD size in VpdInit() + * Editorial changes + * + * Revision 1.36 2002/11/14 15:16:56 gheinig + * Added const specifier to key and buf parameters for VpdPara, VpdRead + * and VpdWrite for Diag 7 GUI + * + * Revision 1.35 2002/10/21 14:31:59 gheinig + * Took out CVS web garbage at head of file + * + * Revision 1.34 2002/10/21 11:47:24 gheinig + * Reverted to version 1.32 due to unwanted commit + * + * Revision 1.32 2002/10/14 16:04:29 rschmidt + * Added saving of VPD ROM Size from PCI_OUR_REG_2 + * Avoid reading of PCI_OUR_REG_2 in VpdTransferBlock() + * Editorial changes + * + * Revision 1.31 2002/09/10 09:21:32 mkarl + * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis + * + * Revision 1.30 2002/09/09 14:43:03 mkarl + * changes for diagnostics in order to read VPD data before the adapter + * has been initialized + * editorial changes + * + * Revision 1.29 2002/07/26 13:20:43 mkarl + * added Yukon support + * save size of VPD in pAC->vpd.vpd_size + * + * Revision 1.28 2002/04/02 15:31:47 afischer + * Bug fix in VpdWait() + * + * Revision 1.27 2000/08/10 11:29:06 rassmann + * Editorial changes. + * Preserving 32-bit alignment in structs for the adapter context. + * Removed unused function VpdWriteDword() (#if 0). + * Made VpdReadKeyword() available for SKDIAG only. + * + * Revision 1.26 2000/06/13 08:00:01 mkarl + * additional cast to avoid compile problems in 64 bit environment + * + * Revision 1.25 1999/11/22 13:39:32 cgoos + * Changed license header to GPL. + * + * Revision 1.24 1999/03/11 14:25:49 malthoff + * Replace __STDC__ with SK_KR_PROTO. + * + * Revision 1.23 1999/01/11 15:13:11 gklug + * fix: syntax error + * + * Revision 1.22 1998/10/30 06:41:15 gklug + * rmv: WARNING + * + * Revision 1.21 1998/10/29 07:15:14 gklug + * fix: Write Stream function needs verify. + * + * Revision 1.20 1998/10/28 18:05:08 gklug + * chg: no DEBUG in VpdMayWrite + * + * Revision 1.19 1998/10/28 15:56:11 gklug + * fix: Return len at end of ReadStream + * fix: Write even less than 4 bytes correctly + * + * Revision 1.18 1998/10/28 09:00:47 gklug + * fix: unreferenced local vars + * + * Revision 1.17 1998/10/28 08:25:45 gklug + * fix: WARNING + * + * Revision 1.16 1998/10/28 08:17:30 gklug + * fix: typo + * + * Revision 1.15 1998/10/28 07:50:32 gklug + * fix: typo + * + * Revision 1.14 1998/10/28 07:20:38 gklug + * chg: Interface functions to use IoC as parameter as well + * fix: VpdRead/WriteDWord now returns SK_U32 + * chg: VPD_IN/OUT names conform to SK_IN/OUT + * add: usage of VPD_IN/OUT8 macros + * add: VpdRead/Write Stream functions to r/w a stream of data + * fix: VpdTransferBlock swapped illegal + * add: VpdMayWrite + * + * Revision 1.13 1998/10/22 10:02:37 gklug + * fix: SysKonnectFileId typo + * + * Revision 1.12 1998/10/20 10:01:01 gklug + * fix: parameter to SkOsGetTime + * + * Revision 1.11 1998/10/15 12:51:48 malthoff + * Remove unrequired parameter p in vpd_setup_para(). + * + * Revision 1.10 1998/10/08 14:52:43 malthoff + * Remove CvsId by SysKonnectFileId. + * + * Revision 1.9 1998/09/16 07:33:52 malthoff + * replace memcmp() by SK_MEMCMP and + * memcpy() by SK_MEMCPY() to be + * independent from the 'C' Standard Library. + * + * Revision 1.8 1998/08/19 12:52:35 malthoff + * compiler fix: use SK_VPD_KEY instead of S_VPD. + * + * Revision 1.7 1998/08/19 08:14:01 gklug + * fix: remove struct keyword as much as possible from the C-code (see CCC) + * + * Revision 1.6 1998/08/18 13:03:58 gklug + * SkOsGetTime now returns SK_U64 + * + * Revision 1.5 1998/08/18 08:17:29 malthoff + * Ensure we issue a VPD read in vpd_read_dword(). + * Discard all VPD keywords other than Vx or Yx, where + * x is '0..9' or 'A..Z'. + * + * Revision 1.4 1998/07/03 14:52:19 malthoff + * Add category SK_DBGCAT_FATAL to some debug macros. + * bug fix: correct the keyword name check in vpd_write(). + * + * Revision 1.3 1998/06/26 11:16:53 malthoff + * Correct the modified File Identifier. + * + * Revision 1.2 1998/06/26 11:13:43 malthoff + * Modify the File Identifier. + * + * Revision 1.1 1998/06/19 14:11:08 malthoff + * Created, Tests with AIX were performed successfully + * + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +/* + Please refer skvpd.txt for infomation how to include this module + */ +static const char SysKonnectFileId[] = + "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK"; + +#include "h/skdrv1st.h" +#include "h/sktypes.h" +#include "h/skdebug.h" +#include "h/skdrv2nd.h" + +/* + * Static functions + */ +#ifndef SK_KR_PROTO +static SK_VPD_PARA *vpd_find_para( + SK_AC *pAC, + const char *key, + SK_VPD_PARA *p); +#else /* SK_KR_PROTO */ +static SK_VPD_PARA *vpd_find_para(); +#endif /* SK_KR_PROTO */ + +/* + * waits for a completion of a VPD transfer + * The VPD transfer must complete within SK_TICKS_PER_SEC/16 + * + * returns 0: success, transfer completes + * error exit(9) with a error message + */ +static int VpdWait( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC, /* IO Context */ +int event) /* event to wait for (VPD_READ / VPD_write) completion*/ +{ + SK_U64 start_time; + SK_U16 state; + + SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD wait for %s\n", event?"Write":"Read")); + start_time = SkOsGetTime(pAC); + do { + if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { + + /* Bug fix AF: Thu Mar 28 2002 + * Do not call: VPD_STOP(pAC, IoC); + * A pending VPD read cycle can not be aborted by writing + * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register). + * Although the write threshold in the OUR-register protects + * VPD read only space from being overwritten this does not + * protect a VPD read from being `converted` into a VPD write + * operation (on the fly). As a consequence the VPD_STOP would + * delete VPD read only data. In case of any problems with the + * I2C bus we exit the loop here. The I2C read operation can + * not be aborted except by a reset (->LR). + */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR, + ("ERROR:VPD wait timeout\n")); + return(1); + } + + VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state); + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("state = %x, event %x\n",state,event)); + } while((int)(state & PCI_VPD_FLAG) == event); + + return(0); +} + +#ifdef SKDIAG + +/* + * Read the dword at address 'addr' from the VPD EEPROM. + * + * Needed Time: MIN 1,3 ms MAX 2,6 ms + * + * Note: The DWord is returned in the endianess of the machine the routine + * is running on. + * + * Returns the data read. + */ +SK_U32 VpdReadDWord( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC, /* IO Context */ +int addr) /* VPD address */ +{ + SK_U32 Rtv; + + /* start VPD read */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD read dword at 0x%x\n",addr)); + addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */ + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr); + + /* ignore return code here */ + (void)VpdWait(pAC, IoC, VPD_READ); + + /* Don't swap here, it's a data stream of bytes */ + Rtv = 0; + + VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv); + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD read dword data = 0x%x\n",Rtv)); + return(Rtv); +} + +#endif /* SKDIAG */ + +#if 0 + +/* + Write the dword 'data' at address 'addr' into the VPD EEPROM, and + verify that the data is written. + + Needed Time: + +. MIN MAX +. ------------------------------------------------------------------- +. write 1.8 ms 3.6 ms +. internal write cyles 0.7 ms 7.0 ms +. ------------------------------------------------------------------- +. over all program time 2.5 ms 10.6 ms +. read 1.3 ms 2.6 ms +. ------------------------------------------------------------------- +. over all 3.8 ms 13.2 ms +. + + + Returns 0: success + 1: error, I2C transfer does not terminate + 2: error, data verify error + + */ +static int VpdWriteDWord( +SK_AC *pAC, /* pAC pointer */ +SK_IOC IoC, /* IO Context */ +int addr, /* VPD address */ +SK_U32 data) /* VPD data to write */ +{ + /* start VPD write */ + /* Don't swap here, it's a data stream of bytes */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD write dword at addr 0x%x, data = 0x%x\n",addr,data)); + VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data); + /* But do it here */ + addr |= VPD_WRITE; + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE)); + + /* this may take up to 10,6 ms */ + if (VpdWait(pAC, IoC, VPD_WRITE)) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("Write Timed Out\n")); + return(1); + }; + + /* verify data */ + if (VpdReadDWord(pAC, IoC, addr) != data) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Data Verify Error\n")); + return(2); + } + return(0); +} /* VpdWriteDWord */ + +#endif /* 0 */ + +/* + * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from + * or to the I2C EEPROM. + * + * Returns number of bytes read / written. + */ +static int VpdWriteStream( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC, /* IO Context */ +char *buf, /* data buffer */ +int Addr, /* VPD start address */ +int Len) /* number of bytes to read / to write */ +{ + int i; + int j; + SK_U16 AdrReg; + int Rtv; + SK_U8 * pComp; /* Compare pointer */ + SK_U8 Data; /* Input Data for Compare */ + + /* Init Compare Pointer */ + pComp = (SK_U8 *) buf; + + for (i = 0; i < Len; i++, buf++) { + if ((i%sizeof(SK_U32)) == 0) { + /* + * At the begin of each cycle read the Data Reg + * So it is initialized even if only a few bytes + * are written. + */ + AdrReg = (SK_U16) Addr; + AdrReg &= ~VPD_WRITE; /* READ operation */ + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); + + /* Wait for termination */ + Rtv = VpdWait(pAC, IoC, VPD_READ); + if (Rtv != 0) { + return(i); + } + } + + /* Write current Byte */ + VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), + *(SK_U8*)buf); + + if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) { + /* New Address needs to be written to VPD_ADDR reg */ + AdrReg = (SK_U16) Addr; + Addr += sizeof(SK_U32); + AdrReg |= VPD_WRITE; /* WRITE operation */ + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); + + /* Wait for termination */ + Rtv = VpdWait(pAC, IoC, VPD_WRITE); + if (Rtv != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("Write Timed Out\n")); + return(i - (i%sizeof(SK_U32))); + } + + /* + * Now re-read to verify + */ + AdrReg &= ~VPD_WRITE; /* READ operation */ + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); + + /* Wait for termination */ + Rtv = VpdWait(pAC, IoC, VPD_READ); + if (Rtv != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("Verify Timed Out\n")); + return(i - (i%sizeof(SK_U32))); + } + + for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { + + VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); + + if (Data != *pComp) { + /* Verify Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("WriteStream Verify Error\n")); + return(i - (i%sizeof(SK_U32)) + j); + } + } + } + } + + return(Len); +} + + +/* + * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from + * or to the I2C EEPROM. + * + * Returns number of bytes read / written. + */ +static int VpdReadStream( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC, /* IO Context */ +char *buf, /* data buffer */ +int Addr, /* VPD start address */ +int Len) /* number of bytes to read / to write */ +{ + int i; + SK_U16 AdrReg; + int Rtv; + + for (i = 0; i < Len; i++, buf++) { + if ((i%sizeof(SK_U32)) == 0) { + /* New Address needs to be written to VPD_ADDR reg */ + AdrReg = (SK_U16) Addr; + Addr += sizeof(SK_U32); + AdrReg &= ~VPD_WRITE; /* READ operation */ + + VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); + + /* Wait for termination */ + Rtv = VpdWait(pAC, IoC, VPD_READ); + if (Rtv != 0) { + return(i); + } + } + VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), + (SK_U8 *)buf); + } + + return(Len); +} + +/* + * Read ore writes 'len' bytes of VPD data, starting at 'addr' from + * or to the I2C EEPROM. + * + * Returns number of bytes read / written. + */ +static int VpdTransferBlock( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC, /* IO Context */ +char *buf, /* data buffer */ +int addr, /* VPD start address */ +int len, /* number of bytes to read / to write */ +int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ +{ + int Rtv; /* Return value */ + int vpd_rom_size; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD %s block, addr = 0x%x, len = %d\n", + dir ? "write" : "read", addr, len)); + + if (len == 0) + return(0); + + vpd_rom_size = pAC->vpd.rom_size; + + if (addr > vpd_rom_size - 4) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Address error: 0x%x, exp. < 0x%x\n", + addr, vpd_rom_size - 4)); + return(0); + } + + if (addr + len > vpd_rom_size) { + len = vpd_rom_size - addr; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("Warning: len was cut to %d\n", len)); + } + + if (dir == VPD_READ) { + Rtv = VpdReadStream(pAC, IoC, buf, addr, len); + } + else { + Rtv = VpdWriteStream(pAC, IoC, buf, addr, len); + } + + return(Rtv); +} + +#ifdef SKDIAG + +/* + * Read 'len' bytes of VPD data, starting at 'addr'. + * + * Returns number of bytes read. + */ +int VpdReadBlock( +SK_AC *pAC, /* pAC pointer */ +SK_IOC IoC, /* IO Context */ +char *buf, /* buffer were the data should be stored */ +int addr, /* start reading at the VPD address */ +int len) /* number of bytes to read */ +{ + return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); +} + +/* + * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. + * + * Returns number of bytes writes. + */ +int VpdWriteBlock( +SK_AC *pAC, /* pAC pointer */ +SK_IOC IoC, /* IO Context */ +char *buf, /* buffer, holds the data to write */ +int addr, /* start writing at the VPD address */ +int len) /* number of bytes to write */ +{ + return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); +} +#endif /* SKDIAG */ + +/* + * (re)initialize the VPD buffer + * + * Reads the VPD data from the EEPROM into the VPD buffer. + * Get the remaining read only and read / write space. + * + * return 0: success + * 1: fatal VPD error + */ +static int VpdInit( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC) /* IO Context */ +{ + SK_VPD_PARA *r, rp; /* RW or RV */ + int i; + unsigned char x; + int vpd_size; + SK_U16 dev_id; + SK_U32 our_reg2; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); + + VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); + + VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); + + pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); + + /* + * this function might get used before the hardware is initialized + * therefore we cannot always trust in GIChipId + */ + if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 && + dev_id != VPD_DEV_ID_GENESIS) || + ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 && + !pAC->GIni.GIGenesis)) { + + /* for Yukon the VPD size is always 256 */ + vpd_size = VPD_SIZE_YUKON; + } + else { + /* Genesis uses the maximum ROM size up to 512 for VPD */ + if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) { + vpd_size = VPD_SIZE_GENESIS; + } + else { + vpd_size = pAC->vpd.rom_size; + } + } + + /* read the VPD data into the VPD buffer */ + if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ) + != vpd_size) { + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("Block Read Error\n")); + return(1); + } + + pAC->vpd.vpd_size = vpd_size; + + /* find the end tag of the RO area */ + if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Encoding Error: RV Tag not found\n")); + return(1); + } + + if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) { + SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Encoding Error: Invalid VPD struct size\n")); + return(1); + } + pAC->vpd.v.vpd_free_ro = r->p_len - 1; + + /* test the checksum */ + for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) { + x += pAC->vpd.vpd_buf[i]; + } + + if (x != 0) { + /* checksum error */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("VPD Checksum Error\n")); + return(1); + } + + /* find and check the end tag of the RW area */ + if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Encoding Error: RV Tag not found\n")); + return(1); + } + + if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Encoding Error: Invalid VPD struct size\n")); + return(1); + } + pAC->vpd.v.vpd_free_rw = r->p_len; + + /* everything seems to be ok */ + if (pAC->GIni.GIChipId != 0) { + pAC->vpd.v.vpd_status |= VPD_VALID; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, + ("done. Free RO = %d, Free RW = %d\n", + pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); + + return(0); +} + +/* + * find the Keyword 'key' in the VPD buffer and fills the + * parameter struct 'p' with it's values + * + * returns *p success + * 0: parameter was not found or VPD encoding error + */ +static SK_VPD_PARA *vpd_find_para( +SK_AC *pAC, /* common data base */ +const char *key, /* keyword to find (e.g. "MN") */ +SK_VPD_PARA *p) /* parameter description struct */ +{ + char *v ; /* points to VPD buffer */ + int max; /* Maximum Number of Iterations */ + + v = pAC->vpd.vpd_buf; + max = 128; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD find para %s .. ",key)); + + /* check mandatory resource type ID string (Product Name) */ + if (*v != (char)RES_ID) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Error: 0x%x missing\n", RES_ID)); + return(0); + } + + if (strcmp(key, VPD_NAME) == 0) { + p->p_len = VPD_GET_RES_LEN(v); + p->p_val = VPD_GET_VAL(v); + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("found, len = %d\n", p->p_len)); + return(p); + } + + v += 3 + VPD_GET_RES_LEN(v) + 3; + for (;; ) { + if (SK_MEMCMP(key,v,2) == 0) { + p->p_len = VPD_GET_VPD_LEN(v); + p->p_val = VPD_GET_VAL(v); + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("found, len = %d\n",p->p_len)); + return(p); + } + + /* exit when reaching the "RW" Tag or the maximum of itera. */ + max--; + if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { + break; + } + + if (SK_MEMCMP(VPD_RV,v,2) == 0) { + v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ + } + else { + v += 3 + VPD_GET_VPD_LEN(v); + } + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])); + } + +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); + if (max == 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Key/Len Encoding error\n")); + } +#endif /* DEBUG */ + return(0); +} + +/* + * Move 'n' bytes. Begin with the last byte if 'n' is > 0, + * Start with the last byte if n is < 0. + * + * returns nothing + */ +static void vpd_move_para( +char *start, /* start of memory block */ +char *end, /* end of memory block to move */ +int n) /* number of bytes the memory block has to be moved */ +{ + char *p; + int i; /* number of byte copied */ + + if (n == 0) + return; + + i = (int) (end - start + 1); + if (n < 0) { + p = start + n; + while (i != 0) { + *p++ = *start++; + i--; + } + } + else { + p = end + n; + while (i != 0) { + *p-- = *end--; + i--; + } + } +} + +/* + * setup the VPD keyword 'key' at 'ip'. + * + * returns nothing + */ +static void vpd_insert_key( +const char *key, /* keyword to insert */ +const char *buf, /* buffer with the keyword value */ +int len, /* length of the value string */ +char *ip) /* inseration point */ +{ + SK_VPD_KEY *p; + + p = (SK_VPD_KEY *) ip; + p->p_key[0] = key[0]; + p->p_key[1] = key[1]; + p->p_len = (unsigned char) len; + SK_MEMCPY(&p->p_val,buf,len); +} + +/* + * Setup the VPD end tag "RV" / "RW". + * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. + * + * returns 0: success + * 1: encoding error + */ +static int vpd_mod_endtag( +SK_AC *pAC, /* common data base */ +char *etp) /* end pointer input position */ +{ + SK_VPD_KEY *p; + unsigned char x; + int i; + int vpd_size; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1])); + + vpd_size = pAC->vpd.vpd_size; + + p = (SK_VPD_KEY *) etp; + + if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { + /* something wrong here, encoding error */ + SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + ("Encoding Error: invalid end tag\n")); + return(1); + } + if (etp > pAC->vpd.vpd_buf + vpd_size/2) { + /* create "RW" tag */ + p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1); + pAC->vpd.v.vpd_free_rw = (int) p->p_len; + i = pAC->vpd.v.vpd_free_rw; + etp += 3; + } + else { + /* create "RV" tag */ + p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3); + pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1; + + /* setup checksum */ + for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { + x += pAC->vpd.vpd_buf[i]; + } + p->p_val = (char) 0 - x; + i = pAC->vpd.v.vpd_free_ro; + etp += 4; + } + while (i) { + *etp++ = 0x00; + i--; + } + + return(0); +} + +/* + * Insert a VPD keyword into the VPD buffer. + * + * The keyword 'key' is inserted at the position 'ip' in the + * VPD buffer. + * The keywords behind the input position will + * be moved. The VPD end tag "RV" or "RW" is generated again. + * + * returns 0: success + * 2: value string was cut + * 4: VPD full, keyword was not written + * 6: fatal VPD error + * + */ +int VpdSetupPara( +SK_AC *pAC, /* common data base */ +const char *key, /* keyword to insert */ +const char *buf, /* buffer with the keyword value */ +int len, /* length of the keyword value */ +int type, /* VPD_RO_KEY or VPD_RW_KEY */ +int op) /* operation to do: ADD_KEY or OWR_KEY */ +{ + SK_VPD_PARA vp; + char *etp; /* end tag position */ + int free; /* remaining space in selected area */ + char *ip; /* input position inside the VPD buffer */ + int rtv; /* return code */ + int head; /* additional haeder bytes to move */ + int found; /* additinoal bytes if the keyword was found */ + int vpd_size; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("VPD setup para key = %s, val = %s\n",key,buf)); + + vpd_size = pAC->vpd.vpd_size; + + rtv = 0; + ip = 0; + if (type == VPD_RW_KEY) { + /* end tag is "RW" */ + free = pAC->vpd.v.vpd_free_rw; + etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3); + } + else { + /* end tag is "RV" */ + free = pAC->vpd.v.vpd_free_ro; + etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4); + } + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("Free RO = %d, Free RW = %d\n", + pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); + + head = 0; + found = 0; + if (op == OWR_KEY) { + if (vpd_find_para(pAC, key, &vp)) { + found = 3; + ip = vp.p_val - 3; + free += vp.p_len + 3; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("Overwrite Key\n")); + } + else { + op = ADD_KEY; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + ("Add Key\n")); + } + } + if (op == ADD_KEY) { + ip = etp; + vp.p_len = 0; + head = 3; + } + + if (len + 3 > free) { + if (free < 7) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD Buffer Overflow, keyword not written\n")); + return(4); + } + /* cut it again */ + len = free - 3; + rtv = 2; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD Buffer Full, Keyword was cut\n")); + } + + vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head); + vpd_insert_key(key, buf, len, ip); + if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) { + pAC->vpd.v.vpd_status &= ~VPD_VALID; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD Encoding Error\n")); + return(6); + } + + return(rtv); +} + + +/* + * Read the contents of the VPD EEPROM and copy it to the + * VPD buffer if not already done. + * + * return: A pointer to the vpd_status structure. The structure contains + * this fields. + */ +SK_VPD_STATUS *VpdStat( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC) /* IO Context */ +{ + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + (void)VpdInit(pAC, IoC); + } + return(&pAC->vpd.v); +} + + +/* + * Read the contents of the VPD EEPROM and copy it to the VPD + * buffer if not already done. + * Scan the VPD buffer for VPD keywords and create the VPD + * keyword list by copying the keywords to 'buf', all after + * each other and terminated with a '\0'. + * + * Exceptions: o The Resource Type ID String (product name) is called "Name" + * o The VPD end tags 'RV' and 'RW' are not listed + * + * The number of copied keywords is counted in 'elements'. + * + * returns 0: success + * 2: buffer overfull, one or more keywords are missing + * 6: fatal VPD error + * + * example values after returning: + * + * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0" + * *len = 30 + * *elements = 9 + */ +int VpdKeys( +SK_AC *pAC, /* common data base */ +SK_IOC IoC, /* IO Context */ +char *buf, /* buffer where to copy the keywords */ +int *len, /* buffer length */ +int *elements) /* number of keywords returned */ +{ + char *v; + int n; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. ")); + *elements = 0; + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + if (VpdInit(pAC, IoC) != 0) { + *len = 0; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD Init Error, terminated\n")); + return(6); + } + } + + if ((signed)strlen(VPD_NAME) + 1 <= *len) { + v = pAC->vpd.vpd_buf; + strcpy(buf,VPD_NAME); + n = strlen(VPD_NAME) + 1; + buf += n; + *elements = 1; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, + ("'%c%c' ",v[0],v[1])); + } + else { + *len = 0; + SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, + ("buffer overflow\n")); + return(2); + } + + v += 3 + VPD_GET_RES_LEN(v) + 3; + for (;; ) { + /* exit when reaching the "RW" Tag */ + if (SK_MEMCMP(VPD_RW,v,2) == 0) { + break; + } + + if (SK_MEMCMP(VPD_RV,v,2) == 0) { + v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ + continue; + } + + if (n+3 <= *len) { + SK_MEMCPY(buf,v,2); + buf += 2; + *buf++ = '\0'; + n += 3; + v += 3 + VPD_GET_VPD_LEN(v); + *elements += 1; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, + ("'%c%c' ",v[0],v[1])); + } + else { + *len = n; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("buffer overflow\n")); + return(2); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n")); + *len = n; + return(0); +} + + +/* + * Read the contents of the VPD EEPROM and copy it to the + * VPD buffer if not already done. Search for the VPD keyword + * 'key' and copy its value to 'buf'. Add a terminating '\0'. + * If the value does not fit into the buffer cut it after + * 'len' - 1 bytes. + * + * returns 0: success + * 1: keyword not found + * 2: value string was cut + * 3: VPD transfer timeout + * 6: fatal VPD error + */ +int VpdRead( +SK_AC *pAC, /* common data base */ +SK_IOC IoC, /* IO Context */ +const char *key, /* keyword to read (e.g. "MN") */ +char *buf, /* buffer where to copy the keyword value */ +int *len) /* buffer length */ +{ + SK_VPD_PARA *p, vp; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key)); + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + if (VpdInit(pAC, IoC) != 0) { + *len = 0; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD init error\n")); + return(6); + } + } + + if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { + if (p->p_len > (*(unsigned *)len)-1) { + p->p_len = *len - 1; + } + SK_MEMCPY(buf, p->p_val, p->p_len); + buf[p->p_len] = '\0'; + *len = p->p_len; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, + ("%c%c%c%c.., len = %d\n", + buf[0],buf[1],buf[2],buf[3],*len)); + } + else { + *len = 0; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n")); + return(1); + } + return(0); +} + + +/* + * Check whether a given key may be written + * + * returns + * SK_TRUE Yes it may be written + * SK_FALSE No it may be written + */ +SK_BOOL VpdMayWrite( +char *key) /* keyword to write (allowed values "Yx", "Vx") */ +{ + if ((*key != 'Y' && *key != 'V') || + key[1] < '0' || key[1] > 'Z' || + (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { + + return(SK_FALSE); + } + return(SK_TRUE); +} + +/* + * Read the contents of the VPD EEPROM and copy it to the VPD + * buffer if not already done. Insert/overwrite the keyword 'key' + * in the VPD buffer. Cut the keyword value if it does not fit + * into the VPD read / write area. + * + * returns 0: success + * 2: value string was cut + * 3: VPD transfer timeout + * 4: VPD full, keyword was not written + * 5: keyword cannot be written + * 6: fatal VPD error + */ +int VpdWrite( +SK_AC *pAC, /* common data base */ +SK_IOC IoC, /* IO Context */ +const char *key, /* keyword to write (allowed values "Yx", "Vx") */ +const char *buf) /* buffer where the keyword value can be read from */ +{ + int len; /* length of the keyword to write */ + int rtv; /* return code */ + int rtv2; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, + ("VPD write %s = %s\n",key,buf)); + + if ((*key != 'Y' && *key != 'V') || + key[1] < '0' || key[1] > 'Z' || + (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("illegal key tag, keyword not written\n")); + return(5); + } + + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + if (VpdInit(pAC, IoC) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD init error\n")); + return(6); + } + } + + rtv = 0; + len = strlen(buf); + if (len > VPD_MAX_LEN) { + /* cut it */ + len = VPD_MAX_LEN; + rtv = 2; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); + } + if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD write error\n")); + return(rtv2); + } + + return(rtv); +} + +/* + * Read the contents of the VPD EEPROM and copy it to the + * VPD buffer if not already done. Remove the VPD keyword + * 'key' from the VPD buffer. + * Only the keywords in the read/write area can be deleted. + * Keywords in the read only area cannot be deleted. + * + * returns 0: success, keyword was removed + * 1: keyword not found + * 5: keyword cannot be deleted + * 6: fatal VPD error + */ +int VpdDelete( +SK_AC *pAC, /* common data base */ +SK_IOC IoC, /* IO Context */ +char *key) /* keyword to read (e.g. "MN") */ +{ + SK_VPD_PARA *p, vp; + char *etp; + int vpd_size; + + vpd_size = pAC->vpd.vpd_size; + + SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key)); + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + if (VpdInit(pAC, IoC) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD init error\n")); + return(6); + } + } + + if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { + if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) { + /* try to delete read only keyword */ + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("cannot delete RO keyword\n")); + return(5); + } + + etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3); + + vpd_move_para(vp.p_val+vp.p_len, etp+2, + - ((int)(vp.p_len + 3))); + if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) { + pAC->vpd.v.vpd_status &= ~VPD_VALID; + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD encoding error\n")); + return(6); + } + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("keyword not found\n")); + return(1); + } + + return(0); +} + +/* + * If the VPD buffer contains valid data write the VPD + * read/write area back to the VPD EEPROM. + * + * returns 0: success + * 3: VPD transfer timeout + */ +int VpdUpdate( +SK_AC *pAC, /* Adapters context */ +SK_IOC IoC) /* IO Context */ +{ + int vpd_size; + + vpd_size = pAC->vpd.vpd_size; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. ")); + if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) { + if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2, + vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) { + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("transfer timed out\n")); + return(3); + } + } + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n")); + return(0); +} + + +/* + * Read the contents of the VPD EEPROM and copy it to the VPD buffer + * if not already done. If the keyword "VF" is not present it will be + * created and the error log message will be stored to this keyword. + * If "VF" is not present the error log message will be stored to the + * keyword "VL". "VL" will created or overwritten if "VF" is present. + * The VPD read/write area is saved to the VPD EEPROM. + * + * returns nothing, errors will be ignored. + */ +void VpdErrLog( +SK_AC *pAC, /* common data base */ +SK_IOC IoC, /* IO Context */ +char *msg) /* error log message */ +{ + SK_VPD_PARA *v, vf; /* VF */ + int len; + + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, + ("VPD error log msg %s\n", msg)); + if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { + if (VpdInit(pAC, IoC) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, + ("VPD init error\n")); + return; + } + } + + len = strlen(msg); + if (len > VPD_MAX_LEN) { + /* cut it */ + len = VPD_MAX_LEN; + } + if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n")); + (void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY); + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n")); + (void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY); + } + + (void)VpdUpdate(pAC, IoC); +} + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c new file mode 100644 index 0000000000..e6b5a95d4a --- /dev/null +++ b/drivers/net/sk98lin/skxmac2.c @@ -0,0 +1,4396 @@ +/****************************************************************************** + * + * Name: skxmac2.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.91 $ + * Date: $Date: 2003/02/05 15:09:34 $ + * Purpose: Contains functions to initialize the MACs and PHYs + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2003 SysKonnect GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skxmac2.c,v $ + * Revision 1.91 2003/02/05 15:09:34 rschmidt + * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv(). + * Disabled auto-update for speed, duplex and flow-control when + * auto-negotiation is not enabled (Bug Id #10766). + * Editorial changes. + * + * Revision 1.90 2003/01/29 13:35:19 rschmidt + * Increment Rx FIFO Overflow counter only in DEBUG-mode. + * Corrected define for blinking active LED. + * + * Revision 1.89 2003/01/28 16:37:45 rschmidt + * Changed init for blinking active LED + * + * Revision 1.88 2003/01/28 10:09:38 rschmidt + * Added debug outputs in SkGmInitMac(). + * Added customized init of LED registers in SkGmInitPhyMarv(), + * for blinking active LED (#ifdef ACT_LED_BLINK) and + * for normal duplex LED (#ifdef DUP_LED_NORMAL). + * Editorial changes. + * + * Revision 1.87 2002/12/10 14:39:05 rschmidt + * Improved initialization of GPHY in SkGmInitPhyMarv(). + * Editorial changes. + * + * Revision 1.86 2002/12/09 15:01:12 rschmidt + * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature). + * + * Revision 1.85 2002/12/05 14:09:16 rschmidt + * Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite(). + * Added additional advertising for 10Base-T when 100Base-T is selected. + * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter. + * Editorial changes. + * + * Revision 1.84 2002/11/15 12:50:09 rschmidt + * Changed SkGmCableDiagStatus() when getting results. + * + * Revision 1.83 2002/11/13 10:28:29 rschmidt + * Added some typecasts to avoid compiler warnings. + * + * Revision 1.82 2002/11/13 09:20:46 rschmidt + * Replaced for(..) with do {} while (...) in SkXmUpdateStats(). + * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic(). + * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT). + * Editorial changes. + * + * Revision 1.81 2002/10/28 14:28:08 rschmidt + * Changed MAC address setup for GMAC in SkGmInitMac(). + * Optimized handling of counter overflow IRQ in SkGmOverflowStatus(). + * Editorial changes. + * + * Revision 1.80 2002/10/14 15:29:44 rschmidt + * Corrected disabling of all PHY IRQs. + * Added WA for deviation #16 (address used for pause packets). + * Set Pause Mode in SkMacRxTxEnable() only for Genesis. + * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode. + * SkXmTimeStamp() replaced by SkMacTimeStamp(). + * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq(). + * Editorial changes. + * + * Revision 1.79 2002/10/10 15:55:36 mkarl + * changes for PLinkSpeedUsed + * + * Revision 1.78 2002/09/12 09:39:51 rwahl + * Removed deactivate code for SIRQ overflow event separate for TX/RX. + * + * Revision 1.77 2002/09/09 12:26:37 mkarl + * added handling for Yukon to SkXmTimeStamp + * + * Revision 1.76 2002/08/21 16:41:16 rschmidt + * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE. + * Added forced speed settings in SkGmInitPhyMarv(). + * Added settings of full/half duplex capabilities for YUKON Fiber. + * Editorial changes. + * + * Revision 1.75 2002/08/16 15:12:01 rschmidt + * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. + * Added function SkMacHashing() for ADDR-Module. + * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced + * with macros). + * Removed functions SkGmGetMuxConfig(). + * Added HWCFG_MODE init for YUKON Fiber. + * Changed initialization of GPHY in SkGmInitPhyMarv(). + * Changed check of parameter in SkXmMacStatistic(). + * Editorial changes. + * + * Revision 1.74 2002/08/12 14:00:17 rschmidt + * Replaced usage of Broadcom PHY Ids with defines. + * Corrected error messages in SkGmMacStatistic(). + * Made SkMacPromiscMode() public for ADDR-Modul. + * Editorial changes. + * + * Revision 1.73 2002/08/08 16:26:24 rschmidt + * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac(). + * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM. + * Editorial changes. + * + * Revision 1.72 2002/07/24 15:11:19 rschmidt + * Fixed wrong placement of parenthesis. + * Editorial changes. + * + * Revision 1.71 2002/07/23 16:05:18 rschmidt + * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite(). + * Fixed Tx Counter Overflow IRQ (Bug ID #10730). + * Editorial changes. + * + * Revision 1.70 2002/07/18 14:27:27 rwahl + * Fixed syntax error. + * + * Revision 1.69 2002/07/17 17:08:47 rwahl + * Fixed check in SkXmMacStatistic(). + * + * Revision 1.68 2002/07/16 07:35:24 rwahl + * Removed check for cleared mib counter in SkGmResetCounter(). + * + * Revision 1.67 2002/07/15 18:35:56 rwahl + * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(), + * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(), + * SkXmOverflowStatus(), SkGmOverflowStatus(). + * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both + * RX & TX. + * Changes to SkGmInitMac(): call to SkGmResetCounter(). + * Editorial changes. + * + * Revision 1.66 2002/07/15 15:59:30 rschmidt + * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite(). + * Added MIB Clear Counter in SkGmInitMac(). + * Added Duplex and Flow-Control settings. + * Reset all Multicast filtering Hash reg. in SkGmInitMac(). + * Added new function: SkGmGetMuxConfig(). + * Editorial changes. + * + * Revision 1.65 2002/06/10 09:35:39 rschmidt + * Replaced C++ comments (//). + * Added #define VCPU around VCPUwaitTime. + * Editorial changes. + * + * Revision 1.64 2002/06/05 08:41:10 rschmidt + * Added function for XMAC2: SkXmTimeStamp(). + * Added function for YUKON: SkGmSetRxCmd(). + * Changed SkGmInitMac() resp. SkGmHardRst(). + * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode). + * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). + * Editorial changes. + * + * Revision 1.63 2002/04/25 13:04:44 rschmidt + * Changes for handling YUKON. + * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. + * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced + * by functions SkXmPhyRead(), SkXmPhyWrite(); + * Removed use of PRxCmd to setup XMAC. + * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. + * Added setting of XM_RX_DIS_CEXT in SkXmInitMac(). + * Removed status parameter from MAC IRQ handler SkMacIrq(), + * SkXmIrq() and SkGmIrq(). + * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy(). + * Added SkMac...() functions to handle both XMAC and GMAC. + * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(), + * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(), + * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite(). + * Changes for V-CPU support. + * Editorial changes. + * + * Revision 1.62 2001/08/06 09:50:14 rschmidt + * Workaround BCOM Errata #1 for the C5 type. + * Editorial changes. + * + * Revision 1.61 2001/02/09 15:40:59 rassmann + * Editorial changes. + * + * Revision 1.60 2001/02/07 15:02:01 cgoos + * Added workaround for Fujitsu switch link down. + * + * Revision 1.59 2001/01/10 09:38:06 cgoos + * Fixed Broadcom C0/A1 Id check for workaround. + * + * Revision 1.58 2000/11/29 11:30:38 cgoos + * Changed DEBUG sections with NW output to xDEBUG + * + * Revision 1.57 2000/11/27 12:40:40 rassmann + * Suppressing preamble after first access to BCom, not before (#10556). + * + * Revision 1.56 2000/11/09 12:32:48 rassmann + * Renamed variables. + * + * Revision 1.55 2000/11/09 11:30:10 rassmann + * WA: Waiting after releasing reset until BCom chip is accessible. + * + * Revision 1.54 2000/10/02 14:10:27 rassmann + * Reading BCOM PHY after releasing reset until it returns a valid value. + * + * Revision 1.53 2000/07/27 12:22:11 gklug + * fix: possible endless loop in XmHardRst. + * + * Revision 1.52 2000/05/22 08:48:31 malthoff + * Fix: #10523 errata valid for all BCOM PHYs. + * + * Revision 1.51 2000/05/17 12:52:18 malthoff + * Fixes BCom link errata (#10523). + * + * Revision 1.50 1999/11/22 13:40:14 cgoos + * Changed license header to GPL. + * + * Revision 1.49 1999/11/22 08:12:13 malthoff + * Add workaround for power consumption feature of BCom C0 chip. + * + * Revision 1.48 1999/11/16 08:39:01 malthoff + * Fix: MDIO preamble suppression is port dependent. + * + * Revision 1.47 1999/08/27 08:55:35 malthoff + * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble. + * + * Revision 1.46 1999/08/13 11:01:12 malthoff + * Fix for 1000BT: pFlowCtrlMode was not set correctly. + * + * Revision 1.45 1999/08/12 19:18:28 malthoff + * 1000BT Fixes: Do not owerwrite XM_MMU_CMD. + * Do not execute BCOM A1 workaround for B1 chips. + * Fix pause frame setting. + * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL. + * + * Revision 1.44 1999/08/03 15:23:48 cgoos + * Fixed setting of PHY interrupt mask in half duplex mode. + * + * Revision 1.43 1999/08/03 15:22:17 cgoos + * Added some debug output. + * Disabled XMac GP0 interrupt for external PHYs. + * + * Revision 1.42 1999/08/02 08:39:23 malthoff + * BCOM PHY: TX LED: To get the mono flop behaviour it is required + * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL. + * + * Revision 1.41 1999/07/30 06:54:31 malthoff + * Add temp. workarounds for the BCOM Phy revision A1. + * + * Revision 1.40 1999/06/01 07:43:26 cgoos + * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to + * AUTOFULL/AUTOHALF. + * + * Revision 1.39 1999/05/19 07:29:51 cgoos + * Changes for 1000Base-T. + * + * Revision 1.38 1999/04/08 14:35:10 malthoff + * Add code for enabling signal detect. Enabling signal detect is disabled. + * + * Revision 1.37 1999/03/12 13:42:54 malthoff + * Add: Jumbo Frame Support. + * Add: Receive modes SK_LENERR_OK_ON/OFF and + * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd(). + * + * Revision 1.36 1999/03/08 10:10:55 gklug + * fix: AutoSensing did switch to next mode even if LiPa indicated offline + * + * Revision 1.35 1999/02/22 15:16:41 malthoff + * Remove some compiler warnings. + * + * Revision 1.34 1999/01/22 09:19:59 gklug + * fix: Init DupMode and InitPauseMd are now called in RxTxEnable + * + * Revision 1.33 1998/12/11 15:19:11 gklug + * chg: lipa autoneg stati + * chg: debug messages + * chg: do NOT use spurious XmIrq + * + * Revision 1.32 1998/12/10 11:08:44 malthoff + * bug fix: pAC has been used for IOs in SkXmHardRst(). + * SkXmInitPhy() is also called for the Diag in SkXmInitMac(). + * + * Revision 1.31 1998/12/10 10:39:11 gklug + * fix: do 4 RESETS of the XMAC at the beginning + * fix: dummy read interrupt source register BEFORE initializing the Phy + * add: debug messages + * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt + * + * Revision 1.30 1998/12/07 12:18:32 gklug + * add: refinement of autosense mode: take into account the autoneg cap of LiPa + * + * Revision 1.29 1998/12/07 07:12:29 gklug + * fix: if page is received the link is down. + * + * Revision 1.28 1998/12/01 10:12:47 gklug + * chg: if spurious IRQ from XMAC encountered, save it + * + * Revision 1.27 1998/11/26 07:33:38 gklug + * add: InitPhy call is now in XmInit function + * + * Revision 1.26 1998/11/18 13:38:24 malthoff + * 'Imsk' is also unused in SkXmAutoNegDone. + * + * Revision 1.25 1998/11/18 13:28:01 malthoff + * Remove unused variable 'Reg' in SkXmAutoNegDone(). + * + * Revision 1.24 1998/11/18 13:18:45 gklug + * add: workaround for xmac errata #1 + * add: detect Link Down also when Link partner requested config + * chg: XMIrq is only used when link is up + * + * Revision 1.23 1998/11/04 07:07:04 cgoos + * Added function SkXmRxTxEnable. + * + * Revision 1.22 1998/10/30 07:35:54 gklug + * fix: serve LinkDown interrupt when link is already down + * + * Revision 1.21 1998/10/29 15:32:03 gklug + * fix: Link Down signaling + * + * Revision 1.20 1998/10/29 11:17:27 gklug + * fix: AutoNegDone bug + * + * Revision 1.19 1998/10/29 10:14:43 malthoff + * Add endainesss comment for reading/writing MAC addresses. + * + * Revision 1.18 1998/10/28 07:48:55 cgoos + * Fix: ASS somtimes signaled although link is up. + * + * Revision 1.17 1998/10/26 07:55:39 malthoff + * Fix in SkXmInitPauseMd(): Pause Mode + * was disabled and not enabled. + * Fix in SkXmAutoNegDone(): Checking Mode bits + * always failed, becaues of some missing braces. + * + * Revision 1.16 1998/10/22 09:46:52 gklug + * fix SysKonnectFileId typo + * + * Revision 1.15 1998/10/21 05:51:37 gklug + * add: para DoLoop to InitPhy function for loopback set-up + * + * Revision 1.14 1998/10/16 10:59:23 malthoff + * Remove Lint warning for dummy reads. + * + * Revision 1.13 1998/10/15 14:01:20 malthoff + * Fix: SkXmAutoNegDone() is (int) but does not return a value. + * + * Revision 1.12 1998/10/14 14:45:04 malthoff + * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by + * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent + * from the Sirq module. + * + * Revision 1.11 1998/10/14 13:59:01 gklug + * add: InitPhy function + * + * Revision 1.10 1998/10/14 11:20:57 malthoff + * Make SkXmAutoNegDone() public, because it's + * used in diagnostics, too. + * The Link Up event to the RLMT is issued in SkXmIrq(). + * SkXmIrq() is not available in diagnostics. + * Use PHY_READ when reading PHY registers. + * + * Revision 1.9 1998/10/14 05:50:10 cgoos + * Added definition for Para. + * + * Revision 1.8 1998/10/14 05:41:28 gklug + * add: Xmac IRQ + * add: auto-negotiation done function + * + * Revision 1.7 1998/10/09 06:55:20 malthoff + * The configuration of the XMACs Tx Request Threshold + * depends from the drivers port usage now. The port + * usage is configured in GIPortUsage. + * + * Revision 1.6 1998/10/05 07:48:00 malthoff + * minor changes + * + * Revision 1.5 1998/10/01 07:03:54 gklug + * add: dummy function for XMAC ISR + * + * Revision 1.4 1998/09/30 12:37:44 malthoff + * Add SkXmSetRxCmd() and related code. + * + * Revision 1.3 1998/09/28 13:26:40 malthoff + * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd() + * + * Revision 1.2 1998/09/16 14:34:21 malthoff + * Add SkXmClrExactAddr(), SkXmClrSrcCheck(), + * SkXmClrHashAddr(), SkXmFlushTxFifo(), + * SkXmFlushRxFifo(), and SkXmHardRst(). + * Finish Coding of SkXmSoftRst(). + * The sources may be compiled now. + * + * Revision 1.1 1998/09/04 10:05:56 malthoff + * Created. + * + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/* typedefs *******************************************************************/ + +/* BCOM PHY magic pattern list */ +typedef struct s_PhyHack { + int PhyReg; /* Phy register */ + SK_U16 PhyVal; /* Value to write */ +} BCOM_HACK; + +/* local variables ************************************************************/ +static const char SysKonnectFileId[] = + "@(#)$Id: skxmac2.c,v 1.91 2003/02/05 15:09:34 rschmidt Exp $ (C) SK "; + +BCOM_HACK BcomRegA1Hack[] = { + { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, + { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, + { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, + { 0, 0 } +}; +BCOM_HACK BcomRegC0Hack[] = { + { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, + { 0x15, 0x0A04 }, { 0x18, 0x0420 }, + { 0, 0 } +}; + +/* function prototypes ********************************************************/ +static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); +static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); +static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); +static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); +static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); +static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); +#ifdef OTHER_PHY +static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); +static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); +static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int); +static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); +#endif /* OTHER_PHY */ + + +/****************************************************************************** + * + * SkXmPhyRead() - Read from XMAC PHY register + * + * Description: reads a 16-bit word from XMAC PHY or ext. PHY + * + * Returns: + * nothing + */ +void SkXmPhyRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 *pVal) /* Pointer to Value */ +{ + SK_U16 Mmu; + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + /* write the PHY register's address */ + XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); + + /* get the PHY register's value */ + XM_IN16(IoC, Port, XM_PHY_DATA, pVal); + + if (pPrt->PhyType != SK_PHY_XMAC) { + do { + XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); + /* wait until 'Ready' is set */ + } while ((Mmu & XM_MMU_PHY_RDY) == 0); + + /* get the PHY register's value */ + XM_IN16(IoC, Port, XM_PHY_DATA, pVal); + } +} /* SkXmPhyRead */ + + +/****************************************************************************** + * + * SkXmPhyWrite() - Write to XMAC PHY register + * + * Description: writes a 16-bit word to XMAC PHY or ext. PHY + * + * Returns: + * nothing + */ +void SkXmPhyWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 Val) /* Value */ +{ + SK_U16 Mmu; + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PhyType != SK_PHY_XMAC) { + do { + XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); + /* wait until 'Busy' is cleared */ + } while ((Mmu & XM_MMU_PHY_BUSY) != 0); + } + + /* write the PHY register's address */ + XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); + + /* write the PHY register's value */ + XM_OUT16(IoC, Port, XM_PHY_DATA, Val); + + if (pPrt->PhyType != SK_PHY_XMAC) { + do { + XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); + /* wait until 'Busy' is cleared */ + } while ((Mmu & XM_MMU_PHY_BUSY) != 0); + } +} /* SkXmPhyWrite */ + + +/****************************************************************************** + * + * SkGmPhyRead() - Read from GPHY register + * + * Description: reads a 16-bit word from GPHY through MDIO + * + * Returns: + * nothing + */ +void SkGmPhyRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 *pVal) /* Pointer to Value */ +{ + SK_U16 Ctrl; + SK_GEPORT *pPrt; +#ifdef VCPU + u_long SimCyle; + u_long SimLowTime; + + VCPUgetTime(&SimCyle, &SimLowTime); + VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", + PhyReg, SimCyle, SimLowTime); +#endif /* VCPU */ + + pPrt = &pAC->GIni.GP[Port]; + + /* set PHY-Register offset and 'Read' OpCode (= 1) */ + *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | + GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); + + GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); + + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + + /* additional check for MDC/MDIO activity */ + if ((Ctrl & GM_SMI_CT_BUSY) == 0) { + *pVal = 0; + return; + } + + *pVal |= GM_SMI_CT_BUSY; + + do { +#ifdef VCPU + VCPUwaitTime(1000); +#endif /* VCPU */ + + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + + /* wait until 'ReadValid' is set */ + } while (Ctrl == *pVal); + + /* get the PHY register's value */ + GM_IN16(IoC, Port, GM_SMI_DATA, pVal); + +#ifdef VCPU + VCPUgetTime(&SimCyle, &SimLowTime); + VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", + SimCyle, SimLowTime); +#endif /* VCPU */ +} /* SkGmPhyRead */ + + +/****************************************************************************** + * + * SkGmPhyWrite() - Write to GPHY register + * + * Description: writes a 16-bit word to GPHY through MDIO + * + * Returns: + * nothing + */ +void SkGmPhyWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 Val) /* Value */ +{ + SK_U16 Ctrl; + SK_GEPORT *pPrt; +#ifdef VCPU + SK_U32 DWord; + u_long SimCyle; + u_long SimLowTime; + + VCPUgetTime(&SimCyle, &SimLowTime); + VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", + PhyReg, Val, SimCyle, SimLowTime); +#endif /* VCPU */ + + pPrt = &pAC->GIni.GP[Port]; + + /* write the PHY register's value */ + GM_OUT16(IoC, Port, GM_SMI_DATA, Val); + + /* set PHY-Register offset and 'Write' OpCode (= 0) */ + Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); + + GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); + + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + + /* additional check for MDC/MDIO activity */ + if ((Ctrl & GM_SMI_CT_BUSY) == 0) { + return; + } + + Val |= GM_SMI_CT_BUSY; + + do { +#ifdef VCPU + /* read Timer value */ + SK_IN32(IoC, B2_TI_VAL, &DWord); + + VCPUwaitTime(1000); +#endif /* VCPU */ + + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + + /* wait until 'Busy' is cleared */ + } while (Ctrl == Val); + +#ifdef VCPU + VCPUgetTime(&SimCyle, &SimLowTime); + VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", + SimCyle, SimLowTime); +#endif /* VCPU */ +} /* SkGmPhyWrite */ + + +/****************************************************************************** + * + * SkGePhyRead() - Read from PHY register + * + * Description: calls a read PHY routine dep. on board type + * + * Returns: + * nothing + */ +void SkGePhyRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 *pVal) /* Pointer to Value */ +{ + void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); + + if (pAC->GIni.GIGenesis) { + r_func = SkXmPhyRead; + } + else { + r_func = SkGmPhyRead; + } + + r_func(pAC, IoC, Port, PhyReg, pVal); +} /* SkGePhyRead */ + + +/****************************************************************************** + * + * SkGePhyWrite() - Write to PHY register + * + * Description: calls a write PHY routine dep. on board type + * + * Returns: + * nothing + */ +void SkGePhyWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 Val) /* Value */ +{ + void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); + + if (pAC->GIni.GIGenesis) { + w_func = SkXmPhyWrite; + } + else { + w_func = SkGmPhyWrite; + } + + w_func(pAC, IoC, Port, PhyReg, Val); +} /* SkGePhyWrite */ + + +/****************************************************************************** + * + * SkMacPromiscMode() - Enable / Disable Promiscuous Mode + * + * Description: + * enables / disables promiscuous mode by setting Mode Register (XMAC) or + * Receive Control Register (GMAC) dep. on board type + * + * Returns: + * nothing + */ +void SkMacPromiscMode( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL Enable) /* Enable / Disable */ +{ + SK_U16 RcReg; + SK_U32 MdReg; + + if (pAC->GIni.GIGenesis) { + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + /* enable or disable promiscuous mode */ + if (Enable) { + MdReg |= XM_MD_ENA_PROM; + } + else { + MdReg &= ~XM_MD_ENA_PROM; + } + /* setup Mode Register */ + XM_OUT32(IoC, Port, XM_MODE, MdReg); + } + else { + + GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); + + /* enable or disable unicast and multicast filtering */ + if (Enable) { + RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + } + else { + RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + } + /* setup Receive Control Register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); + } +} /* SkMacPromiscMode*/ + + +/****************************************************************************** + * + * SkMacHashing() - Enable / Disable Hashing + * + * Description: + * enables / disables hashing by setting Mode Register (XMAC) or + * Receive Control Register (GMAC) dep. on board type + * + * Returns: + * nothing + */ +void SkMacHashing( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL Enable) /* Enable / Disable */ +{ + SK_U16 RcReg; + SK_U32 MdReg; + + if (pAC->GIni.GIGenesis) { + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + /* enable or disable hashing */ + if (Enable) { + MdReg |= XM_MD_ENA_HASH; + } + else { + MdReg &= ~XM_MD_ENA_HASH; + } + /* setup Mode Register */ + XM_OUT32(IoC, Port, XM_MODE, MdReg); + } + else { + + GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); + + /* enable or disable multicast filtering */ + if (Enable) { + RcReg |= GM_RXCR_MCF_ENA; + } + else { + RcReg &= ~GM_RXCR_MCF_ENA; + } + /* setup Receive Control Register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); + } +} /* SkMacHashing*/ + + +#ifdef SK_DIAG +/****************************************************************************** + * + * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register + * + * Description: + * The features + * - FCS stripping, SK_STRIP_FCS_ON/OFF + * - pad byte stripping, SK_STRIP_PAD_ON/OFF + * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF + * for inrange length error frames + * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF + * for frames > 1514 bytes + * - enable Rx of own packets SK_SELF_RX_ON/OFF + * + * for incoming packets may be enabled/disabled by this function. + * Additional modes may be added later. + * Multiple modes can be enabled/disabled at the same time. + * The new configuration is written to the Rx Command register immediately. + * + * Returns: + * nothing + */ +static void SkXmSetRxCmd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, + SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ +{ + SK_U16 OldRxCmd; + SK_U16 RxCmd; + + XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd); + + RxCmd = OldRxCmd; + + switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) { + case SK_STRIP_FCS_ON: + RxCmd |= XM_RX_STRIP_FCS; + break; + case SK_STRIP_FCS_OFF: + RxCmd &= ~XM_RX_STRIP_FCS; + break; + } + + switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) { + case SK_STRIP_PAD_ON: + RxCmd |= XM_RX_STRIP_PAD; + break; + case SK_STRIP_PAD_OFF: + RxCmd &= ~XM_RX_STRIP_PAD; + break; + } + + switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) { + case SK_LENERR_OK_ON: + RxCmd |= XM_RX_LENERR_OK; + break; + case SK_LENERR_OK_OFF: + RxCmd &= ~XM_RX_LENERR_OK; + break; + } + + switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) { + case SK_BIG_PK_OK_ON: + RxCmd |= XM_RX_BIG_PK_OK; + break; + case SK_BIG_PK_OK_OFF: + RxCmd &= ~XM_RX_BIG_PK_OK; + break; + } + + switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) { + case SK_SELF_RX_ON: + RxCmd |= XM_RX_SELF_RX; + break; + case SK_SELF_RX_OFF: + RxCmd &= ~XM_RX_SELF_RX; + break; + } + + /* Write the new mode to the Rx command register if required */ + if (OldRxCmd != RxCmd) { + XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd); + } +} /* SkXmSetRxCmd */ + + +/****************************************************************************** + * + * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register + * + * Description: + * The features + * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF + * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF + * for frames > 1514 bytes + * - enable Rx of own packets SK_SELF_RX_ON/OFF + * + * for incoming packets may be enabled/disabled by this function. + * Additional modes may be added later. + * Multiple modes can be enabled/disabled at the same time. + * The new configuration is written to the Rx Command register immediately. + * + * Returns: + * nothing + */ +static void SkGmSetRxCmd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, + SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ +{ + SK_U16 OldRxCmd; + SK_U16 RxCmd; + + if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { + + GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); + + RxCmd = OldRxCmd; + + if ((Mode & SK_STRIP_FCS_ON) != 0) { + RxCmd |= GM_RXCR_CRC_DIS; + } + else { + RxCmd &= ~GM_RXCR_CRC_DIS; + } + /* Write the new mode to the Rx control register if required */ + if (OldRxCmd != RxCmd) { + GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); + } + } + + if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { + + GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); + + RxCmd = OldRxCmd; + + if ((Mode & SK_BIG_PK_OK_ON) != 0) { + RxCmd |= GM_SMOD_JUMBO_ENA; + } + else { + RxCmd &= ~GM_SMOD_JUMBO_ENA; + } + /* Write the new mode to the Rx control register if required */ + if (OldRxCmd != RxCmd) { + GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); + } + } +} /* SkGmSetRxCmd */ + + +/****************************************************************************** + * + * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register + * + * Description: modifies the MAC's Rx Control reg. dep. on board type + * + * Returns: + * nothing + */ +void SkMacSetRxCmd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Mode) /* Rx Mode */ +{ + if (pAC->GIni.GIGenesis) { + + SkXmSetRxCmd(pAC, IoC, Port, Mode); + } + else { + + SkGmSetRxCmd(pAC, IoC, Port, Mode); + } +} /* SkMacSetRxCmd */ + + +/****************************************************************************** + * + * SkMacCrcGener() - Enable / Disable CRC Generation + * + * Description: enables / disables CRC generation dep. on board type + * + * Returns: + * nothing + */ +void SkMacCrcGener( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL Enable) /* Enable / Disable */ +{ + SK_U16 Word; + + if (pAC->GIni.GIGenesis) { + + XM_IN16(IoC, Port, XM_TX_CMD, &Word); + + if (Enable) { + Word &= ~XM_TX_NO_CRC; + } + else { + Word |= XM_TX_NO_CRC; + } + /* setup Tx Command Register */ + XM_OUT16(pAC, Port, XM_TX_CMD, Word); + } + else { + + GM_IN16(IoC, Port, GM_TX_CTRL, &Word); + + if (Enable) { + Word &= ~GM_TXCR_CRC_DIS; + } + else { + Word |= GM_TXCR_CRC_DIS; + } + /* setup Tx Control Register */ + GM_OUT16(IoC, Port, GM_TX_CTRL, Word); + } +} /* SkMacCrcGener*/ + +#endif /* SK_DIAG */ + + +/****************************************************************************** + * + * SkXmClrExactAddr() - Clear Exact Match Address Registers + * + * Description: + * All Exact Match Address registers of the XMAC 'Port' will be + * cleared starting with 'StartNum' up to (and including) the + * Exact Match address number of 'StopNum'. + * + * Returns: + * nothing + */ +void SkXmClrExactAddr( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int StartNum, /* Begin with this Address Register Index (0..15) */ +int StopNum) /* Stop after finished with this Register Idx (0..15) */ +{ + int i; + SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; + + if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || + StartNum > StopNum) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG); + return; + } + + for (i = StartNum; i <= StopNum; i++) { + XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); + } +} /* SkXmClrExactAddr */ + + +/****************************************************************************** + * + * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO + * + * Description: + * Flush the transmit FIFO of the MAC specified by the index 'Port' + * + * Returns: + * nothing + */ +void SkMacFlushTxFifo( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 MdReg; + + if (pAC->GIni.GIGenesis) { + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + + XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); + } + else { + /* no way to flush the FIFO we have to issue a reset */ + /* TBD */ + } +} /* SkMacFlushTxFifo */ + + +/****************************************************************************** + * + * SkMacFlushRxFifo() - Flush the MAC's receive FIFO + * + * Description: + * Flush the receive FIFO of the MAC specified by the index 'Port' + * + * Returns: + * nothing + */ +void SkMacFlushRxFifo( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 MdReg; + + if (pAC->GIni.GIGenesis) { + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + + XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); + } + else { + /* no way to flush the FIFO we have to issue a reset */ + /* TBD */ + } +} /* SkMacFlushRxFifo */ + + +/****************************************************************************** + * + * SkXmSoftRst() - Do a XMAC software reset + * + * Description: + * The PHY registers should not be destroyed during this + * kind of software reset. Therefore the XMAC Software Reset + * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used! + * + * The software reset is done by + * - disabling the Rx and Tx state machine, + * - resetting the statistics module, + * - clear all other significant XMAC Mode, + * Command, and Control Registers + * - clearing the Hash Register and the + * Exact Match Address registers, and + * - flushing the XMAC's Rx and Tx FIFOs. + * + * Note: + * Another requirement when stopping the XMAC is to + * avoid sending corrupted frames on the network. + * Disabling the Tx state machine will NOT interrupt + * the currently transmitted frame. But we must take care + * that the Tx FIFO is cleared AFTER the current frame + * is complete sent to the network. + * + * It takes about 12ns to send a frame with 1538 bytes. + * One PCI clock goes at least 15ns (66MHz). Therefore + * after reading XM_GP_PORT back, we are sure that the + * transmitter is disabled AND idle. And this means + * we may flush the transmit FIFO now. + * + * Returns: + * nothing + */ +static void SkXmSoftRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; + + /* reset the statistics module */ + XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); + + /* disable all XMAC IRQs */ + XM_OUT16(IoC, Port, XM_IMSK, 0xffff); + + XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */ + + XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */ + XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */ + + /* disable all PHY IRQs */ + switch (pAC->GIni.GP[Port].PhyType) { + case SK_PHY_BCOM: + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); + break; + case SK_PHY_NAT: + /* todo: National + SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ + break; +#endif /* OTHER_PHY */ + } + + /* clear the Hash Register */ + XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); + + /* clear the Exact Match Address registers */ + SkXmClrExactAddr(pAC, IoC, Port, 0, 15); + + /* clear the Source Check Address registers */ + XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); + +} /* SkXmSoftRst */ + + +/****************************************************************************** + * + * SkXmHardRst() - Do a XMAC hardware reset + * + * Description: + * The XMAC of the specified 'Port' and all connected devices + * (PHY and SERDES) will receive a reset signal on its *Reset pins. + * External PHYs must be reset be clearing a bit in the GPIO register + * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). + * + * ATTENTION: + * It is absolutely necessary to reset the SW_RST Bit first + * before calling this function. + * + * Returns: + * nothing + */ +static void SkXmHardRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 Reg; + int i; + int TOut; + SK_U16 Word; + + for (i = 0; i < 4; i++) { + /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */ + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + + TOut = 0; + do { + if (TOut++ > 10000) { + /* + * Adapter seems to be in RESET state. + * Registers cannot be written. + */ + return; + } + + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + + SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word); + + } while ((Word & MFF_SET_MAC_RST) == 0); + } + + /* For external PHYs there must be special handling */ + if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { + /* reset external PHY */ + SK_IN32(IoC, B2_GP_IO, &Reg); + if (Port == 0) { + Reg |= GP_DIR_0; /* set to output */ + Reg &= ~GP_IO_0; + } + else { + Reg |= GP_DIR_2; /* set to output */ + Reg &= ~GP_IO_2; + } + SK_OUT32(IoC, B2_GP_IO, Reg); + + /* short delay */ + SK_IN32(IoC, B2_GP_IO, &Reg); + } + +} /* SkXmHardRst */ + + +/****************************************************************************** + * + * SkGmSoftRst() - Do a GMAC software reset + * + * Description: + * The GPHY registers should not be destroyed during this + * kind of software reset. + * + * Returns: + * nothing + */ +static void SkGmSoftRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; + SK_U16 RxCtrl; + + /* reset the statistics module */ + + /* disable all GMAC IRQs */ + SK_OUT8(IoC, GMAC_IRQ_MSK, 0); + + /* disable all PHY IRQs */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); + + /* clear the Hash Register */ + GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); + + /* Enable Unicast and Multicast filtering */ + GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); + + GM_OUT16(IoC, Port, GM_RX_CTRL, + RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + +} /* SkGmSoftRst */ + + +/****************************************************************************** + * + * SkGmHardRst() - Do a GMAC hardware reset + * + * Description: + * + * ATTENTION: + * It is absolutely necessary to reset the SW_RST Bit first + * before calling this function. + * + * Returns: + * nothing + */ +static void SkGmHardRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + /* set GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); + + /* set GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); + +} /* SkGmHardRst */ + + +/****************************************************************************** + * + * SkMacSoftRst() - Do a MAC software reset + * + * Description: calls a MAC software reset routine dep. on board type + * + * Returns: + * nothing + */ +void SkMacSoftRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + /* disable receiver and transmitter */ + SkMacRxTxDisable(pAC, IoC, Port); + + if (pAC->GIni.GIGenesis) { + + SkXmSoftRst(pAC, IoC, Port); + } + else { + + SkGmSoftRst(pAC, IoC, Port); + } + + /* flush the MAC's Rx and Tx FIFOs */ + SkMacFlushTxFifo(pAC, IoC, Port); + + SkMacFlushRxFifo(pAC, IoC, Port); + + pPrt->PState = SK_PRT_STOP; + +} /* SkMacSoftRst */ + + +/****************************************************************************** + * + * SkMacHardRst() - Do a MAC hardware reset + * + * Description: calls a MAC hardware reset routine dep. on board type + * + * Returns: + * nothing + */ +void SkMacHardRst( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + + if (pAC->GIni.GIGenesis) { + + SkXmHardRst(pAC, IoC, Port); + } + else { + + SkGmHardRst(pAC, IoC, Port); + } + + pAC->GIni.GP[Port].PState = SK_PRT_RESET; + +} /* SkMacHardRst */ + + +/****************************************************************************** + * + * SkXmInitMac() - Initialize the XMAC II + * + * Description: + * Initialize the XMAC of the specified port. + * The XMAC must be reset or stopped before calling this function. + * + * Note: + * The XMAC's Rx and Tx state machine is still disabled when returning. + * + * Returns: + * nothing + */ +void SkXmInitMac( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U32 Reg; + int i; + SK_U16 SWord; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PState == SK_PRT_STOP) { + /* Port State: SK_PRT_STOP */ + /* Verify that the reset bit is cleared */ + SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); + + if ((SWord & MFF_SET_MAC_RST) != 0) { + /* PState does not match HW state */ + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); + /* Correct it */ + pPrt->PState = SK_PRT_RESET; + } + } + + if (pPrt->PState == SK_PRT_RESET) { + /* + * clear HW reset + * Note: The SW reset is self clearing, therefore there is + * nothing to do here. + */ + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + + /* Ensure that XMAC reset release is done (errata from LReinbold?) */ + SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); + + /* Clear PHY reset */ + if (pPrt->PhyType != SK_PHY_XMAC) { + + SK_IN32(IoC, B2_GP_IO, &Reg); + + if (Port == 0) { + Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */ + } + else { + Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */ + } + SK_OUT32(IoC, B2_GP_IO, Reg); + + /* Enable GMII interface */ + XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); + + /* read Id from external PHY (all have the same address) */ + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); + + /* + * Optimize MDIO transfer by suppressing preamble. + * Must be done AFTER first access to BCOM chip. + */ + XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); + + XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); + + if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { + /* + * Workaround BCOM Errata for the C0 type. + * Write magic patterns to reserved registers. + */ + i = 0; + while (BcomRegC0Hack[i].PhyReg != 0) { + SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, + BcomRegC0Hack[i].PhyVal); + i++; + } + } + else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { + /* + * Workaround BCOM Errata for the A1 type. + * Write magic patterns to reserved registers. + */ + i = 0; + while (BcomRegA1Hack[i].PhyReg != 0) { + SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, + BcomRegA1Hack[i].PhyVal); + i++; + } + } + + /* + * Workaround BCOM Errata (#10523) for all BCom PHYs. + * Disable Power Management after reset. + */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); + + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, + (SK_U16)(SWord | PHY_B_AC_DIS_PM)); + + /* PHY LED initialization is done in SkGeXmitLED() */ + } + + /* Dummy read the Interrupt source register */ + XM_IN16(IoC, Port, XM_ISRC, &SWord); + + /* + * The auto-negotiation process starts immediately after + * clearing the reset. The auto-negotiation process should be + * started by the SIRQ, therefore stop it here immediately. + */ + SkMacInitPhy(pAC, IoC, Port, SK_FALSE); + +#if 0 + /* temp. code: enable signal detect */ + /* WARNING: do not override GMII setting above */ + XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG); +#endif + } + + /* + * configure the XMACs Station Address + * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A + * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B + */ + for (i = 0; i < 3; i++) { + /* + * The following 2 statements are together endianess + * independent. Remember this when changing. + */ + SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); + + XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); + } + + /* Tx Inter Packet Gap (XM_TX_IPG): use default */ + /* Tx High Water Mark (XM_TX_HI_WM): use default */ + /* Tx Low Water Mark (XM_TX_LO_WM): use default */ + /* Host Request Threshold (XM_HT_THR): use default */ + /* Rx Request Threshold (XM_RX_THR): use default */ + /* Rx Low Water Mark (XM_RX_LO_WM): use default */ + + /* configure Rx High Water Mark (XM_RX_HI_WM) */ + XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); + + /* Configure Tx Request Threshold */ + SWord = SK_XM_THR_SL; /* for single port */ + + if (pAC->GIni.GIMacsFound > 1) { + switch (pAC->GIni.GIPortUsage) { + case SK_RED_LINK: + SWord = SK_XM_THR_REDL; /* redundant link */ + break; + case SK_MUL_LINK: + SWord = SK_XM_THR_MULL; /* load balancing */ + break; + case SK_JUMBO_LINK: + SWord = SK_XM_THR_JUMBO; /* jumbo frames */ + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); + break; + } + } + XM_OUT16(IoC, Port, XM_TX_THR, SWord); + + /* setup register defaults for the Tx Command Register */ + XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); + + /* setup register defaults for the Rx Command Register */ + SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; + + if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + SWord |= XM_RX_BIG_PK_OK; + } + + if (pPrt->PLinkModeConf == SK_LMODE_HALF) { + /* + * If in manual half duplex mode the other side might be in + * full duplex mode, so ignore if a carrier extension is not seen + * on frames received + */ + SWord |= XM_RX_DIS_CEXT; + } + + XM_OUT16(IoC, Port, XM_RX_CMD, SWord); + + /* + * setup register defaults for the Mode Register + * - Don't strip error frames to avoid Store & Forward + * on the Rx side. + * - Enable 'Check Station Address' bit + * - Enable 'Check Address Array' bit + */ + XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); + + /* + * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) + * - Enable all bits excepting 'Octets Rx OK Low CntOv' + * and 'Octets Rx OK Hi Cnt Ov'. + */ + XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); + + /* + * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) + * - Enable all bits excepting 'Octets Tx OK Low CntOv' + * and 'Octets Tx OK Hi Cnt Ov'. + */ + XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); + + /* + * Do NOT init XMAC interrupt mask here. + * All interrupts remain disable until link comes up! + */ + + /* + * Any additional configuration changes may be done now. + * The last action is to enable the Rx and Tx state machine. + * This should be done after the auto-negotiation process + * has been completed successfully. + */ +} /* SkXmInitMac */ + +/****************************************************************************** + * + * SkGmInitMac() - Initialize the GMAC + * + * Description: + * Initialize the GMAC of the specified port. + * The GMAC must be reset or stopped before calling this function. + * + * Note: + * The GMAC's Rx and Tx state machine is still disabled when returning. + * + * Returns: + * nothing + */ +void SkGmInitMac( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + int i; + SK_U16 SWord; + SK_U32 DWord; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PState == SK_PRT_STOP) { + /* Port State: SK_PRT_STOP */ + /* Verify that the reset bit is cleared */ + SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); + + if ((DWord & GMC_RST_SET) != 0) { + /* PState does not match HW state */ + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); + /* Correct it */ + pPrt->PState = SK_PRT_RESET; + } + } + + if (pPrt->PState == SK_PRT_RESET) { + /* set GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); + + /* set GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); + + /* clear GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); + + /* set GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); + + /* set HWCFG_MODE */ + DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | + GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | + (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : + GPC_HWCFG_GMII_FIB); + + /* set GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); + + /* release GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); + + /* clear GMAC Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + + /* Dummy read the Interrupt source register */ + SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); + +#ifndef VCPU + /* read Id from PHY */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); + + SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); +#endif /* VCPU */ + } + + (void)SkGmResetCounter(pAC, IoC, Port); + + SWord = 0; + + /* speed settings */ + switch (pPrt->PLinkSpeed) { + case SK_LSPEED_AUTO: + case SK_LSPEED_1000MBPS: + SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; + break; + case SK_LSPEED_100MBPS: + SWord |= GM_GPCR_SPEED_100; + break; + case SK_LSPEED_10MBPS: + break; + } + + /* duplex settings */ + if (pPrt->PLinkMode != SK_LMODE_HALF) { + /* set full duplex */ + SWord |= GM_GPCR_DUP_FULL; + } + + /* flow control settings */ + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + /* disable auto-negotiation for flow-control */ + SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS; + break; + case SK_FLOW_MODE_LOC_SEND: + SWord |= GM_GPCR_FC_RX_DIS; + break; + case SK_FLOW_MODE_SYMMETRIC: + /* TBD */ + case SK_FLOW_MODE_SYM_OR_REM: + /* enable auto-negotiation for flow-control and */ + /* enable Rx and Tx of pause frames */ + break; + } + + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + /* disable auto-update for speed, duplex and flow-control */ + SWord |= GM_GPCR_AU_ALL_DIS; + } + + /* setup General Purpose Control Register */ + GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); + + /* setup Transmit Control Register */ + GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR); + + /* setup Receive Control Register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | + GM_RXCR_CRC_DIS); + + /* setup Transmit Flow Control Register */ + GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); + + /* setup Transmit Parameter Register */ +#ifdef VCPU + GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); +#endif /* VCPU */ + + SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26); + + GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); + + /* configure the Serial Mode Register */ +#ifdef VCPU + GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); +#endif /* VCPU */ + + SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH; + + if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + /* enable jumbo mode (Max. Frame Length = 9018) */ + SWord |= GM_SMOD_JUMBO_ENA; + } + + GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); + + /* + * configure the GMACs Station Addresses + * in PROM you can find our addresses at: + * B2_MAC_1 = xx xx xx xx xx x0 virtual address + * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A + * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort + */ + + for (i = 0; i < 3; i++) { + /* + * The following 2 statements are together endianess + * independent. Remember this when changing. + */ + /* physical address: will be used for pause frames */ + SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); + +#ifdef WA_DEV_16 + /* WA for deviation #16 */ + if (pAC->GIni.GIChipRev == 0) { + /* swap the address bytes */ + SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); + + /* write to register in reversed order */ + GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); + } + else { + GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); + } +#else + GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); +#endif /* WA_DEV_16 */ + + /* virtual address: will be used for data */ + SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); + + GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); + + /* reset Multicast filtering Hash registers 1-3 */ + GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); + } + + /* reset Multicast filtering Hash register 4 */ + GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); + + /* enable interrupt mask for counter overflows */ + GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); + GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); + GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); + + /* read General Purpose Status */ + GM_IN16(IoC, Port, GM_GP_STAT, &SWord); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("MAC Stat Reg=0x%04X\n", SWord)); + +#ifdef SK_DIAG + c_print("MAC Stat Reg=0x%04X\n", SWord); +#endif /* SK_DIAG */ + +} /* SkGmInitMac */ + + +/****************************************************************************** + * + * SkXmInitDupMd() - Initialize the XMACs Duplex Mode + * + * Description: + * This function initializes the XMACs Duplex Mode. + * It should be called after successfully finishing + * the Auto-negotiation Process + * + * Returns: + * nothing + */ +void SkXmInitDupMd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + switch (pAC->GIni.GP[Port].PLinkModeStatus) { + case SK_LMODE_STAT_AUTOHALF: + case SK_LMODE_STAT_HALF: + /* Configuration Actions for Half Duplex Mode */ + /* + * XM_BURST = default value. We are probable not quick + * enough at the 'XMAC' bus to burst 8kB. + * The XMAC stops bursting if no transmit frames + * are available or the burst limit is exceeded. + */ + /* XM_TX_RT_LIM = default value (15) */ + /* XM_TX_STIME = default value (0xff = 4096 bit times) */ + break; + case SK_LMODE_STAT_AUTOFULL: + case SK_LMODE_STAT_FULL: + /* Configuration Actions for Full Duplex Mode */ + /* + * The duplex mode is configured by the PHY, + * therefore it seems to be that there is nothing + * to do here. + */ + break; + case SK_LMODE_STAT_UNKNOWN: + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); + break; + } +} /* SkXmInitDupMd */ + + +/****************************************************************************** + * + * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port + * + * Description: + * This function initializes the Pause Mode which should + * be used for this port. + * It should be called after successfully finishing + * the Auto-negotiation Process + * + * Returns: + * nothing + */ +void SkXmInitPauseMd( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U32 DWord; + SK_U16 Word; + + pPrt = &pAC->GIni.GP[Port]; + + XM_IN16(IoC, Port, XM_MMU_CMD, &Word); + + if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || + pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { + + /* Disable Pause Frame Reception */ + Word |= XM_MMU_IGN_PF; + } + else { + /* + * enabling pause frame reception is required for 1000BT + * because the XMAC is not reset if the link is going down + */ + /* Enable Pause Frame Reception */ + Word &= ~XM_MMU_IGN_PF; + } + + XM_OUT16(IoC, Port, XM_MMU_CMD, Word); + + XM_IN32(IoC, Port, XM_MODE, &DWord); + + if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || + pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { + + /* + * Configure Pause Frame Generation + * Use internal and external Pause Frame Generation. + * Sending pause frames is edge triggered. + * Send a Pause frame with the maximum pause time if + * internal oder external FIFO full condition occurs. + * Send a zero pause time frame to re-start transmission. + */ + + /* XM_PAUSE_DA = '010000C28001' (default) */ + + /* XM_MAC_PTIME = 0xffff (maximum) */ + /* remember this value is defined in big endian (!) */ + XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); + + /* Set Pause Mode in Mode Register */ + DWord |= XM_PAUSE_MODE; + + /* Set Pause Mode in MAC Rx FIFO */ + SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); + } + else { + /* + * disable pause frame generation is required for 1000BT + * because the XMAC is not reset if the link is going down + */ + /* Disable Pause Mode in Mode Register */ + DWord &= ~XM_PAUSE_MODE; + + /* Disable Pause Mode in MAC Rx FIFO */ + SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); + } + + XM_OUT32(IoC, Port, XM_MODE, DWord); +} /* SkXmInitPauseMd*/ + + +/****************************************************************************** + * + * SkXmInitPhyXmac() - Initialize the XMAC Phy registers + * + * Description: initializes all the XMACs Phy registers + * + * Note: + * + * Returns: + * nothing + */ +static void SkXmInitPhyXmac( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ + SK_GEPORT *pPrt; + SK_U16 Ctrl; + + pPrt = &pAC->GIni.GP[Port]; + Ctrl = 0; + + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); + /* Set DuplexMode in Config register */ + if (pPrt->PLinkMode == SK_LMODE_FULL) { + Ctrl |= PHY_CT_DUP_MD; + } + + /* + * Do NOT enable Auto-negotiation here. This would hold + * the link down because no IDLEs are transmitted + */ + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); + /* Set Auto-negotiation advertisement */ + + /* Set Full/half duplex capabilities */ + switch (pPrt->PLinkMode) { + case SK_LMODE_AUTOHALF: + Ctrl |= PHY_X_AN_HD; + break; + case SK_LMODE_AUTOFULL: + Ctrl |= PHY_X_AN_FD; + break; + case SK_LMODE_AUTOBOTH: + Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, + SKERR_HWI_E015MSG); + } + + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + Ctrl |= PHY_X_P_NO_PAUSE; + break; + case SK_FLOW_MODE_LOC_SEND: + Ctrl |= PHY_X_P_ASYM_MD; + break; + case SK_FLOW_MODE_SYMMETRIC: + Ctrl |= PHY_X_P_SYM_MD; + break; + case SK_FLOW_MODE_SYM_OR_REM: + Ctrl |= PHY_X_P_BOTH_MD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + + /* Write AutoNeg Advertisement Register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl); + + /* Restart Auto-negotiation */ + Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; + } + + if (DoLoop) { + /* Set the Phy Loopback bit, too */ + Ctrl |= PHY_CT_LOOP; + } + + /* Write to the Phy control register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); +} /* SkXmInitPhyXmac */ + + +/****************************************************************************** + * + * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers + * + * Description: initializes all the Broadcom Phy registers + * + * Note: + * + * Returns: + * nothing + */ +static void SkXmInitPhyBcom( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ + SK_GEPORT *pPrt; + SK_U16 Ctrl1; + SK_U16 Ctrl2; + SK_U16 Ctrl3; + SK_U16 Ctrl4; + SK_U16 Ctrl5; + + Ctrl1 = PHY_CT_SP1000; + Ctrl2 = 0; + Ctrl3 = PHY_SEL_TYPE; + Ctrl4 = PHY_B_PEC_EN_LTR; + Ctrl5 = PHY_B_AC_TX_TST; + + pPrt = &pAC->GIni.GP[Port]; + + /* manually Master/Slave ? */ + if (pPrt->PMSMode != SK_MS_MODE_AUTO) { + Ctrl2 |= PHY_B_1000C_MSE; + + if (pPrt->PMSMode == SK_MS_MODE_MASTER) { + Ctrl2 |= PHY_B_1000C_MSC; + } + } + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); + /* Set DuplexMode in Config register */ + Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + + /* Determine Master/Slave manually if not already done */ + if (pPrt->PMSMode == SK_MS_MODE_AUTO) { + Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ + } + + /* + * Do NOT enable Auto-negotiation here. This would hold + * the link down because no IDLES are transmitted + */ + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); + /* Set Auto-negotiation advertisement */ + + /* + * Workaround BCOM Errata #1 for the C5 type. + * 1000Base-T Link Acquisition Failure in Slave Mode + * Set Repeater/DTE bit 10 of the 1000Base-T Control Register + */ + Ctrl2 |= PHY_B_1000C_RD; + + /* Set Full/half duplex capabilities */ + switch (pPrt->PLinkMode) { + case SK_LMODE_AUTOHALF: + Ctrl2 |= PHY_B_1000C_AHD; + break; + case SK_LMODE_AUTOFULL: + Ctrl2 |= PHY_B_1000C_AFD; + break; + case SK_LMODE_AUTOBOTH: + Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, + SKERR_HWI_E015MSG); + } + + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + Ctrl3 |= PHY_B_P_NO_PAUSE; + break; + case SK_FLOW_MODE_LOC_SEND: + Ctrl3 |= PHY_B_P_ASYM_MD; + break; + case SK_FLOW_MODE_SYMMETRIC: + Ctrl3 |= PHY_B_P_SYM_MD; + break; + case SK_FLOW_MODE_SYM_OR_REM: + Ctrl3 |= PHY_B_P_BOTH_MD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + + /* Restart Auto-negotiation */ + Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; + } + + /* Initialize LED register here? */ + /* No. Please do it in SkDgXmitLed() (if required) and swap + init order of LEDs and XMAC. (MAl) */ + + /* Write 1000Base-T Control Register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); + + /* Write AutoNeg Advertisement Register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); + + if (DoLoop) { + /* Set the Phy Loopback bit, too */ + Ctrl1 |= PHY_CT_LOOP; + } + + if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + /* configure FIFO to high latency for transmission of ext. packets */ + Ctrl4 |= PHY_B_PEC_HIGH_LA; + + /* configure reception of extended packets */ + Ctrl5 |= PHY_B_AC_LONG_PACK; + + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5); + } + + /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); + + /* Write to the Phy control register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Control Reg=0x%04X\n", Ctrl1)); +} /* SkXmInitPhyBcom */ + + +/****************************************************************************** + * + * SkGmInitPhyMarv() - Initialize the Marvell Phy registers + * + * Description: initializes all the Marvell Phy registers + * + * Note: + * + * Returns: + * nothing + */ +static void SkGmInitPhyMarv( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ + SK_GEPORT *pPrt; + SK_U16 PhyCtrl; + SK_U16 C1000BaseT; + SK_U16 AutoNegAdv; + SK_U16 ExtPhyCtrl; + SK_U16 PhyStat; + SK_U16 PhyStat1; + SK_U16 PhySpecStat; + SK_U16 LedCtrl; + SK_BOOL AutoNeg; + +#ifdef VCPU + VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", + Port, DoLoop); +#else /* VCPU */ + + pPrt = &pAC->GIni.GP[Port]; + + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + AutoNeg = SK_FALSE; + } + else { + AutoNeg = SK_TRUE; + } + + if (!DoLoop) { + /* Read Ext. PHY Specific Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); + + ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | + PHY_M_EC_MAC_S_MSK); + + ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) | + PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl)); + + /* Read PHY Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); + + /* Assert software reset */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, + (SK_U16)(PhyCtrl | PHY_CT_RESET)); + } +#endif /* VCPU */ + + PhyCtrl = 0 /* PHY_CT_COL_TST */; + C1000BaseT = 0; + AutoNegAdv = PHY_SEL_TYPE; + + /* manually Master/Slave ? */ + if (pPrt->PMSMode != SK_MS_MODE_AUTO) { + /* enable Manual Master/Slave */ + C1000BaseT |= PHY_M_1000C_MSE; + + if (pPrt->PMSMode == SK_MS_MODE_MASTER) { + C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ + } + } + + /* Auto-negotiation ? */ + if (!AutoNeg) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyMarv: no auto-negotiation Port %d\n", Port)); + + if (pPrt->PLinkMode == SK_LMODE_FULL) { + /* Set Full Duplex Mode */ + PhyCtrl |= PHY_CT_DUP_MD; + } + + /* Set Master/Slave manually if not already done */ + if (pPrt->PMSMode == SK_MS_MODE_AUTO) { + C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ + } + + /* Set Speed */ + switch (pPrt->PLinkSpeed) { + case SK_LSPEED_AUTO: + case SK_LSPEED_1000MBPS: + PhyCtrl |= PHY_CT_SP1000; + break; + case SK_LSPEED_100MBPS: + PhyCtrl |= PHY_CT_SP100; + break; + case SK_LSPEED_10MBPS: + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, + SKERR_HWI_E019MSG); + } + + if (!DoLoop) { + PhyCtrl |= PHY_CT_RESET; + } + /* + * Do NOT enable Auto-negotiation here. This would hold + * the link down because no IDLES are transmitted + */ + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyMarv: with auto-negotiation Port %d\n", Port)); + + PhyCtrl |= PHY_CT_ANE; + + if (pAC->GIni.GICopperType) { + /* Set Speed capabilities */ + switch (pPrt->PLinkSpeed) { + case SK_LSPEED_AUTO: + C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; + AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | + PHY_M_AN_10_FD | PHY_M_AN_10_HD; + break; + case SK_LSPEED_1000MBPS: + C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; + break; + case SK_LSPEED_100MBPS: + AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | + PHY_M_AN_10_FD | PHY_M_AN_10_HD; + break; + case SK_LSPEED_10MBPS: + AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, + SKERR_HWI_E019MSG); + } + + /* Set Full/half duplex capabilities */ + switch (pPrt->PLinkMode) { + case SK_LMODE_AUTOHALF: + C1000BaseT &= ~PHY_M_1000C_AFD; + AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD); + break; + case SK_LMODE_AUTOFULL: + C1000BaseT &= ~PHY_M_1000C_AHD; + AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD); + break; + case SK_LMODE_AUTOBOTH: + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, + SKERR_HWI_E015MSG); + } + + /* Set Auto-negotiation advertisement */ + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + AutoNegAdv |= PHY_B_P_NO_PAUSE; + break; + case SK_FLOW_MODE_LOC_SEND: + AutoNegAdv |= PHY_B_P_ASYM_MD; + break; + case SK_FLOW_MODE_SYMMETRIC: + AutoNegAdv |= PHY_B_P_SYM_MD; + break; + case SK_FLOW_MODE_SYM_OR_REM: + AutoNegAdv |= PHY_B_P_BOTH_MD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + } + else { /* special defines for FIBER (88E1011S only) */ + + /* Set Full/half duplex capabilities */ + switch (pPrt->PLinkMode) { + case SK_LMODE_AUTOHALF: + AutoNegAdv |= PHY_M_AN_1000X_AHD; + break; + case SK_LMODE_AUTOFULL: + AutoNegAdv |= PHY_M_AN_1000X_AFD; + break; + case SK_LMODE_AUTOBOTH: + AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, + SKERR_HWI_E015MSG); + } + + /* Set Auto-negotiation advertisement */ + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + AutoNegAdv |= PHY_M_P_NO_PAUSE_X; + break; + case SK_FLOW_MODE_LOC_SEND: + AutoNegAdv |= PHY_M_P_ASYM_MD_X; + break; + case SK_FLOW_MODE_SYMMETRIC: + AutoNegAdv |= PHY_M_P_SYM_MD_X; + break; + case SK_FLOW_MODE_SYM_OR_REM: + AutoNegAdv |= PHY_M_P_BOTH_MD_X; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + } + + if (!DoLoop) { + /* Restart Auto-negotiation */ + PhyCtrl |= PHY_CT_RE_CFG; + } + } + +#ifdef VCPU + /* + * E-mail from Gu Lin (08-03-2002): + */ + + /* Program PHY register 30 as 16'h0708 for simulation speed up */ + SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708); + + VCpuWait(2000); + +#else /* VCPU */ + + /* Write 1000Base-T Control Register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("1000B-T Ctrl=0x%04X\n", C1000BaseT)); + + /* Write AutoNeg Advertisement Register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv)); +#endif /* VCPU */ + + if (DoLoop) { + /* Set the PHY Loopback bit */ + PhyCtrl |= PHY_CT_LOOP; + + /* Program PHY register 16 as 16'h0400 to force link good */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); + +#if 0 + if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { + /* Write Ext. PHY Specific Control */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, + (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); + } + } + else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { + /* Write PHY Specific Control */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK); + } +#endif /* 0 */ + } + + /* Write to the PHY Control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); + +#ifdef VCPU + VCpuWait(2000); +#else + + LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); + +#ifdef ACT_LED_BLINK + LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; +#endif /* ACT_LED_BLINK */ + +#ifdef DUP_LED_NORMAL + LedCtrl |= PHY_M_LEDC_DP_CTRL; +#endif /* DUP_LED_NORMAL */ + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); + +#endif /* VCPU */ + +#ifdef SK_DIAG + c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); + c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); + c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); + c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); +#endif /* SK_DIAG */ + +#ifndef xDEBUG + /* Read PHY Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); + + /* Read 1000Base-T Control Register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); + + /* Read AutoNeg Advertisement Register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv)); + + /* Read Ext. PHY Specific Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl)); + + /* Read PHY Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Stat Reg.=0x%04X\n", PhyStat)); + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Stat Reg.=0x%04X\n", PhyStat1)); + + /* Read PHY Specific Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Spec Stat=0x%04X\n", PhySpecStat)); +#endif /* DEBUG */ + +#ifdef SK_DIAG + c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); + c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); + c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); + c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); + c_print("PHY Stat Reg=0x%04X\n", PhyStat); + c_print("PHY Stat Reg=0x%04X\n", PhyStat1); + c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); +#endif /* SK_DIAG */ + +} /* SkGmInitPhyMarv */ + + +#ifdef OTHER_PHY +/****************************************************************************** + * + * SkXmInitPhyLone() - Initialize the Level One Phy registers + * + * Description: initializes all the Level One Phy registers + * + * Note: + * + * Returns: + * nothing + */ +static void SkXmInitPhyLone( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ + SK_GEPORT *pPrt; + SK_U16 Ctrl1; + SK_U16 Ctrl2; + SK_U16 Ctrl3; + + Ctrl1 = PHY_CT_SP1000; + Ctrl2 = 0; + Ctrl3 = PHY_SEL_TYPE; + + pPrt = &pAC->GIni.GP[Port]; + + /* manually Master/Slave ? */ + if (pPrt->PMSMode != SK_MS_MODE_AUTO) { + Ctrl2 |= PHY_L_1000C_MSE; + + if (pPrt->PMSMode == SK_MS_MODE_MASTER) { + Ctrl2 |= PHY_L_1000C_MSC; + } + } + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { + /* + * level one spec say: "1000Mbps: manual mode not allowed" + * but lets see what happens... + */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyLone: no auto-negotiation Port %d\n", Port)); + /* Set DuplexMode in Config register */ + Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + + /* Determine Master/Slave manually if not already done */ + if (pPrt->PMSMode == SK_MS_MODE_AUTO) { + Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ + } + + /* + * Do NOT enable Auto-negotiation here. This would hold + * the link down because no IDLES are transmitted + */ + } + else { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyLone: with auto-negotiation Port %d\n", Port)); + /* Set Auto-negotiation advertisement */ + + /* Set Full/half duplex capabilities */ + switch (pPrt->PLinkMode) { + case SK_LMODE_AUTOHALF: + Ctrl2 |= PHY_L_1000C_AHD; + break; + case SK_LMODE_AUTOFULL: + Ctrl2 |= PHY_L_1000C_AFD; + break; + case SK_LMODE_AUTOBOTH: + Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, + SKERR_HWI_E015MSG); + } + + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + Ctrl3 |= PHY_L_P_NO_PAUSE; + break; + case SK_FLOW_MODE_LOC_SEND: + Ctrl3 |= PHY_L_P_ASYM_MD; + break; + case SK_FLOW_MODE_SYMMETRIC: + Ctrl3 |= PHY_L_P_SYM_MD; + break; + case SK_FLOW_MODE_SYM_OR_REM: + Ctrl3 |= PHY_L_P_BOTH_MD; + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + + /* Restart Auto-negotiation */ + Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; + + } + + /* Initialize LED register here ? */ + /* No. Please do it in SkDgXmitLed() (if required) and swap + init order of LEDs and XMAC. (MAl) */ + + /* Write 1000Base-T Control Register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); + + /* Write AutoNeg Advertisement Register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); + + + if (DoLoop) { + /* Set the Phy Loopback bit, too */ + Ctrl1 |= PHY_CT_LOOP; + } + + /* Write to the Phy control register */ + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Control Reg=0x%04X\n", Ctrl1)); +} /* SkXmInitPhyLone */ + + +/****************************************************************************** + * + * SkXmInitPhyNat() - Initialize the National Phy registers + * + * Description: initializes all the National Phy registers + * + * Note: + * + * Returns: + * nothing + */ +static void SkXmInitPhyNat( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ +/* todo: National */ +} /* SkXmInitPhyNat */ +#endif /* OTHER_PHY */ + + +/****************************************************************************** + * + * SkMacInitPhy() - Initialize the PHY registers + * + * Description: calls the Init PHY routines dep. on board type + * + * Note: + * + * Returns: + * nothing + */ +void SkMacInitPhy( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + switch (pPrt->PhyType) { + case SK_PHY_XMAC: + SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); + break; + case SK_PHY_BCOM: + SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); + break; + case SK_PHY_MARV_COPPER: + case SK_PHY_MARV_FIBER: + SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmInitPhyLone(pAC, IoC, Port, DoLoop); + break; + case SK_PHY_NAT: + SkXmInitPhyNat(pAC, IoC, Port, DoLoop); + break; +#endif /* OTHER_PHY */ + } +} /* SkMacInitPhy */ + + +#ifndef SK_DIAG +/****************************************************************************** + * + * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg + * + * This function analyses the Interrupt status word. If any of the + * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable + * is set true. + */ +void SkXmAutoNegLipaXmac( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus) /* Interrupt Status word to analyse */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && + (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n", + Port, IStatus)); + pPrt->PLipaAutoNeg = SK_LIPA_AUTO; + } +} /* SkXmAutoNegLipaXmac */ + + +/****************************************************************************** + * + * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg + * + * This function analyses the PHY status word. + * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable + * is set true. + */ +void SkMacAutoNegLipaPhy( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U16 PhyStat) /* PHY Status word to analyse */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && + (PhyStat & PHY_ST_AN_OVER) != 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n", + Port, PhyStat)); + pPrt->PLipaAutoNeg = SK_LIPA_AUTO; + } +} /* SkMacAutoNegLipaPhy */ +#endif /* SK_DIAG */ + + +/****************************************************************************** + * + * SkXmAutoNegDoneXmac() - Auto-negotiation handling + * + * Description: + * This function handles the auto-negotiation if the Done bit is set. + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +static int SkXmAutoNegDoneXmac( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 ResAb; /* Resolved Ability */ + SK_U16 LPAb; /* Link Partner Ability */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegDoneXmac, Port %d\n",Port)); + + pPrt = &pAC->GIni.GP[Port]; + + /* Get PHY parameters */ + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); + + if ((LPAb & PHY_X_AN_RFB) != 0) { + /* At least one of the remote fault bit is set */ + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Remote fault bit set Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); + } + + /* Check Duplex mismatch */ + if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + } + else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + } + else { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_DUP_CAP); + } + + /* Check PAUSE mismatch */ + /* We are NOT using chapter 4.23 of the Xaqti manual */ + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || + pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && + (LPAb & PHY_X_P_SYM_MD) != 0) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && + (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { + /* Enable PAUSE receive, disable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; + } + else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && + (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { + /* Disable PAUSE receive, enable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; + } + else { + /* PAUSE mismatch -> no PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + } + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + + return(SK_AND_OK); +} /* SkXmAutoNegDoneXmac */ + + +/****************************************************************************** + * + * SkXmAutoNegDoneBcom() - Auto-negotiation handling + * + * Description: + * This function handles the auto-negotiation if the Done bit is set. + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +static int SkXmAutoNegDoneBcom( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 LPAb; /* Link Partner Ability */ + SK_U16 AuxStat; /* Auxiliary Status */ + +#if 0 +01-Sep-2000 RA;:;: + SK_U16 ResAb; /* Resolved Ability */ +#endif /* 0 */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegDoneBcom, Port %d\n", Port)); + pPrt = &pAC->GIni.GP[Port]; + + /* Get PHY parameters */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); +#if 0 +01-Sep-2000 RA;:;: + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); +#endif /* 0 */ + + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); + + if ((LPAb & PHY_B_AN_RF) != 0) { + /* Remote fault bit is set: Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Remote fault bit set Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); + } + + /* Check Duplex mismatch */ + if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + } + else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + } + else { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_DUP_CAP); + } + +#if 0 +01-Sep-2000 RA;:;: + /* Check Master/Slave resolution */ + if ((ResAb & PHY_B_1000S_MSF) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Master/Slave Fault Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + return(SK_AND_OTHER); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; +#endif /* 0 */ + + /* Check PAUSE mismatch */ + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { + /* Enable PAUSE receive, disable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; + } + else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { + /* Disable PAUSE receive, enable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; + } + else { + /* PAUSE mismatch -> no PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + } + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + + return(SK_AND_OK); +} /* SkXmAutoNegDoneBcom */ + + +/****************************************************************************** + * + * SkGmAutoNegDoneMarv() - Auto-negotiation handling + * + * Description: + * This function handles the auto-negotiation if the Done bit is set. + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +static int SkGmAutoNegDoneMarv( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 LPAb; /* Link Partner Ability */ + SK_U16 ResAb; /* Resolved Ability */ + SK_U16 AuxStat; /* Auxiliary Status */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegDoneMarv, Port %d\n", Port)); + pPrt = &pAC->GIni.GP[Port]; + + /* Get PHY parameters */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); + + if ((LPAb & PHY_M_AN_RF) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Remote fault bit set Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); + } + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); + + /* Check Master/Slave resolution */ + if ((ResAb & PHY_B_1000S_MSF) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Master/Slave Fault Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + return(SK_AND_OTHER); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; + + /* Read PHY Specific Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); + + /* Check Speed & Duplex resolved */ + if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + return(SK_AND_DUP_CAP); + } + + if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + } + else { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + } + + /* Check PAUSE mismatch */ + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { + /* Enable PAUSE receive, disable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; + } + else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { + /* Disable PAUSE receive, enable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; + } + else { + /* PAUSE mismatch -> no PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + } + + /* set used link speed */ + switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { + case (unsigned)PHY_M_PS_SPEED_1000: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + break; + case PHY_M_PS_SPEED_100: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; + break; + default: + pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; + } + + return(SK_AND_OK); +} /* SkGmAutoNegDoneMarv */ + + +#ifdef OTHER_PHY +/****************************************************************************** + * + * SkXmAutoNegDoneLone() - Auto-negotiation handling + * + * Description: + * This function handles the auto-negotiation if the Done bit is set. + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +static int SkXmAutoNegDoneLone( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 ResAb; /* Resolved Ability */ + SK_U16 LPAb; /* Link Partner Ability */ + SK_U16 QuickStat; /* Auxiliary Status */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegDoneLone, Port %d\n",Port)); + pPrt = &pAC->GIni.GP[Port]; + + /* Get PHY parameters */ + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); + + if ((LPAb & PHY_L_AN_RF) != 0) { + /* Remote fault bit is set */ + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegFail: Remote fault bit set Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); + } + + /* Check Duplex mismatch */ + if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + } + else { + pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + } + + /* Check Master/Slave resolution */ + if ((ResAb & PHY_L_1000S_MSF) != 0) { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Master/Slave Fault Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + return(SK_AND_OTHER); + } + else if (ResAb & PHY_L_1000S_MSR) { + pPrt->PMSStatus = SK_MS_STAT_MASTER; + } + else { + pPrt->PMSStatus = SK_MS_STAT_SLAVE; + } + + /* Check PAUSE mismatch */ + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + /* we must manually resolve the abilities here */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + /* default */ + break; + case SK_FLOW_MODE_LOC_SEND: + if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == + (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { + /* Disable PAUSE receive, enable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; + } + break; + case SK_FLOW_MODE_SYMMETRIC: + if ((QuickStat & PHY_L_QS_PAUSE) != 0) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + break; + case SK_FLOW_MODE_SYM_OR_REM: + if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == + PHY_L_QS_AS_PAUSE) { + /* Enable PAUSE receive, disable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; + } + else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, + SKERR_HWI_E016MSG); + } + + return(SK_AND_OK); +} /* SkXmAutoNegDoneLone */ + + +/****************************************************************************** + * + * SkXmAutoNegDoneNat() - Auto-negotiation handling + * + * Description: + * This function handles the auto-negotiation if the Done bit is set. + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +static int SkXmAutoNegDoneNat( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ +/* todo: National */ + return(SK_AND_OK); +} /* SkXmAutoNegDoneNat */ +#endif /* OTHER_PHY */ + + +/****************************************************************************** + * + * SkMacAutoNegDone() - Auto-negotiation handling + * + * Description: calls the auto-negotiation done routines dep. on board type + * + * Returns: + * SK_AND_OK o.k. + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened + */ +int SkMacAutoNegDone( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + int Rtv; + + pPrt = &pAC->GIni.GP[Port]; + + switch (pPrt->PhyType) { + case SK_PHY_XMAC: + Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); + break; + case SK_PHY_BCOM: + Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); + break; + case SK_PHY_MARV_COPPER: + case SK_PHY_MARV_FIBER: + Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); + break; + case SK_PHY_NAT: + Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); + break; +#endif /* OTHER_PHY */ + default: + return(SK_AND_OTHER); + } + + if (Rtv != SK_AND_OK) { + return(Rtv); + } + + /* We checked everything and may now enable the link */ + pPrt->PAutoNegFail = SK_FALSE; + + SkMacRxTxEnable(pAC, IoC, Port); + + return(SK_AND_OK); +} /* SkMacAutoNegDone */ + + +/****************************************************************************** + * + * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC + * + * Description: + * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg. + * enables Rx/Tx + * + * Returns: N/A + */ +static void SkXmSetRxTxEn( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ +{ + SK_U16 Word; + + XM_IN16(IoC, Port, XM_MMU_CMD, &Word); + + switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { + case SK_MAC_LOOPB_ON: + Word |= XM_MMU_MAC_LB; + break; + case SK_MAC_LOOPB_OFF: + Word &= ~XM_MMU_MAC_LB; + break; + } + + switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) { + case SK_PHY_LOOPB_ON: + Word |= XM_MMU_GMII_LOOP; + break; + case SK_PHY_LOOPB_OFF: + Word &= ~XM_MMU_GMII_LOOP; + break; + } + + switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { + case SK_PHY_FULLD_ON: + Word |= XM_MMU_GMII_FD; + break; + case SK_PHY_FULLD_OFF: + Word &= ~XM_MMU_GMII_FD; + break; + } + + XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX); + + /* dummy read to ensure writing */ + XM_IN16(IoC, Port, XM_MMU_CMD, &Word); + +} /* SkXmSetRxTxEn */ + + +/****************************************************************************** + * + * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC + * + * Description: + * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg. + * enables Rx/Tx + * + * Returns: N/A + */ +static void SkGmSetRxTxEn( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ +{ + SK_U16 Ctrl; + + GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); + + switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { + case SK_MAC_LOOPB_ON: + Ctrl |= GM_GPCR_LOOP_ENA; + break; + case SK_MAC_LOOPB_OFF: + Ctrl &= ~GM_GPCR_LOOP_ENA; + break; + } + + switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { + case SK_PHY_FULLD_ON: + Ctrl |= GM_GPCR_DUP_FULL; + break; + case SK_PHY_FULLD_OFF: + Ctrl &= ~GM_GPCR_DUP_FULL; + break; + } + + GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + + /* dummy read to ensure writing */ + GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); + +} /* SkGmSetRxTxEn */ + + +/****************************************************************************** + * + * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters + * + * Description: calls the Special Set Rx/Tx Enable routines dep. on board type + * + * Returns: N/A + */ +void SkMacSetRxTxEn( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +int Para) +{ + if (pAC->GIni.GIGenesis) { + + SkXmSetRxTxEn(pAC, IoC, Port, Para); + } + else { + + SkGmSetRxTxEn(pAC, IoC, Port, Para); + } + +} /* SkMacSetRxTxEn */ + + +/****************************************************************************** + * + * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up + * + * Description: enables Rx/Tx dep. on board type + * + * Returns: + * 0 o.k. + * != 0 Error happened + */ +int SkMacRxTxEnable( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 Reg; /* 16-bit register value */ + SK_U16 IntMask; /* MAC interrupt mask */ + SK_U16 SWord; + + pPrt = &pAC->GIni.GP[Port]; + + if (!pPrt->PHWLinkUp) { + /* The Hardware link is NOT up */ + return(0); + } + + if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || + pPrt->PLinkMode == SK_LMODE_AUTOFULL || + pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && + pPrt->PAutoNegFail) { + /* Auto-negotiation is not done or failed */ + return(0); + } + + if (pAC->GIni.GIGenesis) { + /* set Duplex Mode and Pause Mode */ + SkXmInitDupMd(pAC, IoC, Port); + + SkXmInitPauseMd(pAC, IoC, Port); + + /* + * Initialize the Interrupt Mask Register. Default IRQs are... + * - Link Asynchronous Event + * - Link Partner requests config + * - Auto Negotiation Done + * - Rx Counter Event Overflow + * - Tx Counter Event Overflow + * - Transmit FIFO Underrun + */ + IntMask = XM_DEF_MSK; + +#ifdef DEBUG + /* add IRQ for Receive FIFO Overflow */ + IntMask &= ~XM_IS_RXF_OV; +#endif /* DEBUG */ + + if (pPrt->PhyType != SK_PHY_XMAC) { + /* disable GP0 interrupt bit */ + IntMask |= XM_IS_INP_ASS; + } + XM_OUT16(IoC, Port, XM_IMSK, IntMask); + + /* get MMU Command Reg. */ + XM_IN16(IoC, Port, XM_MMU_CMD, &Reg); + + if (pPrt->PhyType != SK_PHY_XMAC && + (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) { + /* set to Full Duplex */ + Reg |= XM_MMU_GMII_FD; + } + + switch (pPrt->PhyType) { + case SK_PHY_BCOM: + /* + * Workaround BCOM Errata (#10523) for all BCom Phys + * Enable Power Management after link up + */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, + (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK); + break; + case SK_PHY_NAT: + /* todo National: + SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */ + /* no interrupts possible from National ??? */ + break; +#endif /* OTHER_PHY */ + } + + /* enable Rx/Tx */ + XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); + } + else { + /* + * Initialize the Interrupt Mask Register. Default IRQs are... + * - Rx Counter Event Overflow + * - Tx Counter Event Overflow + * - Transmit FIFO Underrun + */ + IntMask = GMAC_DEF_MSK; + +#ifdef DEBUG + /* add IRQ for Receive FIFO Overrun */ + IntMask |= GM_IS_RX_FF_OR; +#endif /* DEBUG */ + + SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); + + /* get General Purpose Control */ + GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); + + if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { + /* set to Full Duplex */ + Reg |= GM_GPCR_DUP_FULL; + } + + /* enable Rx/Tx */ + GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + +#ifndef VCPU + /* Enable all PHY interrupts */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); +#endif /* VCPU */ + } + + return(0); + +} /* SkMacRxTxEnable */ + + +/****************************************************************************** + * + * SkMacRxTxDisable() - Disable Receiver and Transmitter + * + * Description: disables Rx/Tx dep. on board type + * + * Returns: N/A + */ +void SkMacRxTxDisable( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 Word; + + if (pAC->GIni.GIGenesis) { + + XM_IN16(IoC, Port, XM_MMU_CMD, &Word); + + XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); + + /* dummy read to ensure writing */ + XM_IN16(IoC, Port, XM_MMU_CMD, &Word); + } + else { + + GM_IN16(IoC, Port, GM_GP_CTRL, &Word); + + GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); + + /* dummy read to ensure writing */ + GM_IN16(IoC, Port, GM_GP_CTRL, &Word); + } +} /* SkMacRxTxDisable */ + + +/****************************************************************************** + * + * SkMacIrqDisable() - Disable IRQ from MAC + * + * Description: sets the IRQ-mask to disable IRQ dep. on board type + * + * Returns: N/A + */ +void SkMacIrqDisable( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 Word; + + pPrt = &pAC->GIni.GP[Port]; + + if (pAC->GIni.GIGenesis) { + + /* disable all XMAC IRQs */ + XM_OUT16(IoC, Port, XM_IMSK, 0xffff); + + /* Disable all PHY interrupts */ + switch (pPrt->PhyType) { + case SK_PHY_BCOM: + /* Make sure that PHY is initialized */ + if (pPrt->PState != SK_PRT_RESET) { + /* NOT allowed if BCOM is in RESET state */ + /* Workaround BCOM Errata (#10523) all BCom */ + /* Disable Power Management if link is down */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, + (SK_U16)(Word | PHY_B_AC_DIS_PM)); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); + } + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); + break; + case SK_PHY_NAT: + /* todo: National + SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ + break; +#endif /* OTHER_PHY */ + } + } + else { + /* disable all GMAC IRQs */ + SK_OUT8(IoC, GMAC_IRQ_MSK, 0); + +#ifndef VCPU + /* Disable all PHY interrupts */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); +#endif /* VCPU */ + } +} /* SkMacIrqDisable */ + + +#ifdef SK_DIAG +/****************************************************************************** + * + * SkXmSendCont() - Enable / Disable Send Continuous Mode + * + * Description: enable / disable Send Continuous Mode on XMAC + * + * Returns: + * nothing + */ +void SkXmSendCont( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL Enable) /* Enable / Disable */ +{ + SK_U32 MdReg; + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + + if (Enable) { + MdReg |= XM_MD_TX_CONT; + } + else { + MdReg &= ~XM_MD_TX_CONT; + } + /* setup Mode Register */ + XM_OUT32(IoC, Port, XM_MODE, MdReg); + +} /* SkXmSendCont*/ + +/****************************************************************************** + * + * SkMacTimeStamp() - Enable / Disable Time Stamp + * + * Description: enable / disable Time Stamp generation for Rx packets + * + * Returns: + * nothing + */ +void SkMacTimeStamp( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL Enable) /* Enable / Disable */ +{ + SK_U32 MdReg; + SK_U8 TimeCtrl; + + if (pAC->GIni.GIGenesis) { + + XM_IN32(IoC, Port, XM_MODE, &MdReg); + + if (Enable) { + MdReg |= XM_MD_ATS; + } + else { + MdReg &= ~XM_MD_ATS; + } + /* setup Mode Register */ + XM_OUT32(IoC, Port, XM_MODE, MdReg); + } + else { + if (Enable) { + TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ; + } + else { + TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; + } + /* Start/Stop Time Stamp Timer */ + SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl); + } +} /* SkMacTimeStamp*/ + +#else /* SK_DIAG */ + +/****************************************************************************** + * + * SkXmIrq() - Interrupt Service Routine + * + * Description: services an Interrupt Request of the XMAC + * + * Note: + * With an external PHY, some interrupt bits are not meaningfull any more: + * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE + * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC + * - Page Received (bit #9) XM_IS_RX_PAGE + * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE + * - AutoNegDone (bit #7) XM_IS_AND + * Also probably not valid any more is the GP0 input bit: + * - GPRegisterBit0set XM_IS_INP_ASS + * + * Returns: + * nothing + */ +void SkXmIrq( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_EVPARA Para; + SK_U16 IStatus; /* Interrupt status read from the XMAC */ + SK_U16 IStatus2; + + pPrt = &pAC->GIni.GP[Port]; + + XM_IN16(IoC, Port, XM_ISRC, &IStatus); + + /* LinkPartner Auto-negable? */ + if (pPrt->PhyType == SK_PHY_XMAC) { + SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus); + } + else { + /* mask bits that are not used with ext. PHY */ + IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC | + XM_IS_RX_PAGE | XM_IS_TX_PAGE | + XM_IS_AND | XM_IS_INP_ASS); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); + + if (!pPrt->PHWLinkUp) { + /* Spurious XMAC interrupt */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("SkXmIrq: spurious interrupt on Port %d\n", Port)); + return; + } + + if ((IStatus & XM_IS_INP_ASS) != 0) { + /* Reread ISR Register if link is not in sync */ + XM_IN16(IoC, Port, XM_ISRC, &IStatus2); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n", + Port, IStatus, IStatus2)); + IStatus &= ~XM_IS_INP_ASS; + IStatus |= IStatus2; + } + + if ((IStatus & XM_IS_LNK_AE) != 0) { + /* not used, GP0 is used instead */ + } + + if ((IStatus & XM_IS_TX_ABORT) != 0) { + /* not used */ + } + + if ((IStatus & XM_IS_FRC_INT) != 0) { + /* not used, use ASIC IRQ instead if needed */ + } + + if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) { + SkHWLinkDown(pAC, IoC, Port); + + /* Signal to RLMT */ + Para.Para32[0] = (SK_U32)Port; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + + /* Start workaround Errata #2 timer */ + SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, + SKGE_HWAC, SK_HWEV_WATIM, Para); + } + + if ((IStatus & XM_IS_RX_PAGE) != 0) { + /* not used */ + } + + if ((IStatus & XM_IS_TX_PAGE) != 0) { + /* not used */ + } + + if ((IStatus & XM_IS_AND) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("SkXmIrq: AND on link that is up Port %d\n", Port)); + } + + if ((IStatus & XM_IS_TSC_OV) != 0) { + /* not used */ + } + + /* Combined Tx & Rx Counter Overflow SIRQ Event */ + if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { + Para.Para32[0] = (SK_U32)Port; + Para.Para32[1] = (SK_U32)IStatus; + SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); + } + + if ((IStatus & XM_IS_RXF_OV) != 0) { + /* normal situation -> no effect */ +#ifdef DEBUG + pPrt->PRxOverCnt++; +#endif /* DEBUG */ + } + + if ((IStatus & XM_IS_TXF_UR) != 0) { + /* may NOT happen -> error log */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); + } + + if ((IStatus & XM_IS_TX_COMP) != 0) { + /* not served here */ + } + + if ((IStatus & XM_IS_RX_COMP) != 0) { + /* not served here */ + } +} /* SkXmIrq */ + + +/****************************************************************************** + * + * SkGmIrq() - Interrupt Service Routine + * + * Description: services an Interrupt Request of the GMAC + * + * Note: + * + * Returns: + * nothing + */ +void SkGmIrq( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_EVPARA Para; + SK_U8 IStatus; /* Interrupt status */ + + pPrt = &pAC->GIni.GP[Port]; + + SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); + + /* LinkPartner Auto-negable? */ + SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); + + /* Combined Tx & Rx Counter Overflow SIRQ Event */ + if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { + /* these IRQs will be cleared by reading GMACs register */ + Para.Para32[0] = (SK_U32)Port; + Para.Para32[1] = (SK_U32)IStatus; + SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); + } + + if (IStatus & GM_IS_RX_FF_OR) { + /* clear GMAC Rx FIFO Overrun IRQ */ + SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); +#ifdef DEBUG + pPrt->PRxOverCnt++; +#endif /* DEBUG */ + } + + if (IStatus & GM_IS_TX_FF_UR) { + /* clear GMAC Tx FIFO Underrun IRQ */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU); + /* may NOT happen -> error log */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); + } + + if (IStatus & GM_IS_TX_COMPL) { + /* not served here */ + } + + if (IStatus & GM_IS_RX_COMPL) { + /* not served here */ + } +} /* SkGmIrq */ + +/****************************************************************************** + * + * SkMacIrq() - Interrupt Service Routine for MAC + * + * Description: calls the Interrupt Service Routine dep. on board type + * + * Returns: + * nothing + */ +void SkMacIrq( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + + if (pAC->GIni.GIGenesis) { + /* IRQ from XMAC */ + SkXmIrq(pAC, IoC, Port); + } + else { + /* IRQ from GMAC */ + SkGmIrq(pAC, IoC, Port); + } +} /* SkMacIrq */ + +#endif /* !SK_DIAG */ + +/****************************************************************************** + * + * SkXmUpdateStats() - Force the XMAC to output the current statistic + * + * Description: + * The XMAC holds its statistic internally. To obtain the current + * values a command must be sent so that the statistic data will + * be written to a predefined memory area on the adapter. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkXmUpdateStats( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + SK_GEPORT *pPrt; + SK_U16 StatReg; + int WaitIndex; + + pPrt = &pAC->GIni.GP[Port]; + WaitIndex = 0; + + /* Send an update command to XMAC specified */ + XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); + + /* + * It is an auto-clearing register. If the command bits + * went to zero again, the statistics are transferred. + * Normally the command should be executed immediately. + * But just to be sure we execute a loop. + */ + do { + + XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg); + + if (++WaitIndex > 10) { + + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG); + + return(1); + } + } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0); + + return(0); +} /* SkXmUpdateStats */ + +/****************************************************************************** + * + * SkGmUpdateStats() - Force the GMAC to output the current statistic + * + * Description: + * Empty function for GMAC. Statistic data is accessible in direct way. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmUpdateStats( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + return(0); +} + +/****************************************************************************** + * + * SkXmMacStatistic() - Get XMAC counter value + * + * Description: + * Gets the 32bit counter value. Except for the octet counters + * the lower 32bit are counted in hardware and the upper 32bit + * must be counted in software by monitoring counter overflow interrupts. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkXmMacStatistic( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 StatAddr, /* MIB counter base address */ +SK_U32 *pVal) /* ptr to return statistic value */ +{ + if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); + + return(1); + } + + XM_IN32(IoC, Port, StatAddr, pVal); + + return(0); +} /* SkXmMacStatistic */ + +/****************************************************************************** + * + * SkGmMacStatistic() - Get GMAC counter value + * + * Description: + * Gets the 32bit counter value. Except for the octet counters + * the lower 32bit are counted in hardware and the upper 32bit + * must be counted in software by monitoring counter overflow interrupts. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmMacStatistic( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 StatAddr, /* MIB counter base address */ +SK_U32 *pVal) /* ptr to return statistic value */ +{ + + if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); + return(1); + } + + GM_IN32(IoC, Port, StatAddr, pVal); + + return(0); +} /* SkGmMacStatistic */ + +/****************************************************************************** + * + * SkXmResetCounter() - Clear MAC statistic counter + * + * Description: + * Force the XMAC to clear its statistic counter. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkXmResetCounter( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); + /* Clear two times according to Errata #3 */ + XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); + + return(0); +} /* SkXmResetCounter */ + +/****************************************************************************** + * + * SkGmResetCounter() - Clear MAC statistic counter + * + * Description: + * Force GMAC to clear its statistic counter. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmResetCounter( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 Reg; /* Phy Address Register */ + SK_U16 Word; + int i; + + GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); + +#ifndef VCPU + /* set MIB Clear Counter Mode */ + GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); + + /* read all MIB Counters with Clear Mode set */ + for (i = 0; i < GM_MIB_CNT_SIZE; i++) { + /* the reset is performed only when the lower 16 bits are read */ + GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); + } + + /* clear MIB Clear Counter Mode */ + GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); +#endif /* !VCPU */ + + return(0); +} /* SkGmResetCounter */ + +/****************************************************************************** + * + * SkXmOverflowStatus() - Gets the status of counter overflow interrupt + * + * Description: + * Checks the source causing an counter overflow interrupt. On success the + * resulting counter overflow status is written to , whereas the + * upper dword stores the XMAC ReceiveCounterEvent register and the lower + * dword the XMAC TransmitCounterEvent register. + * + * Note: + * For XMAC the interrupt source is a self-clearing register, so the source + * must be checked only once. SIRQ module does another check to be sure + * that no interrupt get lost during process time. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkXmOverflowStatus( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus, /* Interupt Status from MAC */ +SK_U64 *pStatus) /* ptr for return overflow status value */ +{ + SK_U64 Status; /* Overflow status */ + SK_U32 RegVal; + + Status = 0; + + if ((IStatus & XM_IS_RXC_OV) != 0) { + + XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal); + Status |= (SK_U64)RegVal << 32; + } + + if ((IStatus & XM_IS_TXC_OV) != 0) { + + XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal); + Status |= (SK_U64)RegVal; + } + + *pStatus = Status; + + return(0); +} /* SkXmOverflowStatus */ + + +/****************************************************************************** + * + * SkGmOverflowStatus() - Gets the status of counter overflow interrupt + * + * Description: + * Checks the source causing an counter overflow interrupt. On success the + * resulting counter overflow status is written to , whereas the + * the following bit coding is used: + * 63:56 - unused + * 55:48 - TxRx interrupt register bit7:0 + * 32:47 - Rx interrupt register + * 31:24 - unused + * 23:16 - TxRx interrupt register bit15:8 + * 15:0 - Tx interrupt register + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmOverflowStatus( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus, /* Interupt Status from MAC */ +SK_U64 *pStatus) /* ptr for return overflow status value */ +{ + SK_U64 Status; /* Overflow status */ + SK_U16 RegVal; + + Status = 0; + + if ((IStatus & GM_IS_RX_CO_OV) != 0) { + /* this register is self-clearing after read */ + GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); + Status |= (SK_U64)RegVal << 32; + } + + if ((IStatus & GM_IS_TX_CO_OV) != 0) { + /* this register is self-clearing after read */ + GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); + Status |= (SK_U64)RegVal; + } + + /* this register is self-clearing after read */ + GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); + /* Rx overflow interrupt register bits (LoByte)*/ + Status |= (SK_U64)((SK_U8)RegVal) << 48; + /* Tx overflow interrupt register bits (HiByte)*/ + Status |= (SK_U64)(RegVal >> 8) << 16; + + *pStatus = Status; + + return(0); +} /* SkGmOverflowStatus */ + +/****************************************************************************** + * + * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test + * + * Description: + * starts the cable diagnostic test if 'StartTest' is true + * gets the results if 'StartTest' is true + * + * NOTE: this test is meaningful only when link is down + * + * Returns: + * 0: success + * 1: no YUKON copper + * 2: test in progress + */ +int SkGmCableDiagStatus( +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* IO context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL StartTest) /* flag for start / get result */ +{ + int i; + SK_U16 RegVal; + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PhyType != SK_PHY_MARV_COPPER) { + + return(1); + } + + if (StartTest) { + /* only start the cable test */ + if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { + /* apply TDR workaround from Marvell */ + SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); + + SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); + SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); + SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); + SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); + SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); + } + + /* set address to 0 for MDI[0] */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); + + /* Read Cable Diagnostic Reg */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); + + /* start Cable Diagnostic Test */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, + (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); + + return(0); + } + + /* Read Cable Diagnostic Reg */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PHY Cable Diag.=0x%04X\n", RegVal)); + + if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { + /* test is running */ + return(2); + } + + /* get the test results */ + for (i = 0; i < 4; i++) { + /* set address to i for MDI[i] */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); + + /* get Cable Diagnostic values */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); + + pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); + + pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); + } + + return(0); +} /* SkGmCableDiagStatus */ + +#endif /* CONFIG_SK98 */ + +/* End of file */ diff --git a/drivers/net/sk98lin/u-boot_compat.h b/drivers/net/sk98lin/u-boot_compat.h new file mode 100644 index 0000000000..1e385f8ef5 --- /dev/null +++ b/drivers/net/sk98lin/u-boot_compat.h @@ -0,0 +1,98 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _UBOOT_COMPAT_H__ +#define _UBOOT_COMPAT_H__ + + +#include +#include +#include +#include +#include + +#define __initdata +#define __init +#define __exit + +#define netif_stop_queue(x) +#define netif_wake_queue(x) +#define netif_running(x) 0 +#define unregister_netdev(x) +#define remove_proc_entry(x,y) + +#define dev_addr enetaddr + +#define spin_lock_irqsave(x,y) y = 0; +#define spin_lock_init(x) +#define spin_lock(x) +#define spin_unlock_irqrestore(x,y) +#define spin_unlock(x) + + +#define ENODEV 1 +#define EAGAIN 2 +#define EBUSY 3 + +#define HZ CFG_HZ + + +#define printk printf +#define KERN_ERR +#define KERN_WARNING +#define KERN_INFO + +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT + + +#define kmalloc(x,y) malloc(x) +#define kfree(x) free(x) +#define GFP_ATOMIC 0 + +#define pci_alloc_consistent(x,y,z) (void *)(*(dma_addr_t *)(z) = (dma_addr_t)malloc(y)) +#define pci_free_consistent(x,y,z,d) free(z) +#define pci_dma_sync_single(x,y,z,d) +#define pci_unmap_page(x,y,z,d) +#define pci_unmap_single(x,y,z,d) +#define pci_present() 1 + +struct sk_buff +{ + u8 * data; + u32 len; + u8 * data_unaligned; +}; + +struct sk_buff * alloc_skb(u32 size, int dummy); +void dev_kfree_skb_any(struct sk_buff *skb); +void skb_reserve(struct sk_buff *skb, unsigned int len); +void skb_put(struct sk_buff *skb, unsigned int len); + +#define dev_kfree_skb dev_kfree_skb_any +#define dev_kfree_skb_irq dev_kfree_skb_any + +#define eth_copy_and_sum(dest,src,len,base) memcpy(dest->data,src,len); + + +#endif /* _UBOOT_COMPAT_H__ */ diff --git a/drivers/net/sk98lin/uboot_drv.c b/drivers/net/sk98lin/uboot_drv.c new file mode 100644 index 0000000000..d02cd1be24 --- /dev/null +++ b/drivers/net/sk98lin/uboot_drv.c @@ -0,0 +1,143 @@ +/* + * Driver for SysKonnect Gigabit Ethernet Server Adapters. + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_SK98) + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" +#include "u-boot_compat.h" + + +#define SKGE_MAX_CARDS 2 + + +extern int skge_probe(struct eth_device **); +extern void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); +extern void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +extern int SkGeOpen(struct eth_device *); +extern int SkGeClose(struct eth_device *); +extern int SkGeXmit(struct sk_buff *skb, struct eth_device *dev); +extern void ReceiveIrq(SK_AC *pAC, RX_PORT *pRxPort, SK_BOOL SlowPathLock); + +static int skge_init(struct eth_device *dev, bd_t * bis); +static int skge_send(struct eth_device *dev, volatile void *packet, int length); +static int skge_recv(struct eth_device *dev); +static void skge_halt(struct eth_device *dev); + +int skge_initialize(bd_t * bis) +{ + int numdev, i; + struct eth_device *dev[SKGE_MAX_CARDS]; + + numdev = skge_probe(&dev[0]); + + if (numdev > SKGE_MAX_CARDS) + { + printf("ERROR: numdev > SKGE_MAX_CARDS\n"); + } + + for (i = 0; i < numdev; i++) + { + sprintf (dev[i]->name, "SK98#%d", i); + + dev[i]->init = skge_init; + dev[i]->halt = skge_halt; + dev[i]->send = skge_send; + dev[i]->recv = skge_recv; + + eth_register(dev[i]); + } + + return numdev; +} + + +static int skge_init(struct eth_device *dev, bd_t * bis) +{ + int ret; + SK_AC * pAC = ((DEV_NET*)dev->priv)->pAC; + int i; + + ret = SkGeOpen(dev); + + while (pAC->Rlmt.Port[0].PortState != SK_RLMT_PS_GOING_UP) + { + SkGeIsrOnePort (0, pAC->dev[0], 0); + } + + for (i = 0; i < 100; i ++) + { + udelay(1000); + } + + return ret; +} + + +static void skge_halt(struct eth_device *dev) +{ + SkGeClose(dev); +} + + +static int skge_send(struct eth_device *dev, volatile void *packet, + int length) +{ + int ret = -1; + struct sk_buff * skb = alloc_skb(length, 0); + + if (! skb) + { + printf("skge_send: failed to alloc skb\n"); + goto Done; + } + + memcpy(skb->data, (void*)packet, length); + ret = SkGeXmit(skb, dev); + +Done: + return ret; +} + + +static int skge_recv(struct eth_device *dev) +{ + DEV_NET *pNet; + SK_AC *pAC; + int FromPort = 0; + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); + + return 0; +} + + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/sk98lin/uboot_skb.c b/drivers/net/sk98lin/uboot_skb.c new file mode 100644 index 0000000000..3a487a8e3d --- /dev/null +++ b/drivers/net/sk98lin/uboot_skb.c @@ -0,0 +1,122 @@ +/* + * Definitions for the 'struct sk_buff' memory handlers in U-Boot. + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#ifdef CONFIG_SK98 + +#include +#include "u-boot_compat.h" + +#define MAX_SKB 50 + +static struct sk_buff *sk_table[MAX_SKB]; + + +struct sk_buff * alloc_skb(u32 size, int dummy) +{ + int i; + struct sk_buff * ret = NULL; + + for (i = 0; i < MAX_SKB; i++) + { + if (sk_table[i]) + { + /* Already allocated. + */ + continue; + } + + sk_table[i] = malloc(sizeof(struct sk_buff)); + if (! sk_table[i]) + { + printf("alloc_skb: malloc failed\n"); + break; + } + + memset(sk_table[i], 0, sizeof(struct sk_buff)); + sk_table[i]->data = sk_table[i]->data_unaligned = + malloc(size + 16); + if (! sk_table[i]->data) + { + printf("alloc_skb: malloc failed\n"); + free(sk_table[i]); + sk_table[i] = NULL; + break; + } + + sk_table[i]->data += 16 - ((u32)sk_table[i]->data & 15); + sk_table[i]->len = size; + + break; + } + + if (i < MAX_SKB) + { + ret = sk_table[i]; + } + + if (! ret) + { + printf("Unable to allocate skb!\n"); + } + + return ret; +} + +void dev_kfree_skb_any(struct sk_buff *skb) +{ + int i; + + for (i = 0; i < MAX_SKB; i++) + { + if (sk_table[i] != skb) + { + continue; + } + + free(skb->data_unaligned); + free(skb); + sk_table[i] = NULL; + break; + } + + if (i == MAX_SKB) + { + printf("SKB allocation error!\n"); + } +} + +void skb_reserve(struct sk_buff *skb, unsigned int len) +{ + skb->data+=len; +} + +void skb_put(struct sk_buff *skb, unsigned int len) +{ + skb->len+=len; +} + +#endif /* CONFIG_SK98 */ diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c new file mode 100644 index 0000000000..8061f12979 --- /dev/null +++ b/drivers/net/smc91111.c @@ -0,0 +1,1623 @@ +/*------------------------------------------------------------------------ + . smc91111.c + . This is a driver for SMSC's 91C111 single-chip Ethernet device. + . + . (C) Copyright 2002 + . Sysgo Real-Time Solutions, GmbH + . Rolf Offermanns + . + . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) + . Developed by Simple Network Magic Corporation (SNMC) + . Copyright (C) 1996 by Erik Stahlman (ES) + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + . Information contained in this file was obtained from the LAN91C111 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . + . "Features" of the SMC chip: + . Integrated PHY/MAC for 10/100BaseT Operation + . Supports internal and external MII + . Integrated 8K packet memory + . EEPROM interface for configuration + . + . Arguments: + . io = for the base address + . irq = for the IRQ + . + . author: + . Erik Stahlman ( erik@vt.edu ) + . Daris A Nevil ( dnevil@snmc.com ) + . + . + . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) + . + . Sources: + . o SMSC LAN91C111 databook (www.smsc.com) + . o smc9194.c by Erik Stahlman + . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) + . + . History: + . 06/19/03 Richard Woodruff Made u-boot environment aware and added mac addr checks. + . 10/17/01 Marco Hasewinkel Modify for DNP/1110 + . 07/25/01 Woojung Huh Modify for ADS Bitsy + . 04/25/01 Daris A Nevil Initial public release through SMSC + . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111 + ----------------------------------------------------------------------------*/ + +#include +#include +#include +#include "smc91111.h" +#include + +#ifdef CONFIG_DRIVER_SMC91111 + +/* Use power-down feature of the chip */ +#define POWER_DOWN 0 + +#define NO_AUTOPROBE + +#define SMC_DEBUG 0 + +#if SMC_DEBUG > 1 +static const char version[] = + "smc91111.c:v1.0 04/25/01 by Daris A Nevil (dnevil@snmc.com)\n"; +#endif + +/* Autonegotiation timeout in seconds */ +#ifndef CONFIG_SMC_AUTONEG_TIMEOUT +#define CONFIG_SMC_AUTONEG_TIMEOUT 10 +#endif + +/*------------------------------------------------------------------------ + . + . Configuration options, for the experienced user to change. + . + -------------------------------------------------------------------------*/ + +/* + . Wait time for memory to be free. This probably shouldn't be + . tuned that much, as waiting for this means nothing else happens + . in the system +*/ +#define MEMORY_WAIT_TIME 16 + + +#if (SMC_DEBUG > 2 ) +#define PRINTK3(args...) printf(args) +#else +#define PRINTK3(args...) +#endif + +#if SMC_DEBUG > 1 +#define PRINTK2(args...) printf(args) +#else +#define PRINTK2(args...) +#endif + +#ifdef SMC_DEBUG +#define PRINTK(args...) printf(args) +#else +#define PRINTK(args...) +#endif + + +/*------------------------------------------------------------------------ + . + . The internal workings of the driver. If you are changing anything + . here with the SMC stuff, you should have the datasheet and know + . what you are doing. + . + -------------------------------------------------------------------------*/ +#define CARDNAME "LAN91C111" + +/* Memory sizing constant */ +#define LAN91C111_MEMORY_MULTIPLIER (1024*2) + +#ifndef CONFIG_SMC91111_BASE +#define CONFIG_SMC91111_BASE 0x20000300 +#endif + +#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE + +#define SMC_DEV_NAME "SMC91111" +#define SMC_PHY_ADDR 0x0000 +#define SMC_ALLOC_MAX_TRY 5 +#define SMC_TX_TIMEOUT 30 + +#define SMC_PHY_CLOCK_DELAY 1000 + +#define ETH_ZLEN 60 + +#ifdef CONFIG_SMC_USE_32_BIT +#define USE_32_BIT 1 +#else +#undef USE_32_BIT +#endif +/*----------------------------------------------------------------- + . + . The driver can be entered at any of the following entry points. + . + .------------------------------------------------------------------ */ + +extern int eth_init(bd_t *bd); +extern void eth_halt(void); +extern int eth_rx(void); +extern int eth_send(volatile void *packet, int length); + +#ifdef SHARED_RESOURCES + extern void swap_to(int device_id); +#endif + +/* + . This is called by register_netdev(). It is responsible for + . checking the portlist for the SMC9000 series chipset. If it finds + . one, then it will initialize the device, find the hardware information, + . and sets up the appropriate device parameters. + . NOTE: Interrupts are *OFF* when this procedure is called. + . + . NB:This shouldn't be static since it is referred to externally. +*/ +int smc_init(void); + +/* + . This is called by unregister_netdev(). It is responsible for + . cleaning up before the driver is finally unregistered and discarded. +*/ +void smc_destructor(void); + +/* + . The kernel calls this function when someone wants to use the device, + . typically 'ifconfig ethX up'. +*/ +static int smc_open(bd_t *bd); + + +/* + . This is called by the kernel in response to 'ifconfig ethX down'. It + . is responsible for cleaning up everything that the open routine + . does, and maybe putting the card into a powerdown state. +*/ +static int smc_close(void); + +/* + . Configures the PHY through the MII Management interface +*/ +#ifndef CONFIG_SMC91111_EXT_PHY +static void smc_phy_configure(void); +#endif /* !CONFIG_SMC91111_EXT_PHY */ + +/* + . This is a separate procedure to handle the receipt of a packet, to + . leave the interrupt code looking slightly cleaner +*/ +static int smc_rcv(void); + +/* See if a MAC address is defined in the current environment. If so use it. If not + . print a warning and set the environment and other globals with the default. + . If an EEPROM is present it really should be consulted. +*/ +int smc_get_ethaddr(bd_t *bd); +int get_rom_mac(uchar *v_rom_mac); + +/* + ------------------------------------------------------------ + . + . Internal routines + . + ------------------------------------------------------------ +*/ + +#ifdef CONFIG_SMC_USE_IOFUNCS +/* + * input and output functions + * + * Implemented due to inx,outx macros accessing the device improperly + * and putting the device into an unkown state. + * + * For instance, on Sharp LPD7A400 SDK, affects were chip memory + * could not be free'd (hence the alloc failures), duplicate packets, + * packets being corrupt (shifted) on the wire, etc. Switching to the + * inx,outx functions fixed this problem. + */ +static inline word SMC_inw(dword offset); +static inline void SMC_outw(word value, dword offset); +static inline byte SMC_inb(dword offset); +static inline void SMC_outb(byte value, dword offset); +static inline void SMC_insw(dword offset, volatile uchar* buf, dword len); +static inline void SMC_outsw(dword offset, uchar* buf, dword len); + +#define barrier() __asm__ __volatile__("": : :"memory") + +static inline word SMC_inw(dword offset) +{ + word v; + v = *((volatile word*)(SMC_BASE_ADDRESS+offset)); + barrier(); *(volatile u32*)(0xc0000000); + return v; +} + +static inline void SMC_outw(word value, dword offset) +{ + *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value; + barrier(); *(volatile u32*)(0xc0000000); +} + +static inline byte SMC_inb(dword offset) +{ + word _w; + + _w = SMC_inw(offset & ~((dword)1)); + return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w); +} + +static inline void SMC_outb(byte value, dword offset) +{ + word _w; + + _w = SMC_inw(offset & ~((dword)1)); + if (offset & 1) + *((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff); + else + *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00); +} + +static inline void SMC_insw(dword offset, volatile uchar* buf, dword len) +{ + volatile word *p = (volatile word *)buf; + + while (len-- > 0) { + *p++ = SMC_inw(offset); + barrier(); + *((volatile u32*)(0xc0000000)); + } +} + +static inline void SMC_outsw(dword offset, uchar* buf, dword len) +{ + volatile word *p = (volatile word *)buf; + + while (len-- > 0) { + SMC_outw(*p++, offset); + barrier(); + *(volatile u32*)(0xc0000000); + } +} +#endif /* CONFIG_SMC_USE_IOFUNCS */ + +static char unsigned smc_mac_addr[6] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8}; + +/* + * This function must be called before smc_open() if you want to override + * the default mac address. + */ + +void smc_set_mac_addr(const unsigned char *addr) { + int i; + + for (i=0; i < sizeof(smc_mac_addr); i++){ + smc_mac_addr[i] = addr[i]; + } +} + +/* + * smc_get_macaddr is no longer used. If you want to override the default + * mac address, call smc_get_mac_addr as a part of the board initialization. + */ + +#if 0 +void smc_get_macaddr( byte *addr ) { + /* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */ + unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010); + int i; + + + for (i=0; i<6; i++) { + addr[0] = *(dnp1110_mac+0); + addr[1] = *(dnp1110_mac+1); + addr[2] = *(dnp1110_mac+2); + addr[3] = *(dnp1110_mac+3); + addr[4] = *(dnp1110_mac+4); + addr[5] = *(dnp1110_mac+5); + } +} +#endif /* 0 */ + +/*********************************************** + * Show available memory * + ***********************************************/ +void dump_memory_info(void) +{ + word mem_info; + word old_bank; + + old_bank = SMC_inw(BANK_SELECT)&0xF; + + SMC_SELECT_BANK(0); + mem_info = SMC_inw( MIR_REG ); + PRINTK2("Memory: %4d available\n", (mem_info >> 8)*2048); + + SMC_SELECT_BANK(old_bank); +} +/* + . A rather simple routine to print out a packet for debugging purposes. +*/ +#if SMC_DEBUG > 2 +static void print_packet( byte *, int ); +#endif + +#define tx_done(dev) 1 + + +/* this does a soft reset on the device */ +static void smc_reset( void ); + +/* Enable Interrupts, Receive, and Transmit */ +static void smc_enable( void ); + +/* this puts the device in an inactive state */ +static void smc_shutdown( void ); + +/* Routines to Read and Write the PHY Registers across the + MII Management Interface +*/ + +#ifndef CONFIG_SMC91111_EXT_PHY +static word smc_read_phy_register(byte phyreg); +static void smc_write_phy_register(byte phyreg, word phydata); +#endif /* !CONFIG_SMC91111_EXT_PHY */ + + +static int poll4int (byte mask, int timeout) +{ + int tmo = get_timer (0) + timeout * CFG_HZ; + int is_timeout = 0; + word old_bank = SMC_inw (BSR_REG); + + PRINTK2 ("Polling...\n"); + SMC_SELECT_BANK (2); + while ((SMC_inw (SMC91111_INT_REG) & mask) == 0) { + if (get_timer (0) >= tmo) { + is_timeout = 1; + break; + } + } + + /* restore old bank selection */ + SMC_SELECT_BANK (old_bank); + + if (is_timeout) + return 1; + else + return 0; +} + +/* Only one release command at a time, please */ +static inline void smc_wait_mmu_release_complete (void) +{ + int count = 0; + + /* assume bank 2 selected */ + while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { + udelay (1); /* Wait until not busy */ + if (++count > 200) + break; + } +} + +/* + . Function: smc_reset( void ) + . Purpose: + . This sets the SMC91111 chip to its normal state, hopefully from whatever + . mess that any other DOS driver has put it in. + . + . Maybe I should reset more registers to defaults in here? SOFTRST should + . do that for me. + . + . Method: + . 1. send a SOFT RESET + . 2. wait for it to finish + . 3. enable autorelease mode + . 4. reset the memory management unit + . 5. clear all interrupts + . +*/ +static void smc_reset (void) +{ + PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME); + + /* This resets the registers mostly to defaults, but doesn't + affect EEPROM. That seems unnecessary */ + SMC_SELECT_BANK (0); + SMC_outw (RCR_SOFTRST, RCR_REG); + + /* Setup the Configuration Register */ + /* This is necessary because the CONFIG_REG is not affected */ + /* by a soft reset */ + + SMC_SELECT_BANK (1); +#if defined(CONFIG_SMC91111_EXT_PHY) + SMC_outw (CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG); +#else + SMC_outw (CONFIG_DEFAULT, CONFIG_REG); +#endif + + + /* Release from possible power-down state */ + /* Configuration register is not affected by Soft Reset */ + SMC_outw (SMC_inw (CONFIG_REG) | CONFIG_EPH_POWER_EN, CONFIG_REG); + + SMC_SELECT_BANK (0); + + /* this should pause enough for the chip to be happy */ + udelay (10); + + /* Disable transmit and receive functionality */ + SMC_outw (RCR_CLEAR, RCR_REG); + SMC_outw (TCR_CLEAR, TCR_REG); + + /* set the control register */ + SMC_SELECT_BANK (1); + SMC_outw (CTL_DEFAULT, CTL_REG); + + /* Reset the MMU */ + SMC_SELECT_BANK (2); + smc_wait_mmu_release_complete (); + SMC_outw (MC_RESET, MMU_CMD_REG); + while (SMC_inw (MMU_CMD_REG) & MC_BUSY) + udelay (1); /* Wait until not busy */ + + /* Note: It doesn't seem that waiting for the MMU busy is needed here, + but this is a place where future chipsets _COULD_ break. Be wary + of issuing another MMU command right after this */ + + /* Disable all interrupts */ + SMC_outb (0, IM_REG); +} + +/* + . Function: smc_enable + . Purpose: let the chip talk to the outside work + . Method: + . 1. Enable the transmitter + . 2. Enable the receiver + . 3. Enable interrupts +*/ +static void smc_enable() +{ + PRINTK2("%s: smc_enable\n", SMC_DEV_NAME); + SMC_SELECT_BANK( 0 ); + /* see the header file for options in TCR/RCR DEFAULT*/ + SMC_outw( TCR_DEFAULT, TCR_REG ); + SMC_outw( RCR_DEFAULT, RCR_REG ); + + /* clear MII_DIS */ +/* smc_write_phy_register(PHY_CNTL_REG, 0x0000); */ +} + +/* + . Function: smc_shutdown + . Purpose: closes down the SMC91xxx chip. + . Method: + . 1. zero the interrupt mask + . 2. clear the enable receive flag + . 3. clear the enable xmit flags + . + . TODO: + . (1) maybe utilize power down mode. + . Why not yet? Because while the chip will go into power down mode, + . the manual says that it will wake up in response to any I/O requests + . in the register space. Empirical results do not show this working. +*/ +static void smc_shutdown() +{ + PRINTK2(CARDNAME ": smc_shutdown\n"); + + /* no more interrupts for me */ + SMC_SELECT_BANK( 2 ); + SMC_outb( 0, IM_REG ); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK( 0 ); + SMC_outb( RCR_CLEAR, RCR_REG ); + SMC_outb( TCR_CLEAR, TCR_REG ); +#ifdef SHARED_RESOURCES + swap_to(FLASH); +#endif +} + + +/* + . Function: smc_hardware_send_packet(struct net_device * ) + . Purpose: + . This sends the actual packet to the SMC9xxx chip. + . + . Algorithm: + . First, see if a saved_skb is available. + . ( this should NOT be called if there is no 'saved_skb' + . Now, find the packet number that the chip allocated + . Point the data pointers at it in memory + . Set the length word in the chip's memory + . Dump the packet to chip memory + . Check if a last byte is needed ( odd length packet ) + . if so, set the control flag right + . Tell the card to send it + . Enable the transmit interrupt, so I know if it failed + . Free the kernel data if I actually sent it. +*/ +static int smc_send_packet (volatile void *packet, int packet_length) +{ + byte packet_no; + unsigned long ioaddr; + byte *buf; + int length; + int numPages; + int try = 0; + int time_out; + byte status; + byte saved_pnr; + word saved_ptr; + + /* save PTR and PNR registers before manipulation */ + SMC_SELECT_BANK (2); + saved_pnr = SMC_inb( PN_REG ); + saved_ptr = SMC_inw( PTR_REG ); + + PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME); + + length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; + + /* allocate memory + ** The MMU wants the number of pages to be the number of 256 bytes + ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + ** + ** The 91C111 ignores the size bits, but the code is left intact + ** for backwards and future compatibility. + ** + ** Pkt size for allocating is data length +6 (for additional status + ** words, length and ctl!) + ** + ** If odd size then last byte is included in this header. + */ + numPages = ((length & 0xfffe) + 6); + numPages >>= 8; /* Divide by 256 */ + + if (numPages > 7) { + printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); + return 0; + } + + /* now, try to allocate the memory */ + SMC_SELECT_BANK (2); + SMC_outw (MC_ALLOC | numPages, MMU_CMD_REG); + + /* FIXME: the ALLOC_INT bit never gets set * + * so the following will always give a * + * memory allocation error. * + * same code works in armboot though * + * -ro + */ + +again: + try++; + time_out = MEMORY_WAIT_TIME; + do { + status = SMC_inb (SMC91111_INT_REG); + if (status & IM_ALLOC_INT) { + /* acknowledge the interrupt */ + SMC_outb (IM_ALLOC_INT, SMC91111_INT_REG); + break; + } + } while (--time_out); + + if (!time_out) { + PRINTK2 ("%s: memory allocation, try %d failed ...\n", + SMC_DEV_NAME, try); + if (try < SMC_ALLOC_MAX_TRY) + goto again; + else + return 0; + } + + PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", + SMC_DEV_NAME, try); + + /* I can send the packet now.. */ + + ioaddr = SMC_BASE_ADDRESS; + + buf = (byte *) packet; + + /* If I get here, I _know_ there is a packet slot waiting for me */ + packet_no = SMC_inb (AR_REG); + if (packet_no & AR_FAILED) { + /* or isn't there? BAD CHIP! */ + printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); + return 0; + } + + /* we have a packet address, so tell the card to use it */ +#ifndef CONFIG_XAENIAX + SMC_outb (packet_no, PN_REG); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl (packet_no << 16, 0); +#endif + /* do not write new ptr value if Write data fifo not empty */ + while ( saved_ptr & PTR_NOTEMPTY ) + printf ("Write data fifo not empty!\n"); + + /* point to the beginning of the packet */ + SMC_outw (PTR_AUTOINC, PTR_REG); + + PRINTK3 ("%s: Trying to xmit packet of length %x\n", + SMC_DEV_NAME, length); + +#if SMC_DEBUG > 2 + printf ("Transmitting Packet\n"); + print_packet (buf, length); +#endif + + /* send the packet length ( +6 for status, length and ctl byte ) + and the status word ( set to zeros ) */ +#ifdef USE_32_BIT + SMC_outl ((length + 6) << 16, SMC91111_DATA_REG); +#else + SMC_outw (0, SMC91111_DATA_REG); + /* send the packet length ( +6 for status words, length, and ctl */ + SMC_outw ((length + 6), SMC91111_DATA_REG); +#endif + + /* send the actual data + . I _think_ it's faster to send the longs first, and then + . mop up by sending the last word. It depends heavily + . on alignment, at least on the 486. Maybe it would be + . a good idea to check which is optimal? But that could take + . almost as much time as is saved? + */ +#ifdef USE_32_BIT + SMC_outsl (SMC91111_DATA_REG, buf, length >> 2); +#ifndef CONFIG_XAENIAX + if (length & 0x2) + SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), + SMC91111_DATA_REG); +#else + /* On XANEIAX, we can only use 32-bit writes, so we need to handle + * unaligned tail part specially. The standard code doesn't work. + */ + if ((length & 3) == 3) { + u16 * ptr = (u16*) &buf[length-3]; + SMC_outl((*ptr) | ((0x2000 | buf[length-1]) << 16), + SMC91111_DATA_REG); + } else if ((length & 2) == 2) { + u16 * ptr = (u16*) &buf[length-2]; + SMC_outl(*ptr, SMC91111_DATA_REG); + } else if (length & 1) { + SMC_outl((0x2000 | buf[length-1]), SMC91111_DATA_REG); + } else { + SMC_outl(0, SMC91111_DATA_REG); + } +#endif +#else + SMC_outsw (SMC91111_DATA_REG, buf, (length) >> 1); +#endif /* USE_32_BIT */ + +#ifndef CONFIG_XAENIAX + /* Send the last byte, if there is one. */ + if ((length & 1) == 0) { + SMC_outw (0, SMC91111_DATA_REG); + } else { + SMC_outw (buf[length - 1] | 0x2000, SMC91111_DATA_REG); + } +#endif + + /* and let the chipset deal with it */ + SMC_outw (MC_ENQUEUE, MMU_CMD_REG); + + /* poll for TX INT */ + /* if (poll4int (IM_TX_INT, SMC_TX_TIMEOUT)) { */ + /* poll for TX_EMPTY INT - autorelease enabled */ + if (poll4int(IM_TX_EMPTY_INT, SMC_TX_TIMEOUT)) { + /* sending failed */ + PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); + + /* release packet */ + /* no need to release, MMU does that now */ +#ifdef CONFIG_XAENIAX + SMC_outw (MC_FREEPKT, MMU_CMD_REG); +#endif + + /* wait for MMU getting ready (low) */ + while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { + udelay (10); + } + + PRINTK2 ("MMU ready\n"); + + + return 0; + } else { + /* ack. int */ + SMC_outb (IM_TX_EMPTY_INT, SMC91111_INT_REG); + /* SMC_outb (IM_TX_INT, SMC91111_INT_REG); */ + PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, + length); + + /* release packet */ + /* no need to release, MMU does that now */ +#ifdef CONFIG_XAENIAX + SMC_outw (MC_FREEPKT, MMU_CMD_REG); +#endif + + /* wait for MMU getting ready (low) */ + while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { + udelay (10); + } + + PRINTK2 ("MMU ready\n"); + + + } + + /* restore previously saved registers */ +#ifndef CONFIG_XAENIAX + SMC_outb( saved_pnr, PN_REG ); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl(saved_pnr << 16, 0); +#endif + SMC_outw( saved_ptr, PTR_REG ); + + return length; +} + +/*------------------------------------------------------------------------- + | + | smc_destructor( struct net_device * dev ) + | Input parameters: + | dev, pointer to the device structure + | + | Output: + | None. + | + --------------------------------------------------------------------------- +*/ +void smc_destructor() +{ + PRINTK2(CARDNAME ": smc_destructor\n"); +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc .. + * + */ +static int smc_open (bd_t * bd) +{ + int i, err; + + PRINTK2 ("%s: smc_open\n", SMC_DEV_NAME); + + /* reset the hardware */ + smc_reset (); + smc_enable (); + + /* Configure the PHY */ +#ifndef CONFIG_SMC91111_EXT_PHY + smc_phy_configure (); +#endif + + /* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */ +/* SMC_SELECT_BANK(0); */ +/* SMC_outw(0, RPC_REG); */ + SMC_SELECT_BANK (1); + + err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ + if (err < 0) { + memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ + return (-1); /* upper code ignores this, but NOT bi_enetaddr */ + } +#ifdef USE_32_BIT + for (i = 0; i < 6; i += 2) { + word address; + + address = smc_mac_addr[i + 1] << 8; + address |= smc_mac_addr[i]; + SMC_outw (address, (ADDR0_REG + i)); + } +#else + for (i = 0; i < 6; i++) + SMC_outb (smc_mac_addr[i], (ADDR0_REG + i)); +#endif + + return 0; +} + +/*------------------------------------------------------------- + . + . smc_rcv - receive a packet from the card + . + . There is ( at least ) a packet waiting to be read from + . chip-memory. + . + . o Read the status + . o If an error, record it + . o otherwise, read in the packet + -------------------------------------------------------------- +*/ +static int smc_rcv() +{ + int packet_number; + word status; + word packet_length; + int is_error = 0; +#ifdef USE_32_BIT + dword stat_len; +#endif + byte saved_pnr; + word saved_ptr; + + SMC_SELECT_BANK(2); + /* save PTR and PTR registers */ + saved_pnr = SMC_inb( PN_REG ); + saved_ptr = SMC_inw( PTR_REG ); + + packet_number = SMC_inw( RXFIFO_REG ); + + if ( packet_number & RXFIFO_REMPTY ) { + + return 0; + } + + PRINTK3("%s: smc_rcv\n", SMC_DEV_NAME); + /* start reading from the start of the packet */ + SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG ); + + /* First two words are status and packet_length */ +#ifdef USE_32_BIT + stat_len = SMC_inl(SMC91111_DATA_REG); + status = stat_len & 0xffff; + packet_length = stat_len >> 16; +#else + status = SMC_inw( SMC91111_DATA_REG ); + packet_length = SMC_inw( SMC91111_DATA_REG ); +#endif + + packet_length &= 0x07ff; /* mask off top bits */ + + PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ); + + if ( !(status & RS_ERRORS ) ){ + /* Adjust for having already read the first two words */ + packet_length -= 4; /*4; */ + + + /* set odd length for bug in LAN91C111, */ + /* which never sets RS_ODDFRAME */ + /* TODO ? */ + + +#ifdef USE_32_BIT + PRINTK3(" Reading %d dwords (and %d bytes) \n", + packet_length >> 2, packet_length & 3 ); + /* QUESTION: Like in the TX routine, do I want + to send the DWORDs or the bytes first, or some + mixture. A mixture might improve already slow PIO + performance */ + SMC_insl( SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 2 ); + /* read the left over bytes */ + if (packet_length & 3) { + int i; + + byte *tail = (byte *)(NetRxPackets[0] + (packet_length & ~3)); + dword leftover = SMC_inl(SMC91111_DATA_REG); + for (i=0; i<(packet_length & 3); i++) + *tail++ = (byte) (leftover >> (8*i)) & 0xff; + } +#else + PRINTK3(" Reading %d words and %d byte(s) \n", + (packet_length >> 1 ), packet_length & 1 ); + SMC_insw(SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 1); + +#endif /* USE_32_BIT */ + +#if SMC_DEBUG > 2 + printf("Receiving Packet\n"); + print_packet( NetRxPackets[0], packet_length ); +#endif + } else { + /* error ... */ + /* TODO ? */ + is_error = 1; + } + + while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) + udelay(1); /* Wait until not busy */ + + /* error or good, tell the card to get rid of this packet */ + SMC_outw( MC_RELEASE, MMU_CMD_REG ); + + while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) + udelay(1); /* Wait until not busy */ + + /* restore saved registers */ +#ifndef CONFIG_XAENIAX + SMC_outb( saved_pnr, PN_REG ); +#else + /* On Xaeniax board, we can't use SMC_outb here because that way + * the Allocate MMU command will end up written to the command register + * as well, which will lead to a problem. + */ + SMC_outl( saved_pnr << 16, 0); +#endif + SMC_outw( saved_ptr, PTR_REG ); + + if (!is_error) { + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[0], packet_length); + return packet_length; + } else { + return 0; + } + +} + + +/*---------------------------------------------------- + . smc_close + . + . this makes the board clean up everything that it can + . and not talk to the outside world. Caused by + . an 'ifconfig ethX down' + . + -----------------------------------------------------*/ +static int smc_close() +{ + PRINTK2("%s: smc_close\n", SMC_DEV_NAME); + + /* clear everything */ + smc_shutdown(); + + return 0; +} + + +#if 0 +/*------------------------------------------------------------ + . Modify a bit in the LAN91C111 register set + .-------------------------------------------------------------*/ +static word smc_modify_regbit(int bank, int ioaddr, int reg, + unsigned int bit, int val) +{ + word regval; + + SMC_SELECT_BANK( bank ); + + regval = SMC_inw( reg ); + if (val) + regval |= bit; + else + regval &= ~bit; + + SMC_outw( regval, 0 ); + return(regval); +} + + +/*------------------------------------------------------------ + . Retrieve a bit in the LAN91C111 register set + .-------------------------------------------------------------*/ +static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit) +{ + SMC_SELECT_BANK( bank ); + if ( SMC_inw( reg ) & bit) + return(1); + else + return(0); +} + + +/*------------------------------------------------------------ + . Modify a LAN91C111 register (word access only) + .-------------------------------------------------------------*/ +static void smc_modify_reg(int bank, int ioaddr, int reg, word val) +{ + SMC_SELECT_BANK( bank ); + SMC_outw( val, reg ); +} + + +/*------------------------------------------------------------ + . Retrieve a LAN91C111 register (word access only) + .-------------------------------------------------------------*/ +static int smc_get_reg(int bank, int ioaddr, int reg) +{ + SMC_SELECT_BANK( bank ); + return(SMC_inw( reg )); +} + +#endif /* 0 */ + +/*---PHY CONTROL AND CONFIGURATION----------------------------------------- */ + +#if (SMC_DEBUG > 2 ) + +/*------------------------------------------------------------ + . Debugging function for viewing MII Management serial bitstream + .-------------------------------------------------------------*/ +static void smc_dump_mii_stream (byte * bits, int size) +{ + int i; + + printf ("BIT#:"); + for (i = 0; i < size; ++i) { + printf ("%d", i % 10); + } + + printf ("\nMDOE:"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDOE) + printf ("1"); + else + printf ("0"); + } + + printf ("\nMDO :"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDO) + printf ("1"); + else + printf ("0"); + } + + printf ("\nMDI :"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDI) + printf ("1"); + else + printf ("0"); + } + + printf ("\n"); +} +#endif + +/*------------------------------------------------------------ + . Reads a register from the MII Management serial interface + .-------------------------------------------------------------*/ +#ifndef CONFIG_SMC91111_EXT_PHY +static word smc_read_phy_register (byte phyreg) +{ + int oldBank; + int i; + byte mask; + word mii_reg; + byte bits[64]; + int clk_idx = 0; + int input_idx; + word phydata; + byte phyaddr = SMC_PHY_ADDR; + + /* 32 consecutive ones on MDO to establish sync */ + for (i = 0; i < 32; ++i) + bits[clk_idx++] = MII_MDOE | MII_MDO; + + /* Start code <01> */ + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + /* Read command <10> */ + bits[clk_idx++] = MII_MDOE | MII_MDO; + bits[clk_idx++] = MII_MDOE; + + /* Output the PHY address, msb first */ + mask = (byte) 0x10; + for (i = 0; i < 5; ++i) { + if (phyaddr & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + /* Shift to next lowest bit */ + mask >>= 1; + } + + /* Output the phy register number, msb first */ + mask = (byte) 0x10; + for (i = 0; i < 5; ++i) { + if (phyreg & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + /* Shift to next lowest bit */ + mask >>= 1; + } + + /* Tristate and turnaround (2 bit times) */ + bits[clk_idx++] = 0; + /*bits[clk_idx++] = 0; */ + + /* Input starts at this bit time */ + input_idx = clk_idx; + + /* Will input 16 bits */ + for (i = 0; i < 16; ++i) + bits[clk_idx++] = 0; + + /* Final clock bit */ + bits[clk_idx++] = 0; + + /* Save the current bank */ + oldBank = SMC_inw (BANK_SELECT); + + /* Select bank 3 */ + SMC_SELECT_BANK (3); + + /* Get the current MII register value */ + mii_reg = SMC_inw (MII_REG); + + /* Turn off all MII Interface bits */ + mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); + + /* Clock all 64 cycles */ + for (i = 0; i < sizeof bits; ++i) { + /* Clock Low - output data */ + SMC_outw (mii_reg | bits[i], MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + + + /* Clock Hi - input data */ + SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + bits[i] |= SMC_inw (MII_REG) & MII_MDI; + } + + /* Return to idle state */ + /* Set clock to low, data to low, and output tristated */ + SMC_outw (mii_reg, MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + + /* Restore original bank select */ + SMC_SELECT_BANK (oldBank); + + /* Recover input data */ + phydata = 0; + for (i = 0; i < 16; ++i) { + phydata <<= 1; + + if (bits[input_idx++] & MII_MDI) + phydata |= 0x0001; + } + +#if (SMC_DEBUG > 2 ) + printf ("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", + phyaddr, phyreg, phydata); + smc_dump_mii_stream (bits, sizeof bits); +#endif + + return (phydata); +} + + +/*------------------------------------------------------------ + . Writes a register to the MII Management serial interface + .-------------------------------------------------------------*/ +static void smc_write_phy_register (byte phyreg, word phydata) +{ + int oldBank; + int i; + word mask; + word mii_reg; + byte bits[65]; + int clk_idx = 0; + byte phyaddr = SMC_PHY_ADDR; + + /* 32 consecutive ones on MDO to establish sync */ + for (i = 0; i < 32; ++i) + bits[clk_idx++] = MII_MDOE | MII_MDO; + + /* Start code <01> */ + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + /* Write command <01> */ + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + /* Output the PHY address, msb first */ + mask = (byte) 0x10; + for (i = 0; i < 5; ++i) { + if (phyaddr & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + /* Shift to next lowest bit */ + mask >>= 1; + } + + /* Output the phy register number, msb first */ + mask = (byte) 0x10; + for (i = 0; i < 5; ++i) { + if (phyreg & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + /* Shift to next lowest bit */ + mask >>= 1; + } + + /* Tristate and turnaround (2 bit times) */ + bits[clk_idx++] = 0; + bits[clk_idx++] = 0; + + /* Write out 16 bits of data, msb first */ + mask = 0x8000; + for (i = 0; i < 16; ++i) { + if (phydata & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + /* Shift to next lowest bit */ + mask >>= 1; + } + + /* Final clock bit (tristate) */ + bits[clk_idx++] = 0; + + /* Save the current bank */ + oldBank = SMC_inw (BANK_SELECT); + + /* Select bank 3 */ + SMC_SELECT_BANK (3); + + /* Get the current MII register value */ + mii_reg = SMC_inw (MII_REG); + + /* Turn off all MII Interface bits */ + mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); + + /* Clock all cycles */ + for (i = 0; i < sizeof bits; ++i) { + /* Clock Low - output data */ + SMC_outw (mii_reg | bits[i], MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + + + /* Clock Hi - input data */ + SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + bits[i] |= SMC_inw (MII_REG) & MII_MDI; + } + + /* Return to idle state */ + /* Set clock to low, data to low, and output tristated */ + SMC_outw (mii_reg, MII_REG); + udelay (SMC_PHY_CLOCK_DELAY); + + /* Restore original bank select */ + SMC_SELECT_BANK (oldBank); + +#if (SMC_DEBUG > 2 ) + printf ("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", + phyaddr, phyreg, phydata); + smc_dump_mii_stream (bits, sizeof bits); +#endif +} +#endif /* !CONFIG_SMC91111_EXT_PHY */ + + +/*------------------------------------------------------------ + . Waits the specified number of milliseconds - kernel friendly + .-------------------------------------------------------------*/ +#ifndef CONFIG_SMC91111_EXT_PHY +static void smc_wait_ms(unsigned int ms) +{ + udelay(ms*1000); +} +#endif /* !CONFIG_SMC91111_EXT_PHY */ + + +/*------------------------------------------------------------ + . Configures the specified PHY using Autonegotiation. Calls + . smc_phy_fixed() if the user has requested a certain config. + .-------------------------------------------------------------*/ +#ifndef CONFIG_SMC91111_EXT_PHY +static void smc_phy_configure () +{ + int timeout; + byte phyaddr; + word my_phy_caps; /* My PHY capabilities */ + word my_ad_caps; /* My Advertised capabilities */ + word status = 0; /*;my status = 0 */ + int failed = 0; + + PRINTK3 ("%s: smc_program_phy()\n", SMC_DEV_NAME); + + + /* Get the detected phy address */ + phyaddr = SMC_PHY_ADDR; + + /* Reset the PHY, setting all other bits to zero */ + smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_RST); + + /* Wait for the reset to complete, or time out */ + timeout = 6; /* Wait up to 3 seconds */ + while (timeout--) { + if (!(smc_read_phy_register (PHY_CNTL_REG) + & PHY_CNTL_RST)) { + /* reset complete */ + break; + } + + smc_wait_ms (500); /* wait 500 millisecs */ + } + + if (timeout < 1) { + printf ("%s:PHY reset timed out\n", SMC_DEV_NAME); + goto smc_phy_configure_exit; + } + + /* Read PHY Register 18, Status Output */ + /* lp->lastPhy18 = smc_read_phy_register(PHY_INT_REG); */ + + /* Enable PHY Interrupts (for register 18) */ + /* Interrupts listed here are disabled */ + smc_write_phy_register (PHY_MASK_REG, 0xffff); + + /* Configure the Receive/Phy Control register */ + SMC_SELECT_BANK (0); + SMC_outw (RPC_DEFAULT, RPC_REG); + + /* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */ + my_phy_caps = smc_read_phy_register (PHY_STAT_REG); + my_ad_caps = PHY_AD_CSMA; /* I am CSMA capable */ + + if (my_phy_caps & PHY_STAT_CAP_T4) + my_ad_caps |= PHY_AD_T4; + + if (my_phy_caps & PHY_STAT_CAP_TXF) + my_ad_caps |= PHY_AD_TX_FDX; + + if (my_phy_caps & PHY_STAT_CAP_TXH) + my_ad_caps |= PHY_AD_TX_HDX; + + if (my_phy_caps & PHY_STAT_CAP_TF) + my_ad_caps |= PHY_AD_10_FDX; + + if (my_phy_caps & PHY_STAT_CAP_TH) + my_ad_caps |= PHY_AD_10_HDX; + + /* Update our Auto-Neg Advertisement Register */ + smc_write_phy_register (PHY_AD_REG, my_ad_caps); + + /* Read the register back. Without this, it appears that when */ + /* auto-negotiation is restarted, sometimes it isn't ready and */ + /* the link does not come up. */ + smc_read_phy_register(PHY_AD_REG); + + PRINTK2 ("%s: phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); + PRINTK2 ("%s: phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps); + + /* Restart auto-negotiation process in order to advertise my caps */ + smc_write_phy_register (PHY_CNTL_REG, + PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST); + + /* Wait for the auto-negotiation to complete. This may take from */ + /* 2 to 3 seconds. */ + /* Wait for the reset to complete, or time out */ + timeout = CONFIG_SMC_AUTONEG_TIMEOUT * 2; + while (timeout--) { + + status = smc_read_phy_register (PHY_STAT_REG); + if (status & PHY_STAT_ANEG_ACK) { + /* auto-negotiate complete */ + break; + } + + smc_wait_ms (500); /* wait 500 millisecs */ + + /* Restart auto-negotiation if remote fault */ + if (status & PHY_STAT_REM_FLT) { + printf ("%s: PHY remote fault detected\n", + SMC_DEV_NAME); + + /* Restart auto-negotiation */ + printf ("%s: PHY restarting auto-negotiation\n", + SMC_DEV_NAME); + smc_write_phy_register (PHY_CNTL_REG, + PHY_CNTL_ANEG_EN | + PHY_CNTL_ANEG_RST | + PHY_CNTL_SPEED | + PHY_CNTL_DPLX); + } + } + + if (timeout < 1) { + printf ("%s: PHY auto-negotiate timed out\n", SMC_DEV_NAME); + failed = 1; + } + + /* Fail if we detected an auto-negotiate remote fault */ + if (status & PHY_STAT_REM_FLT) { + printf ("%s: PHY remote fault detected\n", SMC_DEV_NAME); + failed = 1; + } + + /* Re-Configure the Receive/Phy Control register */ + SMC_outw (RPC_DEFAULT, RPC_REG); + +smc_phy_configure_exit: ; + +} +#endif /* !CONFIG_SMC91111_EXT_PHY */ + + +#if SMC_DEBUG > 2 +static void print_packet( byte * buf, int length ) +{ + int i; + int remainder; + int lines; + + printf("Packet of length %d \n", length ); + +#if SMC_DEBUG > 3 + lines = length / 16; + remainder = length % 16; + + for ( i = 0; i < lines ; i ++ ) { + int cur; + + for ( cur = 0; cur < 8; cur ++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + printf("%02x%02x ", a, b ); + } + printf("\n"); + } + for ( i = 0; i < remainder/2 ; i++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + printf("%02x%02x ", a, b ); + } + printf("\n"); +#endif +} +#endif + +int eth_init(bd_t *bd) { +#ifdef SHARED_RESOURCES + swap_to(ETHERNET); +#endif + return (smc_open(bd)); +} + +void eth_halt() { + smc_close(); +} + +int eth_rx() { + return smc_rcv(); +} + +int eth_send(volatile void *packet, int length) { + return smc_send_packet(packet, length); +} + +int smc_get_ethaddr (bd_t * bd) +{ + int env_size, rom_valid, env_present = 0, reg; + char *s = NULL, *e, es[] = "11:22:33:44:55:66"; + char s_env_mac[64]; + uchar v_env_mac[6], v_rom_mac[6], *v_mac; + + env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); + if ((env_size > 0) && (env_size < sizeof (es))) { /* exit if env is bad */ + printf ("\n*** ERROR: ethaddr is not set properly!!\n"); + return (-1); + } + + if (env_size > 0) { + env_present = 1; + s = s_env_mac; + } + + for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ + v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + + rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ + + if (!env_present) { /* if NO env */ + if (rom_valid) { /* but ROM is valid */ + v_mac = v_rom_mac; + sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", + v_mac[0], v_mac[1], v_mac[2], v_mac[3], + v_mac[4], v_mac[5]); + setenv ("ethaddr", s_env_mac); + } else { /* no env, bad ROM */ + printf ("\n*** ERROR: ethaddr is NOT set !!\n"); + return (-1); + } + } else { /* good env, don't care ROM */ + v_mac = v_env_mac; /* always use a good env over a ROM */ + } + + if (env_present && rom_valid) { /* if both env and ROM are good */ + if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { + printf ("\nWarning: MAC addresses don't match:\n"); + printf ("\tHW MAC address: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_rom_mac[0], v_rom_mac[1], + v_rom_mac[2], v_rom_mac[3], + v_rom_mac[4], v_rom_mac[5] ); + printf ("\t\"ethaddr\" value: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_env_mac[0], v_env_mac[1], + v_env_mac[2], v_env_mac[3], + v_env_mac[4], v_env_mac[5]) ; + debug ("### Set MAC addr from environment\n"); + } + } + memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ + smc_set_mac_addr ((uchar *)v_mac); /* use old function to update smc default */ + PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], + v_mac[2], v_mac[3], v_mac[4], v_mac[5]); + return (0); +} + +int get_rom_mac (uchar *v_rom_mac) +{ +#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ + char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; + + memcpy (v_rom_mac, hw_mac_addr, 6); + return (1); +#else + int i; + int valid_mac = 0; + + SMC_SELECT_BANK (1); + for (i=0; i<6; i++) + { + v_rom_mac[i] = SMC_inb ((ADDR0_REG + i)); + valid_mac |= v_rom_mac[i]; + } + + return (valid_mac ? 1 : 0); +#endif +} +#endif /* CONFIG_DRIVER_SMC91111 */ diff --git a/drivers/net/smc91111.h b/drivers/net/smc91111.h new file mode 100644 index 0000000000..d03cbc320b --- /dev/null +++ b/drivers/net/smc91111.h @@ -0,0 +1,719 @@ +/*------------------------------------------------------------------------ + . smc91111.h - macros for the LAN91C111 Ethernet Driver + . + . (C) Copyright 2002 + . Sysgo Real-Time Solutions, GmbH + . Rolf Offermanns + . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) + . Developed by Simple Network Magic Corporation (SNMC) + . Copyright (C) 1996 by Erik Stahlman (ES) + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + . This file contains register information and access macros for + . the LAN91C111 single chip ethernet controller. It is a modified + . version of the smc9194.h file. + . + . Information contained in this file was obtained from the LAN91C111 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Erik Stahlman ( erik@vt.edu ) + . Daris A Nevil ( dnevil@snmc.com ) + . + . History + . 03/16/01 Daris A Nevil Modified for use with LAN91C111 device + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC91111_H_ +#define _SMC91111_H_ + +#include +#include + +/* + * This function may be called by the board specific initialisation code + * in order to override the default mac address. + */ + +void smc_set_mac_addr (const unsigned char *addr); + + +/* I want some simple types */ + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long int dword; + +/* + . DEBUGGING LEVELS + . + . 0 for normal operation + . 1 for slightly more details + . >2 for various levels of increasingly useless information + . 2 for interrupt tracking, status flags + . 3 for packet info + . 4 for complete packet dumps +*/ +/*#define SMC_DEBUG 0 */ + +/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ + +#define SMC_IO_EXTENT 16 + +#ifdef CONFIG_PXA250 + +#ifdef CONFIG_XSENGINE +#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1)))) +#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r<<1)))) +#define SMC_inb(p) ({ \ + unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p<<1)); \ + unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \ + if (__p & 2) __v >>= 8; \ + else __v &= 0xff; \ + __v; }) +#elif defined(CONFIG_XAENIAX) +#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) +#define SMC_inw(z) ({ \ + unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (z)); \ + unsigned int __v = *(volatile unsigned int *)((__p) & ~3); \ + if (__p & 3) __v >>= 16; \ + else __v &= 0xffff; \ + __v; }) +#define SMC_inb(p) ({ \ + unsigned int ___v = SMC_inw((p) & ~1); \ + if (p & 1) ___v >>= 8; \ + else ___v &= 0xff; \ + ___v; }) +#else +#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) +#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) +#define SMC_inb(p) ({ \ + unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p)); \ + unsigned int __v = *(volatile unsigned short *)((__p) & ~1); \ + if (__p & 1) __v >>= 8; \ + else __v &= 0xff; \ + __v; }) +#endif + +#ifdef CONFIG_XSENGINE +#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))) = d) +#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r<<1))) = d) +#elif defined (CONFIG_XAENIAX) +#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) +#define SMC_outw(d,p) ({ \ + dword __dwo = SMC_inl((p) & ~3); \ + dword __dwn = (word)(d); \ + __dwo &= ((p) & 3) ? 0x0000ffff : 0xffff0000; \ + __dwo |= ((p) & 3) ? __dwn << 16 : __dwn; \ + SMC_outl(__dwo, (p) & ~3); \ +}) +#else +#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) +#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) +#endif + +#define SMC_outb(d,r) ({ word __d = (byte)(d); \ + word __w = SMC_inw((r)&~1); \ + __w &= ((r)&1) ? 0x00FF : 0xFF00; \ + __w |= ((r)&1) ? __d<<8 : __d; \ + SMC_outw(__w,(r)&~1); \ + }) + +#define SMC_outsl(r,b,l) ({ int __i; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outl( *(__b2 + __i), r); \ + } \ + }) + +#define SMC_outsw(r,b,l) ({ int __i; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outw( *(__b2 + __i), r); \ + } \ + }) + +#define SMC_insl(r,b,l) ({ int __i ; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inl(r); \ + SMC_inl(0); \ + }; \ + }) + +#define SMC_insw(r,b,l) ({ int __i ; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inw(r); \ + SMC_inw(0); \ + }; \ + }) + +#define SMC_insb(r,b,l) ({ int __i ; \ + byte *__b2; \ + __b2 = (byte *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inb(r); \ + SMC_inb(0); \ + }; \ + }) + +#else /* if not CONFIG_PXA250 */ + +#ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */ +/* + * We have only 16 Bit PCMCIA access on Socket 0 + */ + +#ifdef CONFIG_ADNPESC1 +#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+((r)<<1)))) +#elif CONFIG_BLACKFIN +#define SMC_inw(r) ({ word __v = (*((volatile word *)(SMC_BASE_ADDRESS+(r)))); asm("ssync;"); __v;}) +#else +#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) +#endif +#define SMC_inb(r) (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF) + +#ifdef CONFIG_ADNPESC1 +#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+((r)<<1))) = d) +#elif CONFIG_BLACKFIN +#define SMC_outw(d,r) {(*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d);asm("ssync;");} +#else +#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) +#endif +#define SMC_outb(d,r) ({ word __d = (byte)(d); \ + word __w = SMC_inw((r)&~1); \ + __w &= ((r)&1) ? 0x00FF : 0xFF00; \ + __w |= ((r)&1) ? __d<<8 : __d; \ + SMC_outw(__w,(r)&~1); \ + }) +#if 0 +#define SMC_outsw(r,b,l) outsw(SMC_BASE_ADDRESS+(r), (b), (l)) +#else +#define SMC_outsw(r,b,l) ({ int __i; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outw( *(__b2 + __i), r); \ + } \ + }) +#endif + +#if 0 +#define SMC_insw(r,b,l) insw(SMC_BASE_ADDRESS+(r), (b), (l)) +#else +#define SMC_insw(r,b,l) ({ int __i ; \ + word *__b2; \ + __b2 = (word *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inw(r); \ + SMC_inw(0); \ + }; \ + }) +#endif + +#endif /* CONFIG_SMC_USE_IOFUNCS */ + +#if defined(CONFIG_SMC_USE_32_BIT) + +#ifdef CONFIG_XSENGINE +#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1)))) +#else +#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) +#endif + +#define SMC_insl(r,b,l) ({ int __i ; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + *(__b2 + __i) = SMC_inl(r); \ + SMC_inl(0); \ + }; \ + }) + +#ifdef CONFIG_XSENGINE +#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))) = d) +#else +#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) +#endif +#define SMC_outsl(r,b,l) ({ int __i; \ + dword *__b2; \ + __b2 = (dword *) b; \ + for (__i = 0; __i < l; __i++) { \ + SMC_outl( *(__b2 + __i), r); \ + } \ + }) + +#endif /* CONFIG_SMC_USE_32_BIT */ + +#endif + +/*--------------------------------------------------------------- + . + . A description of the SMSC registers is probably in order here, + . although for details, the SMC datasheet is invaluable. + . + . Basically, the chip has 4 banks of registers ( 0 to 3 ), which + . are accessed by writing a number into the BANK_SELECT register + . ( I also use a SMC_SELECT_BANK macro for this ). + . + . The banks are configured so that for most purposes, bank 2 is all + . that is needed for simple run time tasks. + -----------------------------------------------------------------------*/ + +/* + . Bank Select Register: + . + . yyyy yyyy 0000 00xx + . xx = bank number + . yyyy yyyy = 0x33, for identification purposes. +*/ +#define BANK_SELECT 14 + +/* Transmit Control Register */ +/* BANK 0 */ +#define TCR_REG 0x0000 /* transmit control register */ +#define TCR_ENABLE 0x0001 /* When 1 we can transmit */ +#define TCR_LOOP 0x0002 /* Controls output pin LBK */ +#define TCR_FORCOL 0x0004 /* When 1 will force a collision */ +#define TCR_PAD_EN 0x0080 /* When 1 will pad tx frames < 64 bytes w/0 */ +#define TCR_NOCRC 0x0100 /* When 1 will not append CRC to tx frames */ +#define TCR_MON_CSN 0x0400 /* When 1 tx monitors carrier */ +#define TCR_FDUPLX 0x0800 /* When 1 enables full duplex operation */ +#define TCR_STP_SQET 0x1000 /* When 1 stops tx if Signal Quality Error */ +#define TCR_EPH_LOOP 0x2000 /* When 1 enables EPH block loopback */ +#define TCR_SWFDUP 0x8000 /* When 1 enables Switched Full Duplex mode */ + +#define TCR_CLEAR 0 /* do NOTHING */ +/* the default settings for the TCR register : */ +/* QUESTION: do I want to enable padding of short packets ? */ +#define TCR_DEFAULT TCR_ENABLE + + +/* EPH Status Register */ +/* BANK 0 */ +#define EPH_STATUS_REG 0x0002 +#define ES_TX_SUC 0x0001 /* Last TX was successful */ +#define ES_SNGL_COL 0x0002 /* Single collision detected for last tx */ +#define ES_MUL_COL 0x0004 /* Multiple collisions detected for last tx */ +#define ES_LTX_MULT 0x0008 /* Last tx was a multicast */ +#define ES_16COL 0x0010 /* 16 Collisions Reached */ +#define ES_SQET 0x0020 /* Signal Quality Error Test */ +#define ES_LTXBRD 0x0040 /* Last tx was a broadcast */ +#define ES_TXDEFR 0x0080 /* Transmit Deferred */ +#define ES_LATCOL 0x0200 /* Late collision detected on last tx */ +#define ES_LOSTCARR 0x0400 /* Lost Carrier Sense */ +#define ES_EXC_DEF 0x0800 /* Excessive Deferral */ +#define ES_CTR_ROL 0x1000 /* Counter Roll Over indication */ +#define ES_LINK_OK 0x4000 /* Driven by inverted value of nLNK pin */ +#define ES_TXUNRN 0x8000 /* Tx Underrun */ + + +/* Receive Control Register */ +/* BANK 0 */ +#define RCR_REG 0x0004 +#define RCR_RX_ABORT 0x0001 /* Set if a rx frame was aborted */ +#define RCR_PRMS 0x0002 /* Enable promiscuous mode */ +#define RCR_ALMUL 0x0004 /* When set accepts all multicast frames */ +#define RCR_RXEN 0x0100 /* IFF this is set, we can receive packets */ +#define RCR_STRIP_CRC 0x0200 /* When set strips CRC from rx packets */ +#define RCR_ABORT_ENB 0x0200 /* When set will abort rx on collision */ +#define RCR_FILT_CAR 0x0400 /* When set filters leading 12 bit s of carrier */ +#define RCR_SOFTRST 0x8000 /* resets the chip */ + +/* the normal settings for the RCR register : */ +#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) +#define RCR_CLEAR 0x0 /* set it to a base state */ + +/* Counter Register */ +/* BANK 0 */ +#define COUNTER_REG 0x0006 + +/* Memory Information Register */ +/* BANK 0 */ +#define MIR_REG 0x0008 + +/* Receive/Phy Control Register */ +/* BANK 0 */ +#define RPC_REG 0x000A +#define RPC_SPEED 0x2000 /* When 1 PHY is in 100Mbps mode. */ +#define RPC_DPLX 0x1000 /* When 1 PHY is in Full-Duplex Mode */ +#define RPC_ANEG 0x0800 /* When 1 PHY is in Auto-Negotiate Mode */ +#define RPC_LSXA_SHFT 5 /* Bits to shift LS2A,LS1A,LS0A to lsb */ +#define RPC_LSXB_SHFT 2 /* Bits to get LS2B,LS1B,LS0B to lsb */ +#define RPC_LED_100_10 (0x00) /* LED = 100Mbps OR's with 10Mbps link detect */ +#define RPC_LED_RES (0x01) /* LED = Reserved */ +#define RPC_LED_10 (0x02) /* LED = 10Mbps link detect */ +#define RPC_LED_FD (0x03) /* LED = Full Duplex Mode */ +#define RPC_LED_TX_RX (0x04) /* LED = TX or RX packet occurred */ +#define RPC_LED_100 (0x05) /* LED = 100Mbps link dectect */ +#define RPC_LED_TX (0x06) /* LED = TX packet occurred */ +#define RPC_LED_RX (0x07) /* LED = RX packet occurred */ +#if defined(CONFIG_DK1C20) || defined(CONFIG_DK1S10) +/* buggy schematic: LEDa -> yellow, LEDb --> green */ +#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ + | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ + | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) +#elif defined(CONFIG_ADNPESC1) +/* SSV ADNP/ESC1 has only one LED: LEDa -> Rx/Tx indicator */ +#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ + | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ + | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) +#else +/* SMSC reference design: LEDa --> green, LEDb --> yellow */ +#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ + | (RPC_LED_100_10 << RPC_LSXA_SHFT) \ + | (RPC_LED_TX_RX << RPC_LSXB_SHFT) ) +#endif + +/* Bank 0 0x000C is reserved */ + +/* Bank Select Register */ +/* All Banks */ +#define BSR_REG 0x000E + + +/* Configuration Reg */ +/* BANK 1 */ +#define CONFIG_REG 0x0000 +#define CONFIG_EXT_PHY 0x0200 /* 1=external MII, 0=internal Phy */ +#define CONFIG_GPCNTRL 0x0400 /* Inverse value drives pin nCNTRL */ +#define CONFIG_NO_WAIT 0x1000 /* When 1 no extra wait states on ISA bus */ +#define CONFIG_EPH_POWER_EN 0x8000 /* When 0 EPH is placed into low power mode. */ + +/* Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low */ +#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) + + +/* Base Address Register */ +/* BANK 1 */ +#define BASE_REG 0x0002 + + +/* Individual Address Registers */ +/* BANK 1 */ +#define ADDR0_REG 0x0004 +#define ADDR1_REG 0x0006 +#define ADDR2_REG 0x0008 + + +/* General Purpose Register */ +/* BANK 1 */ +#define GP_REG 0x000A + + +/* Control Register */ +/* BANK 1 */ +#define CTL_REG 0x000C +#define CTL_RCV_BAD 0x4000 /* When 1 bad CRC packets are received */ +#define CTL_AUTO_RELEASE 0x0800 /* When 1 tx pages are released automatically */ +#define CTL_LE_ENABLE 0x0080 /* When 1 enables Link Error interrupt */ +#define CTL_CR_ENABLE 0x0040 /* When 1 enables Counter Rollover interrupt */ +#define CTL_TE_ENABLE 0x0020 /* When 1 enables Transmit Error interrupt */ +#define CTL_EEPROM_SELECT 0x0004 /* Controls EEPROM reload & store */ +#define CTL_RELOAD 0x0002 /* When set reads EEPROM into registers */ +#define CTL_STORE 0x0001 /* When set stores registers into EEPROM */ +#define CTL_DEFAULT (0x1A10) /* Autorelease enabled*/ + +/* MMU Command Register */ +/* BANK 2 */ +#define MMU_CMD_REG 0x0000 +#define MC_BUSY 1 /* When 1 the last release has not completed */ +#define MC_NOP (0<<5) /* No Op */ +#define MC_ALLOC (1<<5) /* OR with number of 256 byte packets */ +#define MC_RESET (2<<5) /* Reset MMU to initial state */ +#define MC_REMOVE (3<<5) /* Remove the current rx packet */ +#define MC_RELEASE (4<<5) /* Remove and release the current rx packet */ +#define MC_FREEPKT (5<<5) /* Release packet in PNR register */ +#define MC_ENQUEUE (6<<5) /* Enqueue the packet for transmit */ +#define MC_RSTTXFIFO (7<<5) /* Reset the TX FIFOs */ + + +/* Packet Number Register */ +/* BANK 2 */ +#define PN_REG 0x0002 + + +/* Allocation Result Register */ +/* BANK 2 */ +#define AR_REG 0x0003 +#define AR_FAILED 0x80 /* Alocation Failed */ + + +/* RX FIFO Ports Register */ +/* BANK 2 */ +#define RXFIFO_REG 0x0004 /* Must be read as a word */ +#define RXFIFO_REMPTY 0x8000 /* RX FIFO Empty */ + + +/* TX FIFO Ports Register */ +/* BANK 2 */ +#define TXFIFO_REG RXFIFO_REG /* Must be read as a word */ +#define TXFIFO_TEMPTY 0x80 /* TX FIFO Empty */ + + +/* Pointer Register */ +/* BANK 2 */ +#define PTR_REG 0x0006 +#define PTR_RCV 0x8000 /* 1=Receive area, 0=Transmit area */ +#define PTR_AUTOINC 0x4000 /* Auto increment the pointer on each access */ +#define PTR_READ 0x2000 /* When 1 the operation is a read */ +#define PTR_NOTEMPTY 0x0800 /* When 1 _do not_ write fifo DATA REG */ + + +/* Data Register */ +/* BANK 2 */ +#define SMC91111_DATA_REG 0x0008 + + +/* Interrupt Status/Acknowledge Register */ +/* BANK 2 */ +#define SMC91111_INT_REG 0x000C + + +/* Interrupt Mask Register */ +/* BANK 2 */ +#define IM_REG 0x000D +#define IM_MDINT 0x80 /* PHY MI Register 18 Interrupt */ +#define IM_ERCV_INT 0x40 /* Early Receive Interrupt */ +#define IM_EPH_INT 0x20 /* Set by Etheret Protocol Handler section */ +#define IM_RX_OVRN_INT 0x10 /* Set by Receiver Overruns */ +#define IM_ALLOC_INT 0x08 /* Set when allocation request is completed */ +#define IM_TX_EMPTY_INT 0x04 /* Set if the TX FIFO goes empty */ +#define IM_TX_INT 0x02 /* Transmit Interrrupt */ +#define IM_RCV_INT 0x01 /* Receive Interrupt */ + + +/* Multicast Table Registers */ +/* BANK 3 */ +#define MCAST_REG1 0x0000 +#define MCAST_REG2 0x0002 +#define MCAST_REG3 0x0004 +#define MCAST_REG4 0x0006 + + +/* Management Interface Register (MII) */ +/* BANK 3 */ +#define MII_REG 0x0008 +#define MII_MSK_CRS100 0x4000 /* Disables CRS100 detection during tx half dup */ +#define MII_MDOE 0x0008 /* MII Output Enable */ +#define MII_MCLK 0x0004 /* MII Clock, pin MDCLK */ +#define MII_MDI 0x0002 /* MII Input, pin MDI */ +#define MII_MDO 0x0001 /* MII Output, pin MDO */ + + +/* Revision Register */ +/* BANK 3 */ +#define REV_REG 0x000A /* ( hi: chip id low: rev # ) */ + + +/* Early RCV Register */ +/* BANK 3 */ +/* this is NOT on SMC9192 */ +#define ERCV_REG 0x000C +#define ERCV_RCV_DISCRD 0x0080 /* When 1 discards a packet being received */ +#define ERCV_THRESHOLD 0x001F /* ERCV Threshold Mask */ + +/* External Register */ +/* BANK 7 */ +#define EXT_REG 0x0000 + + +#define CHIP_9192 3 +#define CHIP_9194 4 +#define CHIP_9195 5 +#define CHIP_9196 6 +#define CHIP_91100 7 +#define CHIP_91100FD 8 +#define CHIP_91111FD 9 + +#if 0 +static const char * chip_ids[ 15 ] = { + NULL, NULL, NULL, + /* 3 */ "SMC91C90/91C92", + /* 4 */ "SMC91C94", + /* 5 */ "SMC91C95", + /* 6 */ "SMC91C96", + /* 7 */ "SMC91C100", + /* 8 */ "SMC91C100FD", + /* 9 */ "SMC91C111", + NULL, NULL, + NULL, NULL, NULL}; +#endif + +/* + . Transmit status bits +*/ +#define TS_SUCCESS 0x0001 +#define TS_LOSTCAR 0x0400 +#define TS_LATCOL 0x0200 +#define TS_16COL 0x0010 + +/* + . Receive status bits +*/ +#define RS_ALGNERR 0x8000 +#define RS_BRODCAST 0x4000 +#define RS_BADCRC 0x2000 +#define RS_ODDFRAME 0x1000 /* bug: the LAN91C111 never sets this on receive */ +#define RS_TOOLONG 0x0800 +#define RS_TOOSHORT 0x0400 +#define RS_MULTICAST 0x0001 +#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) + + +/* PHY Types */ +enum { + PHY_LAN83C183 = 1, /* LAN91C111 Internal PHY */ + PHY_LAN83C180 +}; + + +/* PHY Register Addresses (LAN91C111 Internal PHY) */ + +/* PHY Control Register */ +#define PHY_CNTL_REG 0x00 +#define PHY_CNTL_RST 0x8000 /* 1=PHY Reset */ +#define PHY_CNTL_LPBK 0x4000 /* 1=PHY Loopback */ +#define PHY_CNTL_SPEED 0x2000 /* 1=100Mbps, 0=10Mpbs */ +#define PHY_CNTL_ANEG_EN 0x1000 /* 1=Enable Auto negotiation */ +#define PHY_CNTL_PDN 0x0800 /* 1=PHY Power Down mode */ +#define PHY_CNTL_MII_DIS 0x0400 /* 1=MII 4 bit interface disabled */ +#define PHY_CNTL_ANEG_RST 0x0200 /* 1=Reset Auto negotiate */ +#define PHY_CNTL_DPLX 0x0100 /* 1=Full Duplex, 0=Half Duplex */ +#define PHY_CNTL_COLTST 0x0080 /* 1= MII Colision Test */ + +/* PHY Status Register */ +#define PHY_STAT_REG 0x01 +#define PHY_STAT_CAP_T4 0x8000 /* 1=100Base-T4 capable */ +#define PHY_STAT_CAP_TXF 0x4000 /* 1=100Base-X full duplex capable */ +#define PHY_STAT_CAP_TXH 0x2000 /* 1=100Base-X half duplex capable */ +#define PHY_STAT_CAP_TF 0x1000 /* 1=10Mbps full duplex capable */ +#define PHY_STAT_CAP_TH 0x0800 /* 1=10Mbps half duplex capable */ +#define PHY_STAT_CAP_SUPR 0x0040 /* 1=recv mgmt frames with not preamble */ +#define PHY_STAT_ANEG_ACK 0x0020 /* 1=ANEG has completed */ +#define PHY_STAT_REM_FLT 0x0010 /* 1=Remote Fault detected */ +#define PHY_STAT_CAP_ANEG 0x0008 /* 1=Auto negotiate capable */ +#define PHY_STAT_LINK 0x0004 /* 1=valid link */ +#define PHY_STAT_JAB 0x0002 /* 1=10Mbps jabber condition */ +#define PHY_STAT_EXREG 0x0001 /* 1=extended registers implemented */ + +/* PHY Identifier Registers */ +#define PHY_ID1_REG 0x02 /* PHY Identifier 1 */ +#define PHY_ID2_REG 0x03 /* PHY Identifier 2 */ + +/* PHY Auto-Negotiation Advertisement Register */ +#define PHY_AD_REG 0x04 +#define PHY_AD_NP 0x8000 /* 1=PHY requests exchange of Next Page */ +#define PHY_AD_ACK 0x4000 /* 1=got link code word from remote */ +#define PHY_AD_RF 0x2000 /* 1=advertise remote fault */ +#define PHY_AD_T4 0x0200 /* 1=PHY is capable of 100Base-T4 */ +#define PHY_AD_TX_FDX 0x0100 /* 1=PHY is capable of 100Base-TX FDPLX */ +#define PHY_AD_TX_HDX 0x0080 /* 1=PHY is capable of 100Base-TX HDPLX */ +#define PHY_AD_10_FDX 0x0040 /* 1=PHY is capable of 10Base-T FDPLX */ +#define PHY_AD_10_HDX 0x0020 /* 1=PHY is capable of 10Base-T HDPLX */ +#define PHY_AD_CSMA 0x0001 /* 1=PHY is capable of 802.3 CMSA */ + +/* PHY Auto-negotiation Remote End Capability Register */ +#define PHY_RMT_REG 0x05 +/* Uses same bit definitions as PHY_AD_REG */ + +/* PHY Configuration Register 1 */ +#define PHY_CFG1_REG 0x10 +#define PHY_CFG1_LNKDIS 0x8000 /* 1=Rx Link Detect Function disabled */ +#define PHY_CFG1_XMTDIS 0x4000 /* 1=TP Transmitter Disabled */ +#define PHY_CFG1_XMTPDN 0x2000 /* 1=TP Transmitter Powered Down */ +#define PHY_CFG1_BYPSCR 0x0400 /* 1=Bypass scrambler/descrambler */ +#define PHY_CFG1_UNSCDS 0x0200 /* 1=Unscramble Idle Reception Disable */ +#define PHY_CFG1_EQLZR 0x0100 /* 1=Rx Equalizer Disabled */ +#define PHY_CFG1_CABLE 0x0080 /* 1=STP(150ohm), 0=UTP(100ohm) */ +#define PHY_CFG1_RLVL0 0x0040 /* 1=Rx Squelch level reduced by 4.5db */ +#define PHY_CFG1_TLVL_SHIFT 2 /* Transmit Output Level Adjust */ +#define PHY_CFG1_TLVL_MASK 0x003C +#define PHY_CFG1_TRF_MASK 0x0003 /* Transmitter Rise/Fall time */ + + +/* PHY Configuration Register 2 */ +#define PHY_CFG2_REG 0x11 +#define PHY_CFG2_APOLDIS 0x0020 /* 1=Auto Polarity Correction disabled */ +#define PHY_CFG2_JABDIS 0x0010 /* 1=Jabber disabled */ +#define PHY_CFG2_MREG 0x0008 /* 1=Multiple register access (MII mgt) */ +#define PHY_CFG2_INTMDIO 0x0004 /* 1=Interrupt signaled with MDIO pulseo */ + +/* PHY Status Output (and Interrupt status) Register */ +#define PHY_INT_REG 0x12 /* Status Output (Interrupt Status) */ +#define PHY_INT_INT 0x8000 /* 1=bits have changed since last read */ +#define PHY_INT_LNKFAIL 0x4000 /* 1=Link Not detected */ +#define PHY_INT_LOSSSYNC 0x2000 /* 1=Descrambler has lost sync */ +#define PHY_INT_CWRD 0x1000 /* 1=Invalid 4B5B code detected on rx */ +#define PHY_INT_SSD 0x0800 /* 1=No Start Of Stream detected on rx */ +#define PHY_INT_ESD 0x0400 /* 1=No End Of Stream detected on rx */ +#define PHY_INT_RPOL 0x0200 /* 1=Reverse Polarity detected */ +#define PHY_INT_JAB 0x0100 /* 1=Jabber detected */ +#define PHY_INT_SPDDET 0x0080 /* 1=100Base-TX mode, 0=10Base-T mode */ +#define PHY_INT_DPLXDET 0x0040 /* 1=Device in Full Duplex */ + +/* PHY Interrupt/Status Mask Register */ +#define PHY_MASK_REG 0x13 /* Interrupt Mask */ +/* Uses the same bit definitions as PHY_INT_REG */ + + +/*------------------------------------------------------------------------- + . I define some macros to make it easier to do somewhat common + . or slightly complicated, repeated tasks. + --------------------------------------------------------------------------*/ + +/* select a register bank, 0 to 3 */ + +#define SMC_SELECT_BANK(x) { SMC_outw( x, BANK_SELECT ); } + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) {\ + unsigned char mask;\ + SMC_SELECT_BANK(2);\ + mask = SMC_inb( IM_REG );\ + mask |= (x);\ + SMC_outb( mask, IM_REG ); \ +} + +/* this disables an interrupt from the interrupt mask register */ + +#define SMC_DISABLE_INT(x) {\ + unsigned char mask;\ + SMC_SELECT_BANK(2);\ + mask = SMC_inb( IM_REG );\ + mask &= ~(x);\ + SMC_outb( mask, IM_REG ); \ +} + +/*---------------------------------------------------------------------- + . Define the interrupts that I want to receive from the card + . + . I want: + . IM_EPH_INT, for nasty errors + . IM_RCV_INT, for happy received packets + . IM_RX_OVRN_INT, because I have to kick the receiver + . IM_MDINT, for PHY Register 18 Status Changes + --------------------------------------------------------------------------*/ +#define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \ + IM_MDINT) + +#endif /* _SMC_91111_H_ */ diff --git a/drivers/net/tigon3.c b/drivers/net/tigon3.c new file mode 100644 index 0000000000..5f6a4ecd0a --- /dev/null +++ b/drivers/net/tigon3.c @@ -0,0 +1,5699 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ +#include +#include +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_TIGON3) +#ifdef CONFIG_BMW +#include +#endif +#include +#include +#include "bcm570x_mm.h" + +#define EMBEDDED 1 +/******************************************************************************/ +/* Local functions. */ +/******************************************************************************/ + +LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice); + +static LM_STATUS LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE + RequestedMediaType, + PLM_MEDIA_TYPE pMediaType, + PLM_LINE_SPEED pLineSpeed, + PLM_DUPLEX_MODE pDuplexMode); + +static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice); + +__inline static LM_VOID LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice); +__inline static LM_VOID LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice); + +static LM_STATUS LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE + RequestedMediaType); +static LM_STATUS LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType); +static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, + LM_UINT32 LocalPhyAd, + LM_UINT32 RemotePhyAd); +#if INCLUDE_TBI_SUPPORT +STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice); +#endif +STATIC LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice); +STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, + LM_UINT16 Ssid); +STATIC LM_STATUS LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, + LM_PHYSICAL_ADDRESS BufferPhy, + LM_UINT32 BufferSize); +STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number); +STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, + PLM_PACKET pPacket, PT3_SND_BD pSendBd); + +/******************************************************************************/ +/* External functions. */ +/******************************************************************************/ + +LM_STATUS LM_LoadRlsFirmware (PLM_DEVICE_BLOCK pDevice); + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register) +{ + LM_UINT32 Value32; + +#if PCIX_TARGET_WORKAROUND + MM_ACQUIRE_UNDI_LOCK (pDevice); +#endif + MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); + MM_ReadConfig32 (pDevice, T3_PCI_REG_DATA_REG, &Value32); +#if PCIX_TARGET_WORKAROUND + MM_RELEASE_UNDI_LOCK (pDevice); +#endif + + return Value32; +} /* LM_RegRdInd */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32) +{ + +#if PCIX_TARGET_WORKAROUND + MM_ACQUIRE_UNDI_LOCK (pDevice); +#endif + MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); + MM_WriteConfig32 (pDevice, T3_PCI_REG_DATA_REG, Value32); +#if PCIX_TARGET_WORKAROUND + MM_RELEASE_UNDI_LOCK (pDevice); +#endif +} /* LM_RegWrInd */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr) +{ + LM_UINT32 Value32; + + MM_ACQUIRE_UNDI_LOCK (pDevice); +#ifdef BIG_ENDIAN_HOST + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + Value32 = REG_RD (pDevice, PciCfg.MemWindowData); + /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */ +#else + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + MM_ReadConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32); +#endif + MM_RELEASE_UNDI_LOCK (pDevice); + + return Value32; +} /* LM_MemRdInd */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_MemWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, LM_UINT32 Value32) +{ + MM_ACQUIRE_UNDI_LOCK (pDevice); +#ifdef BIG_ENDIAN_HOST + REG_WR (pDevice, PciCfg.MemWindowBaseAddr, MemAddr); + REG_WR (pDevice, uIntMem.Mbuf[(MemAddr & 0x7fff) / 4], Value32); +#else + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32); +#endif + MM_RELEASE_UNDI_LOCK (pDevice); +} /* LM_MemWrInd */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS Lmstatus; + PLM_PACKET pPacket; + PT3_RCV_BD pRcvBd; + LM_UINT32 StdBdAdded = 0; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + LM_UINT32 JumboBdAdded = 0; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + Lmstatus = LM_STATUS_SUCCESS; + + pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); + while (pPacket) { + switch (pPacket->u.Rx.RcvProdRing) { +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + case T3_JUMBO_RCV_PROD_RING: /* Jumbo Receive Ring. */ + /* Initialize the buffer descriptor. */ + pRcvBd = + &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx]; + pRcvBd->Flags = + RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING; + pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize; + + /* Initialize the receive buffer pointer */ +#if 0 /* Jimmy, deleted in new */ + pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; + pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; +#endif + MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); + + /* The opaque field may point to an offset from a fix addr. */ + pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - + MM_UINT_PTR (pDevice-> + pPacketDescBase)); + + /* Update the producer index. */ + pDevice->RxJumboProdIdx = + (pDevice->RxJumboProdIdx + + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; + + JumboBdAdded++; + break; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + case T3_STD_RCV_PROD_RING: /* Standard Receive Ring. */ + /* Initialize the buffer descriptor. */ + pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx]; + pRcvBd->Flags = RCV_BD_FLAG_END; + pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE; + + /* Initialize the receive buffer pointer */ +#if 0 /* Jimmy, deleted in new replaced with MM_MapRxDma */ + pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; + pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; +#endif + MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); + + /* The opaque field may point to an offset from a fix addr. */ + pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - + MM_UINT_PTR (pDevice-> + pPacketDescBase)); + + /* Update the producer index. */ + pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & + T3_STD_RCV_RCB_ENTRY_COUNT_MASK; + + StdBdAdded++; + break; + + case T3_UNKNOWN_RCV_PROD_RING: + default: + Lmstatus = LM_STATUS_FAILURE; + break; + } /* switch */ + + /* Bail out if there is any error. */ + if (Lmstatus != LM_STATUS_SUCCESS) { + break; + } + + pPacket = + (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); + } /* while */ + + wmb (); + /* Update the procedure index. */ + if (StdBdAdded) { + MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, + pDevice->RxStdProdIdx); + } +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + if (JumboBdAdded) { + MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, + pDevice->RxJumboProdIdx); + } +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + return Lmstatus; +} /* LM_QueueRxPackets */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_VOID LM_NvramInit (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + /* Intialize clock period and state machine. */ + Value32 = SEEPROM_ADDR_CLK_PERD (SEEPROM_CLOCK_PERIOD) | + SEEPROM_ADDR_FSM_RESET; + REG_WR (pDevice, Grc.EepromAddr, Value32); + + for (j = 0; j < 100; j++) { + MM_Wait (10); + } + + /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */ + Value32 = REG_RD (pDevice, Grc.LocalCtrl); + REG_WR (pDevice, Grc.LocalCtrl, + Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM); + + /* Set the 5701 compatibility mode if we are using EEPROM. */ + if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { + Value32 = REG_RD (pDevice, Nvram.Config1); + if ((Value32 & FLASH_INTERFACE_ENABLE) == 0) { + /* Use the new interface to read EEPROM. */ + Value32 &= ~FLASH_COMPAT_BYPASS; + + REG_WR (pDevice, Nvram.Config1, Value32); + } + } +} /* LM_NvRamInit */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_EepromRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) +{ + LM_UINT32 Value32; + LM_UINT32 Addr; + LM_UINT32 Dev; + LM_UINT32 j; + + if (Offset > SEEPROM_CHIP_SIZE) { + return LM_STATUS_FAILURE; + } + + Dev = Offset / SEEPROM_CHIP_SIZE; + Addr = Offset % SEEPROM_CHIP_SIZE; + + Value32 = REG_RD (pDevice, Grc.EepromAddr); + Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK | + SEEPROM_ADDR_RW_MASK); + REG_WR (pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID (Dev) | + SEEPROM_ADDR_ADDRESS (Addr) | SEEPROM_ADDR_START | + SEEPROM_ADDR_READ); + + for (j = 0; j < 1000; j++) { + Value32 = REG_RD (pDevice, Grc.EepromAddr); + if (Value32 & SEEPROM_ADDR_COMPLETE) { + break; + } + MM_Wait (10); + } + + if (Value32 & SEEPROM_ADDR_COMPLETE) { + Value32 = REG_RD (pDevice, Grc.EepromData); + *pData = Value32; + + return LM_STATUS_SUCCESS; + } + + return LM_STATUS_FAILURE; +} /* LM_EepromRead */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_NvramRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) +{ + LM_UINT32 Value32; + LM_STATUS Status; + LM_UINT32 j; + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Status = LM_EepromRead (pDevice, Offset, pData); + } else { + /* Determine if we have flash or EEPROM. */ + Value32 = REG_RD (pDevice, Nvram.Config1); + if (Value32 & FLASH_INTERFACE_ENABLE) { + if (Value32 & FLASH_SSRAM_BUFFERRED_MODE) { + Offset = ((Offset / BUFFERED_FLASH_PAGE_SIZE) << + BUFFERED_FLASH_PAGE_POS) + + (Offset % BUFFERED_FLASH_PAGE_SIZE); + } + } + + REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); + for (j = 0; j < 1000; j++) { + if (REG_RD (pDevice, Nvram.SwArb) & SW_ARB_GNT1) { + break; + } + MM_Wait (20); + } + if (j == 1000) { + return LM_STATUS_FAILURE; + } + + /* Read from flash or EEPROM with the new 5703/02 interface. */ + REG_WR (pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK); + + REG_WR (pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT | + NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); + + /* Wait for the done bit to clear. */ + for (j = 0; j < 500; j++) { + MM_Wait (10); + + Value32 = REG_RD (pDevice, Nvram.Cmd); + if (!(Value32 & NVRAM_CMD_DONE)) { + break; + } + } + + /* Wait for the done bit. */ + if (!(Value32 & NVRAM_CMD_DONE)) { + for (j = 0; j < 500; j++) { + MM_Wait (10); + + Value32 = REG_RD (pDevice, Nvram.Cmd); + if (Value32 & NVRAM_CMD_DONE) { + MM_Wait (10); + + *pData = + REG_RD (pDevice, Nvram.ReadData); + + /* Change the endianess. */ + *pData = + ((*pData & 0xff) << 24) | + ((*pData & 0xff00) << 8) | + ((*pData & 0xff0000) >> 8) | + ((*pData >> 24) & 0xff); + + break; + } + } + } + + REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1); + if (Value32 & NVRAM_CMD_DONE) { + Status = LM_STATUS_SUCCESS; + } else { + Status = LM_STATUS_FAILURE; + } + } + + return Status; +} /* LM_NvramRead */ + +STATIC void LM_ReadVPD (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Vpd_arr[256 / 4]; + LM_UINT8 *Vpd = (LM_UINT8 *) & Vpd_arr[0]; + LM_UINT32 *Vpd_dptr = &Vpd_arr[0]; + LM_UINT32 Value32; + unsigned int j; + + /* Read PN from VPD */ + for (j = 0; j < 256; j += 4, Vpd_dptr++) { + if (LM_NvramRead (pDevice, 0x100 + j, &Value32) != + LM_STATUS_SUCCESS) { + printf ("BCM570x: LM_ReadVPD: VPD read failed" + " (no EEPROM onboard)\n"); + return; + } + *Vpd_dptr = cpu_to_le32 (Value32); + } + for (j = 0; j < 256;) { + unsigned int Vpd_r_len; + unsigned int Vpd_r_end; + + if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91)) { + j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8); + } else if (Vpd[j] == 0x90) { + Vpd_r_len = Vpd[j + 1] + (Vpd[j + 2] << 8); + j += 3; + Vpd_r_end = Vpd_r_len + j; + while (j < Vpd_r_end) { + if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N')) { + unsigned int len = Vpd[j + 2]; + + if (len <= 24) { + memcpy (pDevice->PartNo, + &Vpd[j + 3], len); + } + break; + } else { + if (Vpd[j + 2] == 0) { + break; + } + j = j + Vpd[j + 2]; + } + } + break; + } else { + break; + } + } +} + +STATIC void LM_ReadBootCodeVersion (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32, offset, ver_offset; + int i; + + if (LM_NvramRead (pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS) + return; + if (Value32 != 0xaa559966) + return; + if (LM_NvramRead (pDevice, 0xc, &offset) != LM_STATUS_SUCCESS) + return; + + offset = ((offset & 0xff) << 24) | ((offset & 0xff00) << 8) | + ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff); + if (LM_NvramRead (pDevice, offset, &Value32) != LM_STATUS_SUCCESS) + return; + if ((Value32 == 0x0300000e) && + (LM_NvramRead (pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) + && (Value32 == 0)) { + + if (LM_NvramRead (pDevice, offset + 8, &ver_offset) != + LM_STATUS_SUCCESS) + return; + ver_offset = ((ver_offset & 0xff0000) >> 8) | + ((ver_offset >> 24) & 0xff); + for (i = 0; i < 16; i += 4) { + if (LM_NvramRead + (pDevice, offset + ver_offset + i, + &Value32) != LM_STATUS_SUCCESS) { + return; + } + *((LM_UINT32 *) & pDevice->BootCodeVer[i]) = + cpu_to_le32 (Value32); + } + } else { + char c; + + if (LM_NvramRead (pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS) + return; + + i = 0; + c = ((Value32 & 0xff0000) >> 16); + + if (c < 10) { + pDevice->BootCodeVer[i++] = c + '0'; + } else { + pDevice->BootCodeVer[i++] = (c / 10) + '0'; + pDevice->BootCodeVer[i++] = (c % 10) + '0'; + } + pDevice->BootCodeVer[i++] = '.'; + c = (Value32 & 0xff000000) >> 24; + if (c < 10) { + pDevice->BootCodeVer[i++] = c + '0'; + } else { + pDevice->BootCodeVer[i++] = (c / 10) + '0'; + pDevice->BootCodeVer[i++] = (c % 10) + '0'; + } + pDevice->BootCodeVer[i] = 0; + } +} + +STATIC void LM_GetBusSpeed (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 PciState = pDevice->PciState; + LM_UINT32 ClockCtrl; + char *SpeedStr = ""; + + if (PciState & T3_PCI_STATE_32BIT_PCI_BUS) { + strcpy (pDevice->BusSpeedStr, "32-bit "); + } else { + strcpy (pDevice->BusSpeedStr, "64-bit "); + } + if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) { + strcat (pDevice->BusSpeedStr, "PCI "); + if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) { + SpeedStr = "66MHz"; + } else { + SpeedStr = "33MHz"; + } + } else { + strcat (pDevice->BusSpeedStr, "PCIX "); + if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE) { + SpeedStr = "133MHz"; + } else { + ClockCtrl = REG_RD (pDevice, PciCfg.ClockCtrl) & 0x1f; + switch (ClockCtrl) { + case 0: + SpeedStr = "33MHz"; + break; + + case 2: + SpeedStr = "50MHz"; + break; + + case 4: + SpeedStr = "66MHz"; + break; + + case 6: + SpeedStr = "100MHz"; + break; + + case 7: + SpeedStr = "133MHz"; + break; + } + } + } + strcat (pDevice->BusSpeedStr, SpeedStr); +} + +/******************************************************************************/ +/* Description: */ +/* This routine initializes default parameters and reads the PCI */ +/* configurations. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_GetAdapterInfo (PLM_DEVICE_BLOCK pDevice) +{ + PLM_ADAPTER_INFO pAdapterInfo; + LM_UINT32 Value32; + LM_STATUS Status; + LM_UINT32 j; + LM_UINT32 EeSigFound; + LM_UINT32 EePhyTypeSerdes = 0; + LM_UINT32 EePhyLedMode = 0; + LM_UINT32 EePhyId = 0; + + /* Get Device Id and Vendor Id */ + Status = MM_ReadConfig32 (pDevice, PCI_VENDOR_ID_REG, &Value32); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + pDevice->PciVendorId = (LM_UINT16) Value32; + pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16); + + /* If we are not getting the write adapter, exit. */ + if ((Value32 != T3_PCI_ID_BCM5700) && + (Value32 != T3_PCI_ID_BCM5701) && + (Value32 != T3_PCI_ID_BCM5702) && + (Value32 != T3_PCI_ID_BCM5702x) && + (Value32 != T3_PCI_ID_BCM5702FE) && + (Value32 != T3_PCI_ID_BCM5703) && + (Value32 != T3_PCI_ID_BCM5703x) && (Value32 != T3_PCI_ID_BCM5704)) { + return LM_STATUS_FAILURE; + } + + Status = MM_ReadConfig32 (pDevice, PCI_REV_ID_REG, &Value32); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + pDevice->PciRevId = (LM_UINT8) Value32; + + /* Get IRQ. */ + Status = MM_ReadConfig32 (pDevice, PCI_INT_LINE_REG, &Value32); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + pDevice->Irq = (LM_UINT8) Value32; + + /* Get interrupt pin. */ + pDevice->IntPin = (LM_UINT8) (Value32 >> 8); + + /* Get chip revision id. */ + Status = MM_ReadConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32); + pDevice->ChipRevId = Value32 >> 16; + + /* Get subsystem vendor. */ + Status = + MM_ReadConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + pDevice->SubsystemVendorId = (LM_UINT16) Value32; + + /* Get PCI subsystem id. */ + pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16); + + /* Get the cache line size. */ + MM_ReadConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32); + pDevice->CacheLineSize = (LM_UINT8) Value32; + pDevice->SavedCacheLineReg = Value32; + + if (pDevice->ChipRevId != T3_CHIP_ID_5703_A1 && + pDevice->ChipRevId != T3_CHIP_ID_5703_A2 && + pDevice->ChipRevId != T3_CHIP_ID_5704_A0) { + pDevice->UndiFix = FALSE; + } +#if !PCIX_TARGET_WORKAROUND + pDevice->UndiFix = FALSE; +#endif + /* Map the memory base to system address space. */ + if (!pDevice->UndiFix) { + Status = MM_MapMemBase (pDevice); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + /* Initialize the memory view pointer. */ + pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase; + } +#if PCIX_TARGET_WORKAROUND + /* store whether we are in PCI are PCI-X mode */ + pDevice->EnablePciXFix = FALSE; + + MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); + if ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0) { + /* Enable PCI-X workaround only if we are running on 5700 BX. */ + if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { + pDevice->EnablePciXFix = TRUE; + } + } + if (pDevice->UndiFix) { + pDevice->EnablePciXFix = TRUE; + } +#endif + /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */ + /* management register may be clobbered which may cause the */ + /* BCM5700 to go into D3 state. While in this state, we will */ + /* not have memory mapped register access. As a workaround, we */ + /* need to restore the device to D0 state. */ + MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32); + Value32 |= T3_PM_PME_ASSERTED; + Value32 &= ~T3_PM_POWER_STATE_MASK; + Value32 |= T3_PM_POWER_STATE_D0; + MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32); + + /* read the current PCI command word */ + MM_ReadConfig32 (pDevice, PCI_COMMAND_REG, &Value32); + + /* Make sure bus-mastering is enabled. */ + Value32 |= PCI_BUSMASTER_ENABLE; + +#if PCIX_TARGET_WORKAROUND + /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR# + are enabled */ + if (pDevice->EnablePciXFix == TRUE) { + Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | + PCI_PARITY_ERROR_ENABLE); + } + if (pDevice->UndiFix) { + Value32 &= ~PCI_MEM_SPACE_ENABLE; + } +#endif + + if (pDevice->EnableMWI) { + Value32 |= PCI_MEMORY_WRITE_INVALIDATE; + } else { + Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE); + } + + /* Error out if mem-mapping is NOT enabled for PCI systems */ + if (!(Value32 | PCI_MEM_SPACE_ENABLE)) { + return LM_STATUS_FAILURE; + } + + /* save the value we are going to write into the PCI command word */ + pDevice->PciCommandStatusWords = Value32; + + Status = MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, Value32); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + + /* Set power state to D0. */ + LM_SetPowerState (pDevice, LM_POWER_STATE_D0); + +#ifdef BIG_ENDIAN_PCI + pDevice->MiscHostCtrl = + MISC_HOST_CTRL_MASK_PCI_INT | + MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | + MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | + MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; +#else /* No CPU Swap modes for PCI IO */ + + /* Setup the mode registers. */ + pDevice->MiscHostCtrl = + MISC_HOST_CTRL_MASK_PCI_INT | + MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | +#ifdef BIG_ENDIAN_HOST + MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP | +#endif /* BIG_ENDIAN_HOST */ + MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | + MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; +#endif /* !BIG_ENDIAN_PCI */ + + /* write to PCI misc host ctr first in order to enable indirect accesses */ + MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, + pDevice->MiscHostCtrl); + + REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl); + +#ifdef BIG_ENDIAN_PCI + Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else +/* No CPU Swap modes for PCI IO */ +#ifdef BIG_ENDIAN_HOST + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; +#endif +#endif /* !BIG_ENDIAN_PCI */ + + REG_WR (pDevice, Grc.Mode, Value32); + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + REG_WR (pDevice, Grc.LocalCtrl, + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1); + } + MM_Wait (40); + + /* Enable indirect memory access */ + REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); + + if (REG_RD (pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK) { + REG_WR (pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK); + REG_WR (pDevice, PciCfg.ClockCtrl, + T3_PCI_SELECT_ALTERNATE_CLOCK); + MM_Wait (40); /* required delay is 27usec */ + } + REG_WR (pDevice, PciCfg.ClockCtrl, 0); + REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); + +#if PCIX_TARGET_WORKAROUND + MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); + if ((pDevice->EnablePciXFix == FALSE) && + ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)) { + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B2 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B5) { + __raw_writel (0, + &(pDevice->pMemView->uIntMem. + MemBlock32K[0x300])); + __raw_writel (0, + &(pDevice->pMemView->uIntMem. + MemBlock32K[0x301])); + __raw_writel (0xffffffff, + &(pDevice->pMemView->uIntMem. + MemBlock32K[0x301])); + if (__raw_readl + (&(pDevice->pMemView->uIntMem.MemBlock32K[0x300]))) + { + pDevice->EnablePciXFix = TRUE; + } + } + } +#endif +#if 1 + /* + * This code was at the beginning of else block below, but that's + * a bug if node address in shared memory. + */ + MM_Wait (50); + LM_NvramInit (pDevice); +#endif + /* Get the node address. First try to get in from the shared memory. */ + /* If the signature is not present, then get it from the NVRAM. */ + Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_HIGH_MAILBOX); + if ((Value32 >> 16) == 0x484b) { + + pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[1] = (LM_UINT8) Value32; + + Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_LOW_MAILBOX); + + pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24); + pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[5] = (LM_UINT8) Value32; + + Status = LM_STATUS_SUCCESS; + } else { + Status = LM_NvramRead (pDevice, 0x7c, &Value32); + if (Status == LM_STATUS_SUCCESS) { + pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24); + + Status = LM_NvramRead (pDevice, 0x80, &Value32); + + pDevice->NodeAddress[2] = (LM_UINT8) Value32; + pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24); + } + } + + /* Assign a default address. */ + if (Status != LM_STATUS_SUCCESS) { +#ifndef EMBEDDED + printk (KERN_ERR + "Cannot get MAC addr from NVRAM. Using default.\n"); +#endif + pDevice->NodeAddress[0] = 0x00; + pDevice->NodeAddress[1] = 0x10; + pDevice->NodeAddress[2] = 0x18; + pDevice->NodeAddress[3] = 0x68; + pDevice->NodeAddress[4] = 0x61; + pDevice->NodeAddress[5] = 0x76; + } + + pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0]; + pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1]; + pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2]; + pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3]; + pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4]; + pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5]; + + /* Initialize the default values. */ + pDevice->NoTxPseudoHdrChksum = FALSE; + pDevice->NoRxPseudoHdrChksum = FALSE; + pDevice->NicSendBd = FALSE; + pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT; + pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT; + pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS; + pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS; + pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES; + pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES; + pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; + pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; + pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; + pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; + pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS; + pDevice->EnableMWI = FALSE; + pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + pDevice->DisableAutoNeg = FALSE; + pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO; + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO; + pDevice->LedMode = LED_MODE_AUTO; + pDevice->ResetPhyOnInit = TRUE; + pDevice->DelayPciGrant = TRUE; + pDevice->UseTaggedStatus = FALSE; + pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE; + + pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO; + pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO; + pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO; + + pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; + pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE; + pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE; + pDevice->EnableTbi = FALSE; +#if INCLUDE_TBI_SUPPORT + pDevice->PollTbiLink = BAD_DEFAULT_VALUE; +#endif + + switch (T3_ASIC_REV (pDevice->ChipRevId)) { + case T3_ASIC_REV_5704: + pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; + pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64; + break; + default: + pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; + pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96; + break; + } + + pDevice->LinkStatus = LM_STATUS_LINK_DOWN; + pDevice->QueueRxPackets = TRUE; + + pDevice->EnableWireSpeed = TRUE; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Make this is a known adapter. */ + pAdapterInfo = LM_GetAdapterInfoBySsid (pDevice->SubsystemVendorId, + pDevice->SubsystemId); + + pDevice->BondId = REG_RD (pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK; + if (pDevice->BondId != GRC_MISC_BD_ID_5700 && + pDevice->BondId != GRC_MISC_BD_ID_5701 && + pDevice->BondId != GRC_MISC_BD_ID_5702FE && + pDevice->BondId != GRC_MISC_BD_ID_5703 && + pDevice->BondId != GRC_MISC_BD_ID_5703S && + pDevice->BondId != GRC_MISC_BD_ID_5704 && + pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE) { + return LM_STATUS_UNKNOWN_ADAPTER; + } + + pDevice->SplitModeEnable = SPLIT_MODE_DISABLE; + if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) && + (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)) { + pDevice->SplitModeEnable = SPLIT_MODE_ENABLE; + pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ; + } + + /* Get Eeprom info. */ + Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_SIG_ADDR); + if (Value32 == T3_NIC_DATA_SIG) { + EeSigFound = TRUE; + Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_NIC_CFG_ADDR); + + /* Determine PHY type. */ + switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK) { + case T3_NIC_CFG_PHY_TYPE_COPPER: + EePhyTypeSerdes = FALSE; + break; + + case T3_NIC_CFG_PHY_TYPE_FIBER: + EePhyTypeSerdes = TRUE; + break; + + default: + EePhyTypeSerdes = FALSE; + break; + } + + /* Determine PHY led mode. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { + case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED: + EePhyLedMode = LED_MODE_THREE_LINK; + break; + + case T3_NIC_CFG_LED_MODE_LINK_SPEED: + EePhyLedMode = LED_MODE_LINK10; + break; + + default: + EePhyLedMode = LED_MODE_AUTO; + break; + } + } else { + switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { + case T3_NIC_CFG_LED_MODE_OPEN_DRAIN: + EePhyLedMode = LED_MODE_OPEN_DRAIN; + break; + + case T3_NIC_CFG_LED_MODE_OUTPUT: + EePhyLedMode = LED_MODE_OUTPUT; + break; + + default: + EePhyLedMode = LED_MODE_AUTO; + break; + } + } + if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || + pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { + /* Enable EEPROM write protection. */ + if (Value32 & T3_NIC_EEPROM_WP) { + pDevice->EepromWp = TRUE; + } + } + + /* Get the PHY Id. */ + Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_PHY_ID_ADDR); + if (Value32) { + EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) & + PHY_ID1_OUI_MASK) << 10; + + Value32 = Value32 & T3_NIC_PHY_ID2_MASK; + + EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | + (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & + PHY_ID2_REV_MASK); + } else { + EePhyId = 0; + } + } else { + EeSigFound = FALSE; + } + + /* Set the PHY address. */ + pDevice->PhyAddr = PHY_DEVICE_ID; + + /* Disable auto polling. */ + pDevice->MiMode = 0xc0000; + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait (40); + + /* Get the PHY id. */ + LM_ReadPhy (pDevice, PHY_ID1_REG, &Value32); + pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10; + + LM_ReadPhy (pDevice, PHY_ID2_REG, &Value32); + pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | + (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK); + + /* Set the EnableTbi flag to false if we have a copper PHY. */ + switch (pDevice->PhyId & PHY_ID_MASK) { + case PHY_BCM5400_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5401_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5411_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5701_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5703_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5704_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM8002_PHY_ID: + pDevice->EnableTbi = TRUE; + break; + + default: + + if (pAdapterInfo) { + pDevice->PhyId = pAdapterInfo->PhyId; + pDevice->EnableTbi = pAdapterInfo->Serdes; + } else if (EeSigFound) { + pDevice->PhyId = EePhyId; + pDevice->EnableTbi = EePhyTypeSerdes; + } + break; + } + + /* Bail out if we don't know the copper PHY id. */ + if (UNKNOWN_PHY_ID (pDevice->PhyId) && !pDevice->EnableTbi) { + return LM_STATUS_FAILURE; + } + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { + if ((pDevice->SavedCacheLineReg & 0xff00) < 0x4000) { + pDevice->SavedCacheLineReg &= 0xffff00ff; + pDevice->SavedCacheLineReg |= 0x4000; + } + } + /* Change driver parameters. */ + Status = MM_GetConfig (pDevice); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } +#if INCLUDE_5701_AX_FIX + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { + pDevice->ResetPhyOnInit = TRUE; + } +#endif + + /* Save the current phy link status. */ + if (!pDevice->EnableTbi) { + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + + /* If we don't have link reset the PHY. */ + if (!(Value32 & PHY_STATUS_LINK_PASS) + || pDevice->ResetPhyOnInit) { + + LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); + + for (j = 0; j < 100; j++) { + MM_Wait (10); + + LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); + if (Value32 && !(Value32 & PHY_CTRL_PHY_RESET)) { + MM_Wait (40); + break; + } + } + +#if INCLUDE_5701_AX_FIX + /* 5701_AX_BX bug: only advertises 10mb speed. */ + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { + + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | + PHY_AN_AD_10BASET_HALF | + PHY_AN_AD_10BASET_FULL | + PHY_AN_AD_100BASETX_FULL | + PHY_AN_AD_100BASETX_HALF; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + Value32 = BCM540X_AN_AD_1000BASET_HALF | + BCM540X_AN_AD_1000BASET_FULL | + BCM540X_CONFIG_AS_MASTER | + BCM540X_ENABLE_CONFIG_AS_MASTER; + LM_WritePhy (pDevice, + BCM540X_1000BASET_CTRL_REG, + Value32); + pDevice->advertising1000 = Value32; + + LM_WritePhy (pDevice, PHY_CTRL_REG, + PHY_CTRL_AUTO_NEG_ENABLE | + PHY_CTRL_RESTART_AUTO_NEG); + } +#endif + if (T3_ASIC_REV (pDevice->ChipRevId) == + T3_ASIC_REV_5703) { + LM_WritePhy (pDevice, 0x18, 0x0c00); + LM_WritePhy (pDevice, 0x17, 0x201f); + LM_WritePhy (pDevice, 0x15, 0x2aaa); + } + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { + LM_WritePhy (pDevice, 0x1c, 0x8d68); + LM_WritePhy (pDevice, 0x1c, 0x8d68); + } + /* Enable Ethernet@WireSpeed. */ + if (pDevice->EnableWireSpeed) { + LM_WritePhy (pDevice, 0x18, 0x7007); + LM_ReadPhy (pDevice, 0x18, &Value32); + LM_WritePhy (pDevice, 0x18, + Value32 | BIT_15 | BIT_4); + } + } + } + + /* Turn off tap power management. */ + if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); + + MM_Wait (40); + } +#if INCLUDE_TBI_SUPPORT + pDevice->IgnoreTbiLinkChange = FALSE; + + if (pDevice->EnableTbi) { + pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; + pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; + if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) || + pDevice->DisableAutoNeg) { + pDevice->PollTbiLink = FALSE; + } + } else { + pDevice->PollTbiLink = FALSE; + } +#endif /* INCLUDE_TBI_SUPPORT */ + + /* UseTaggedStatus is only valid for 5701 and later. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->UseTaggedStatus = FALSE; + + pDevice->CoalesceMode = 0; + } else { + pDevice->CoalesceMode = + HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT | + HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT; + } + + /* Set the status block size. */ + if (T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_AX && + T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_BX) { + pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE; + } + + /* Check the DURING_INT coalescing ticks parameters. */ + if (pDevice->UseTaggedStatus) { + if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { + pDevice->RxCoalescingTicksDuringInt = + DEFAULT_RX_COALESCING_TICKS_DURING_INT; + } + + if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { + pDevice->TxCoalescingTicksDuringInt = + DEFAULT_TX_COALESCING_TICKS_DURING_INT; + } + + if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { + pDevice->RxMaxCoalescedFramesDuringInt = + DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT; + } + + if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { + pDevice->TxMaxCoalescedFramesDuringInt = + DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT; + } + } else { + if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { + pDevice->RxCoalescingTicksDuringInt = 0; + } + + if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { + pDevice->TxCoalescingTicksDuringInt = 0; + } + + if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { + pDevice->RxMaxCoalescedFramesDuringInt = 0; + } + + if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { + pDevice->TxMaxCoalescedFramesDuringInt = 0; + } + } + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + if (pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */ )) { + pDevice->RxJumboDescCnt = 0; + if (pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC) { + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + } + } else { + pDevice->RxJumboBufferSize = + (pDevice->RxMtu + 8 /* CRC + VLAN */ + + COMMON_CACHE_LINE_SIZE - 1) & ~COMMON_CACHE_LINE_MASK; + + if (pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE) { + pDevice->RxJumboBufferSize = + DEFAULT_JUMBO_RCV_BUFFER_SIZE; + pDevice->RxMtu = + pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */ ; + } + pDevice->TxMtu = pDevice->RxMtu; + + } +#else + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + pDevice->RxPacketDescCnt = +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboDescCnt + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + pDevice->RxStdDescCnt; + + if (pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC) { + pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + } + + if (pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE) { + pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE; + } + + /* Configure the proper ways to get link change interrupt. */ + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO) { + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; + } else { + pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; + } + } else if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + /* Auto-polling does not work on 5700_AX and 5700_BX. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; + } + } + + /* Determine the method to get link change status. */ + if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO) { + /* The link status bit in the status block does not work on 5700_AX */ + /* and 5700_BX chips. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->LinkChngMode = + T3_LINK_CHNG_MODE_USE_STATUS_REG; + } else { + pDevice->LinkChngMode = + T3_LINK_CHNG_MODE_USE_STATUS_BLOCK; + } + } + + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; + } + + /* Configure PHY led mode. */ + if (pDevice->LedMode == LED_MODE_AUTO) { + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + if (pDevice->SubsystemVendorId == T3_SVID_DELL) { + pDevice->LedMode = LED_MODE_LINK10; + } else { + pDevice->LedMode = LED_MODE_THREE_LINK; + + if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { + pDevice->LedMode = EePhyLedMode; + } + } + + /* bug? 5701 in LINK10 mode does not seem to work when */ + /* PhyIntMode is LINK_READY. */ + if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 + && +#if INCLUDE_TBI_SUPPORT + pDevice->EnableTbi == FALSE && +#endif + pDevice->LedMode == LED_MODE_LINK10) { + pDevice->PhyIntMode = + T3_PHY_INT_MODE_MI_INTERRUPT; + pDevice->LinkChngMode = + T3_LINK_CHNG_MODE_USE_STATUS_REG; + } + + if (pDevice->EnableTbi) { + pDevice->LedMode = LED_MODE_THREE_LINK; + } + } else { + if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { + pDevice->LedMode = EePhyLedMode; + } else { + pDevice->LedMode = LED_MODE_OPEN_DRAIN; + } + } + } + + /* Enable OneDmaAtOnce. */ + if (pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE) { + pDevice->OneDmaAtOnce = FALSE; + } + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B2) { + pDevice->WolSpeed = WOL_SPEED_10MB; + } else { + pDevice->WolSpeed = WOL_SPEED_100MB; + } + + /* Offloadings. */ + pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; + + /* Turn off task offloading on Ax. */ + if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) { + pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | + LM_TASK_OFFLOAD_TX_UDP_CHECKSUM); + } + pDevice->PciState = REG_RD (pDevice, PciCfg.PciState); + LM_ReadVPD (pDevice); + LM_ReadBootCodeVersion (pDevice); + LM_GetBusSpeed (pDevice); + + return LM_STATUS_SUCCESS; +} /* LM_GetAdapterInfo */ + +STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, LM_UINT16 Ssid) +{ + static LM_ADAPTER_INFO AdapterArr[] = { + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, + PHY_BCM5401_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, + PHY_BCM8002_PHY_ID, 1}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, + PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, + PHY_BCM5701_PHY_ID, 0}, + + {T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0}, + {T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1}, + {T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0}, + + {T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0}, + {T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0}, + {T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0}, + {T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0}, + + {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, + 0}, + {T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1}, + {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0}, + {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, + 0}, + + }; + LM_UINT32 j; + + for (j = 0; j < sizeof (AdapterArr) / sizeof (LM_ADAPTER_INFO); j++) { + if (AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid) { + return &AdapterArr[j]; + } + } + + return NULL; +} + +/******************************************************************************/ +/* Description: */ +/* This routine sets up receive/transmit buffer descriptions queues. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_InitializeAdapter (PLM_DEVICE_BLOCK pDevice) +{ + LM_PHYSICAL_ADDRESS MemPhy; + PLM_UINT8 pMemVirt; + PLM_PACKET pPacket; + LM_STATUS Status; + LM_UINT32 Size; + LM_UINT32 j; + + /* Set power state to D0. */ + LM_SetPowerState (pDevice, LM_POWER_STATE_D0); + + /* Intialize the queues. */ + QQ_InitQueue (&pDevice->RxPacketReceivedQ.Container, + MAX_RX_PACKET_DESC_COUNT); + QQ_InitQueue (&pDevice->RxPacketFreeQ.Container, + MAX_RX_PACKET_DESC_COUNT); + + QQ_InitQueue (&pDevice->TxPacketFreeQ.Container, + MAX_TX_PACKET_DESC_COUNT); + QQ_InitQueue (&pDevice->TxPacketActiveQ.Container, + MAX_TX_PACKET_DESC_COUNT); + QQ_InitQueue (&pDevice->TxPacketXmittedQ.Container, + MAX_TX_PACKET_DESC_COUNT); + + /* Allocate shared memory for: status block, the buffers for receive */ + /* rings -- standard, mini, jumbo, and return rings. */ + Size = T3_STATUS_BLOCK_SIZE + sizeof (T3_STATS_BLOCK) + + T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); + + /* Memory for host based Send BD. */ + if (pDevice->NicSendBd == FALSE) { + Size += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; + } + + /* Allocate the memory block. */ + Status = + MM_AllocateSharedMemory (pDevice, Size, (PLM_VOID) & pMemVirt, + &MemPhy, FALSE); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + + /* Program DMA Read/Write */ + if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) { + pDevice->DmaReadWriteCtrl = 0x763f000f; + } else { + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5704) { + pDevice->DmaReadWriteCtrl = 0x761f0000; + } else { + pDevice->DmaReadWriteCtrl = 0x761b000f; + } + if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || + pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { + pDevice->OneDmaAtOnce = TRUE; + } + } + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { + pDevice->DmaReadWriteCtrl &= 0xfffffff0; + } + + if (pDevice->OneDmaAtOnce) { + pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE; + } + REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); + + if (LM_DmaTest (pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS) { + return LM_STATUS_FAILURE; + } + + /* Status block. */ + pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt; + pDevice->StatusBlkPhy = MemPhy; + pMemVirt += T3_STATUS_BLOCK_SIZE; + LM_INC_PHYSICAL_ADDRESS (&MemPhy, T3_STATUS_BLOCK_SIZE); + + /* Statistics block. */ + pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt; + pDevice->StatsBlkPhy = MemPhy; + pMemVirt += sizeof (T3_STATS_BLOCK); + LM_INC_PHYSICAL_ADDRESS (&MemPhy, sizeof (T3_STATS_BLOCK)); + + /* Receive standard BD buffer. */ + pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RxStdBdPhy = MemPhy; + + pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS (&MemPhy, + T3_STD_RCV_RCB_ENTRY_COUNT * + sizeof (T3_RCV_BD)); + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Receive jumbo BD buffer. */ + pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RxJumboBdPhy = MemPhy; + + pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS (&MemPhy, + T3_JUMBO_RCV_RCB_ENTRY_COUNT * + sizeof (T3_RCV_BD)); +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Receive return BD buffer. */ + pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RcvRetBdPhy = MemPhy; + + pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS (&MemPhy, + T3_RCV_RETURN_RCB_ENTRY_COUNT * + sizeof (T3_RCV_BD)); + + /* Set up Send BD. */ + if (pDevice->NicSendBd == FALSE) { + pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt; + pDevice->SendBdPhy = MemPhy; + + pMemVirt += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; + LM_INC_PHYSICAL_ADDRESS (&MemPhy, + sizeof (T3_SND_BD) * + T3_SEND_RCB_ENTRY_COUNT); + } else { + pDevice->pSendBdVirt = (PT3_SND_BD) + pDevice->pMemView->uIntMem.First32k.BufferDesc; + pDevice->SendBdPhy.High = 0; + pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR; + } + + /* Allocate memory for packet descriptors. */ + Size = (pDevice->RxPacketDescCnt + + pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE; + Status = MM_AllocateMemory (pDevice, Size, (PLM_VOID *) & pPacket); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + pDevice->pPacketDescBase = (PLM_VOID) pPacket; + + /* Create transmit packet descriptors from the memory block and add them */ + /* to the TxPacketFreeQ for each send ring. */ + for (j = 0; j < pDevice->TxPacketDescCnt; j++) { + /* Ring index. */ + pPacket->Flags = 0; + + /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */ + QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = + (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for(j.. */ + + /* Create receive packet descriptors from the memory block and add them */ + /* to the RxPacketFreeQ. Create the Standard packet descriptors. */ + for (j = 0; j < pDevice->RxStdDescCnt; j++) { + /* Receive producer ring. */ + pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING; + + /* Receive buffer size. */ + pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE; + + /* Add the descriptor to RxPacketFreeQ. */ + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = + (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for */ + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Create the Jumbo packet descriptors. */ + for (j = 0; j < pDevice->RxJumboDescCnt; j++) { + /* Receive producer ring. */ + pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING; + + /* Receive buffer size. */ + pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize; + + /* Add the descriptor to RxPacketFreeQ. */ + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = + (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for */ +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Initialize the rest of the packet descriptors. */ + Status = MM_InitializeUmPackets (pDevice); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + + /* if */ + /* Default receive mask. */ + pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST | + LM_ACCEPT_UNICAST; + + /* Make sure we are in the first 32k memory window or NicSendBd. */ + REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); + + /* Initialize the hardware. */ + Status = LM_ResetAdapter (pDevice); + if (Status != LM_STATUS_SUCCESS) { + return Status; + } + + /* We are done with initialization. */ + pDevice->InitDone = TRUE; + + return LM_STATUS_SUCCESS; +} /* LM_InitializeAdapter */ + +/******************************************************************************/ +/* Description: */ +/* This function Enables/Disables a given block. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_CntrlBlock (PLM_DEVICE_BLOCK pDevice, LM_UINT32 mask, LM_UINT32 cntrl) +{ + LM_UINT32 j, i, data; + LM_UINT32 MaxWaitCnt; + + MaxWaitCnt = 2; + j = 0; + + for (i = 0; i < 32; i++) { + if (!(mask & (1 << i))) + continue; + + switch (1 << i) { + case T3_BLOCK_DMA_RD: + data = REG_RD (pDevice, DmaRead.Mode); + if (cntrl == LM_DISABLE) { + data &= ~DMA_READ_MODE_ENABLE; + REG_WR (pDevice, DmaRead.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, DmaRead.Mode) & + DMA_READ_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, DmaRead.Mode, + data | DMA_READ_MODE_ENABLE); + break; + + case T3_BLOCK_DMA_COMP: + data = REG_RD (pDevice, DmaComp.Mode); + if (cntrl == LM_DISABLE) { + data &= ~DMA_COMP_MODE_ENABLE; + REG_WR (pDevice, DmaComp.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, DmaComp.Mode) & + DMA_COMP_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, DmaComp.Mode, + data | DMA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_RX_BD_INITIATOR: + data = REG_RD (pDevice, RcvBdIn.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_BD_IN_MODE_ENABLE; + REG_WR (pDevice, RcvBdIn.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvBdIn.Mode) & + RCV_BD_IN_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvBdIn.Mode, + data | RCV_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_RX_BD_COMP: + data = REG_RD (pDevice, RcvBdComp.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_BD_COMP_MODE_ENABLE; + REG_WR (pDevice, RcvBdComp.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvBdComp.Mode) & + RCV_BD_COMP_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvBdComp.Mode, + data | RCV_BD_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_DMA_WR: + data = REG_RD (pDevice, DmaWrite.Mode); + if (cntrl == LM_DISABLE) { + data &= ~DMA_WRITE_MODE_ENABLE; + REG_WR (pDevice, DmaWrite.Mode, data); + + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, DmaWrite.Mode) & + DMA_WRITE_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, DmaWrite.Mode, + data | DMA_WRITE_MODE_ENABLE); + break; + + case T3_BLOCK_MSI_HANDLER: + data = REG_RD (pDevice, Msi.Mode); + if (cntrl == LM_DISABLE) { + data &= ~MSI_MODE_ENABLE; + REG_WR (pDevice, Msi.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, Msi.Mode) & + MSI_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, Msi.Mode, + data | MSI_MODE_ENABLE); + break; + + case T3_BLOCK_RX_LIST_PLMT: + data = REG_RD (pDevice, RcvListPlmt.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_LIST_PLMT_MODE_ENABLE; + REG_WR (pDevice, RcvListPlmt.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvListPlmt.Mode) + & RCV_LIST_PLMT_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvListPlmt.Mode, + data | RCV_LIST_PLMT_MODE_ENABLE); + break; + + case T3_BLOCK_RX_LIST_SELECTOR: + data = REG_RD (pDevice, RcvListSel.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_LIST_SEL_MODE_ENABLE; + REG_WR (pDevice, RcvListSel.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvListSel.Mode) & + RCV_LIST_SEL_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvListSel.Mode, + data | RCV_LIST_SEL_MODE_ENABLE); + break; + + case T3_BLOCK_RX_DATA_INITIATOR: + data = REG_RD (pDevice, RcvDataBdIn.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_DATA_BD_IN_MODE_ENABLE; + REG_WR (pDevice, RcvDataBdIn.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvDataBdIn.Mode) + & RCV_DATA_BD_IN_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvDataBdIn.Mode, + data | RCV_DATA_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_RX_DATA_COMP: + data = REG_RD (pDevice, RcvDataComp.Mode); + if (cntrl == LM_DISABLE) { + data &= ~RCV_DATA_COMP_MODE_ENABLE; + REG_WR (pDevice, RcvDataComp.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, RcvDataBdIn.Mode) + & RCV_DATA_COMP_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, RcvDataComp.Mode, + data | RCV_DATA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_HOST_COALESING: + data = REG_RD (pDevice, HostCoalesce.Mode); + if (cntrl == LM_DISABLE) { + data &= ~HOST_COALESCE_ENABLE; + REG_WR (pDevice, HostCoalesce.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndBdIn.Mode) & + HOST_COALESCE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, HostCoalesce.Mode, + data | HOST_COALESCE_ENABLE); + break; + + case T3_BLOCK_MAC_RX_ENGINE: + if (cntrl == LM_DISABLE) { + pDevice->RxMode &= ~RX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.RxMode, + pDevice->RxMode); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, MacCtrl.RxMode) & + RX_MODE_ENABLE)) { + break; + } + MM_Wait (10); + } + } else { + pDevice->RxMode |= RX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.RxMode, + pDevice->RxMode); + } + break; + + case T3_BLOCK_MBUF_CLUSTER_FREE: + data = REG_RD (pDevice, MbufClusterFree.Mode); + if (cntrl == LM_DISABLE) { + data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE; + REG_WR (pDevice, MbufClusterFree.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD + (pDevice, + MbufClusterFree. + Mode) & + MBUF_CLUSTER_FREE_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, MbufClusterFree.Mode, + data | MBUF_CLUSTER_FREE_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_INITIATOR: + data = REG_RD (pDevice, SndBdIn.Mode); + if (cntrl == LM_DISABLE) { + data &= ~SND_BD_IN_MODE_ENABLE; + REG_WR (pDevice, SndBdIn.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndBdIn.Mode) & + SND_BD_IN_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, SndBdIn.Mode, + data | SND_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_COMP: + data = REG_RD (pDevice, SndBdComp.Mode); + if (cntrl == LM_DISABLE) { + data &= ~SND_BD_COMP_MODE_ENABLE; + REG_WR (pDevice, SndBdComp.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndBdComp.Mode) & + SND_BD_COMP_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, SndBdComp.Mode, + data | SND_BD_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_SELECTOR: + data = REG_RD (pDevice, SndBdSel.Mode); + if (cntrl == LM_DISABLE) { + data &= ~SND_BD_SEL_MODE_ENABLE; + REG_WR (pDevice, SndBdSel.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndBdSel.Mode) & + SND_BD_SEL_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, SndBdSel.Mode, + data | SND_BD_SEL_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_DATA_INITIATOR: + data = REG_RD (pDevice, SndDataIn.Mode); + if (cntrl == LM_DISABLE) { + data &= ~T3_SND_DATA_IN_MODE_ENABLE; + REG_WR (pDevice, SndDataIn.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndDataIn.Mode) & + T3_SND_DATA_IN_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, SndDataIn.Mode, + data | T3_SND_DATA_IN_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_DATA_COMP: + data = REG_RD (pDevice, SndDataComp.Mode); + if (cntrl == LM_DISABLE) { + data &= ~SND_DATA_COMP_MODE_ENABLE; + REG_WR (pDevice, SndDataComp.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, SndDataComp.Mode) + & SND_DATA_COMP_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, SndDataComp.Mode, + data | SND_DATA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_MAC_TX_ENGINE: + if (cntrl == LM_DISABLE) { + pDevice->TxMode &= ~TX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.TxMode, + pDevice->TxMode); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, MacCtrl.TxMode) & + TX_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else { + pDevice->TxMode |= TX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.TxMode, + pDevice->TxMode); + } + break; + + case T3_BLOCK_MEM_ARBITOR: + data = REG_RD (pDevice, MemArbiter.Mode); + if (cntrl == LM_DISABLE) { + data &= ~T3_MEM_ARBITER_MODE_ENABLE; + REG_WR (pDevice, MemArbiter.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, MemArbiter.Mode) & + T3_MEM_ARBITER_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, MemArbiter.Mode, + data | T3_MEM_ARBITER_MODE_ENABLE); + break; + + case T3_BLOCK_MBUF_MANAGER: + data = REG_RD (pDevice, BufMgr.Mode); + if (cntrl == LM_DISABLE) { + data &= ~BUFMGR_MODE_ENABLE; + REG_WR (pDevice, BufMgr.Mode, data); + for (j = 0; j < MaxWaitCnt; j++) { + if (! + (REG_RD (pDevice, BufMgr.Mode) & + BUFMGR_MODE_ENABLE)) + break; + MM_Wait (10); + } + } else + REG_WR (pDevice, BufMgr.Mode, + data | BUFMGR_MODE_ENABLE); + break; + + case T3_BLOCK_MAC_GLOBAL: + if (cntrl == LM_DISABLE) { + pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | + MAC_MODE_ENABLE_FHDE); + } else { + pDevice->MacMode |= (MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | + MAC_MODE_ENABLE_FHDE); + } + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + break; + + default: + return LM_STATUS_FAILURE; + } /* switch */ + + if (j >= MaxWaitCnt) { + return LM_STATUS_FAILURE; + } + } + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* This function reinitializes the adapter. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT16 Value16; + LM_UINT32 j, k; + + /* Disable interrupt. */ + LM_DisableInterrupt (pDevice); + + /* May get a spurious interrupt */ + pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED; + + /* Disable transmit and receive DMA engines. Abort all pending requests. */ + if (pDevice->InitDone) { + LM_Abort (pDevice); + } + + pDevice->ShuttingDown = FALSE; + + LM_ResetChip (pDevice); + + /* Bug: Athlon fix for B3 silicon only. This bit does not do anything */ + /* in other chip revisions. */ + if (pDevice->DelayPciGrant) { + Value32 = REG_RD (pDevice, PciCfg.ClockCtrl); + REG_WR (pDevice, PciCfg.ClockCtrl, Value32 | BIT_31); + } + + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { + Value32 = REG_RD (pDevice, PciCfg.PciState); + Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; + REG_WR (pDevice, PciCfg.PciState, Value32); + } + } + + /* Enable TaggedStatus mode. */ + if (pDevice->UseTaggedStatus) { + pDevice->MiscHostCtrl |= + MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE; + } + + /* Restore PCI configuration registers. */ + MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, + pDevice->SavedCacheLineReg); + MM_WriteConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, + (pDevice->SubsystemId << 16) | pDevice-> + SubsystemVendorId); + + /* Clear the statistics block. */ + for (j = 0x0300; j < 0x0b00; j++) { + MEM_WR_OFFSET (pDevice, j, 0); + } + + /* Initialize the statistis Block */ + pDevice->pStatusBlkVirt->Status = 0; + pDevice->pStatusBlkVirt->RcvStdConIdx = 0; + pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; + pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; + + for (j = 0; j < 16; j++) { + pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0; + pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0; + } + + for (k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT; k++) { + pDevice->pRxStdBdVirt[k].HostAddr.High = 0; + pDevice->pRxStdBdVirt[k].HostAddr.Low = 0; + } + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Receive jumbo BD buffer. */ + for (k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++) { + pDevice->pRxJumboBdVirt[k].HostAddr.High = 0; + pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0; + } +#endif + + REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); + + /* GRC mode control register. */ +#ifdef BIG_ENDIAN_PCI /* Jimmy, this ifdef block deleted in new code! */ + Value32 = + GRC_MODE_WORD_SWAP_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; +#else + /* No CPU Swap modes for PCI IO */ + Value32 = +#ifdef BIG_ENDIAN_HOST + GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | +#else + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | +#endif + GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; +#endif /* !BIG_ENDIAN_PCI */ + + /* Configure send BD mode. */ + if (pDevice->NicSendBd == FALSE) { + Value32 |= GRC_MODE_HOST_SEND_BDS; + } else { + Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS; + } + + /* Configure pseudo checksum mode. */ + if (pDevice->NoTxPseudoHdrChksum) { + Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM; + } + + if (pDevice->NoRxPseudoHdrChksum) { + Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM; + } + + REG_WR (pDevice, Grc.Mode, Value32); + + /* Setup the timer prescalar register. */ + REG_WR (pDevice, Grc.MiscCfg, 65 << 1); /* Clock is alwasy 66Mhz. */ + + /* Set up the MBUF pool base address and size. */ + REG_WR (pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase); + REG_WR (pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize); + + /* Set up the DMA descriptor pool base address and size. */ + REG_WR (pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR); + REG_WR (pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE); + + /* Configure MBUF and Threshold watermarks */ + /* Configure the DMA read MBUF low water mark. */ + if (pDevice->DmaMbufLowMark) { + REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, + pDevice->DmaMbufLowMark); + } else { + if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { + REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, + T3_DEF_DMA_MBUF_LOW_WMARK); + } else { + REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, + T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO); + } + } + + /* Configure the MAC Rx MBUF low water mark. */ + if (pDevice->RxMacMbufLowMark) { + REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, + pDevice->RxMacMbufLowMark); + } else { + if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { + REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, + T3_DEF_RX_MAC_MBUF_LOW_WMARK); + } else { + REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, + T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO); + } + } + + /* Configure the MBUF high water mark. */ + if (pDevice->MbufHighMark) { + REG_WR (pDevice, BufMgr.MbufHighWaterMark, + pDevice->MbufHighMark); + } else { + if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { + REG_WR (pDevice, BufMgr.MbufHighWaterMark, + T3_DEF_MBUF_HIGH_WMARK); + } else { + REG_WR (pDevice, BufMgr.MbufHighWaterMark, + T3_DEF_MBUF_HIGH_WMARK_JUMBO); + } + } + + REG_WR (pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK); + REG_WR (pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK); + + /* Enable buffer manager. */ + REG_WR (pDevice, BufMgr.Mode, + BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); + + for (j = 0; j < 2000; j++) { + if (REG_RD (pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE) + break; + MM_Wait (10); + } + + if (j >= 2000) { + return LM_STATUS_FAILURE; + } + + /* Enable the FTQs. */ + REG_WR (pDevice, Ftq.Reset, 0xffffffff); + REG_WR (pDevice, Ftq.Reset, 0); + + /* Wait until FTQ is ready */ + for (j = 0; j < 2000; j++) { + if (REG_RD (pDevice, Ftq.Reset) == 0) + break; + MM_Wait (10); + } + + if (j >= 2000) { + return LM_STATUS_FAILURE; + } + + /* Initialize the Standard Receive RCB. */ + REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High, + pDevice->RxStdBdPhy.High); + REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low, + pDevice->RxStdBdPhy.Low); + REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags, + MAX_STD_RCV_BUFFER_SIZE << 16); + + /* Initialize the Jumbo Receive RCB. */ + REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High, + pDevice->RxJumboBdPhy.High); + REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low, + pDevice->RxJumboBdPhy.Low); + + REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0); + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Initialize the Mini Receive RCB. */ + REG_WR (pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); + + { + REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr, + (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR); + REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr, + (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR); + } + + /* Receive BD Ring replenish threshold. */ + REG_WR (pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt / 8); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + REG_WR (pDevice, RcvBdIn.JumboRcvThreshold, + pDevice->RxJumboDescCnt / 8); +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Disable all the unused rings. */ + for (j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) { + MEM_WR (pDevice, SendRcb[j].u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); + } /* for */ + + /* Initialize the indices. */ + pDevice->SendProdIdx = 0; + pDevice->SendConIdx = 0; + + MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, 0); + MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, 0); + + /* Set up host or NIC based send RCB. */ + if (pDevice->NicSendBd == FALSE) { + MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, + pDevice->SendBdPhy.High); + MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, + pDevice->SendBdPhy.Low); + + /* Set up the NIC ring address in the RCB. */ + MEM_WR (pDevice, SendRcb[0].NicRingAddr, + T3_NIC_SND_BUFFER_DESC_ADDR); + + /* Setup the RCB. */ + MEM_WR (pDevice, SendRcb[0].u.MaxLen_Flags, + T3_SEND_RCB_ENTRY_COUNT << 16); + + for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { + pDevice->pSendBdVirt[k].HostAddr.High = 0; + pDevice->pSendBdVirt[k].HostAddr.Low = 0; + } + } else { + MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, 0); + MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, 0); + MEM_WR (pDevice, SendRcb[0].NicRingAddr, + pDevice->SendBdPhy.Low); + + for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { + __raw_writel (0, + &(pDevice->pSendBdVirt[k].HostAddr.High)); + __raw_writel (0, + &(pDevice->pSendBdVirt[k].HostAddr.Low)); + __raw_writel (0, + &(pDevice->pSendBdVirt[k].u1.Len_Flags)); + pDevice->ShadowSendBd[k].HostAddr.High = 0; + pDevice->ShadowSendBd[k].u1.Len_Flags = 0; + } + } + atomic_set (&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT - 1); + + /* Configure the receive return rings. */ + for (j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++) { + MEM_WR (pDevice, RcvRetRcb[j].u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); + } + + pDevice->RcvRetConIdx = 0; + + MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.High, + pDevice->RcvRetBdPhy.High); + MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.Low, + pDevice->RcvRetBdPhy.Low); + + /* Set up the NIC ring address in the RCB. */ + /* Not very clear from the spec. I am guessing that for Receive */ + /* Return Ring, NicRingAddr is not used. */ + MEM_WR (pDevice, RcvRetRcb[0].NicRingAddr, 0); + + /* Setup the RCB. */ + MEM_WR (pDevice, RcvRetRcb[0].u.MaxLen_Flags, + T3_RCV_RETURN_RCB_ENTRY_COUNT << 16); + + /* Reinitialize RX ring producer index */ + MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, 0); + MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, 0); + MB_REG_WR (pDevice, Mailbox.RcvMiniProdIdx.Low, 0); + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboProdIdx = 0; + pDevice->RxJumboQueuedCnt = 0; +#endif + + /* Reinitialize our copy of the indices. */ + pDevice->RxStdProdIdx = 0; + pDevice->RxStdQueuedCnt = 0; + +#if T3_JUMBO_RCV_ENTRY_COUNT + pDevice->RxJumboProdIdx = 0; +#endif /* T3_JUMBO_RCV_ENTRY_COUNT */ + + /* Configure the MAC address. */ + LM_SetMacAddress (pDevice, pDevice->NodeAddress); + + /* Initialize the transmit random backoff seed. */ + Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + + pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + + pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & + MAC_TX_BACKOFF_SEED_MASK; + REG_WR (pDevice, MacCtrl.TxBackoffSeed, Value32); + + /* Receive MTU. Frames larger than the MTU is marked as oversized. */ + REG_WR (pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8); /* CRC + VLAN. */ + + /* Configure Time slot/IPG per 802.3 */ + REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); + + /* + * Configure Receive Rules so that packets don't match + * Programmble rule will be queued to Return Ring 1 + */ + REG_WR (pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS); + + /* + * Configure to have 16 Classes of Services (COS) and one + * queue per class. Bad frames are queued to RRR#1. + * And frames don't match rules are also queued to COS#1. + */ + REG_WR (pDevice, RcvListPlmt.Config, 0x181); + + /* Enable Receive Placement Statistics */ + REG_WR (pDevice, RcvListPlmt.StatsEnableMask, 0xffffff); + REG_WR (pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE); + + /* Enable Send Data Initator Statistics */ + REG_WR (pDevice, SndDataIn.StatsEnableMask, 0xffffff); + REG_WR (pDevice, SndDataIn.StatsCtrl, + T3_SND_DATA_IN_STATS_CTRL_ENABLE | + T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE); + + /* Disable the host coalescing state machine before configuring it's */ + /* parameters. */ + REG_WR (pDevice, HostCoalesce.Mode, 0); + for (j = 0; j < 2000; j++) { + Value32 = REG_RD (pDevice, HostCoalesce.Mode); + if (!(Value32 & HOST_COALESCE_ENABLE)) { + break; + } + MM_Wait (10); + } + + /* Host coalescing configurations. */ + REG_WR (pDevice, HostCoalesce.RxCoalescingTicks, + pDevice->RxCoalescingTicks); + REG_WR (pDevice, HostCoalesce.TxCoalescingTicks, + pDevice->TxCoalescingTicks); + REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFrames, + pDevice->RxMaxCoalescedFrames); + REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFrames, + pDevice->TxMaxCoalescedFrames); + REG_WR (pDevice, HostCoalesce.RxCoalescedTickDuringInt, + pDevice->RxCoalescingTicksDuringInt); + REG_WR (pDevice, HostCoalesce.TxCoalescedTickDuringInt, + pDevice->TxCoalescingTicksDuringInt); + REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt, + pDevice->RxMaxCoalescedFramesDuringInt); + REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt, + pDevice->TxMaxCoalescedFramesDuringInt); + + /* Initialize the address of the status block. The NIC will DMA */ + /* the status block to this memory which resides on the host. */ + REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.High, + pDevice->StatusBlkPhy.High); + REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.Low, + pDevice->StatusBlkPhy.Low); + + /* Initialize the address of the statistics block. The NIC will DMA */ + /* the statistics to this block of memory. */ + REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.High, + pDevice->StatsBlkPhy.High); + REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.Low, + pDevice->StatsBlkPhy.Low); + + REG_WR (pDevice, HostCoalesce.StatsCoalescingTicks, + pDevice->StatsCoalescingTicks); + + REG_WR (pDevice, HostCoalesce.StatsBlkNicAddr, 0x300); + REG_WR (pDevice, HostCoalesce.StatusBlkNicAddr, 0xb00); + + /* Enable Host Coalesing state machine */ + REG_WR (pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE | + pDevice->CoalesceMode); + + /* Enable the Receive BD Completion state machine. */ + REG_WR (pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE | + RCV_BD_COMP_MODE_ATTN_ENABLE); + + /* Enable the Receive List Placement state machine. */ + REG_WR (pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE); + + /* Enable the Receive List Selector state machine. */ + REG_WR (pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE | + RCV_LIST_SEL_MODE_ATTN_ENABLE); + + /* Enable transmit DMA, clear statistics. */ + pDevice->MacMode = MAC_MODE_ENABLE_TX_STATISTICS | + MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE; + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS); + + /* GRC miscellaneous local control register. */ + pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN | + GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM; + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1; + } + + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); + MM_Wait (40); + + /* Reset RX counters. */ + for (j = 0; j < sizeof (LM_RX_COUNTERS); j++) { + ((PLM_UINT8) & pDevice->RxCounters)[j] = 0; + } + + /* Reset TX counters. */ + for (j = 0; j < sizeof (LM_TX_COUNTERS); j++) { + ((PLM_UINT8) & pDevice->TxCounters)[j] = 0; + } + + MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); + + /* Enable the DMA Completion state machine. */ + REG_WR (pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE); + + /* Enable the DMA Write state machine. */ + Value32 = DMA_WRITE_MODE_ENABLE | + DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE | + DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE | + DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE | + DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE | + DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE; + REG_WR (pDevice, DmaWrite.Mode, Value32); + + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { + Value16 = REG_RD (pDevice, PciCfg.PciXCommand); + Value16 &= + ~(PCIX_CMD_MAX_SPLIT_MASK | + PCIX_CMD_MAX_BURST_MASK); + Value16 |= + ((PCIX_CMD_MAX_BURST_CPIOB << + PCIX_CMD_MAX_BURST_SHL) & + PCIX_CMD_MAX_BURST_MASK); + if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { + Value16 |= + (pDevice-> + SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL) + & PCIX_CMD_MAX_SPLIT_MASK; + } + REG_WR (pDevice, PciCfg.PciXCommand, Value16); + } + } + + /* Enable the Read DMA state machine. */ + Value32 = DMA_READ_MODE_ENABLE | + DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE | + DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE | + DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE | + DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE | + DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE | + DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE | + DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE | + DMA_READ_MODE_LONG_READ_ATTN_ENABLE; + + if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { + Value32 |= DMA_READ_MODE_SPLIT_ENABLE; + } + REG_WR (pDevice, DmaRead.Mode, Value32); + + /* Enable the Receive Data Completion state machine. */ + REG_WR (pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE | + RCV_DATA_COMP_MODE_ATTN_ENABLE); + + /* Enable the Mbuf Cluster Free state machine. */ + REG_WR (pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE); + + /* Enable the Send Data Completion state machine. */ + REG_WR (pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE); + + /* Enable the Send BD Completion state machine. */ + REG_WR (pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE | + SND_BD_COMP_MODE_ATTN_ENABLE); + + /* Enable the Receive BD Initiator state machine. */ + REG_WR (pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE | + RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE); + + /* Enable the Receive Data and Receive BD Initiator state machine. */ + REG_WR (pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE | + RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE); + + /* Enable the Send Data Initiator state machine. */ + REG_WR (pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE); + + /* Enable the Send BD Initiator state machine. */ + REG_WR (pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE | + SND_BD_IN_MODE_ATTN_ENABLE); + + /* Enable the Send BD Selector state machine. */ + REG_WR (pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE | + SND_BD_SEL_MODE_ATTN_ENABLE); + +#if INCLUDE_5701_AX_FIX + /* Load the firmware for the 5701_A0 workaround. */ + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0) { + LM_LoadRlsFirmware (pDevice); + } +#endif + + /* Enable the transmitter. */ + pDevice->TxMode = TX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); + + /* Enable the receiver. */ + pDevice->RxMode = RX_MODE_ENABLE; + REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); + + if (pDevice->RestoreOnWakeUp) { + pDevice->RestoreOnWakeUp = FALSE; + pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg; + pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType; + } + + /* Disable auto polling. */ + pDevice->MiMode = 0xc0000; + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = LED_CTRL_PHY_MODE_1; + } else { + if (pDevice->LedMode == LED_MODE_OUTPUT) { + Value32 = LED_CTRL_PHY_MODE_2; + } else { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + REG_WR (pDevice, MacCtrl.LedCtrl, Value32); + + /* Activate Link to enable MAC state machine */ + REG_WR (pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN); + + if (pDevice->EnableTbi) { + REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_RESET); + MM_Wait (10); + REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); + if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1) { + REG_WR (pDevice, MacCtrl.SerdesCfg, 0x616000); + } + } + /* Setup the phy chip. */ + LM_SetupPhy (pDevice); + + if (!pDevice->EnableTbi) { + /* Clear CRC stats */ + LM_ReadPhy (pDevice, 0x1e, &Value32); + LM_WritePhy (pDevice, 0x1e, Value32 | 0x8000); + LM_ReadPhy (pDevice, 0x14, &Value32); + } + + /* Set up the receive mask. */ + LM_SetReceiveMask (pDevice, pDevice->ReceiveMask); + + /* Queue Rx packet buffers. */ + if (pDevice->QueueRxPackets) { + LM_QueueRxPackets (pDevice); + } + + /* Enable interrupt to the host. */ + if (pDevice->InitDone) { + LM_EnableInterrupt (pDevice); + } + + return LM_STATUS_SUCCESS; +} /* LM_ResetAdapter */ + +/******************************************************************************/ +/* Description: */ +/* This routine disables the adapter from generating interrupts. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_DisableInterrupt (PLM_DEVICE_BLOCK pDevice) +{ + REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl | + MISC_HOST_CTRL_MASK_PCI_INT); + MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1); + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* This routine enables the adapter to generate interrupts. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_EnableInterrupt (PLM_DEVICE_BLOCK pDevice) +{ + REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl & + ~MISC_HOST_CTRL_MASK_PCI_INT); + MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); + + if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_SET_INT); + } + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* This routine puts a packet on the wire if there is a transmit DMA */ +/* descriptor available; otherwise the packet is queued for later */ +/* transmission. If the second argue is NULL, this routine will put */ +/* the queued packet on the wire if possible. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +#if 0 +LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + LM_UINT32 FragCount; + PT3_SND_BD pSendBd; + PT3_SND_BD pShadowSendBd; + LM_UINT32 Value32, Len; + LM_UINT32 Idx; + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + return LM_5700SendPacket (pDevice, pPacket); + } + + /* Update the SendBdLeft count. */ + atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Initalize the send buffer descriptors. */ + Idx = pDevice->SendProdIdx; + + pSendBd = &pDevice->pSendBdVirt[Idx]; + + /* Next producer index. */ + if (pDevice->NicSendBd == TRUE) { + T3_64BIT_HOST_ADDR paddr; + + pShadowSendBd = &pDevice->ShadowSendBd[Idx]; + for (FragCount = 0;;) { + MM_MapTxDma (pDevice, pPacket, &paddr, &Len, FragCount); + /* Initialize the pointer to the send buffer fragment. */ + if (paddr.High != pShadowSendBd->HostAddr.High) { + __raw_writel (paddr.High, + &(pSendBd->HostAddr.High)); + pShadowSendBd->HostAddr.High = paddr.High; + } + __raw_writel (paddr.Low, &(pSendBd->HostAddr.Low)); + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) { + Value32 |= SND_BD_FLAG_END; + if (Value32 != pShadowSendBd->u1.Len_Flags) { + __raw_writel (Value32, + &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { + __raw_writel (pPacket->VlanTag, + &(pSendBd->u2.VlanTag)); + } + break; + } else { + if (Value32 != pShadowSendBd->u1.Len_Flags) { + __raw_writel (Value32, + &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { + __raw_writel (pPacket->VlanTag, + &(pSendBd->u2.VlanTag)); + } + } + + pSendBd++; + pShadowSendBd++; + if (Idx == 0) { + pSendBd = &pDevice->pSendBdVirt[0]; + pShadowSendBd = &pDevice->ShadowSendBd[0]; + } + } /* for */ + + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); + + wmb (); + MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + + } else { + for (FragCount = 0;;) { + /* Initialize the pointer to the send buffer fragment. */ + MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, + FragCount); + + pSendBd->u2.VlanTag = pPacket->VlanTag; + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) { + pSendBd->u1.Len_Flags = + Value32 | SND_BD_FLAG_END; + break; + } else { + pSendBd->u1.Len_Flags = Value32; + } + pSendBd++; + if (Idx == 0) { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } /* for */ + + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); + + wmb (); + MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); + + } + + /* Update the producer index. */ + pDevice->SendProdIdx = Idx; + + return LM_STATUS_SUCCESS; +} +#endif + +LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + LM_UINT32 FragCount; + PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd; + T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT]; + LM_UINT32 StartIdx, Idx; + + while (1) { + /* Initalize the send buffer descriptors. */ + StartIdx = Idx = pDevice->SendProdIdx; + + if (pDevice->NicSendBd) { + pTmpSendBd = pSendBd = &NicSendBdArr[0]; + } else { + pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx]; + } + + /* Next producer index. */ + for (FragCount = 0;;) { + LM_UINT32 Value32, Len; + + /* Initialize the pointer to the send buffer fragment. */ + MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, + FragCount); + + pSendBd->u2.VlanTag = pPacket->VlanTag; + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) { + pSendBd->u1.Len_Flags = + Value32 | SND_BD_FLAG_END; + break; + } else { + pSendBd->u1.Len_Flags = Value32; + } + pSendBd++; + if ((Idx == 0) && !pDevice->NicSendBd) { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } /* for */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + if (LM_Test4GBoundary (pDevice, pPacket, pTmpSendBd) == + LM_STATUS_SUCCESS) { + if (MM_CoalesceTxBuffer (pDevice, pPacket) != + LM_STATUS_SUCCESS) { + QQ_PushHead (&pDevice->TxPacketFreeQ. + Container, pPacket); + return LM_STATUS_FAILURE; + } + continue; + } + } + break; + } + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); + + if (pDevice->NicSendBd) { + pSendBd = &pDevice->pSendBdVirt[StartIdx]; + pShadowSendBd = &pDevice->ShadowSendBd[StartIdx]; + + while (StartIdx != Idx) { + LM_UINT32 Value32; + + if ((Value32 = pTmpSendBd->HostAddr.High) != + pShadowSendBd->HostAddr.High) { + __raw_writel (Value32, + &(pSendBd->HostAddr.High)); + pShadowSendBd->HostAddr.High = Value32; + } + + __raw_writel (pTmpSendBd->HostAddr.Low, + &(pSendBd->HostAddr.Low)); + + if ((Value32 = pTmpSendBd->u1.Len_Flags) != + pShadowSendBd->u1.Len_Flags) { + __raw_writel (Value32, + &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { + __raw_writel (pTmpSendBd->u2.VlanTag, + &(pSendBd->u2.VlanTag)); + } + + StartIdx = + (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + if (StartIdx == 0) + pSendBd = &pDevice->pSendBdVirt[0]; + else + pSendBd++; + pTmpSendBd++; + } + wmb (); + MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + + if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { + MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + } + } else { + wmb (); + MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); + + if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { + MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, + Idx); + } + } + + /* Update the SendBdLeft count. */ + atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Update the producer index. */ + pDevice->SendProdIdx = Idx; + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS +LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket, + PT3_SND_BD pSendBd) +{ + int FragCount; + LM_UINT32 Idx, Base, Len; + + Idx = pDevice->SendProdIdx; + for (FragCount = 0;;) { + Len = pSendBd->u1.Len_Flags >> 16; + if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) && + (pSendBd->HostAddr.High == 0) && + ((Base + 8 + Len) < Base)) { + return LM_STATUS_SUCCESS; + } + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) { + break; + } + pSendBd++; + if (!pDevice->NicSendBd) { + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + if (Idx == 0) { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } + } + return LM_STATUS_FAILURE; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static unsigned long +ComputeCrc32 (unsigned char *pBuffer, unsigned long BufferSize) +{ + unsigned long Reg; + unsigned long Tmp; + unsigned long j, k; + + Reg = 0xffffffff; + + for (j = 0; j < BufferSize; j++) { + Reg ^= pBuffer[j]; + + for (k = 0; k < 8; k++) { + Tmp = Reg & 0x01; + + Reg >>= 1; + + if (Tmp) { + Reg ^= 0xedb88320; + } + } + } + + return ~Reg; +} /* ComputeCrc32 */ + +/******************************************************************************/ +/* Description: */ +/* This routine sets the receive control register according to ReceiveMask */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask) +{ + LM_UINT32 ReceiveMask; + LM_UINT32 RxMode; + LM_UINT32 j, k; + + ReceiveMask = Mask; + + RxMode = pDevice->RxMode; + + if (Mask & LM_ACCEPT_UNICAST) { + Mask &= ~LM_ACCEPT_UNICAST; + } + + if (Mask & LM_ACCEPT_MULTICAST) { + Mask &= ~LM_ACCEPT_MULTICAST; + } + + if (Mask & LM_ACCEPT_ALL_MULTICAST) { + Mask &= ~LM_ACCEPT_ALL_MULTICAST; + } + + if (Mask & LM_ACCEPT_BROADCAST) { + Mask &= ~LM_ACCEPT_BROADCAST; + } + + RxMode &= ~RX_MODE_PROMISCUOUS_MODE; + if (Mask & LM_PROMISCUOUS_MODE) { + RxMode |= RX_MODE_PROMISCUOUS_MODE; + Mask &= ~LM_PROMISCUOUS_MODE; + } + + RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED); + if (Mask & LM_ACCEPT_ERROR_PACKET) { + RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED; + Mask &= ~LM_ACCEPT_ERROR_PACKET; + } + + /* Make sure all the bits are valid before committing changes. */ + if (Mask) { + return LM_STATUS_FAILURE; + } + + /* Commit the new filter. */ + pDevice->RxMode = RxMode; + REG_WR (pDevice, MacCtrl.RxMode, RxMode); + + pDevice->ReceiveMask = ReceiveMask; + + /* Set up the MC hash table. */ + if (ReceiveMask & LM_ACCEPT_ALL_MULTICAST) { + for (k = 0; k < 4; k++) { + REG_WR (pDevice, MacCtrl.HashReg[k], 0xffffffff); + } + } else if (ReceiveMask & LM_ACCEPT_MULTICAST) { + LM_UINT32 HashReg[4]; + + HashReg[0] = 0; + HashReg[1] = 0; + HashReg[2] = 0; + HashReg[3] = 0; + for (j = 0; j < pDevice->McEntryCount; j++) { + LM_UINT32 RegIndex; + LM_UINT32 Bitpos; + LM_UINT32 Crc32; + + Crc32 = + ComputeCrc32 (pDevice->McTable[j], + ETHERNET_ADDRESS_SIZE); + + /* The most significant 7 bits of the CRC32 (no inversion), */ + /* are used to index into one of the possible 128 bit positions. */ + Bitpos = ~Crc32 & 0x7f; + + /* Hash register index. */ + RegIndex = (Bitpos & 0x60) >> 5; + + /* Bit to turn on within a hash register. */ + Bitpos &= 0x1f; + + /* Enable the multicast bit. */ + HashReg[RegIndex] |= (1 << Bitpos); + } + + /* REV_AX has problem with multicast filtering where it uses both */ + /* DA and SA to perform hashing. */ + for (k = 0; k < 4; k++) { + REG_WR (pDevice, MacCtrl.HashReg[k], HashReg[k]); + } + } else { + /* Reject all multicast frames. */ + for (j = 0; j < 4; j++) { + REG_WR (pDevice, MacCtrl.HashReg[j], 0); + } + } + + /* By default, Tigon3 will accept broadcast frames. We need to setup */ + if (ReceiveMask & LM_ACCEPT_BROADCAST) { + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); + } else { + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE2_RULE); + REG_WR (pDevice, + MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE2_VALUE); + } + + /* disable the rest of the rules. */ + for (j = RCV_LAST_RULE_IDX; j < 16; j++) { + REG_WR (pDevice, MacCtrl.RcvRules[j].Rule, 0); + REG_WR (pDevice, MacCtrl.RcvRules[j].Value, 0); + } + + return LM_STATUS_SUCCESS; +} /* LM_SetReceiveMask */ + +/******************************************************************************/ +/* Description: */ +/* Disable the interrupt and put the transmitter and receiver engines in */ +/* an idle state. Also aborts all pending send requests and receive */ +/* buffers. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice) +{ + PLM_PACKET pPacket; + LM_UINT Idx; + + LM_DisableInterrupt (pDevice); + + /* Disable all the state machines. */ + LM_CntrlBlock (pDevice, T3_BLOCK_MAC_RX_ENGINE, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_INITIATOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_PLMT, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_SELECTOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_INITIATOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_COMP, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_COMP, LM_DISABLE); + + LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_SELECTOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_INITIATOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_INITIATOR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_DMA_RD, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_COMP, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_DMA_COMP, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_COMP, LM_DISABLE); + + /* Clear TDE bit */ + pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE; + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + + LM_CntrlBlock (pDevice, T3_BLOCK_MAC_TX_ENGINE, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_HOST_COALESING, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_DMA_WR, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_CLUSTER_FREE, LM_DISABLE); + + /* Reset all FTQs */ + REG_WR (pDevice, Ftq.Reset, 0xffffffff); + REG_WR (pDevice, Ftq.Reset, 0x0); + + LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_MANAGER, LM_DISABLE); + LM_CntrlBlock (pDevice, T3_BLOCK_MEM_ARBITOR, LM_DISABLE); + + MM_ACQUIRE_INT_LOCK (pDevice); + + /* Abort packets that have already queued to go out. */ + pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ.Container); + while (pPacket) { + + pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED; + pDevice->TxCounters.TxPacketAbortedCnt++; + + atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); + + pPacket = (PLM_PACKET) + QQ_PopHead (&pDevice->TxPacketActiveQ.Container); + } + + /* Cleanup the receive return rings. */ + LM_ServiceRxInterrupt (pDevice); + + /* Don't want to indicate rx packets in Ndis miniport shutdown context. */ + /* Doing so may cause system crash. */ + if (!pDevice->ShuttingDown) { + /* Indicate packets to the protocol. */ + MM_IndicateTxPackets (pDevice); + + /* Indicate received packets to the protocols. */ + MM_IndicateRxPackets (pDevice); + } else { + /* Move the receive packet descriptors in the ReceivedQ to the */ + /* free queue. */ + for (;;) { + pPacket = + (PLM_PACKET) QQ_PopHead (&pDevice-> + RxPacketReceivedQ. + Container); + if (pPacket == NULL) { + break; + } + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, + pPacket); + } + } + + /* Clean up the Std Receive Producer ring. */ + Idx = pDevice->pStatusBlkVirt->RcvStdConIdx; + + while (Idx != pDevice->RxStdProdIdx) { + pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + + MM_UINT_PTR (pDevice->pRxStdBdVirt[Idx]. + Opaque)); + + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + + Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK; + } /* while */ + + /* Reinitialize our copy of the indices. */ + pDevice->RxStdProdIdx = 0; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Clean up the Jumbo Receive Producer ring. */ + Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx; + + while (Idx != pDevice->RxJumboProdIdx) { + pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + + MM_UINT_PTR (pDevice-> + pRxJumboBdVirt[Idx]. + Opaque)); + + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + + Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; + } /* while */ + + /* Reinitialize our copy of the indices. */ + pDevice->RxJumboProdIdx = 0; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + MM_RELEASE_INT_LOCK (pDevice); + + /* Initialize the statistis Block */ + pDevice->pStatusBlkVirt->Status = 0; + pDevice->pStatusBlkVirt->RcvStdConIdx = 0; + pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; + pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; + + return LM_STATUS_SUCCESS; +} /* LM_Abort */ + +/******************************************************************************/ +/* Description: */ +/* Disable the interrupt and put the transmitter and receiver engines in */ +/* an idle state. Aborts all pending send requests and receive buffers. */ +/* Also free all the receive buffers. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice) +{ + PLM_PACKET pPacket; + LM_UINT32 EntryCnt; + + LM_Abort (pDevice); + + /* Get the number of entries in the queue. */ + EntryCnt = QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container); + + /* Make sure all the packets have been accounted for. */ + for (EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++) { + pPacket = + (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); + if (pPacket == 0) + break; + + MM_FreeRxBuffer (pDevice, pPacket); + + QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); + } + + LM_ResetChip (pDevice); + + /* Restore PCI configuration registers. */ + MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, + pDevice->SavedCacheLineReg); + LM_RegWrInd (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, + (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId); + + /* Reprogram the MAC address. */ + LM_SetMacAddress (pDevice, pDevice->NodeAddress); + + return LM_STATUS_SUCCESS; +} /* LM_Halt */ + +STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + /* Wait for access to the nvram interface before resetting. This is */ + /* a workaround to prevent EEPROM corruption. */ + if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { + /* Request access to the flash interface. */ + REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); + + for (j = 0; j < 100000; j++) { + Value32 = REG_RD (pDevice, Nvram.SwArb); + if (Value32 & SW_ARB_GNT1) { + break; + } + MM_Wait (10); + } + } + + /* Global reset. */ + REG_WR (pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET); + MM_Wait (40); + MM_Wait (40); + MM_Wait (40); + + /* make sure we re-enable indirect accesses */ + MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, + pDevice->MiscHostCtrl); + + /* Set MAX PCI retry to zero. */ + Value32 = + T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE; + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { + Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; + } + } + MM_WriteConfig32 (pDevice, T3_PCI_STATE_REG, Value32); + + /* Restore PCI command register. */ + MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, + pDevice->PciCommandStatusWords); + + /* Disable PCI-X relaxed ordering bit. */ + MM_ReadConfig32 (pDevice, PCIX_CAP_REG, &Value32); + Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING; + MM_WriteConfig32 (pDevice, PCIX_CAP_REG, Value32); + + /* Enable memory arbiter. */ + REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); + +#ifdef BIG_ENDIAN_PCI /* This from jfd */ + Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else +#ifdef BIG_ENDIAN_HOST + /* Reconfigure the mode register. */ + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA; +#else + /* Reconfigure the mode register. */ + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; +#endif +#endif + REG_WR (pDevice, Grc.Mode, Value32); + + /* Prevent PXE from restarting. */ + MEM_WR_OFFSET (pDevice, 0x0b50, T3_MAGIC_NUM); + + if (pDevice->EnableTbi) { + pDevice->MacMode = MAC_MODE_PORT_MODE_TBI; + REG_WR (pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI); + } else { + REG_WR (pDevice, MacCtrl.Mode, 0); + } + + /* Wait for the firmware to finish initialization. */ + for (j = 0; j < 100000; j++) { + MM_Wait (10); + + Value32 = MEM_RD_OFFSET (pDevice, 0x0b50); + if (Value32 == ~T3_MAGIC_NUM) { + break; + } + } + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static void LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice) +{ + PLM_PACKET pPacket; + LM_UINT32 HwConIdx; + LM_UINT32 SwConIdx; + + HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; + + /* Get our copy of the consumer index. The buffer descriptors */ + /* that are in between the consumer indices are freed. */ + SwConIdx = pDevice->SendConIdx; + + /* Move the packets from the TxPacketActiveQ that are sent out to */ + /* the TxPacketXmittedQ. Packets that are sent use the */ + /* descriptors that are between SwConIdx and HwConIdx. */ + while (SwConIdx != HwConIdx) { + /* Get the packet that was sent from the TxPacketActiveQ. */ + pPacket = + (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ. + Container); + + /* Set the return status. */ + pPacket->PacketStatus = LM_STATUS_SUCCESS; + + /* Put the packet in the TxPacketXmittedQ for indication later. */ + QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); + + /* Move to the next packet's BD. */ + SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & + T3_SEND_RCB_ENTRY_COUNT_MASK; + + /* Update the number of unused BDs. */ + atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Get the new updated HwConIdx. */ + HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; + } /* while */ + + /* Save the new SwConIdx. */ + pDevice->SendConIdx = SwConIdx; + +} /* LM_ServiceTxInterrupt */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static void LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice) +{ + PLM_PACKET pPacket; + PT3_RCV_BD pRcvBd; + LM_UINT32 HwRcvRetProdIdx; + LM_UINT32 SwRcvRetConIdx; + + /* Loop thru the receive return rings for received packets. */ + HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; + + SwRcvRetConIdx = pDevice->RcvRetConIdx; + while (SwRcvRetConIdx != HwRcvRetProdIdx) { + pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx]; + + /* Get the received packet descriptor. */ + pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + + MM_UINT_PTR (pRcvBd->Opaque)); + + /* Check the error flag. */ + if (pRcvBd->ErrorFlag && + pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { + pPacket->PacketStatus = LM_STATUS_FAILURE; + + pDevice->RxCounters.RxPacketErrCnt++; + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC) { + pDevice->RxCounters.RxErrCrcCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT) { + pDevice->RxCounters.RxErrCollCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT) { + pDevice->RxCounters.RxErrLinkLostCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR) { + pDevice->RxCounters.RxErrPhyDecodeCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { + pDevice->RxCounters.RxErrOddNibbleCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT) { + pDevice->RxCounters.RxErrMacAbortCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64) { + pDevice->RxCounters.RxErrShortPacketCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES) { + pDevice->RxCounters.RxErrNoResourceCnt++; + } + + if (pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD) { + pDevice->RxCounters.RxErrLargePacketCnt++; + } + } else { + pPacket->PacketStatus = LM_STATUS_SUCCESS; + pPacket->PacketSize = pRcvBd->Len - 4; + + pPacket->Flags = pRcvBd->Flags; + if (pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG) { + pPacket->VlanTag = pRcvBd->VlanTag; + } + + pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum; + } + + /* Put the packet descriptor containing the received packet */ + /* buffer in the RxPacketReceivedQ for indication later. */ + QQ_PushTail (&pDevice->RxPacketReceivedQ.Container, pPacket); + + /* Go to the next buffer descriptor. */ + SwRcvRetConIdx = (SwRcvRetConIdx + 1) & + T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK; + + /* Get the updated HwRcvRetProdIdx. */ + HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; + } /* while */ + + pDevice->RcvRetConIdx = SwRcvRetConIdx; + + /* Update the receive return ring consumer index. */ + MB_REG_WR (pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx); +} /* LM_ServiceRxInterrupt */ + +/******************************************************************************/ +/* Description: */ +/* This is the interrupt event handler routine. It acknowledges all */ +/* pending interrupts and process all pending events. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS LM_ServiceInterrupts (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + int ServicePhyInt = FALSE; + + /* Setup the phy chip whenever the link status changes. */ + if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG) { + Value32 = REG_RD (pDevice, MacCtrl.Status); + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { + if (Value32 & MAC_STATUS_MI_INTERRUPT) { + ServicePhyInt = TRUE; + } + } else if (Value32 & MAC_STATUS_LINK_STATE_CHANGED) { + ServicePhyInt = TRUE; + } + } else { + if (pDevice->pStatusBlkVirt-> + Status & STATUS_BLOCK_LINK_CHANGED_STATUS) { + pDevice->pStatusBlkVirt->Status = + STATUS_BLOCK_UPDATED | (pDevice->pStatusBlkVirt-> + Status & + ~STATUS_BLOCK_LINK_CHANGED_STATUS); + ServicePhyInt = TRUE; + } + } +#if INCLUDE_TBI_SUPPORT + if (pDevice->IgnoreTbiLinkChange == TRUE) { + ServicePhyInt = FALSE; + } +#endif + if (ServicePhyInt == TRUE) { + LM_SetupPhy (pDevice); + } + + /* Service receive and transmit interrupts. */ + LM_ServiceRxInterrupt (pDevice); + LM_ServiceTxInterrupt (pDevice); + + /* No spinlock for this queue since this routine is serialized. */ + if (!QQ_Empty (&pDevice->RxPacketReceivedQ.Container)) { + /* Indicate receive packets. */ + MM_IndicateRxPackets (pDevice); + /* LM_QueueRxPackets(pDevice); */ + } + + /* No spinlock for this queue since this routine is serialized. */ + if (!QQ_Empty (&pDevice->TxPacketXmittedQ.Container)) { + MM_IndicateTxPackets (pDevice); + } + + return LM_STATUS_SUCCESS; +} /* LM_ServiceInterrupts */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) +{ + PLM_UINT8 pEntry; + LM_UINT32 j; + + pEntry = pDevice->McTable[0]; + for (j = 0; j < pDevice->McEntryCount; j++) { + if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { + /* Found a match, increment the instance count. */ + pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1; + + return LM_STATUS_SUCCESS; + } + + pEntry += LM_MC_ENTRY_SIZE; + } + + if (pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) { + return LM_STATUS_FAILURE; + } + + pEntry = pDevice->McTable[pDevice->McEntryCount]; + + COPY_ETH_ADDRESS (pMcAddress, pEntry); + pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1; + + pDevice->McEntryCount++; + + LM_SetReceiveMask (pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST); + + return LM_STATUS_SUCCESS; +} /* LM_MulticastAdd */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_MulticastDel (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) +{ + PLM_UINT8 pEntry; + LM_UINT32 j; + + pEntry = pDevice->McTable[0]; + for (j = 0; j < pDevice->McEntryCount; j++) { + if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { + /* Found a match, decrement the instance count. */ + pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1; + + /* No more instance left, remove the address from the table. */ + /* Move the last entry in the table to the delete slot. */ + if (pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 && + pDevice->McEntryCount > 1) { + + COPY_ETH_ADDRESS (pDevice-> + McTable[pDevice-> + McEntryCount - 1], + pEntry); + pEntry[LM_MC_INSTANCE_COUNT_INDEX] = + pDevice->McTable[pDevice->McEntryCount - 1] + [LM_MC_INSTANCE_COUNT_INDEX]; + } + pDevice->McEntryCount--; + + /* Update the receive mask if the table is empty. */ + if (pDevice->McEntryCount == 0) { + LM_SetReceiveMask (pDevice, + pDevice-> + ReceiveMask & + ~LM_ACCEPT_MULTICAST); + } + + return LM_STATUS_SUCCESS; + } + + pEntry += LM_MC_ENTRY_SIZE; + } + + return LM_STATUS_FAILURE; +} /* LM_MulticastDel */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice) +{ + pDevice->McEntryCount = 0; + + LM_SetReceiveMask (pDevice, + pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); + + return LM_STATUS_SUCCESS; +} /* LM_MulticastClear */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_SetMacAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress) +{ + LM_UINT32 j; + + for (j = 0; j < 4; j++) { + REG_WR (pDevice, MacCtrl.MacAddr[j].High, + (pMacAddress[0] << 8) | pMacAddress[1]); + REG_WR (pDevice, MacCtrl.MacAddr[j].Low, + (pMacAddress[2] << 24) | (pMacAddress[3] << 16) | + (pMacAddress[4] << 8) | pMacAddress[5]); + } + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* Sets up the default line speed, and duplex modes based on the requested */ +/* media type. */ +/* */ +/* Return: */ +/* None. */ +/******************************************************************************/ +static LM_STATUS +LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE RequestedMediaType, + PLM_MEDIA_TYPE pMediaType, + PLM_LINE_SPEED pLineSpeed, + PLM_DUPLEX_MODE pDuplexMode) +{ + *pMediaType = LM_MEDIA_TYPE_AUTO; + *pLineSpeed = LM_LINE_SPEED_UNKNOWN; + *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN; + + /* determine media type */ + switch (RequestedMediaType) { + case LM_REQUESTED_MEDIA_TYPE_BNC: + *pMediaType = LM_MEDIA_TYPE_BNC; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO: + *pMediaType = LM_MEDIA_TYPE_UTP; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + default: + break; + } /* switch */ + + return LM_STATUS_SUCCESS; +} /* LM_TranslateRequestedMediaType */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* LM_STATUS_LINK_ACTIVE */ +/* LM_STATUS_LINK_DOWN */ +/******************************************************************************/ +static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice) +{ + LM_LINE_SPEED CurrentLineSpeed; + LM_DUPLEX_MODE CurrentDuplexMode; + LM_STATUS CurrentLinkStatus; + LM_UINT32 Value32; + LM_UINT32 j; + +#if 1 /* jmb: bugfix -- moved here, out of code that sets initial pwr state */ + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x2); +#endif + if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + + if (!pDevice->InitDone) { + Value32 = 0; + } + + if (!(Value32 & PHY_STATUS_LINK_PASS)) { + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); + + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); + + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); + + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); + + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); + + LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); + LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); + + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + for (j = 0; j < 1000; j++) { + MM_Wait (10); + + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + if (Value32 & PHY_STATUS_LINK_PASS) { + MM_Wait (40); + break; + } + } + + if ((pDevice->PhyId & PHY_ID_REV_MASK) == + PHY_BCM5401_B0_REV) { + if (!(Value32 & PHY_STATUS_LINK_PASS) + && (pDevice->OldLineSpeed == + LM_LINE_SPEED_1000MBPS)) { + LM_WritePhy (pDevice, PHY_CTRL_REG, + PHY_CTRL_PHY_RESET); + for (j = 0; j < 100; j++) { + MM_Wait (10); + + LM_ReadPhy (pDevice, + PHY_CTRL_REG, + &Value32); + if (! + (Value32 & + PHY_CTRL_PHY_RESET)) { + MM_Wait (40); + break; + } + } + + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, + 0x0c20); + + LM_WritePhy (pDevice, + BCM540X_DSP_ADDRESS_REG, + 0x0012); + LM_WritePhy (pDevice, + BCM540X_DSP_RW_PORT, + 0x1804); + + LM_WritePhy (pDevice, + BCM540X_DSP_ADDRESS_REG, + 0x0013); + LM_WritePhy (pDevice, + BCM540X_DSP_RW_PORT, + 0x1204); + + LM_WritePhy (pDevice, + BCM540X_DSP_ADDRESS_REG, + 0x8006); + LM_WritePhy (pDevice, + BCM540X_DSP_RW_PORT, + 0x0132); + + LM_WritePhy (pDevice, + BCM540X_DSP_ADDRESS_REG, + 0x8006); + LM_WritePhy (pDevice, + BCM540X_DSP_RW_PORT, + 0x0232); + + LM_WritePhy (pDevice, + BCM540X_DSP_ADDRESS_REG, + 0x201f); + LM_WritePhy (pDevice, + BCM540X_DSP_RW_PORT, + 0x0a20); + } + } + } + } else if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { + /* Bug: 5701 A0, B0 TX CRC workaround. */ + LM_WritePhy (pDevice, 0x15, 0x0a75); + LM_WritePhy (pDevice, 0x1c, 0x8c68); + LM_WritePhy (pDevice, 0x1c, 0x8d68); + LM_WritePhy (pDevice, 0x1c, 0x8c68); + } + + /* Acknowledge interrupts. */ + LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); + + /* Configure the interrupt mask. */ + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { + LM_WritePhy (pDevice, BCM540X_INT_MASK_REG, + ~BCM540X_INT_LINK_CHANGE); + } + + /* Configure PHY led mode. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701 || + (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700)) { + if (pDevice->LedMode == LED_MODE_THREE_LINK) { + LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, + BCM540X_EXT_CTRL_LINK3_LED_MODE); + } else { + LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, 0); + } + } + + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Get current link and duplex mode. */ + for (j = 0; j < 100; j++) { + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + + if (Value32 & PHY_STATUS_LINK_PASS) { + break; + } + MM_Wait (40); + } + + if (Value32 & PHY_STATUS_LINK_PASS) { + + /* Determine the current line and duplex settings. */ + LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); + for (j = 0; j < 2000; j++) { + MM_Wait (10); + + LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); + if (Value32) { + break; + } + } + + switch (Value32 & BCM540X_AUX_SPEED_MASK) { + case BCM540X_AUX_10BASET_HD: + CurrentLineSpeed = LM_LINE_SPEED_10MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_10BASET_FD: + CurrentLineSpeed = LM_LINE_SPEED_10MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case BCM540X_AUX_100BASETX_HD: + CurrentLineSpeed = LM_LINE_SPEED_100MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_100BASETX_FD: + CurrentLineSpeed = LM_LINE_SPEED_100MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case BCM540X_AUX_100BASET_HD: + CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_100BASET_FD: + CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + default: + + CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN; + CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN; + break; + } + + /* Make sure we are in auto-neg mode. */ + for (j = 0; j < 200; j++) { + LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); + if (Value32 && Value32 != 0x7fff) { + break; + } + + if (Value32 == 0 && pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS) { + break; + } + + MM_Wait (10); + } + + /* Use the current line settings for "auto" mode. */ + if (pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO + || pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { + if (Value32 & PHY_CTRL_AUTO_NEG_ENABLE) { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + + /* We may be exiting low power mode and the link is in */ + /* 10mb. In this case, we need to restart autoneg. */ + LM_ReadPhy (pDevice, BCM540X_1000BASET_CTRL_REG, + &Value32); + pDevice->advertising1000 = Value32; + /* 5702FE supports 10/100Mb only. */ + if (T3_ASIC_REV (pDevice->ChipRevId) != + T3_ASIC_REV_5703 + || pDevice->BondId != + GRC_MISC_BD_ID_5702FE) { + if (! + (Value32 & + (BCM540X_AN_AD_1000BASET_HALF | + BCM540X_AN_AD_1000BASET_FULL))) { + CurrentLinkStatus = + LM_STATUS_LINK_SETTING_MISMATCH; + } + } + } else { + CurrentLinkStatus = + LM_STATUS_LINK_SETTING_MISMATCH; + } + } else { + /* Force line settings. */ + /* Use the current setting if it matches the user's requested */ + /* setting. */ + LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); + if ((pDevice->LineSpeed == CurrentLineSpeed) && + (pDevice->DuplexMode == CurrentDuplexMode)) { + if ((pDevice->DisableAutoNeg && + !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) || + (!pDevice->DisableAutoNeg && + (Value32 & PHY_CTRL_AUTO_NEG_ENABLE))) { + CurrentLinkStatus = + LM_STATUS_LINK_ACTIVE; + } else { + CurrentLinkStatus = + LM_STATUS_LINK_SETTING_MISMATCH; + } + } else { + CurrentLinkStatus = + LM_STATUS_LINK_SETTING_MISMATCH; + } + } + + /* Save line settings. */ + pDevice->LineSpeed = CurrentLineSpeed; + pDevice->DuplexMode = CurrentDuplexMode; + pDevice->MediaType = LM_MEDIA_TYPE_UTP; + } + + return CurrentLinkStatus; +} /* LM_InitBcm540xPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, + LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd) +{ + LM_FLOW_CONTROL FlowCap; + + /* Resolve flow control. */ + FlowCap = LM_FLOW_CONTROL_NONE; + + /* See Table 28B-3 of 802.3ab-1999 spec. */ + if (pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE) { + if (LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE) { + if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { + if (RemotePhyAd & + PHY_LINK_PARTNER_PAUSE_CAPABLE) { + FlowCap = + LM_FLOW_CONTROL_TRANSMIT_PAUSE | + LM_FLOW_CONTROL_RECEIVE_PAUSE; + } else if (RemotePhyAd & + PHY_LINK_PARTNER_ASYM_PAUSE) { + FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + } else { + if (RemotePhyAd & + PHY_LINK_PARTNER_PAUSE_CAPABLE) { + FlowCap = + LM_FLOW_CONTROL_TRANSMIT_PAUSE | + LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + } + } else if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { + if ((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) && + (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)) { + FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE; + } + } + } else { + FlowCap = pDevice->FlowControlCap; + } + + /* Enable/disable rx PAUSE. */ + pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL; + if (FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE && + (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || + pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)) { + pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; + pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL; + + } + REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); + + /* Enable/disable tx PAUSE. */ + pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL; + if (FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE && + (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || + pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) { + pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; + pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL; + + } + REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); + + return LM_STATUS_SUCCESS; +} + +#if INCLUDE_TBI_SUPPORT +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + Value32 = REG_RD (pDevice, MacCtrl.Status); + + /* Reset the SERDES during init and when we have link. */ + if (!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED) { + /* Set PLL lock range. */ + LM_WritePhy (pDevice, 0x16, 0x8007); + + /* Software reset. */ + LM_WritePhy (pDevice, 0x00, 0x8000); + + /* Wait for reset to complete. */ + for (j = 0; j < 500; j++) { + MM_Wait (10); + } + + /* Config mode; seletct PMA/Ch 1 regs. */ + LM_WritePhy (pDevice, 0x10, 0x8411); + + /* Enable auto-lock and comdet, select txclk for tx. */ + LM_WritePhy (pDevice, 0x11, 0x0a10); + + LM_WritePhy (pDevice, 0x18, 0x00a0); + LM_WritePhy (pDevice, 0x16, 0x41ff); + + /* Assert and deassert POR. */ + LM_WritePhy (pDevice, 0x13, 0x0400); + MM_Wait (40); + LM_WritePhy (pDevice, 0x13, 0x0000); + + LM_WritePhy (pDevice, 0x11, 0x0a50); + MM_Wait (40); + LM_WritePhy (pDevice, 0x11, 0x0a10); + + /* Delay for signal to stabilize. */ + for (j = 0; j < 15000; j++) { + MM_Wait (10); + } + + /* Deselect the channel register so we can read the PHY id later. */ + LM_WritePhy (pDevice, 0x10, 0x8011); + } + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS CurrentLinkStatus; + AUTONEG_STATUS AnStatus = 0; + LM_UINT32 Value32; + LM_UINT32 Cnt; + LM_UINT32 j, k; + + pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK); + + /* Initialize the send_config register. */ + REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); + + /* Enable TBI and full duplex mode. */ + pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI; + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + + /* Initialize the BCM8002 SERDES PHY. */ + switch (pDevice->PhyId & PHY_ID_MASK) { + case PHY_BCM8002_PHY_ID: + LM_InitBcm800xPhy (pDevice); + break; + + default: + break; + } + + /* Enable link change interrupt. */ + REG_WR (pDevice, MacCtrl.MacEvent, + MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); + + /* Default to link down. */ + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Get the link status. */ + Value32 = REG_RD (pDevice, MacCtrl.Status); + if (Value32 & MAC_STATUS_PCS_SYNCED) { + if ((pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_AUTO) + || (pDevice->DisableAutoNeg == FALSE)) { + /* auto-negotiation mode. */ + /* Initialize the autoneg default capaiblities. */ + AutonegInit (&pDevice->AnInfo); + + /* Set the context pointer to point to the main device structure. */ + pDevice->AnInfo.pContext = pDevice; + + /* Setup flow control advertisement register. */ + Value32 = GetPhyAdFlowCntrlSettings (pDevice); + if (Value32 & PHY_AN_AD_PAUSE_CAPABLE) { + pDevice->AnInfo.mr_adv_sym_pause = 1; + } else { + pDevice->AnInfo.mr_adv_sym_pause = 0; + } + + if (Value32 & PHY_AN_AD_ASYM_PAUSE) { + pDevice->AnInfo.mr_adv_asym_pause = 1; + } else { + pDevice->AnInfo.mr_adv_asym_pause = 0; + } + + /* Try to autoneg up to six times. */ + if (pDevice->IgnoreTbiLinkChange) { + Cnt = 1; + } else { + Cnt = 6; + } + for (j = 0; j < Cnt; j++) { + REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); + + Value32 = + pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK; + REG_WR (pDevice, MacCtrl.Mode, Value32); + MM_Wait (20); + + REG_WR (pDevice, MacCtrl.Mode, + pDevice-> + MacMode | MAC_MODE_SEND_CONFIGS); + + MM_Wait (20); + + pDevice->AnInfo.State = AN_STATE_UNKNOWN; + pDevice->AnInfo.CurrentTime_us = 0; + + REG_WR (pDevice, Grc.Timer, 0); + for (k = 0; + (pDevice->AnInfo.CurrentTime_us < 75000) + && (k < 75000); k++) { + AnStatus = + Autoneg8023z (&pDevice->AnInfo); + + if ((AnStatus == AUTONEG_STATUS_DONE) || + (AnStatus == AUTONEG_STATUS_FAILED)) + { + break; + } + + pDevice->AnInfo.CurrentTime_us = + REG_RD (pDevice, Grc.Timer); + + } + if ((AnStatus == AUTONEG_STATUS_DONE) || + (AnStatus == AUTONEG_STATUS_FAILED)) { + break; + } + if (j >= 1) { + if (!(REG_RD (pDevice, MacCtrl.Status) & + MAC_STATUS_PCS_SYNCED)) { + break; + } + } + } + + /* Stop sending configs. */ + MM_AnTxIdle (&pDevice->AnInfo); + + /* Resolve flow control settings. */ + if ((AnStatus == AUTONEG_STATUS_DONE) && + pDevice->AnInfo.mr_an_complete + && pDevice->AnInfo.mr_link_ok + && pDevice->AnInfo.mr_lp_adv_full_duplex) { + LM_UINT32 RemotePhyAd; + LM_UINT32 LocalPhyAd; + + LocalPhyAd = 0; + if (pDevice->AnInfo.mr_adv_sym_pause) { + LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE; + } + + if (pDevice->AnInfo.mr_adv_asym_pause) { + LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE; + } + + RemotePhyAd = 0; + if (pDevice->AnInfo.mr_lp_adv_sym_pause) { + RemotePhyAd |= + PHY_LINK_PARTNER_PAUSE_CAPABLE; + } + + if (pDevice->AnInfo.mr_lp_adv_asym_pause) { + RemotePhyAd |= + PHY_LINK_PARTNER_ASYM_PAUSE; + } + + LM_SetFlowControl (pDevice, LocalPhyAd, + RemotePhyAd); + + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + for (j = 0; j < 30; j++) { + MM_Wait (20); + REG_WR (pDevice, MacCtrl.Status, + MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MM_Wait (20); + if ((REG_RD (pDevice, MacCtrl.Status) & + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + if (pDevice->PollTbiLink) { + Value32 = REG_RD (pDevice, MacCtrl.Status); + if (Value32 & MAC_STATUS_RECEIVING_CFG) { + pDevice->IgnoreTbiLinkChange = TRUE; + } else { + pDevice->IgnoreTbiLinkChange = FALSE; + } + } + Value32 = REG_RD (pDevice, MacCtrl.Status); + if (CurrentLinkStatus == LM_STATUS_LINK_DOWN && + (Value32 & MAC_STATUS_PCS_SYNCED) && + ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0)) { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + } else { + /* We are forcing line speed. */ + pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE; + LM_SetFlowControl (pDevice, 0, 0); + + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_SEND_CONFIGS); + } + } + /* Set the link polarity bit. */ + pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + + pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED | + (pDevice->pStatusBlkVirt-> + Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS); + + for (j = 0; j < 100; j++) { + REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MM_Wait (5); + if ((REG_RD (pDevice, MacCtrl.Status) & + (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + + Value32 = REG_RD (pDevice, MacCtrl.Status); + if ((Value32 & MAC_STATUS_PCS_SYNCED) == 0) { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + if (pDevice->DisableAutoNeg == FALSE) { + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_SEND_CONFIGS); + MM_Wait (1); + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + } + } + + /* Initialize the current link status. */ + if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { + pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS; + pDevice->DuplexMode = LM_DUPLEX_MODE_FULL; + REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_1000MBPS_LED_ON); + } else { + pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN; + pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN; + REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_OVERRIDE_TRAFFIC_LED); + } + + /* Indicate link status. */ + if (pDevice->LinkStatus != CurrentLinkStatus) { + pDevice->LinkStatus = CurrentLinkStatus; + MM_IndicateStatus (pDevice, CurrentLinkStatus); + } + + return LM_STATUS_SUCCESS; +} +#endif /* INCLUDE_TBI_SUPPORT */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS CurrentLinkStatus; + LM_UINT32 Value32; + + /* Assume there is not link first. */ + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Disable phy link change attention. */ + REG_WR (pDevice, MacCtrl.MacEvent, 0); + + /* Clear link change attention. */ + REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + + /* Disable auto-polling for the moment. */ + pDevice->MiMode = 0xc0000; + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait (40); + + /* Determine the requested line speed and duplex. */ + pDevice->OldLineSpeed = pDevice->LineSpeed; + LM_TranslateRequestedMediaType (pDevice->RequestedMediaType, + &pDevice->MediaType, + &pDevice->LineSpeed, + &pDevice->DuplexMode); + + /* Initialize the phy chip. */ + switch (pDevice->PhyId & PHY_ID_MASK) { + case PHY_BCM5400_PHY_ID: + case PHY_BCM5401_PHY_ID: + case PHY_BCM5411_PHY_ID: + case PHY_BCM5701_PHY_ID: + case PHY_BCM5703_PHY_ID: + case PHY_BCM5704_PHY_ID: + CurrentLinkStatus = LM_InitBcm540xPhy (pDevice); + break; + + default: + break; + } + + if (CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH) { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + } + + /* Setup flow control. */ + pDevice->FlowControl = LM_FLOW_CONTROL_NONE; + if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { + LM_FLOW_CONTROL FlowCap; /* Flow control capability. */ + + FlowCap = LM_FLOW_CONTROL_NONE; + + if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) { + if (pDevice->DisableAutoNeg == FALSE || + pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_AUTO + || pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { + LM_UINT32 ExpectedPhyAd; + LM_UINT32 LocalPhyAd; + LM_UINT32 RemotePhyAd; + + LM_ReadPhy (pDevice, PHY_AN_AD_REG, + &LocalPhyAd); + pDevice->advertising = LocalPhyAd; + LocalPhyAd &= + (PHY_AN_AD_ASYM_PAUSE | + PHY_AN_AD_PAUSE_CAPABLE); + + ExpectedPhyAd = + GetPhyAdFlowCntrlSettings (pDevice); + + if (LocalPhyAd != ExpectedPhyAd) { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + } else { + LM_ReadPhy (pDevice, + PHY_LINK_PARTNER_ABILITY_REG, + &RemotePhyAd); + + LM_SetFlowControl (pDevice, LocalPhyAd, + RemotePhyAd); + } + } else { + pDevice->FlowControlCap &= + ~LM_FLOW_CONTROL_AUTO_PAUSE; + LM_SetFlowControl (pDevice, 0, 0); + } + } + } + + if (CurrentLinkStatus == LM_STATUS_LINK_DOWN) { + LM_ForceAutoNeg (pDevice, pDevice->RequestedMediaType); + + /* If we force line speed, we make get link right away. */ + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + if (Value32 & PHY_STATUS_LINK_PASS) { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + } + + /* GMII interface. */ + pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK; + if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { + if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS || + pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { + pDevice->MacMode |= MAC_MODE_PORT_MODE_MII; + } else { + pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; + } + } else { + pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; + } + + /* Set the MAC to operate in the appropriate duplex mode. */ + pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX; + if (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF) { + pDevice->MacMode |= MAC_MODE_HALF_DUPLEX; + } + + /* Set the link polarity bit. */ + pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + if ((pDevice->LedMode == LED_MODE_LINK10) || + (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE && + pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)) { + pDevice->MacMode |= MAC_MODE_LINK_POLARITY; + } + } else { + if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { + pDevice->MacMode |= MAC_MODE_LINK_POLARITY; + } + + /* Set LED mode. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = LED_CTRL_PHY_MODE_1; + } else { + if (pDevice->LedMode == LED_MODE_OUTPUT) { + Value32 = LED_CTRL_PHY_MODE_2; + } else { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + REG_WR (pDevice, MacCtrl.LedCtrl, Value32); + } + + REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); + + /* Enable auto polling. */ + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE; + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + } + + /* Enable phy link change attention. */ + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { + REG_WR (pDevice, MacCtrl.MacEvent, + MAC_EVENT_ENABLE_MI_INTERRUPT); + } else { + REG_WR (pDevice, MacCtrl.MacEvent, + MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); + } + if ((T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) && + (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) && + (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && + (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) && + (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) || + !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))) { + MM_Wait (120); + REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MEM_WR_OFFSET (pDevice, T3_FIRMWARE_MAILBOX, + T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE); + } + + /* Indicate link status. */ + if (pDevice->LinkStatus != CurrentLinkStatus) { + pDevice->LinkStatus = CurrentLinkStatus; + MM_IndicateStatus (pDevice, CurrentLinkStatus); + } + + return LM_STATUS_SUCCESS; +} /* LM_SetupCopperPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS LmStatus; + LM_UINT32 Value32; + +#if INCLUDE_TBI_SUPPORT + if (pDevice->EnableTbi) { + LmStatus = LM_SetupFiberPhy (pDevice); + } else +#endif /* INCLUDE_TBI_SUPPORT */ + { + LmStatus = LM_SetupCopperPhy (pDevice); + } + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { + Value32 = REG_RD (pDevice, PciCfg.PciState); + REG_WR (pDevice, PciCfg.PciState, + Value32 | T3_PCI_STATE_RETRY_SAME_DMA); + } + } + if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && + (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)) { + REG_WR (pDevice, MacCtrl.TxLengths, 0x26ff); + } else { + REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); + } + + return LmStatus; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_ReadPhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, PLM_UINT32 pData32) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & + ~MI_MODE_AUTO_POLLING_ENABLE); + MM_Wait (40); + } + + Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | + ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << + MI_COM_FIRST_PHY_REG_ADDR_BIT) | MI_COM_CMD_READ | MI_COM_START; + + REG_WR (pDevice, MacCtrl.MiCom, Value32); + + for (j = 0; j < 20; j++) { + MM_Wait (25); + + Value32 = REG_RD (pDevice, MacCtrl.MiCom); + + if (!(Value32 & MI_COM_BUSY)) { + MM_Wait (5); + Value32 = REG_RD (pDevice, MacCtrl.MiCom); + Value32 &= MI_COM_PHY_DATA_MASK; + break; + } + } + + if (Value32 & MI_COM_BUSY) { + Value32 = 0; + } + + *pData32 = Value32; + + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait (40); + } +} /* LM_ReadPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_WritePhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, LM_UINT32 Data32) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & + ~MI_MODE_AUTO_POLLING_ENABLE); + MM_Wait (40); + } + + Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | + ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << + MI_COM_FIRST_PHY_REG_ADDR_BIT) | (Data32 & MI_COM_PHY_DATA_MASK) | + MI_COM_CMD_WRITE | MI_COM_START; + + REG_WR (pDevice, MacCtrl.MiCom, Value32); + + for (j = 0; j < 20; j++) { + MM_Wait (25); + + Value32 = REG_RD (pDevice, MacCtrl.MiCom); + + if (!(Value32 & MI_COM_BUSY)) { + MM_Wait (5); + break; + } + } + + if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { + REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait (40); + } +} /* LM_WritePhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_SetPowerState (PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel) +{ + LM_UINT32 PmeSupport; + LM_UINT32 Value32; + LM_UINT32 PmCtrl; + + /* make sureindirect accesses are enabled */ + MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, + pDevice->MiscHostCtrl); + + /* Clear the PME_ASSERT bit and the power state bits. Also enable */ + /* the PME bit. */ + MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl); + + PmCtrl |= T3_PM_PME_ASSERTED; + PmCtrl &= ~T3_PM_POWER_STATE_MASK; + + /* Set the appropriate power state. */ + if (PowerLevel == LM_POWER_STATE_D0) { + + /* Bring the card out of low power mode. */ + PmCtrl |= T3_PM_POWER_STATE_D0; + MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); + + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); + MM_Wait (40); +#if 0 /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */ + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x02); +#endif + + return LM_STATUS_SUCCESS; + } else if (PowerLevel == LM_POWER_STATE_D1) { + PmCtrl |= T3_PM_POWER_STATE_D1; + } else if (PowerLevel == LM_POWER_STATE_D2) { + PmCtrl |= T3_PM_POWER_STATE_D2; + } else if (PowerLevel == LM_POWER_STATE_D3) { + PmCtrl |= T3_PM_POWER_STATE_D3; + } else { + return LM_STATUS_FAILURE; + } + PmCtrl |= T3_PM_PME_ENABLE; + + /* Mask out all interrupts so LM_SetupPhy won't be called while we are */ + /* setting new line speed. */ + Value32 = REG_RD (pDevice, PciCfg.MiscHostCtrl); + REG_WR (pDevice, PciCfg.MiscHostCtrl, + Value32 | MISC_HOST_CTRL_MASK_PCI_INT); + + if (!pDevice->RestoreOnWakeUp) { + pDevice->RestoreOnWakeUp = TRUE; + pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg; + pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType; + } + + /* Force auto-negotiation to 10 line speed. */ + pDevice->DisableAutoNeg = FALSE; + pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; + LM_SetupPhy (pDevice); + + /* Put the driver in the initial state, and go through the power down */ + /* sequence. */ + LM_Halt (pDevice); + + MM_ReadConfig32 (pDevice, T3_PCI_PM_CAP_REG, &PmeSupport); + + if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) { + + /* Enable WOL. */ + LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x5a); + MM_Wait (40); + + /* Set LED mode. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = LED_CTRL_PHY_MODE_1; + } else { + if (pDevice->LedMode == LED_MODE_OUTPUT) { + Value32 = LED_CTRL_PHY_MODE_2; + } else { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + + Value32 = MAC_MODE_PORT_MODE_MII; + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { + if (pDevice->LedMode == LED_MODE_LINK10 || + pDevice->WolSpeed == WOL_SPEED_10MB) { + Value32 |= MAC_MODE_LINK_POLARITY; + } + } else { + Value32 |= MAC_MODE_LINK_POLARITY; + } + REG_WR (pDevice, MacCtrl.Mode, Value32); + MM_Wait (40); + MM_Wait (40); + MM_Wait (40); + + /* Always enable magic packet wake-up if we have vaux. */ + if ((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && + (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET)) { + Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE; + } + + REG_WR (pDevice, MacCtrl.Mode, Value32); + + /* Enable the receiver. */ + REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_ENABLE); + } + + /* Disable tx/rx clocks, and seletect an alternate clock. */ + if (pDevice->WolSpeed == WOL_SPEED_100MB) { + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = + T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK; + } else { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK; + } + REG_WR (pDevice, PciCfg.ClockCtrl, Value32); + + MM_Wait (40); + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = + T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_44MHZ_CORE_CLOCK; + } else { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_44MHZ_CORE_CLOCK; + } + + REG_WR (pDevice, PciCfg.ClockCtrl, Value32); + + MM_Wait (40); + + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = + T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_44MHZ_CORE_CLOCK; + } else { + Value32 = T3_PCI_44MHZ_CORE_CLOCK; + } + + REG_WR (pDevice, PciCfg.ClockCtrl, Value32); + } else { + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + Value32 = + T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_POWER_DOWN_PCI_PLL133; + } else { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_POWER_DOWN_PCI_PLL133; + } + + REG_WR (pDevice, PciCfg.ClockCtrl, Value32); + } + + MM_Wait (40); + + if (!pDevice->EepromWp + && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)) { + /* Switch adapter to auxilliary power. */ + if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); + MM_Wait (40); + } else { + /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */ + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); + MM_Wait (40); + + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */ + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); + MM_Wait (40); + + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ + REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); + MM_Wait (40); + } + } + + /* Set the phy to low power mode. */ + /* Put the the hardware in low power mode. */ + MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); + + return LM_STATUS_SUCCESS; +} /* LM_SetPowerState */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + + Value32 = 0; + + /* Auto negotiation flow control only when autonegotiation is enabled. */ + if (pDevice->DisableAutoNeg == FALSE || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { + /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */ + if ((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) || + ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) + && (pDevice-> + FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) { + Value32 |= PHY_AN_AD_PAUSE_CAPABLE; + } else if (pDevice-> + FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE) { + Value32 |= PHY_AN_AD_ASYM_PAUSE; + } else if (pDevice-> + FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) { + Value32 |= + PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; + } + } + + return Value32; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* LM_STATUS_FAILURE */ +/* LM_STATUS_SUCCESS */ +/* */ +/******************************************************************************/ +static LM_STATUS +LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType) +{ + LM_MEDIA_TYPE MediaType; + LM_LINE_SPEED LineSpeed; + LM_DUPLEX_MODE DuplexMode; + LM_UINT32 NewPhyCtrl; + LM_UINT32 Value32; + LM_UINT32 Cnt; + + /* Get the interface type, line speed, and duplex mode. */ + LM_TranslateRequestedMediaType (RequestedMediaType, &MediaType, + &LineSpeed, &DuplexMode); + + if (pDevice->RestoreOnWakeUp) { + LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF; + if (pDevice->WolSpeed == WOL_SPEED_100MB) { + Value32 |= + PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; + } + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } + /* Setup the auto-negotiation advertisement register. */ + else if (LineSpeed == LM_LINE_SPEED_UNKNOWN) { + /* Setup the 10/100 Mbps auto-negotiation advertisement register. */ + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | + PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL | + PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + /* Advertise 1000Mbps */ + Value32 = + BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL; + +#if INCLUDE_5701_AX_FIX + /* Bug: workaround for CRC error in gigabit mode when we are in */ + /* slave mode. This will force the PHY to operate in */ + /* master mode. */ + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { + Value32 |= BCM540X_CONFIG_AS_MASTER | + BCM540X_ENABLE_CONFIG_AS_MASTER; + } +#endif + + LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, Value32); + pDevice->advertising1000 = Value32; + } else { + if (LineSpeed == LM_LINE_SPEED_1000MBPS) { + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + if (DuplexMode != LM_DUPLEX_MODE_FULL) { + Value32 = BCM540X_AN_AD_1000BASET_HALF; + } else { + Value32 = BCM540X_AN_AD_1000BASET_FULL; + } + + LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, + Value32); + pDevice->advertising1000 = Value32; + } else if (LineSpeed == LM_LINE_SPEED_100MBPS) { + LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + + if (DuplexMode != LM_DUPLEX_MODE_FULL) { + Value32 = PHY_AN_AD_100BASETX_HALF; + } else { + Value32 = PHY_AN_AD_100BASETX_FULL; + } + + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } else if (LineSpeed == LM_LINE_SPEED_10MBPS) { + LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + + if (DuplexMode != LM_DUPLEX_MODE_FULL) { + Value32 = PHY_AN_AD_10BASET_HALF; + } else { + Value32 = PHY_AN_AD_10BASET_FULL; + } + + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings (pDevice); + + LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } + } + + /* Force line speed if auto-negotiation is disabled. */ + if (pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN) { + /* This code path is executed only when there is link. */ + pDevice->MediaType = MediaType; + pDevice->LineSpeed = LineSpeed; + pDevice->DuplexMode = DuplexMode; + + /* Force line seepd. */ + NewPhyCtrl = 0; + switch (LineSpeed) { + case LM_LINE_SPEED_10MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS; + break; + case LM_LINE_SPEED_100MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS; + break; + case LM_LINE_SPEED_1000MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; + break; + default: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; + break; + } + + if (DuplexMode == LM_DUPLEX_MODE_FULL) { + NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE; + } + + /* Don't do anything if the PHY_CTRL is already what we wanted. */ + LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); + if (Value32 != NewPhyCtrl) { + /* Temporary bring the link down before forcing line speed. */ + LM_WritePhy (pDevice, PHY_CTRL_REG, + PHY_CTRL_LOOPBACK_MODE); + + /* Wait for link to go down. */ + for (Cnt = 0; Cnt < 15000; Cnt++) { + MM_Wait (10); + + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); + + if (!(Value32 & PHY_STATUS_LINK_PASS)) { + MM_Wait (40); + break; + } + } + + LM_WritePhy (pDevice, PHY_CTRL_REG, NewPhyCtrl); + MM_Wait (40); + } + } else { + LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE | + PHY_CTRL_RESTART_AUTO_NEG); + } + + return LM_STATUS_SUCCESS; +} /* LM_ForceAutoNegBcm540xPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +static LM_STATUS +LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType) +{ + LM_STATUS LmStatus; + + /* Initialize the phy chip. */ + switch (pDevice->PhyId & PHY_ID_MASK) { + case PHY_BCM5400_PHY_ID: + case PHY_BCM5401_PHY_ID: + case PHY_BCM5411_PHY_ID: + case PHY_BCM5701_PHY_ID: + case PHY_BCM5703_PHY_ID: + case PHY_BCM5704_PHY_ID: + LmStatus = + LM_ForceAutoNegBcm540xPhy (pDevice, RequestedMediaType); + break; + + default: + LmStatus = LM_STATUS_FAILURE; + break; + } + + return LmStatus; +} /* LM_ForceAutoNeg */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_LoadFirmware (PLM_DEVICE_BLOCK pDevice, + PT3_FWIMG_INFO pFwImg, + LM_UINT32 LoadCpu, LM_UINT32 StartCpu) +{ + LM_UINT32 i; + LM_UINT32 address; + + if (LoadCpu & T3_RX_CPU_ID) { + if (LM_HaltCpu (pDevice, T3_RX_CPU_ID) != LM_STATUS_SUCCESS) { + return LM_STATUS_FAILURE; + } + + /* First of all clear scrach pad memory */ + for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i += 4) { + LM_RegWrInd (pDevice, T3_RX_CPU_SPAD_ADDR + i, 0); + } + + /* Copy code first */ + address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); + for (i = 0; i <= pFwImg->Text.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->Text.Buffer)[i / + 4]); + } + + address = + T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); + for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->ROnlyData. + Buffer)[i / 4]); + } + + address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); + for (i = 0; i <= pFwImg->Data.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->Data.Buffer)[i / + 4]); + } + } + + if (LoadCpu & T3_TX_CPU_ID) { + if (LM_HaltCpu (pDevice, T3_TX_CPU_ID) != LM_STATUS_SUCCESS) { + return LM_STATUS_FAILURE; + } + + /* First of all clear scrach pad memory */ + for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i += 4) { + LM_RegWrInd (pDevice, T3_TX_CPU_SPAD_ADDR + i, 0); + } + + /* Copy code first */ + address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); + for (i = 0; i <= pFwImg->Text.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->Text.Buffer)[i / + 4]); + } + + address = + T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); + for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->ROnlyData. + Buffer)[i / 4]); + } + + address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); + for (i = 0; i <= pFwImg->Data.Length; i += 4) { + LM_RegWrInd (pDevice, address + i, + ((LM_UINT32 *) pFwImg->Data.Buffer)[i / + 4]); + } + } + + if (StartCpu & T3_RX_CPU_ID) { + /* Start Rx CPU */ + REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); + REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); + for (i = 0; i < 5; i++) { + if (pFwImg->StartAddress == + REG_RD (pDevice, rxCpu.reg.PC)) + break; + + REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); + REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); + REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); + MM_Wait (1000); + } + + REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); + REG_WR (pDevice, rxCpu.reg.mode, 0); + } + + if (StartCpu & T3_TX_CPU_ID) { + /* Start Tx CPU */ + REG_WR (pDevice, txCpu.reg.state, 0xffffffff); + REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); + for (i = 0; i < 5; i++) { + if (pFwImg->StartAddress == + REG_RD (pDevice, txCpu.reg.PC)) + break; + + REG_WR (pDevice, txCpu.reg.state, 0xffffffff); + REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); + REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); + MM_Wait (1000); + } + + REG_WR (pDevice, txCpu.reg.state, 0xffffffff); + REG_WR (pDevice, txCpu.reg.mode, 0); + } + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number) +{ + LM_UINT32 i; + + if (cpu_number == T3_RX_CPU_ID) { + for (i = 0; i < 10000; i++) { + REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); + REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); + + if (REG_RD (pDevice, rxCpu.reg.mode) & CPU_MODE_HALT) + break; + } + + REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); + REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); + MM_Wait (10); + } else { + for (i = 0; i < 10000; i++) { + REG_WR (pDevice, txCpu.reg.state, 0xffffffff); + REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); + + if (REG_RD (pDevice, txCpu.reg.mode) & CPU_MODE_HALT) + break; + } + } + + return ((i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS); +} + +int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec) +{ + LM_UINT32 Oldcfg; + int j; + int ret = 0; + + if (BlinkDurationSec == 0) { + return 0; + } + if (BlinkDurationSec > 120) { + BlinkDurationSec = 120; + } + + Oldcfg = REG_RD (pDevice, MacCtrl.LedCtrl); + for (j = 0; j < BlinkDurationSec * 2; j++) { + if (j % 2) { + /* Turn on the LEDs. */ + REG_WR (pDevice, MacCtrl.LedCtrl, + LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_1000MBPS_LED_ON | + LED_CTRL_100MBPS_LED_ON | + LED_CTRL_10MBPS_LED_ON | + LED_CTRL_OVERRIDE_TRAFFIC_LED | + LED_CTRL_BLINK_TRAFFIC_LED | + LED_CTRL_TRAFFIC_LED); + } else { + /* Turn off the LEDs. */ + REG_WR (pDevice, MacCtrl.LedCtrl, + LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_OVERRIDE_TRAFFIC_LED); + } + +#ifndef EMBEDDED + current->state = TASK_INTERRUPTIBLE; + if (schedule_timeout (HZ / 2) != 0) { + ret = -EINTR; + break; + } +#else + udelay (100000); /* 1s sleep */ +#endif + } + REG_WR (pDevice, MacCtrl.LedCtrl, Oldcfg); + return ret; +} + +int t3_do_dma (PLM_DEVICE_BLOCK pDevice, + LM_PHYSICAL_ADDRESS host_addr_phy, int length, int dma_read) +{ + T3_DMA_DESC dma_desc; + int i; + LM_UINT32 dma_desc_addr; + LM_UINT32 value32; + + REG_WR (pDevice, BufMgr.Mode, 0); + REG_WR (pDevice, Ftq.Reset, 0); + + dma_desc.host_addr.High = host_addr_phy.High; + dma_desc.host_addr.Low = host_addr_phy.Low; + dma_desc.nic_mbuf = 0x2100; + dma_desc.len = length; + dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */ + + if (dma_read) { + dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) | + T3_QID_DMA_HIGH_PRI_READ; + REG_WR (pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE); + } else { + dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) | + T3_QID_DMA_HIGH_PRI_WRITE; + REG_WR (pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE); + } + + dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR; + + /* Writing this DMA descriptor to DMA memory */ + for (i = 0; i < sizeof (T3_DMA_DESC); i += 4) { + value32 = *((PLM_UINT32) (((PLM_UINT8) & dma_desc) + i)); + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, + dma_desc_addr + i); + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, + cpu_to_le32 (value32)); + } + MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0); + + if (dma_read) + REG_WR (pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, + dma_desc_addr); + else + REG_WR (pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, + dma_desc_addr); + + for (i = 0; i < 40; i++) { + if (dma_read) + value32 = + REG_RD (pDevice, + Ftq.RcvBdCompFtqFifoEnqueueDequeue); + else + value32 = + REG_RD (pDevice, + Ftq.RcvDataCompFtqFifoEnqueueDequeue); + + if ((value32 & 0xffff) == dma_desc_addr) + break; + + MM_Wait (10); + } + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS +LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, + LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize) +{ + int j; + LM_UINT32 *ptr; + int dma_success = 0; + + if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { + return LM_STATUS_SUCCESS; + } + while (!dma_success) { + /* Fill data with incremental patterns */ + ptr = (LM_UINT32 *) pBufferVirt; + for (j = 0; j < BufferSize / 4; j++) + *ptr++ = j; + + if (t3_do_dma (pDevice, BufferPhy, BufferSize, 1) == + LM_STATUS_FAILURE) { + return LM_STATUS_FAILURE; + } + + MM_Wait (40); + ptr = (LM_UINT32 *) pBufferVirt; + /* Fill data with zero */ + for (j = 0; j < BufferSize / 4; j++) + *ptr++ = 0; + + if (t3_do_dma (pDevice, BufferPhy, BufferSize, 0) == + LM_STATUS_FAILURE) { + return LM_STATUS_FAILURE; + } + + MM_Wait (40); + /* Check for data */ + ptr = (LM_UINT32 *) pBufferVirt; + for (j = 0; j < BufferSize / 4; j++) { + if (*ptr++ != j) { + if ((pDevice-> + DmaReadWriteCtrl & + DMA_CTRL_WRITE_BOUNDARY_MASK) + == DMA_CTRL_WRITE_BOUNDARY_DISABLE) { + pDevice->DmaReadWriteCtrl = + (pDevice-> + DmaReadWriteCtrl & + ~DMA_CTRL_WRITE_BOUNDARY_MASK) | + DMA_CTRL_WRITE_BOUNDARY_16; + REG_WR (pDevice, + PciCfg.DmaReadWriteCtrl, + pDevice->DmaReadWriteCtrl); + break; + } else { + return LM_STATUS_FAILURE; + } + } + } + if (j == (BufferSize / 4)) + dma_success = 1; + } + return LM_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/net/tigon3.h b/drivers/net/tigon3.h new file mode 100644 index 0000000000..c03347fdc9 --- /dev/null +++ b/drivers/net/tigon3.h @@ -0,0 +1,3339 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* */ +/******************************************************************************/ + +#ifndef TIGON3_H +#define TIGON3_H + +#include "bcm570x_lm.h" +#if INCLUDE_TBI_SUPPORT +#include "bcm570x_autoneg.h" +#endif + +/* io defines */ +#if !defined(BIG_ENDIAN_HOST) +#define readl(addr) \ + (LONGSWAP((*(volatile unsigned int *)(addr)))) +#define writel(b,addr) \ + ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b))) +#else +#if 0 /* !defined(PPC603) */ +#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr))) +#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b)) +#else +#if 1 +#define readl(addr) (*(volatile unsigned int*)(addr)) +#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) +#else +extern int sprintf (char *buf, const char *f, ...); +static __inline unsigned int readl (void *addr) +{ + char buf[128]; + unsigned int tmp = (*(volatile unsigned int *)(addr)); + sprintf (buf, "%s:%s: read 0x%x from 0x%x\n", __FILE__, __LINE__, tmp, + addr, 0, 0); + sysSerialPrintString (buf); + return tmp; +} +static __inline void writel (unsigned int b, unsigned int addr) +{ + char buf[128]; + ((*(volatile unsigned int *)(addr)) = (b)); + sprintf (buf, "%s:%s: write 0x%x to 0x%x\n", __FILE__, __LINE__, b, + addr, 0, 0); + sysSerialPrintString (buf); +} +#endif +#endif /* PPC603 */ +#endif + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +/* Maxim number of packet descriptors used for sending packets. */ +#define MAX_TX_PACKET_DESC_COUNT 600 +#define DEFAULT_TX_PACKET_DESC_COUNT 2 + +/* Maximum number of packet descriptors used for receiving packets. */ +#if T3_JUMBO_RCB_ENTRY_COUNT +#define MAX_RX_PACKET_DESC_COUNT \ + (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT) +#else +#define MAX_RX_PACKET_DESC_COUNT 800 +#endif +#define DEFAULT_RX_PACKET_DESC_COUNT 2 + +/* Threshhold for double copying small tx packets. 0 will disable double */ +/* copying of small Tx packets. */ +#define DEFAULT_TX_COPY_BUFFER_SIZE 0 +#define MIN_TX_COPY_BUFFER_SIZE 64 +#define MAX_TX_COPY_BUFFER_SIZE 512 + +/* Cache line. */ +#define COMMON_CACHE_LINE_SIZE 0x20 +#define COMMON_CACHE_LINE_MASK (COMMON_CACHE_LINE_SIZE-1) + +/* Maximum number of fragment we can handle. */ +#ifndef MAX_FRAGMENT_COUNT +#define MAX_FRAGMENT_COUNT 32 +#endif + +/* B0 bug. */ +#define BCM5700_BX_MIN_FRAG_SIZE 10 +#define BCM5700_BX_MIN_FRAG_BUF_SIZE 16 /* nice aligned size. */ +#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK (BCM5700_BX_MIN_FRAG_BUF_SIZE-1) +#define BCM5700_BX_TX_COPY_BUF_SIZE (BCM5700_BX_MIN_FRAG_BUF_SIZE * \ + MAX_FRAGMENT_COUNT) + +/* MAGIC number. */ +/* #define T3_MAGIC_NUM 'KevT' */ +#define T3_FIRMWARE_MAILBOX 0x0b50 +#define T3_MAGIC_NUM 0x4B657654 +#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b + +#define T3_NIC_DATA_SIG_ADDR 0x0b54 +#define T3_NIC_DATA_SIG 0x4b657654 + +#define T3_NIC_DATA_NIC_CFG_ADDR 0x0b58 +#define T3_NIC_CFG_LED_MODE_UNKNOWN BIT_NONE +#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED BIT_2 +#define T3_NIC_CFG_LED_MODE_LINK_SPEED BIT_3 +#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN BIT_2 +#define T3_NIC_CFG_LED_MODE_OUTPUT BIT_3 +#define T3_NIC_CFG_LED_MODE_MASK (BIT_2 | BIT_3) +#define T3_NIC_CFG_PHY_TYPE_UNKNOWN BIT_NONE +#define T3_NIC_CFG_PHY_TYPE_COPPER BIT_4 +#define T3_NIC_CFG_PHY_TYPE_FIBER BIT_5 +#define T3_NIC_CFG_PHY_TYPE_MASK (BIT_4 | BIT_5) +#define T3_NIC_CFG_ENABLE_WOL BIT_6 +#define T3_NIC_CFG_ENABLE_ASF BIT_7 +#define T3_NIC_EEPROM_WP BIT_8 + +#define T3_NIC_DATA_PHY_ID_ADDR 0x0b74 +#define T3_NIC_PHY_ID1_MASK 0xffff0000 +#define T3_NIC_PHY_ID2_MASK 0x0000ffff + +#define T3_CMD_MAILBOX 0x0b78 +#define T3_CMD_NICDRV_ALIVE 0x01 +#define T3_CMD_NICDRV_PAUSE_FW 0x02 +#define T3_CMD_NICDRV_IPV4ADDR_CHANGE 0x03 +#define T3_CMD_NICDRV_IPV6ADDR_CHANGE 0x04 +#define T3_CMD_5703A0_FIX_DMAFW_DMAR 0x05 +#define T3_CMD_5703A0_FIX_DMAFW_DMAW 0x06 + +#define T3_CMD_LENGTH_MAILBOX 0x0b7c +#define T3_CMD_DATA_MAILBOX 0x0b80 + +#define T3_ASF_FW_STATUS_MAILBOX 0x0c00 + +#define T3_DRV_STATE_MAILBOX 0x0c04 +#define T3_DRV_STATE_START 0x01 +#define T3_DRV_STATE_UNLOAD 0x02 +#define T3_DRV_STATE_WOL 0x03 +#define T3_DRV_STATE_SUSPEND 0x04 + +#define T3_FW_RESET_TYPE_MAILBOX 0x0c08 + +#define T3_MAC_ADDR_HIGH_MAILBOX 0x0c14 +#define T3_MAC_ADDR_LOW_MAILBOX 0x0c18 + +/******************************************************************************/ +/* Hardware constants. */ +/******************************************************************************/ + +/* Number of entries in the send ring: must be 512. */ +#define T3_SEND_RCB_ENTRY_COUNT 512 +#define T3_SEND_RCB_ENTRY_COUNT_MASK (T3_SEND_RCB_ENTRY_COUNT-1) + +/* Number of send RCBs. May be 1-16 but for now, only support one. */ +#define T3_MAX_SEND_RCB_COUNT 16 + +/* Number of entries in the Standard Receive RCB. Must be 512 entries. */ +#define T3_STD_RCV_RCB_ENTRY_COUNT 512 +#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK (T3_STD_RCV_RCB_ENTRY_COUNT-1) +#define DEFAULT_STD_RCV_DESC_COUNT 200 /* Must be < 512. */ +#define MAX_STD_RCV_BUFFER_SIZE 0x600 + +/* Number of entries in the Mini Receive RCB. This value can either be */ +/* 0, 1024. Currently Mini Receive RCB is disabled. */ +#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT +#define T3_MINI_RCV_RCB_ENTRY_COUNT 0 +#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */ +#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK (T3_MINI_RCV_RCB_ENTRY_COUNT-1) +#define MAX_MINI_RCV_BUFFER_SIZE 512 +#define DEFAULT_MINI_RCV_BUFFER_SIZE 64 +#define DEFAULT_MINI_RCV_DESC_COUNT 100 /* Must be < 1024. */ + +/* Number of entries in the Jumbo Receive RCB. This value must 256 or 0. */ +/* Currently, Jumbo Receive RCB is disabled. */ +#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT +#define T3_JUMBO_RCV_RCB_ENTRY_COUNT 0 +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ +#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1) + +#define MAX_JUMBO_RCV_BUFFER_SIZE (10 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_RCV_BUFFER_SIZE (4 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_RCV_DESC_COUNT 128 /* Must be < 256. */ + +#define MAX_JUMBO_TX_BUFFER_SIZE (8 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_TX_BUFFER_SIZE (4 * 1024) /* > 1514 */ + +/* Number of receive return RCBs. Maybe 1-16 but for now, only support one. */ +#define T3_MAX_RCV_RETURN_RCB_COUNT 16 + +/* Number of entries in a Receive Return ring. This value is either 1024 */ +/* or 2048. */ +#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT +#define T3_RCV_RETURN_RCB_ENTRY_COUNT 1024 +#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */ +#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK (T3_RCV_RETURN_RCB_ENTRY_COUNT-1) + +/* Default coalescing parameters. */ +#define DEFAULT_RX_COALESCING_TICKS 100 +#define MAX_RX_COALESCING_TICKS 500 +#define DEFAULT_TX_COALESCING_TICKS 400 +#define MAX_TX_COALESCING_TICKS 500 +#define DEFAULT_RX_MAX_COALESCED_FRAMES 10 +#define MAX_RX_MAX_COALESCED_FRAMES 100 +#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES 5 +#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES 42 +#define ADAPTIVE_LO_RX_COALESCING_TICKS 50 +#define ADAPTIVE_HI_RX_COALESCING_TICKS 300 +#define ADAPTIVE_LO_PKT_THRESH 30000 +#define ADAPTIVE_HI_PKT_THRESH 74000 +#define DEFAULT_TX_MAX_COALESCED_FRAMES 40 +#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES 25 +#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES 75 +#define MAX_TX_MAX_COALESCED_FRAMES 100 + +#define DEFAULT_RX_COALESCING_TICKS_DURING_INT 25 +#define DEFAULT_TX_COALESCING_TICKS_DURING_INT 25 +#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT 5 +#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT 5 + +#define BAD_DEFAULT_VALUE 0xffffffff + +#define DEFAULT_STATS_COALESCING_TICKS 1000000 +#define MAX_STATS_COALESCING_TICKS 3600000000U + +/* Receive BD Replenish thresholds. */ +#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD 4 +#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD 4 + +#define SPLIT_MODE_DISABLE 0 +#define SPLIT_MODE_ENABLE 1 + +#define SPLIT_MODE_5704_MAX_REQ 3 + +/* Maximum physical fragment size. */ +#define MAX_FRAGMENT_SIZE (64 * 1024) + +/* Standard view. */ +#define T3_STD_VIEW_SIZE (64 * 1024) +#define T3_FLAT_VIEW_SIZE (32 * 1024 * 1024) + +/* Buffer descriptor base address on the NIC's memory. */ + +#define T3_NIC_SND_BUFFER_DESC_ADDR 0x4000 +#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR 0x6000 +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR 0x7000 + +#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xc000 +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xd000 +#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xe000 + +#define T3_NIC_SND_BUFFER_DESC_SIZE (T3_SEND_RCB_ENTRY_COUNT * \ + sizeof(T3_SND_BD) / 4) + +#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE (T3_STD_RCV_RCB_ENTRY_COUNT * \ + sizeof(T3_RCV_BD) / 4) + +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \ + sizeof(T3_EXT_RCV_BD) / 4) + +/* MBUF pool. */ +#define T3_NIC_MBUF_POOL_ADDR 0x8000 +/* #define T3_NIC_MBUF_POOL_SIZE 0x18000 */ +#define T3_NIC_MBUF_POOL_SIZE96 0x18000 +#define T3_NIC_MBUF_POOL_SIZE64 0x10000 + +#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM 0x20000 + +/* DMA descriptor pool */ +#define T3_NIC_DMA_DESC_POOL_ADDR 0x2000 +#define T3_NIC_DMA_DESC_POOL_SIZE 0x2000 /* 8KB. */ + +#define T3_DEF_DMA_MBUF_LOW_WMARK 0x40 +#define T3_DEF_RX_MAC_MBUF_LOW_WMARK 0x20 +#define T3_DEF_MBUF_HIGH_WMARK 0x60 + +#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO 304 +#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO 152 +#define T3_DEF_MBUF_HIGH_WMARK_JUMBO 380 + +#define T3_DEF_DMA_DESC_LOW_WMARK 5 +#define T3_DEF_DMA_DESC_HIGH_WMARK 10 + +/* Maximum size of giant TCP packet can be sent */ +#define T3_TCP_SEG_MAX_OFFLOAD_SIZE 64*1000 +#define T3_TCP_SEG_MIN_NUM_SEG 20 + +#define T3_RX_CPU_ID 0x1 +#define T3_TX_CPU_ID 0x2 +#define T3_RX_CPU_SPAD_ADDR 0x30000 +#define T3_RX_CPU_SPAD_SIZE 0x4000 +#define T3_TX_CPU_SPAD_ADDR 0x34000 +#define T3_TX_CPU_SPAD_SIZE 0x4000 + +typedef struct T3_DIR_ENTRY { + PLM_UINT8 Buffer; + LM_UINT32 Offset; + LM_UINT32 Length; +} T3_DIR_ENTRY, *PT3_DIR_ENTRY; + +typedef struct T3_FWIMG_INFO { + LM_UINT32 StartAddress; + T3_DIR_ENTRY Text; + T3_DIR_ENTRY ROnlyData; + T3_DIR_ENTRY Data; + T3_DIR_ENTRY Sbss; + T3_DIR_ENTRY Bss; +} T3_FWIMG_INFO, *PT3_FWIMG_INFO; + +/******************************************************************************/ +/* Tigon3 PCI Registers. */ +/******************************************************************************/ +#define T3_PCI_ID_BCM5700 0x164414e4 +#define T3_PCI_ID_BCM5701 0x164514e4 +#define T3_PCI_ID_BCM5702 0x164614e4 +#define T3_PCI_ID_BCM5702x 0x16A614e4 +#define T3_PCI_ID_BCM5703 0x164714e4 +#define T3_PCI_ID_BCM5703x 0x16A714e4 +#define T3_PCI_ID_BCM5702FE 0x164D14e4 +#define T3_PCI_ID_BCM5704 0x164814e4 + +#define T3_PCI_VENDOR_ID (T3_PCI_ID & 0xffff) +#define T3_PCI_DEVICE_ID (T3_PCI_ID >> 16) + +#define T3_PCI_MISC_HOST_CTRL_REG 0x68 + +/* The most significant 16bit of register 0x68. */ +/* ChipId:4, ChipRev:4, MetalRev:8 */ +#define T3_CHIP_ID_5700_A0 0x7000 +#define T3_CHIP_ID_5700_A1 0x7001 +#define T3_CHIP_ID_5700_B0 0x7100 +#define T3_CHIP_ID_5700_B1 0x7101 +#define T3_CHIP_ID_5700_C0 0x7200 + +#define T3_CHIP_ID_5701_A0 0x0000 +#define T3_CHIP_ID_5701_B0 0x0100 +#define T3_CHIP_ID_5701_B2 0x0102 +#define T3_CHIP_ID_5701_B5 0x0105 + +#define T3_CHIP_ID_5703_A0 0x1000 +#define T3_CHIP_ID_5703_A1 0x1001 +#define T3_CHIP_ID_5703_A2 0x1002 + +#define T3_CHIP_ID_5704_A0 0x2000 + +/* Chip Id. */ +#define T3_ASIC_REV(_ChipRevId) ((_ChipRevId) >> 12) +#define T3_ASIC_REV_5700 0x07 +#define T3_ASIC_REV_5701 0x00 +#define T3_ASIC_REV_5703 0x01 +#define T3_ASIC_REV_5704 0x02 + +/* Chip id and revision. */ +#define T3_CHIP_REV(_ChipRevId) ((_ChipRevId) >> 8) +#define T3_CHIP_REV_5700_AX 0x70 +#define T3_CHIP_REV_5700_BX 0x71 +#define T3_CHIP_REV_5700_CX 0x72 +#define T3_CHIP_REV_5701_AX 0x00 + +/* Metal revision. */ +#define T3_METAL_REV(_ChipRevId) ((_ChipRevId) & 0xff) +#define T3_METAL_REV_A0 0x00 +#define T3_METAL_REV_A1 0x01 +#define T3_METAL_REV_B0 0x00 +#define T3_METAL_REV_B1 0x01 +#define T3_METAL_REV_B2 0x02 + +#define T3_PCI_REG_CLOCK_CTRL 0x74 + +#define T3_PCI_DISABLE_RX_CLOCK BIT_10 +#define T3_PCI_DISABLE_TX_CLOCK BIT_11 +#define T3_PCI_SELECT_ALTERNATE_CLOCK BIT_12 +#define T3_PCI_POWER_DOWN_PCI_PLL133 BIT_15 +#define T3_PCI_44MHZ_CORE_CLOCK BIT_18 + +#define T3_PCI_REG_ADDR_REG 0x78 +#define T3_PCI_REG_DATA_REG 0x80 + +#define T3_PCI_MEM_WIN_ADDR_REG 0x7c +#define T3_PCI_MEM_WIN_DATA_REG 0x84 + +#define T3_PCI_PM_CAP_REG 0x48 + +#define T3_PCI_PM_CAP_PME_D3COLD BIT_31 +#define T3_PCI_PM_CAP_PME_D3HOT BIT_30 + +#define T3_PCI_PM_STATUS_CTRL_REG 0x4c + +#define T3_PM_POWER_STATE_MASK (BIT_0 | BIT_1) +#define T3_PM_POWER_STATE_D0 BIT_NONE +#define T3_PM_POWER_STATE_D1 BIT_0 +#define T3_PM_POWER_STATE_D2 BIT_1 +#define T3_PM_POWER_STATE_D3 (BIT_0 | BIT_1) + +#define T3_PM_PME_ENABLE BIT_8 +#define T3_PM_PME_ASSERTED BIT_15 + +/* PCI state register. */ +#define T3_PCI_STATE_REG 0x70 + +#define T3_PCI_STATE_FORCE_RESET BIT_0 +#define T3_PCI_STATE_INT_NOT_ACTIVE BIT_1 +#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE BIT_2 +#define T3_PCI_STATE_BUS_SPEED_HIGH BIT_3 +#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 + +/* Broadcom subsystem/subvendor IDs. */ +#define T3_SVID_BROADCOM 0x14e4 + +#define T3_SSID_BROADCOM_BCM95700A6 0x1644 +#define T3_SSID_BROADCOM_BCM95701A5 0x0001 +#define T3_SSID_BROADCOM_BCM95700T6 0x0002 /* BCM8002 */ +#define T3_SSID_BROADCOM_BCM95700A9 0x0003 /* Agilent */ +#define T3_SSID_BROADCOM_BCM95701T1 0x0005 +#define T3_SSID_BROADCOM_BCM95701T8 0x0006 +#define T3_SSID_BROADCOM_BCM95701A7 0x0007 /* Agilent */ +#define T3_SSID_BROADCOM_BCM95701A10 0x0008 +#define T3_SSID_BROADCOM_BCM95701A12 0x8008 +#define T3_SSID_BROADCOM_BCM95703Ax1 0x0009 +#define T3_SSID_BROADCOM_BCM95703Ax2 0x8009 + +/* 3COM subsystem/subvendor IDs. */ +#define T3_SVID_3COM 0x10b7 + +#define T3_SSID_3COM_3C996T 0x1000 +#define T3_SSID_3COM_3C996BT 0x1006 +#define T3_SSID_3COM_3C996CT 0x1002 +#define T3_SSID_3COM_3C997T 0x1003 +#define T3_SSID_3COM_3C1000T 0x1007 +#define T3_SSID_3COM_3C940BR01 0x1008 + +/* Fiber boards. */ +#define T3_SSID_3COM_3C996SX 0x1004 +#define T3_SSID_3COM_3C997SX 0x1005 + +/* Dell subsystem/subvendor IDs. */ + +#define T3_SVID_DELL 0x1028 + +#define T3_SSID_DELL_VIPER 0x00d1 +#define T3_SSID_DELL_JAGUAR 0x0106 +#define T3_SSID_DELL_MERLOT 0x0109 +#define T3_SSID_DELL_SLIM_MERLOT 0x010a + +/* Compaq subsystem/subvendor IDs */ + +#define T3_SVID_COMPAQ 0x0e11 + +#define T3_SSID_COMPAQ_BANSHEE 0x007c +#define T3_SSID_COMPAQ_BANSHEE_2 0x009a +#define T3_SSID_COMPAQ_CHANGELING 0x007d +#define T3_SSID_COMPAQ_NC7780 0x0085 +#define T3_SSID_COMPAQ_NC7780_2 0x0099 + +/******************************************************************************/ +/* MII registers. */ +/******************************************************************************/ + +/* Control register. */ +#define PHY_CTRL_REG 0x00 + +#define PHY_CTRL_SPEED_MASK (BIT_6 | BIT_13) +#define PHY_CTRL_SPEED_SELECT_10MBPS BIT_NONE +#define PHY_CTRL_SPEED_SELECT_100MBPS BIT_13 +#define PHY_CTRL_SPEED_SELECT_1000MBPS BIT_6 +#define PHY_CTRL_COLLISION_TEST_ENABLE BIT_7 +#define PHY_CTRL_FULL_DUPLEX_MODE BIT_8 +#define PHY_CTRL_RESTART_AUTO_NEG BIT_9 +#define PHY_CTRL_ISOLATE_PHY BIT_10 +#define PHY_CTRL_LOWER_POWER_MODE BIT_11 +#define PHY_CTRL_AUTO_NEG_ENABLE BIT_12 +#define PHY_CTRL_LOOPBACK_MODE BIT_14 +#define PHY_CTRL_PHY_RESET BIT_15 + +/* Status register. */ +#define PHY_STATUS_REG 0x01 + +#define PHY_STATUS_LINK_PASS BIT_2 +#define PHY_STATUS_AUTO_NEG_COMPLETE BIT_5 + +/* Phy Id registers. */ +#define PHY_ID1_REG 0x02 +#define PHY_ID1_OUI_MASK 0xffff + +#define PHY_ID2_REG 0x03 +#define PHY_ID2_REV_MASK 0x000f +#define PHY_ID2_MODEL_MASK 0x03f0 +#define PHY_ID2_OUI_MASK 0xfc00 + +/* Auto-negotiation advertisement register. */ +#define PHY_AN_AD_REG 0x04 + +#define PHY_AN_AD_ASYM_PAUSE BIT_11 +#define PHY_AN_AD_PAUSE_CAPABLE BIT_10 +#define PHY_AN_AD_10BASET_HALF BIT_5 +#define PHY_AN_AD_10BASET_FULL BIT_6 +#define PHY_AN_AD_100BASETX_HALF BIT_7 +#define PHY_AN_AD_100BASETX_FULL BIT_8 +#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD 0x01 + +/* Auto-negotiation Link Partner Ability register. */ +#define PHY_LINK_PARTNER_ABILITY_REG 0x05 + +#define PHY_LINK_PARTNER_ASYM_PAUSE BIT_11 +#define PHY_LINK_PARTNER_PAUSE_CAPABLE BIT_10 + +/* Auto-negotiation expansion register. */ +#define PHY_AN_EXPANSION_REG 0x06 + +/******************************************************************************/ +/* BCM5400 and BCM5401 phy info. */ +/******************************************************************************/ + +#define PHY_DEVICE_ID 1 + +/* OUI: bit 31-10; Model#: bit 9-4; Rev# bit 3-0. */ +#define PHY_UNKNOWN_PHY 0x00000000 +#define PHY_BCM5400_PHY_ID 0x60008040 +#define PHY_BCM5401_PHY_ID 0x60008050 +#define PHY_BCM5411_PHY_ID 0x60008070 +#define PHY_BCM5701_PHY_ID 0x60008110 +#define PHY_BCM5703_PHY_ID 0x60008160 +#define PHY_BCM5704_PHY_ID 0x60008190 +#define PHY_BCM8002_PHY_ID 0x60010140 + +#define PHY_BCM5401_B0_REV 0x1 +#define PHY_BCM5401_B2_REV 0x3 +#define PHY_BCM5401_C0_REV 0x6 + +#define PHY_ID_OUI_MASK 0xfffffc00 +#define PHY_ID_MODEL_MASK 0x000003f0 +#define PHY_ID_REV_MASK 0x0000000f +#define PHY_ID_MASK (PHY_ID_OUI_MASK | \ + PHY_ID_MODEL_MASK) + +#define UNKNOWN_PHY_ID(x) ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID)) + +/* 1000Base-T control register. */ +#define BCM540X_1000BASET_CTRL_REG 0x09 + +#define BCM540X_AN_AD_1000BASET_HALF BIT_8 +#define BCM540X_AN_AD_1000BASET_FULL BIT_9 +#define BCM540X_CONFIG_AS_MASTER BIT_11 +#define BCM540X_ENABLE_CONFIG_AS_MASTER BIT_12 + +/* Extended control register. */ +#define BCM540X_EXT_CTRL_REG 0x10 + +#define BCM540X_EXT_CTRL_LINK3_LED_MODE BIT_1 +#define BCM540X_EXT_CTRL_TBI BIT_15 + +/* PHY extended status register. */ +#define BCM540X_EXT_STATUS_REG 0x11 + +#define BCM540X_EXT_STATUS_LINK_PASS BIT_8 + +/* DSP Coefficient Read/Write Port. */ +#define BCM540X_DSP_RW_PORT 0x15 + +/* DSP Coeficient Address Register. */ +#define BCM540X_DSP_ADDRESS_REG 0x17 + +#define BCM540X_DSP_TAP_NUMBER_MASK 0x00 +#define BCM540X_DSP_AGC_A 0x00 +#define BCM540X_DSP_AGC_B 0x01 +#define BCM540X_DSP_MSE_PAIR_STATUS 0x02 +#define BCM540X_DSP_SOFT_DECISION 0x03 +#define BCM540X_DSP_PHASE_REG 0x04 +#define BCM540X_DSP_SKEW 0x05 +#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND 0x06 +#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND 0x07 +#define BCM540X_DSP_LAST_ECHO 0x08 +#define BCM540X_DSP_FREQUENCY 0x09 +#define BCM540X_DSP_PLL_BANDWIDTH 0x0a +#define BCM540X_DSP_PLL_PHASE_OFFSET 0x0b + +#define BCM540X_DSP_FILTER_DCOFFSET (BIT_10 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT3 (BIT_8 | BIT_9 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT2 (BIT_9 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT1 (BIT_8 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT0 BIT_11 +#define BCM540X_DSP_FILTER_NEXT3 (BIT_8 | BIT_9 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT2 (BIT_9 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT1 (BIT_8 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT0 BIT_10 +#define BCM540X_DSP_FILTER_ECHO (BIT_8 | BIT_9) +#define BCM540X_DSP_FILTER_DFE BIT_9 +#define BCM540X_DSP_FILTER_FFE BIT_8 + +#define BCM540X_DSP_CONTROL_ALL_FILTERS BIT_12 + +#define BCM540X_DSP_SEL_CH_0 BIT_NONE +#define BCM540X_DSP_SEL_CH_1 BIT_13 +#define BCM540X_DSP_SEL_CH_2 BIT_14 +#define BCM540X_DSP_SEL_CH_3 (BIT_13 | BIT_14) + +#define BCM540X_CONTROL_ALL_CHANNELS BIT_15 + +/* Auxilliary Control Register (Shadow Register) */ +#define BCM5401_AUX_CTRL 0x18 + +#define BCM5401_SHADOW_SEL_MASK 0x7 +#define BCM5401_SHADOW_SEL_NORMAL 0x00 +#define BCM5401_SHADOW_SEL_10BASET 0x01 +#define BCM5401_SHADOW_SEL_POWER_CONTROL 0x02 +#define BCM5401_SHADOW_SEL_IP_PHONE 0x03 +#define BCM5401_SHADOW_SEL_MISC_TEST1 0x04 +#define BCM5401_SHADOW_SEL_MISC_TEST2 0x05 +#define BCM5401_SHADOW_SEL_IP_PHONE_SEED 0x06 + +/* Shadow register selector == '000' */ +#define BCM5401_SHDW_NORMAL_DIAG_MODE BIT_3 +#define BCM5401_SHDW_NORMAL_DISABLE_MBP BIT_4 +#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR BIT_5 +#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF BIT_6 +#define BCM5401_SHDW_NORMAL_DISABLE_PRF BIT_7 +#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL BIT_NONE +#define BCM5401_SHDW_NORMAL_RX_SLICING_4D BIT_8 +#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D BIT_9 +#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D (BIT_8 | BIT_9) +#define BCM5401_SHDW_NORMAL_TX_6DB_CODING BIT_10 +#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK BIT_11 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS BIT_NONE +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS BIT_12 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS BIT_13 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS (BIT_12 | BIT_13) +#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH BIT_14 +#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK BIT_15 + +/* Auxilliary status summary. */ +#define BCM540X_AUX_STATUS_REG 0x19 + +#define BCM540X_AUX_LINK_PASS BIT_2 +#define BCM540X_AUX_SPEED_MASK (BIT_8 | BIT_9 | BIT_10) +#define BCM540X_AUX_10BASET_HD BIT_8 +#define BCM540X_AUX_10BASET_FD BIT_9 +#define BCM540X_AUX_100BASETX_HD (BIT_8 | BIT_9) +#define BCM540X_AUX_100BASET4 BIT_10 +#define BCM540X_AUX_100BASETX_FD (BIT_8 | BIT_10) +#define BCM540X_AUX_100BASET_HD (BIT_9 | BIT_10) +#define BCM540X_AUX_100BASET_FD (BIT_8 | BIT_9 | BIT_10) + +/* Interrupt status. */ +#define BCM540X_INT_STATUS_REG 0x1a + +#define BCM540X_INT_LINK_CHANGE BIT_1 +#define BCM540X_INT_SPEED_CHANGE BIT_2 +#define BCM540X_INT_DUPLEX_CHANGE BIT_3 +#define BCM540X_INT_AUTO_NEG_PAGE_RX BIT_10 + +/* Interrupt mask register. */ +#define BCM540X_INT_MASK_REG 0x1b + +/******************************************************************************/ +/* Register definitions. */ +/******************************************************************************/ + +typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER; +typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER; +typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER; + +typedef struct { + /* Big endian format. */ + T3_32BIT_REGISTER High; + T3_32BIT_REGISTER Low; +} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER; + +typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR; + +#define T3_NUM_OF_DMA_DESC 256 +#define T3_NUM_OF_MBUF 768 + +typedef struct { + T3_64BIT_REGISTER host_addr; + T3_32BIT_REGISTER nic_mbuf; + T3_16BIT_REGISTER len; + T3_16BIT_REGISTER cqid_sqid; + T3_32BIT_REGISTER flags; + T3_32BIT_REGISTER opaque1; + T3_32BIT_REGISTER opaque2; + T3_32BIT_REGISTER opaque3; +} T3_DMA_DESC, *PT3_DMA_DESC; + +/******************************************************************************/ +/* Ring control block. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_REGISTER HostRingAddr; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + T3_16BIT_REGISTER MaxLen; + T3_16BIT_REGISTER Flags; +#else /* BIG_ENDIAN_HOST */ + T3_16BIT_REGISTER Flags; + T3_16BIT_REGISTER MaxLen; +#endif + } s; + + T3_32BIT_REGISTER MaxLen_Flags; + } u; + + T3_32BIT_REGISTER NicRingAddr; +} T3_RCB, *PT3_RCB; + +#define T3_RCB_FLAG_USE_EXT_RECV_BD BIT_0 +#define T3_RCB_FLAG_RING_DISABLED BIT_1 + +/******************************************************************************/ +/* Status block. */ +/******************************************************************************/ + +/* + * Size of status block is actually 0x50 bytes. Use 0x80 bytes for + * cache line alignment. + */ +#define T3_STATUS_BLOCK_SIZE 0x80 + +typedef struct { + volatile LM_UINT32 Status; +#define STATUS_BLOCK_UPDATED BIT_0 +#define STATUS_BLOCK_LINK_CHANGED_STATUS BIT_1 +#define STATUS_BLOCK_ERROR BIT_2 + + volatile LM_UINT32 StatusTag; + +#ifdef BIG_ENDIAN_HOST + volatile LM_UINT16 RcvStdConIdx; + volatile LM_UINT16 RcvJumboConIdx; + + volatile LM_UINT16 Reserved2; + volatile LM_UINT16 RcvMiniConIdx; + + struct { + volatile LM_UINT16 SendConIdx; /* Send consumer index. */ + volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ + } Idx[16]; +#else /* BIG_ENDIAN_HOST */ + volatile LM_UINT16 RcvJumboConIdx; + volatile LM_UINT16 RcvStdConIdx; + + volatile LM_UINT16 RcvMiniConIdx; + volatile LM_UINT16 Reserved2; + + struct { + volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ + volatile LM_UINT16 SendConIdx; /* Send consumer index. */ + } Idx[16]; +#endif +} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK; + +/******************************************************************************/ +/* Receive buffer descriptors. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr; + +#ifdef BIG_ENDIAN_HOST + volatile LM_UINT16 Index; + volatile LM_UINT16 Len; + + volatile LM_UINT16 Type; + volatile LM_UINT16 Flags; + + volatile LM_UINT16 IpCksum; + volatile LM_UINT16 TcpUdpCksum; + + volatile LM_UINT16 ErrorFlag; + volatile LM_UINT16 VlanTag; +#else /* BIG_ENDIAN_HOST */ + volatile LM_UINT16 Len; + volatile LM_UINT16 Index; + + volatile LM_UINT16 Flags; + volatile LM_UINT16 Type; + + volatile LM_UINT16 TcpUdpCksum; + volatile LM_UINT16 IpCksum; + + volatile LM_UINT16 VlanTag; + volatile LM_UINT16 ErrorFlag; +#endif + + volatile LM_UINT32 Reserved; + volatile LM_UINT32 Opaque; +} T3_RCV_BD, *PT3_RCV_BD; + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr[3]; + +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Len1; + LM_UINT16 Len2; + + LM_UINT16 Len3; + LM_UINT16 Reserved1; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 Len2; + LM_UINT16 Len1; + + LM_UINT16 Reserved1; + LM_UINT16 Len3; +#endif + + T3_RCV_BD StdRcvBd; +} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD; + +/* Error flags. */ +#define RCV_BD_ERR_BAD_CRC 0x0001 +#define RCV_BD_ERR_COLL_DETECT 0x0002 +#define RCV_BD_ERR_LINK_LOST_DURING_PKT 0x0004 +#define RCV_BD_ERR_PHY_DECODE_ERR 0x0008 +#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII 0x0010 +#define RCV_BD_ERR_MAC_ABORT 0x0020 +#define RCV_BD_ERR_LEN_LT_64 0x0040 +#define RCV_BD_ERR_TRUNC_NO_RESOURCES 0x0080 +#define RCV_BD_ERR_GIANT_FRAME_RCVD 0x0100 + +/* Buffer descriptor flags. */ +#define RCV_BD_FLAG_END 0x0004 +#define RCV_BD_FLAG_JUMBO_RING 0x0020 +#define RCV_BD_FLAG_VLAN_TAG 0x0040 +#define RCV_BD_FLAG_FRAME_HAS_ERROR 0x0400 +#define RCV_BD_FLAG_MINI_RING 0x0800 +#define RCV_BD_FLAG_IP_CHKSUM_FIELD 0x1000 +#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD 0x2000 +#define RCV_BD_FLAG_TCP_PACKET 0x4000 + +/******************************************************************************/ +/* Send buffer descriptor. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Len; + LM_UINT16 Flags; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 Flags; + LM_UINT16 Len; +#endif + } s1; + + LM_UINT32 Len_Flags; + } u1; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Reserved; + LM_UINT16 VlanTag; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 VlanTag; + LM_UINT16 Reserved; +#endif + } s2; + + LM_UINT32 VlanTag; + } u2; +} T3_SND_BD, *PT3_SND_BD; + +/* Send buffer descriptor flags. */ +#define SND_BD_FLAG_TCP_UDP_CKSUM 0x0001 +#define SND_BD_FLAG_IP_CKSUM 0x0002 +#define SND_BD_FLAG_END 0x0004 +#define SND_BD_FLAG_IP_FRAG 0x0008 +#define SND_BD_FLAG_IP_FRAG_END 0x0010 +#define SND_BD_FLAG_VLAN_TAG 0x0040 +#define SND_BD_FLAG_COAL_NOW 0x0080 +#define SND_BD_FLAG_CPU_PRE_DMA 0x0100 +#define SND_BD_FLAG_CPU_POST_DMA 0x0200 +#define SND_BD_FLAG_INSERT_SRC_ADDR 0x1000 +#define SND_BD_FLAG_CHOOSE_SRC_ADDR 0x6000 +#define SND_BD_FLAG_DONT_GEN_CRC 0x8000 + +/* MBUFs */ +typedef struct T3_MBUF_FRAME_DESC { +#ifdef BIG_ENDIAN_HOST + LM_UINT32 status_control; + union { + struct { + LM_UINT8 cqid; + LM_UINT8 reserved1; + LM_UINT16 length; + } s1; + LM_UINT32 word; + } u1; + union { + struct { + LM_UINT16 ip_hdr_start; + LM_UINT16 tcp_udp_hdr_start; + } s2; + + LM_UINT32 word; + } u2; + + union { + struct { + LM_UINT16 data_start; + LM_UINT16 vlan_id; + } s3; + + LM_UINT32 word; + } u3; + + union { + struct { + LM_UINT16 ip_checksum; + LM_UINT16 tcp_udp_checksum; + } s4; + + LM_UINT32 word; + } u4; + + union { + struct { + LM_UINT16 pseudo_checksum; + LM_UINT16 checksum_status; + } s5; + + LM_UINT32 word; + } u5; + + union { + struct { + LM_UINT16 rule_match; + LM_UINT8 class; + LM_UINT8 rupt; + } s6; + + LM_UINT32 word; + } u6; + + union { + struct { + LM_UINT16 reserved2; + LM_UINT16 mbuf_num; + } s7; + + LM_UINT32 word; + } u7; + + LM_UINT32 reserved3; + LM_UINT32 reserved4; +#else + LM_UINT32 status_control; + union { + struct { + LM_UINT16 length; + LM_UINT8 reserved1; + LM_UINT8 cqid; + } s1; + LM_UINT32 word; + } u1; + union { + struct { + LM_UINT16 tcp_udp_hdr_start; + LM_UINT16 ip_hdr_start; + } s2; + + LM_UINT32 word; + } u2; + + union { + struct { + LM_UINT16 vlan_id; + LM_UINT16 data_start; + } s3; + + LM_UINT32 word; + } u3; + + union { + struct { + LM_UINT16 tcp_udp_checksum; + LM_UINT16 ip_checksum; + } s4; + + LM_UINT32 word; + } u4; + + union { + struct { + LM_UINT16 checksum_status; + LM_UINT16 pseudo_checksum; + } s5; + + LM_UINT32 word; + } u5; + + union { + struct { + LM_UINT8 rupt; + LM_UINT8 class; + LM_UINT16 rule_match; + } s6; + + LM_UINT32 word; + } u6; + + union { + struct { + LM_UINT16 mbuf_num; + LM_UINT16 reserved2; + } s7; + + LM_UINT32 word; + } u7; + + LM_UINT32 reserved3; + LM_UINT32 reserved4; +#endif +} T3_MBUF_FRAME_DESC, *PT3_MBUF_FRAME_DESC; + +typedef struct T3_MBUF_HDR { + union { + struct { + unsigned int C:1; + unsigned int F:1; + unsigned int reserved1:7; + unsigned int next_mbuf:16; + unsigned int length:7; + } s1; + + LM_UINT32 word; + } u1; + + LM_UINT32 next_frame_ptr; +} T3_MBUF_HDR, *PT3_MBUF_HDR; + +typedef struct T3_MBUF { + T3_MBUF_HDR hdr; + union { + struct { + T3_MBUF_FRAME_DESC frame_hdr; + LM_UINT32 data[20]; + } s1; + + struct { + LM_UINT32 data[30]; + } s2; + } body; +} T3_MBUF, *PT3_MBUF; + +#define T3_MBUF_BASE (T3_NIC_MBUF_POOL_ADDR >> 7) +#define T3_MBUF_END ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7) + +/******************************************************************************/ +/* Statistics block. */ +/******************************************************************************/ + +typedef struct { + LM_UINT8 Reserved0[0x400 - 0x300]; + + /* Statistics maintained by Receive MAC. */ + T3_64BIT_REGISTER ifHCInOctets; + T3_64BIT_REGISTER Reserved1; + T3_64BIT_REGISTER etherStatsFragments; + T3_64BIT_REGISTER ifHCInUcastPkts; + T3_64BIT_REGISTER ifHCInMulticastPkts; + T3_64BIT_REGISTER ifHCInBroadcastPkts; + T3_64BIT_REGISTER dot3StatsFCSErrors; + T3_64BIT_REGISTER dot3StatsAlignmentErrors; + T3_64BIT_REGISTER xonPauseFramesReceived; + T3_64BIT_REGISTER xoffPauseFramesReceived; + T3_64BIT_REGISTER macControlFramesReceived; + T3_64BIT_REGISTER xoffStateEntered; + T3_64BIT_REGISTER dot3StatsFramesTooLong; + T3_64BIT_REGISTER etherStatsJabbers; + T3_64BIT_REGISTER etherStatsUndersizePkts; + T3_64BIT_REGISTER inRangeLengthError; + T3_64BIT_REGISTER outRangeLengthError; + T3_64BIT_REGISTER etherStatsPkts64Octets; + T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets; + T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets; + T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets; + T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets; + T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets; + T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets; + T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets; + T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets; + T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets; + + T3_64BIT_REGISTER Unused1[37]; + + /* Statistics maintained by Transmit MAC. */ + T3_64BIT_REGISTER ifHCOutOctets; + T3_64BIT_REGISTER Reserved2; + T3_64BIT_REGISTER etherStatsCollisions; + T3_64BIT_REGISTER outXonSent; + T3_64BIT_REGISTER outXoffSent; + T3_64BIT_REGISTER flowControlDone; + T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors; + T3_64BIT_REGISTER dot3StatsSingleCollisionFrames; + T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames; + T3_64BIT_REGISTER dot3StatsDeferredTransmissions; + T3_64BIT_REGISTER Reserved3; + T3_64BIT_REGISTER dot3StatsExcessiveCollisions; + T3_64BIT_REGISTER dot3StatsLateCollisions; + T3_64BIT_REGISTER dot3Collided2Times; + T3_64BIT_REGISTER dot3Collided3Times; + T3_64BIT_REGISTER dot3Collided4Times; + T3_64BIT_REGISTER dot3Collided5Times; + T3_64BIT_REGISTER dot3Collided6Times; + T3_64BIT_REGISTER dot3Collided7Times; + T3_64BIT_REGISTER dot3Collided8Times; + T3_64BIT_REGISTER dot3Collided9Times; + T3_64BIT_REGISTER dot3Collided10Times; + T3_64BIT_REGISTER dot3Collided11Times; + T3_64BIT_REGISTER dot3Collided12Times; + T3_64BIT_REGISTER dot3Collided13Times; + T3_64BIT_REGISTER dot3Collided14Times; + T3_64BIT_REGISTER dot3Collided15Times; + T3_64BIT_REGISTER ifHCOutUcastPkts; + T3_64BIT_REGISTER ifHCOutMulticastPkts; + T3_64BIT_REGISTER ifHCOutBroadcastPkts; + T3_64BIT_REGISTER dot3StatsCarrierSenseErrors; + T3_64BIT_REGISTER ifOutDiscards; + T3_64BIT_REGISTER ifOutErrors; + + T3_64BIT_REGISTER Unused2[31]; + + /* Statistics maintained by Receive List Placement. */ + T3_64BIT_REGISTER COSIfHCInPkts[16]; + T3_64BIT_REGISTER COSFramesDroppedDueToFilters; + T3_64BIT_REGISTER nicDmaWriteQueueFull; + T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull; + T3_64BIT_REGISTER nicNoMoreRxBDs; + T3_64BIT_REGISTER ifInDiscards; + T3_64BIT_REGISTER ifInErrors; + T3_64BIT_REGISTER nicRecvThresholdHit; + + T3_64BIT_REGISTER Unused3[9]; + + /* Statistics maintained by Send Data Initiator. */ + T3_64BIT_REGISTER COSIfHCOutPkts[16]; + T3_64BIT_REGISTER nicDmaReadQueueFull; + T3_64BIT_REGISTER nicDmaReadHighPriQueueFull; + T3_64BIT_REGISTER nicSendDataCompQueueFull; + + /* Statistics maintained by Host Coalescing. */ + T3_64BIT_REGISTER nicRingSetSendProdIndex; + T3_64BIT_REGISTER nicRingStatusUpdate; + T3_64BIT_REGISTER nicInterrupts; + T3_64BIT_REGISTER nicAvoidedInterrupts; + T3_64BIT_REGISTER nicSendThresholdHit; + + LM_UINT8 Reserved4[0xb00 - 0x9c0]; +} T3_STATS_BLOCK, *PT3_STATS_BLOCK; + +/******************************************************************************/ +/* PCI configuration registers. */ +/******************************************************************************/ + +typedef struct { + T3_16BIT_REGISTER VendorId; + T3_16BIT_REGISTER DeviceId; + + T3_16BIT_REGISTER Command; + T3_16BIT_REGISTER Status; + + T3_32BIT_REGISTER ClassCodeRevId; + + T3_8BIT_REGISTER CacheLineSize; + T3_8BIT_REGISTER LatencyTimer; + T3_8BIT_REGISTER HeaderType; + T3_8BIT_REGISTER Bist; + + T3_32BIT_REGISTER MemBaseAddrLow; + T3_32BIT_REGISTER MemBaseAddrHigh; + + LM_UINT8 Unused1[20]; + + T3_16BIT_REGISTER SubsystemVendorId; + T3_16BIT_REGISTER SubsystemId; + + T3_32BIT_REGISTER RomBaseAddr; + + T3_8BIT_REGISTER PciXCapiblityPtr; + LM_UINT8 Unused2[7]; + + T3_8BIT_REGISTER IntLine; + T3_8BIT_REGISTER IntPin; + T3_8BIT_REGISTER MinGnt; + T3_8BIT_REGISTER MaxLat; + + T3_8BIT_REGISTER PciXCapabilities; + T3_8BIT_REGISTER PmCapabilityPtr; + T3_16BIT_REGISTER PciXCommand; + + T3_32BIT_REGISTER PciXStatus; + + T3_8BIT_REGISTER PmCapabilityId; + T3_8BIT_REGISTER VpdCapabilityPtr; + T3_16BIT_REGISTER PmCapabilities; + + T3_16BIT_REGISTER PmCtrlStatus; +#define PM_CTRL_PME_STATUS BIT_15 +#define PM_CTRL_PME_ENABLE BIT_8 +#define PM_CTRL_PME_POWER_STATE_D0 0 +#define PM_CTRL_PME_POWER_STATE_D1 1 +#define PM_CTRL_PME_POWER_STATE_D2 2 +#define PM_CTRL_PME_POWER_STATE_D3H 3 + + T3_8BIT_REGISTER BridgeSupportExt; + T3_8BIT_REGISTER PmData; + + T3_8BIT_REGISTER VpdCapabilityId; + T3_8BIT_REGISTER MsiCapabilityPtr; + T3_16BIT_REGISTER VpdAddrFlag; +#define VPD_FLAG_WRITE (1 << 15) +#define VPD_FLAG_RW_MASK (1 << 15) +#define VPD_FLAG_READ 0 + + T3_32BIT_REGISTER VpdData; + + T3_8BIT_REGISTER MsiCapabilityId; + T3_8BIT_REGISTER NextCapabilityPtr; + T3_16BIT_REGISTER MsiCtrl; +#define MSI_CTRL_64BIT_CAP (1 << 7) +#define MSI_CTRL_MSG_ENABLE(x) (x << 4) +#define MSI_CTRL_MSG_CAP(x) (x << 1) +#define MSI_CTRL_ENABLE (1 << 0) + + T3_32BIT_REGISTER MsiAddrLow; + T3_32BIT_REGISTER MsiAddrHigh; + + T3_16BIT_REGISTER MsiData; + T3_16BIT_REGISTER Unused3; + + T3_32BIT_REGISTER MiscHostCtrl; +#define MISC_HOST_CTRL_CLEAR_INT BIT_0 +#define MISC_HOST_CTRL_MASK_PCI_INT BIT_1 +#define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP BIT_2 +#define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP BIT_3 +#define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW BIT_4 +#define MISC_HOST_CTRL_ENABLE_CLK_REG_RW BIT_5 +#define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP BIT_6 +#define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS BIT_7 +#define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE BIT_8 +#define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE BIT_9 + + T3_32BIT_REGISTER DmaReadWriteCtrl; +#define DMA_CTRL_WRITE_BOUNDARY_MASK (BIT_11 | BIT_12 | BIT_13) +#define DMA_CTRL_WRITE_BOUNDARY_DISABLE 0 +#define DMA_CTRL_WRITE_BOUNDARY_16 BIT_11 +#define DMA_CTRL_WRITE_BOUNDARY_32 BIT_12 +#define DMA_CTRL_WRITE_BOUNDARY_64 (BIT_12 | BIT_11) +#define DMA_CTRL_WRITE_BOUNDARY_128 BIT_13 +#define DMA_CTRL_WRITE_BOUNDARY_256 (BIT_13 | BIT_11) +#define DMA_CTRL_WRITE_BOUNDARY_512 (BIT_13 | BIT_12) +#define DMA_CTRL_WRITE_BOUNDARY_1024 (BIT_13 | BIT_12 | BIT_11) +#define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE BIT_14 + + T3_32BIT_REGISTER PciState; +#define T3_PCI_STATE_FORCE_PCI_RESET BIT_0 +#define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE BIT_1 +#define T3_PCI_STATE_NOT_PCI_X_BUS BIT_2 +#define T3_PCI_STATE_HIGH_BUS_SPEED BIT_3 +#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 +#define T3_PCI_STATE_PCI_ROM_ENABLE BIT_5 +#define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE BIT_6 +#define T3_PCI_STATE_FLAT_VIEW BIT_8 +#define T3_PCI_STATE_RETRY_SAME_DMA BIT_13 + + T3_32BIT_REGISTER ClockCtrl; +#define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE BIT_11 +#define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE BIT_10 +#define T3_PCI_CLKCTRL_CORE_CLK_DISABLE BIT_9 + + T3_32BIT_REGISTER RegBaseAddr; + + T3_32BIT_REGISTER MemWindowBaseAddr; + +#ifdef NIC_CPU_VIEW + /* These registers are ONLY visible to NIC CPU */ + T3_32BIT_REGISTER PowerConsumed; + T3_32BIT_REGISTER PowerDissipated; +#else /* NIC_CPU_VIEW */ + T3_32BIT_REGISTER RegData; + T3_32BIT_REGISTER MemWindowData; +#endif /* !NIC_CPU_VIEW */ + + T3_32BIT_REGISTER ModeCtrl; + + T3_32BIT_REGISTER MiscCfg; + + T3_32BIT_REGISTER MiscLocalCtrl; + + T3_32BIT_REGISTER Unused4; + + /* NOTE: Big/Little-endian clarification needed. Are these register */ + /* in big or little endian formate. */ + T3_64BIT_REGISTER StdRingProdIdx; + T3_64BIT_REGISTER RcvRetRingConIdx; + T3_64BIT_REGISTER SndProdIdx; + + LM_UINT8 Unused5[80]; +} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION; + +#define PCIX_CMD_MAX_SPLIT_MASK 0x0070 +#define PCIX_CMD_MAX_SPLIT_SHL 4 +#define PCIX_CMD_MAX_BURST_MASK 0x000c +#define PCIX_CMD_MAX_BURST_SHL 2 +#define PCIX_CMD_MAX_BURST_CPIOB 2 + +/******************************************************************************/ +/* Mac control registers. */ +/******************************************************************************/ + +typedef struct { + /* MAC mode control. */ + T3_32BIT_REGISTER Mode; +#define MAC_MODE_GLOBAL_RESET BIT_0 +#define MAC_MODE_HALF_DUPLEX BIT_1 +#define MAC_MODE_PORT_MODE_MASK (BIT_2 | BIT_3) +#define MAC_MODE_PORT_MODE_TBI (BIT_2 | BIT_3) +#define MAC_MODE_PORT_MODE_GMII BIT_3 +#define MAC_MODE_PORT_MODE_MII BIT_2 +#define MAC_MODE_PORT_MODE_NONE BIT_NONE +#define MAC_MODE_PORT_INTERNAL_LOOPBACK BIT_4 +#define MAC_MODE_TAGGED_MAC_CONTROL BIT_7 +#define MAC_MODE_TX_BURSTING BIT_8 +#define MAC_MODE_MAX_DEFER BIT_9 +#define MAC_MODE_LINK_POLARITY BIT_10 +#define MAC_MODE_ENABLE_RX_STATISTICS BIT_11 +#define MAC_MODE_CLEAR_RX_STATISTICS BIT_12 +#define MAC_MODE_FLUSH_RX_STATISTICS BIT_13 +#define MAC_MODE_ENABLE_TX_STATISTICS BIT_14 +#define MAC_MODE_CLEAR_TX_STATISTICS BIT_15 +#define MAC_MODE_FLUSH_TX_STATISTICS BIT_16 +#define MAC_MODE_SEND_CONFIGS BIT_17 +#define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE BIT_18 +#define MAC_MODE_ACPI_POWER_ON_ENABLE BIT_19 +#define MAC_MODE_ENABLE_MIP BIT_20 +#define MAC_MODE_ENABLE_TDE BIT_21 +#define MAC_MODE_ENABLE_RDE BIT_22 +#define MAC_MODE_ENABLE_FHDE BIT_23 + + /* MAC status */ + T3_32BIT_REGISTER Status; +#define MAC_STATUS_PCS_SYNCED BIT_0 +#define MAC_STATUS_SIGNAL_DETECTED BIT_1 +#define MAC_STATUS_RECEIVING_CFG BIT_2 +#define MAC_STATUS_CFG_CHANGED BIT_3 +#define MAC_STATUS_SYNC_CHANGED BIT_4 +#define MAC_STATUS_PORT_DECODE_ERROR BIT_10 +#define MAC_STATUS_LINK_STATE_CHANGED BIT_12 +#define MAC_STATUS_MI_COMPLETION BIT_22 +#define MAC_STATUS_MI_INTERRUPT BIT_23 +#define MAC_STATUS_AP_ERROR BIT_24 +#define MAC_STATUS_ODI_ERROR BIT_25 +#define MAC_STATUS_RX_STATS_OVERRUN BIT_26 +#define MAC_STATUS_TX_STATS_OVERRUN BIT_27 + + /* Event Enable */ + T3_32BIT_REGISTER MacEvent; +#define MAC_EVENT_ENABLE_PORT_DECODE_ERR BIT_10 +#define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN BIT_12 +#define MAC_EVENT_ENABLE_MI_COMPLETION BIT_22 +#define MAC_EVENT_ENABLE_MI_INTERRUPT BIT_23 +#define MAC_EVENT_ENABLE_AP_ERROR BIT_24 +#define MAC_EVENT_ENABLE_ODI_ERROR BIT_25 +#define MAC_EVENT_ENABLE_RX_STATS_OVERRUN BIT_26 +#define MAC_EVENT_ENABLE_TX_STATS_OVERRUN BIT_27 + + /* Led control. */ + T3_32BIT_REGISTER LedCtrl; +#define LED_CTRL_OVERRIDE_LINK_LED BIT_0 +#define LED_CTRL_1000MBPS_LED_ON BIT_1 +#define LED_CTRL_100MBPS_LED_ON BIT_2 +#define LED_CTRL_10MBPS_LED_ON BIT_3 +#define LED_CTRL_OVERRIDE_TRAFFIC_LED BIT_4 +#define LED_CTRL_BLINK_TRAFFIC_LED BIT_5 +#define LED_CTRL_TRAFFIC_LED BIT_6 +#define LED_CTRL_1000MBPS_LED_STATUS BIT_7 +#define LED_CTRL_100MBPS_LED_STATUS BIT_8 +#define LED_CTRL_10MBPS_LED_STATUS BIT_9 +#define LED_CTRL_TRAFFIC_LED_STATUS BIT_10 +#define LED_CTRL_MAC_MODE BIT_NONE +#define LED_CTRL_PHY_MODE_1 BIT_11 +#define LED_CTRL_PHY_MODE_2 BIT_12 +#define LED_CTRL_BLINK_RATE_MASK 0x7ff80000 +#define LED_CTRL_OVERRIDE_BLINK_PERIOD BIT_19 +#define LED_CTRL_OVERRIDE_BLINK_RATE BIT_31 + + /* MAC addresses. */ + struct { + T3_32BIT_REGISTER High; /* Upper 2 bytes. */ + T3_32BIT_REGISTER Low; /* Lower 4 bytes. */ + } MacAddr[4]; + + /* ACPI Mbuf pointer. */ + T3_32BIT_REGISTER AcpiMbufPtr; + + /* ACPI Length and Offset. */ + T3_32BIT_REGISTER AcpiLengthOffset; +#define ACPI_LENGTH_MASK 0xffff +#define ACPI_OFFSET_MASK 0x0fff0000 +#define ACPI_LENGTH(x) x +#define ACPI_OFFSET(x) ((x) << 16) + + /* Transmit random backoff. */ + T3_32BIT_REGISTER TxBackoffSeed; +#define MAC_TX_BACKOFF_SEED_MASK 0x3ff + + /* Receive MTU */ + T3_32BIT_REGISTER MtuSize; +#define MAC_RX_MTU_MASK 0xffff + + /* Gigabit PCS Test. */ + T3_32BIT_REGISTER PcsTest; +#define MAC_PCS_TEST_DATA_PATTERN_MASK 0x0fffff +#define MAC_PCS_TEST_ENABLE BIT_20 + + /* Transmit Gigabit Auto-Negotiation. */ + T3_32BIT_REGISTER TxAutoNeg; +#define MAC_AN_TX_AN_DATA_MASK 0xffff + + /* Receive Gigabit Auto-Negotiation. */ + T3_32BIT_REGISTER RxAutoNeg; +#define MAC_AN_RX_AN_DATA_MASK 0xffff + + /* MI Communication. */ + T3_32BIT_REGISTER MiCom; +#define MI_COM_CMD_MASK (BIT_26 | BIT_27) +#define MI_COM_CMD_WRITE BIT_26 +#define MI_COM_CMD_READ BIT_27 +#define MI_COM_READ_FAILED BIT_28 +#define MI_COM_START BIT_29 +#define MI_COM_BUSY BIT_29 + +#define MI_COM_PHY_ADDR_MASK 0x1f +#define MI_COM_FIRST_PHY_ADDR_BIT 21 + +#define MI_COM_PHY_REG_ADDR_MASK 0x1f +#define MI_COM_FIRST_PHY_REG_ADDR_BIT 16 + +#define MI_COM_PHY_DATA_MASK 0xffff + + /* MI Status. */ + T3_32BIT_REGISTER MiStatus; +#define MI_STATUS_ENABLE_LINK_STATUS_ATTN BIT_0 + + /* MI Mode. */ + T3_32BIT_REGISTER MiMode; +#define MI_MODE_CLOCK_SPEED_10MHZ BIT_0 +#define MI_MODE_USE_SHORT_PREAMBLE BIT_1 +#define MI_MODE_AUTO_POLLING_ENABLE BIT_4 +#define MI_MODE_CORE_CLOCK_SPEED_62MHZ BIT_15 + + /* Auto-polling status. */ + T3_32BIT_REGISTER AutoPollStatus; +#define AUTO_POLL_ERROR BIT_0 + + /* Transmit MAC mode. */ + T3_32BIT_REGISTER TxMode; +#define TX_MODE_RESET BIT_0 +#define TX_MODE_ENABLE BIT_1 +#define TX_MODE_ENABLE_FLOW_CONTROL BIT_4 +#define TX_MODE_ENABLE_BIG_BACKOFF BIT_5 +#define TX_MODE_ENABLE_LONG_PAUSE BIT_6 + + /* Transmit MAC status. */ + T3_32BIT_REGISTER TxStatus; +#define TX_STATUS_RX_CURRENTLY_XOFFED BIT_0 +#define TX_STATUS_SENT_XOFF BIT_1 +#define TX_STATUS_SENT_XON BIT_2 +#define TX_STATUS_LINK_UP BIT_3 +#define TX_STATUS_ODI_UNDERRUN BIT_4 +#define TX_STATUS_ODI_OVERRUN BIT_5 + + /* Transmit MAC length. */ + T3_32BIT_REGISTER TxLengths; +#define TX_LEN_SLOT_TIME_MASK 0xff +#define TX_LEN_IPG_MASK 0x0f00 +#define TX_LEN_IPG_CRS_MASK (BIT_12 | BIT_13) + + /* Receive MAC mode. */ + T3_32BIT_REGISTER RxMode; +#define RX_MODE_RESET BIT_0 +#define RX_MODE_ENABLE BIT_1 +#define RX_MODE_ENABLE_FLOW_CONTROL BIT_2 +#define RX_MODE_KEEP_MAC_CONTROL BIT_3 +#define RX_MODE_KEEP_PAUSE BIT_4 +#define RX_MODE_ACCEPT_OVERSIZED BIT_5 +#define RX_MODE_ACCEPT_RUNTS BIT_6 +#define RX_MODE_LENGTH_CHECK BIT_7 +#define RX_MODE_PROMISCUOUS_MODE BIT_8 +#define RX_MODE_NO_CRC_CHECK BIT_9 +#define RX_MODE_KEEP_VLAN_TAG BIT_10 + + /* Receive MAC status. */ + T3_32BIT_REGISTER RxStatus; +#define RX_STATUS_REMOTE_TRANSMITTER_XOFFED BIT_0 +#define RX_STATUS_XOFF_RECEIVED BIT_1 +#define RX_STATUS_XON_RECEIVED BIT_2 + + /* Hash registers. */ + T3_32BIT_REGISTER HashReg[4]; + + /* Receive placement rules registers. */ + struct { + T3_32BIT_REGISTER Rule; + T3_32BIT_REGISTER Value; + } RcvRules[16]; + +#define RCV_DISABLE_RULE_MASK 0x7fffffff + +#define RCV_RULE1_REJECT_BROADCAST_IDX 0x00 +#define REJECT_BROADCAST_RULE1_RULE 0xc2000000 +#define REJECT_BROADCAST_RULE1_VALUE 0xffffffff + +#define RCV_RULE2_REJECT_BROADCAST_IDX 0x01 +#define REJECT_BROADCAST_RULE2_RULE 0x86000004 +#define REJECT_BROADCAST_RULE2_VALUE 0xffffffff + +#if INCLUDE_5701_AX_FIX +#define RCV_LAST_RULE_IDX 0x04 +#else +#define RCV_LAST_RULE_IDX 0x02 +#endif + + T3_32BIT_REGISTER RcvRuleCfg; +#define RX_RULE_DEFAULT_CLASS (1 << 3) + + LM_UINT8 Reserved1[140]; + + T3_32BIT_REGISTER SerdesCfg; + T3_32BIT_REGISTER SerdesStatus; + + LM_UINT8 Reserved2[104]; + + volatile LM_UINT8 TxMacState[16]; + volatile LM_UINT8 RxMacState[20]; + + LM_UINT8 Reserved3[476]; + + T3_32BIT_REGISTER RxStats[26]; + + LM_UINT8 Reserved4[24]; + + T3_32BIT_REGISTER TxStats[28]; + + LM_UINT8 Reserved5[784]; +} T3_MAC_CONTROL, *PT3_MAC_CONTROL; + +/******************************************************************************/ +/* Send data initiator control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define T3_SND_DATA_IN_MODE_RESET BIT_0 +#define T3_SND_DATA_IN_MODE_ENABLE BIT_1 +#define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN BIT_2 + + T3_32BIT_REGISTER StatsCtrl; +#define T3_SND_DATA_IN_STATS_CTRL_ENABLE BIT_0 +#define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE BIT_1 +#define T3_SND_DATA_IN_STATS_CTRL_CLEAR BIT_2 +#define T3_SND_DATA_IN_STATS_CTRL_FLUSH BIT_3 +#define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO BIT_4 + + T3_32BIT_REGISTER StatsEnableMask; + T3_32BIT_REGISTER StatsIncMask; + + LM_UINT8 Reserved[108]; + + T3_32BIT_REGISTER ClassOfServCnt[16]; + T3_32BIT_REGISTER DmaReadQFullCnt; + T3_32BIT_REGISTER DmaPriorityReadQFullCnt; + T3_32BIT_REGISTER SdcQFullCnt; + + T3_32BIT_REGISTER NicRingSetSendProdIdxCnt; + T3_32BIT_REGISTER StatusUpdatedCnt; + T3_32BIT_REGISTER InterruptsCnt; + T3_32BIT_REGISTER AvoidInterruptsCnt; + T3_32BIT_REGISTER SendThresholdHitCnt; + + /* Unused space. */ + LM_UINT8 Unused[800]; +} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR; + +/******************************************************************************/ +/* Send data completion control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define SND_DATA_COMP_MODE_RESET BIT_0 +#define SND_DATA_COMP_MODE_ENABLE BIT_1 + + /* Unused space. */ + LM_UINT8 Unused[1020]; +} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION; + +/******************************************************************************/ +/* Send BD Ring Selector Control Registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define SND_BD_SEL_MODE_RESET BIT_0 +#define SND_BD_SEL_MODE_ENABLE BIT_1 +#define SND_BD_SEL_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define SND_BD_SEL_STATUS_ERROR_ATTN BIT_2 + + T3_32BIT_REGISTER HwDiag; + + /* Unused space. */ + LM_UINT8 Unused1[52]; + + /* Send BD Ring Selector Local NIC Send BD Consumer Index. */ + T3_32BIT_REGISTER NicSendBdSelConIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused2[896]; +} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR; + +/******************************************************************************/ +/* Send BD initiator control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define SND_BD_IN_MODE_RESET BIT_0 +#define SND_BD_IN_MODE_ENABLE BIT_1 +#define SND_BD_IN_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define SND_BD_IN_STATUS_ERROR_ATTN BIT_2 + + /* Send BD initiator local NIC send BD producer index. */ + T3_32BIT_REGISTER NicSendBdInProdIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused2[952]; +} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR; + +/******************************************************************************/ +/* Send BD Completion Control. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define SND_BD_COMP_MODE_RESET BIT_0 +#define SND_BD_COMP_MODE_ENABLE BIT_1 +#define SND_BD_COMP_MODE_ATTN_ENABLE BIT_2 + + /* Unused space. */ + LM_UINT8 Unused2[1020]; +} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION; + +/******************************************************************************/ +/* Receive list placement control registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; +#define RCV_LIST_PLMT_MODE_RESET BIT_0 +#define RCV_LIST_PLMT_MODE_ENABLE BIT_1 +#define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE BIT_2 +#define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE BIT_3 +#define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE BIT_4 + + /* Status. */ + T3_32BIT_REGISTER Status; +#define RCV_LIST_PLMT_STATUS_CLASS0_ATTN BIT_2 +#define RCV_LIST_PLMT_STATUS_MAPPING_ATTN BIT_3 +#define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN BIT_4 + + /* Receive selector list lock register. */ + T3_32BIT_REGISTER Lock; +#define RCV_LIST_SEL_LOCK_REQUEST_MASK 0xffff +#define RCV_LIST_SEL_LOCK_GRANT_MASK 0xffff0000 + + /* Selector non-empty bits. */ + T3_32BIT_REGISTER NonEmptyBits; +#define RCV_LIST_SEL_NON_EMPTY_MASK 0xffff + + /* Receive list placement configuration register. */ + T3_32BIT_REGISTER Config; + + /* Receive List Placement statistics Control. */ + T3_32BIT_REGISTER StatsCtrl; +#define RCV_LIST_STATS_ENABLE BIT_0 +#define RCV_LIST_STATS_FAST_UPDATE BIT_1 + + /* Receive List Placement statistics Enable Mask. */ + T3_32BIT_REGISTER StatsEnableMask; + + /* Receive List Placement statistics Increment Mask. */ + T3_32BIT_REGISTER StatsIncMask; + + /* Unused space. */ + LM_UINT8 Unused1[224]; + + struct { + T3_32BIT_REGISTER Head; + T3_32BIT_REGISTER Tail; + T3_32BIT_REGISTER Count; + + /* Unused space. */ + LM_UINT8 Unused[4]; + } RcvSelectorList[16]; + + /* Local statistics counter. */ + T3_32BIT_REGISTER ClassOfServCnt[16]; + + T3_32BIT_REGISTER DropDueToFilterCnt; + T3_32BIT_REGISTER DmaWriteQFullCnt; + T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt; + T3_32BIT_REGISTER NoMoreReceiveBdCnt; + T3_32BIT_REGISTER IfInDiscardsCnt; + T3_32BIT_REGISTER IfInErrorsCnt; + T3_32BIT_REGISTER RcvThresholdHitCnt; + + /* Another unused space. */ + LM_UINT8 Unused2[420]; +} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT; + +/******************************************************************************/ +/* Receive Data and Receive BD Initiator Control. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; +#define RCV_DATA_BD_IN_MODE_RESET BIT_0 +#define RCV_DATA_BD_IN_MODE_ENABLE BIT_1 +#define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED BIT_2 +#define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG BIT_3 +#define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE BIT_4 + + /* Status. */ + T3_32BIT_REGISTER Status; +#define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED BIT_2 +#define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG BIT_3 +#define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE BIT_4 + + /* Split frame minium size. */ + T3_32BIT_REGISTER SplitFrameMinSize; + + /* Unused space. */ + LM_UINT8 Unused1[0x2440 - 0x240c]; + + /* Receive RCBs. */ + T3_RCB JumboRcvRcb; + T3_RCB StdRcvRcb; + T3_RCB MiniRcvRcb; + + /* Receive Data and Receive BD Ring Initiator Local NIC Receive */ + /* BD Consumber Index. */ + T3_32BIT_REGISTER NicJumboConIdx; + T3_32BIT_REGISTER NicStdConIdx; + T3_32BIT_REGISTER NicMiniConIdx; + + /* Unused space. */ + LM_UINT8 Unused2[4]; + + /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */ + T3_32BIT_REGISTER RcvDataBdProdIdx[16]; + + /* Receive Data and Receive BD Initiator Hardware Diagnostic. */ + T3_32BIT_REGISTER HwDiag; + + /* Unused space. */ + LM_UINT8 Unused3[828]; +} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR; + +/******************************************************************************/ +/* Receive Data Completion Control Registes. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define RCV_DATA_COMP_MODE_RESET BIT_0 +#define RCV_DATA_COMP_MODE_ENABLE BIT_1 +#define RCV_DATA_COMP_MODE_ATTN_ENABLE BIT_2 + + /* Unused spaced. */ + LM_UINT8 Unused[1020]; +} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION; + +/******************************************************************************/ +/* Receive BD Initiator Control. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define RCV_BD_IN_MODE_RESET BIT_0 +#define RCV_BD_IN_MODE_ENABLE BIT_1 +#define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN BIT_2 + + T3_32BIT_REGISTER NicJumboRcvProdIdx; + T3_32BIT_REGISTER NicStdRcvProdIdx; + T3_32BIT_REGISTER NicMiniRcvProdIdx; + + T3_32BIT_REGISTER MiniRcvThreshold; + T3_32BIT_REGISTER StdRcvThreshold; + T3_32BIT_REGISTER JumboRcvThreshold; + + /* Unused space. */ + LM_UINT8 Unused[992]; +} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR; + +/******************************************************************************/ +/* Receive BD Completion Control Registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define RCV_BD_COMP_MODE_RESET BIT_0 +#define RCV_BD_COMP_MODE_ENABLE BIT_1 +#define RCV_BD_COMP_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define RCV_BD_COMP_STATUS_ERROR_ATTN BIT_2 + + T3_32BIT_REGISTER NicJumboRcvBdProdIdx; + T3_32BIT_REGISTER NicStdRcvBdProdIdx; + T3_32BIT_REGISTER NicMiniRcvBdProdIdx; + + /* Unused space. */ + LM_UINT8 Unused[1004]; +} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION; + +/******************************************************************************/ +/* Receive list selector control register. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define RCV_LIST_SEL_MODE_RESET BIT_0 +#define RCV_LIST_SEL_MODE_ENABLE BIT_1 +#define RCV_LIST_SEL_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; +#define RCV_LIST_SEL_STATUS_ERROR_ATTN BIT_2 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR; + +/******************************************************************************/ +/* Mbuf cluster free registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define MBUF_CLUSTER_FREE_MODE_RESET BIT_0 +#define MBUF_CLUSTER_FREE_MODE_ENABLE BIT_1 + + T3_32BIT_REGISTER Status; + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE; + +/******************************************************************************/ +/* Host coalescing control registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; +#define HOST_COALESCE_RESET BIT_0 +#define HOST_COALESCE_ENABLE BIT_1 +#define HOST_COALESCE_ATTN BIT_2 +#define HOST_COALESCE_NOW BIT_3 +#define HOST_COALESCE_FULL_STATUS_MODE BIT_NONE +#define HOST_COALESCE_64_BYTE_STATUS_MODE BIT_7 +#define HOST_COALESCE_32_BYTE_STATUS_MODE BIT_8 +#define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT BIT_9 +#define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT BIT_10 +#define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE BIT_11 +#define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE BIT_12 + + /* Status. */ + T3_32BIT_REGISTER Status; +#define HOST_COALESCE_ERROR_ATTN BIT_2 + + /* Receive coalescing ticks. */ + T3_32BIT_REGISTER RxCoalescingTicks; + + /* Send coalescing ticks. */ + T3_32BIT_REGISTER TxCoalescingTicks; + + /* Receive max coalesced frames. */ + T3_32BIT_REGISTER RxMaxCoalescedFrames; + + /* Send max coalesced frames. */ + T3_32BIT_REGISTER TxMaxCoalescedFrames; + + /* Receive coalescing ticks during interrupt. */ + T3_32BIT_REGISTER RxCoalescedTickDuringInt; + + /* Send coalescing ticks during interrupt. */ + T3_32BIT_REGISTER TxCoalescedTickDuringInt; + + /* Receive max coalesced frames during interrupt. */ + T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt; + + /* Send max coalesced frames during interrupt. */ + T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt; + + /* Statistics tick. */ + T3_32BIT_REGISTER StatsCoalescingTicks; + + /* Unused space. */ + LM_UINT8 Unused2[4]; + + /* Statistics host address. */ + T3_64BIT_REGISTER StatsBlkHostAddr; + + /* Status block host address. */ + T3_64BIT_REGISTER StatusBlkHostAddr; + + /* Statistics NIC address. */ + T3_32BIT_REGISTER StatsBlkNicAddr; + + /* Statust block NIC address. */ + T3_32BIT_REGISTER StatusBlkNicAddr; + + /* Flow attention registers. */ + T3_32BIT_REGISTER FlowAttn; + + /* Unused space. */ + LM_UINT8 Unused3[4]; + + T3_32BIT_REGISTER NicJumboRcvBdConIdx; + T3_32BIT_REGISTER NicStdRcvBdConIdx; + T3_32BIT_REGISTER NicMiniRcvBdConIdx; + + /* Unused space. */ + LM_UINT8 Unused4[36]; + + T3_32BIT_REGISTER NicRetProdIdx[16]; + T3_32BIT_REGISTER NicSndBdConIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused5[768]; +} T3_HOST_COALESCING, *PT3_HOST_COALESCING; + +/******************************************************************************/ +/* Memory arbiter registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define T3_MEM_ARBITER_MODE_RESET BIT_0 +#define T3_MEM_ARBITER_MODE_ENABLE BIT_1 + + T3_32BIT_REGISTER Status; + + T3_32BIT_REGISTER ArbTrapAddrLow; + T3_32BIT_REGISTER ArbTrapAddrHigh; + + /* Unused space. */ + LM_UINT8 Unused[1008]; +} T3_MEM_ARBITER, *PT3_MEM_ARBITER; + +/******************************************************************************/ +/* Buffer manager control register. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define BUFMGR_MODE_RESET BIT_0 +#define BUFMGR_MODE_ENABLE BIT_1 +#define BUFMGR_MODE_ATTN_ENABLE BIT_2 +#define BUFMGR_MODE_BM_TEST BIT_3 +#define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE BIT_4 + + T3_32BIT_REGISTER Status; +#define BUFMGR_STATUS_ERROR BIT_2 +#define BUFMGR_STATUS_MBUF_LOW BIT_4 + + T3_32BIT_REGISTER MbufPoolAddr; + T3_32BIT_REGISTER MbufPoolSize; + T3_32BIT_REGISTER MbufReadDmaLowWaterMark; + T3_32BIT_REGISTER MbufMacRxLowWaterMark; + T3_32BIT_REGISTER MbufHighWaterMark; + + T3_32BIT_REGISTER RxCpuMbufAllocReq; +#define BUFMGR_MBUF_ALLOC_BIT BIT_31 + T3_32BIT_REGISTER RxCpuMbufAllocResp; + T3_32BIT_REGISTER TxCpuMbufAllocReq; + T3_32BIT_REGISTER TxCpuMbufAllocResp; + + T3_32BIT_REGISTER DmaDescPoolAddr; + T3_32BIT_REGISTER DmaDescPoolSize; + T3_32BIT_REGISTER DmaLowWaterMark; + T3_32BIT_REGISTER DmaHighWaterMark; + + T3_32BIT_REGISTER RxCpuDmaAllocReq; + T3_32BIT_REGISTER RxCpuDmaAllocResp; + T3_32BIT_REGISTER TxCpuDmaAllocReq; + T3_32BIT_REGISTER TxCpuDmaAllocResp; + + T3_32BIT_REGISTER Hwdiag[3]; + + /* Unused space. */ + LM_UINT8 Unused[936]; +} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER; + +/******************************************************************************/ +/* Read DMA control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define DMA_READ_MODE_RESET BIT_0 +#define DMA_READ_MODE_ENABLE BIT_1 +#define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 +#define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 +#define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 +#define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 +#define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 +#define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 +#define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 +#define DMA_READ_MODE_LONG_READ_ATTN_ENABLE BIT_9 +#define DMA_READ_MODE_SPLIT_ENABLE BIT_11 +#define DMA_READ_MODE_SPLIT_RESET BIT_12 + + T3_32BIT_REGISTER Status; +#define DMA_READ_STATUS_TARGET_ABORT_ATTN BIT_2 +#define DMA_READ_STATUS_MASTER_ABORT_ATTN BIT_3 +#define DMA_READ_STATUS_PARITY_ERROR_ATTN BIT_4 +#define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN BIT_5 +#define DMA_READ_STATUS_FIFO_OVERRUN_ATTN BIT_6 +#define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN BIT_7 +#define DMA_READ_STATUS_FIFO_OVERREAD_ATTN BIT_8 +#define DMA_READ_STATUS_LONG_READ_ATTN BIT_9 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_DMA_READ, *PT3_DMA_READ; + +typedef union T3_CPU { + struct { + T3_32BIT_REGISTER mode; +#define CPU_MODE_HALT BIT_10 +#define CPU_MODE_RESET BIT_0 + T3_32BIT_REGISTER state; + T3_32BIT_REGISTER EventMask; + T3_32BIT_REGISTER reserved1[4]; + T3_32BIT_REGISTER PC; + T3_32BIT_REGISTER Instruction; + T3_32BIT_REGISTER SpadUnderflow; + T3_32BIT_REGISTER WatchdogClear; + T3_32BIT_REGISTER WatchdogVector; + T3_32BIT_REGISTER WatchdogSavedPC; + T3_32BIT_REGISTER HardwareBp; + T3_32BIT_REGISTER reserved2[3]; + T3_32BIT_REGISTER WatchdogSavedState; + T3_32BIT_REGISTER LastBrchAddr; + T3_32BIT_REGISTER SpadUnderflowSet; + T3_32BIT_REGISTER reserved3[(0x200 - 0x50) / 4]; + T3_32BIT_REGISTER Regs[32]; + T3_32BIT_REGISTER reserved4[(0x400 - 0x280) / 4]; + } reg; +} T3_CPU, *PT3_CPU; + +/******************************************************************************/ +/* Write DMA control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define DMA_WRITE_MODE_RESET BIT_0 +#define DMA_WRITE_MODE_ENABLE BIT_1 +#define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 +#define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 +#define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 +#define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 +#define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 +#define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 +#define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 +#define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE BIT_9 + + T3_32BIT_REGISTER Status; +#define DMA_WRITE_STATUS_TARGET_ABORT_ATTN BIT_2 +#define DMA_WRITE_STATUS_MASTER_ABORT_ATTN BIT_3 +#define DMA_WRITE_STATUS_PARITY_ERROR_ATTN BIT_4 +#define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN BIT_5 +#define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN BIT_6 +#define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN BIT_7 +#define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN BIT_8 +#define DMA_WRITE_STATUS_LONG_READ_ATTN BIT_9 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_DMA_WRITE, *PT3_DMA_WRITE; + +/******************************************************************************/ +/* Mailbox registers. */ +/******************************************************************************/ + +typedef struct { + /* Interrupt mailbox registers. */ + T3_64BIT_REGISTER Interrupt[4]; + + /* General mailbox registers. */ + T3_64BIT_REGISTER General[8]; + + /* Reload statistics mailbox. */ + T3_64BIT_REGISTER ReloadStat; + + /* Receive BD ring producer index registers. */ + T3_64BIT_REGISTER RcvStdProdIdx; + T3_64BIT_REGISTER RcvJumboProdIdx; + T3_64BIT_REGISTER RcvMiniProdIdx; + + /* Receive return ring consumer index registers. */ + T3_64BIT_REGISTER RcvRetConIdx[16]; + + /* Send BD ring host producer index registers. */ + T3_64BIT_REGISTER SendHostProdIdx[16]; + + /* Send BD ring nic producer index registers. */ + T3_64BIT_REGISTER SendNicProdIdx[16]; +} T3_MAILBOX, *PT3_MAILBOX; + +typedef struct { + T3_MAILBOX Mailbox; + + /* Priority mailbox registers. */ + T3_32BIT_REGISTER HighPriorityEventVector; + T3_32BIT_REGISTER HighPriorityEventMask; + T3_32BIT_REGISTER LowPriorityEventVector; + T3_32BIT_REGISTER LowPriorityEventMask; + + /* Unused space. */ + LM_UINT8 Unused[496]; +} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX; + +/******************************************************************************/ +/* Flow through queues. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Reset; + + LM_UINT8 Unused[12]; + + T3_32BIT_REGISTER DmaNormalReadFtqCtrl; + T3_32BIT_REGISTER DmaNormalReadFtqFullCnt; + T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaHighReadFtqCtrl; + T3_32BIT_REGISTER DmaHighReadFtqFullCnt; + T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaCompDiscardFtqCtrl; + T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt; + T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek; + + T3_32BIT_REGISTER SendBdCompFtqCtrl; + T3_32BIT_REGISTER SendBdCompFtqFullCnt; + T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek; + + T3_32BIT_REGISTER SendDataInitiatorFtqCtrl; + T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt; + T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaNormalWriteFtqCtrl; + T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt; + T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaHighWriteFtqCtrl; + T3_32BIT_REGISTER DmaHighWriteFtqFullCnt; + T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek; + + T3_32BIT_REGISTER SwType1FtqCtrl; + T3_32BIT_REGISTER SwType1FtqFullCnt; + T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SwType1FtqFifoWritePeek; + + T3_32BIT_REGISTER SendDataCompFtqCtrl; + T3_32BIT_REGISTER SendDataCompFtqFullCnt; + T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek; + + T3_32BIT_REGISTER HostCoalesceFtqCtrl; + T3_32BIT_REGISTER HostCoalesceFtqFullCnt; + T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek; + + T3_32BIT_REGISTER MacTxFtqCtrl; + T3_32BIT_REGISTER MacTxFtqFullCnt; + T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER MacTxFtqFifoWritePeek; + + T3_32BIT_REGISTER MbufClustFreeFtqCtrl; + T3_32BIT_REGISTER MbufClustFreeFtqFullCnt; + T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvBdCompFtqCtrl; + T3_32BIT_REGISTER RcvBdCompFtqFullCnt; + T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvListPlmtFtqCtrl; + T3_32BIT_REGISTER RcvListPlmtFtqFullCnt; + T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvDataCompFtqCtrl; + T3_32BIT_REGISTER RcvDataCompFtqFullCnt; + T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek; + + T3_32BIT_REGISTER SwType2FtqCtrl; + T3_32BIT_REGISTER SwType2FtqFullCnt; + T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SwType2FtqFifoWritePeek; + + /* Unused space. */ + LM_UINT8 Unused2[736]; +} T3_FTQ, *PT3_FTQ; + +/******************************************************************************/ +/* Message signaled interrupt registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define MSI_MODE_RESET BIT_0 +#define MSI_MODE_ENABLE BIT_1 + T3_32BIT_REGISTER Status; + + T3_32BIT_REGISTER MsiFifoAccess; + + /* Unused space. */ + LM_UINT8 Unused[1012]; +} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT; + +/******************************************************************************/ +/* DMA Completion registes. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define DMA_COMP_MODE_RESET BIT_0 +#define DMA_COMP_MODE_ENABLE BIT_1 + + /* Unused space. */ + LM_UINT8 Unused[1020]; +} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION; + +/******************************************************************************/ +/* GRC registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode control register. */ + T3_32BIT_REGISTER Mode; +#define GRC_MODE_UPDATE_ON_COALESCING BIT_0 +#define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA BIT_1 +#define GRC_MODE_WORD_SWAP_NON_FRAME_DATA BIT_2 +#define GRC_MODE_BYTE_SWAP_DATA BIT_4 +#define GRC_MODE_WORD_SWAP_DATA BIT_5 +#define GRC_MODE_SPLIT_HEADER_MODE BIT_8 +#define GRC_MODE_NO_FRAME_CRACKING BIT_9 +#define GRC_MODE_INCLUDE_CRC BIT_10 +#define GRC_MODE_ALLOW_BAD_FRAMES BIT_11 +#define GRC_MODE_NO_INTERRUPT_ON_SENDS BIT_13 +#define GRC_MODE_NO_INTERRUPT_ON_RECEIVE BIT_14 +#define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE BIT_15 +#define GRC_MODE_HOST_STACK_UP BIT_16 +#define GRC_MODE_HOST_SEND_BDS BIT_17 +#define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM BIT_20 +#define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM BIT_23 +#define GRC_MODE_INT_ON_TX_CPU_ATTN BIT_24 +#define GRC_MODE_INT_ON_RX_CPU_ATTN BIT_25 +#define GRC_MODE_INT_ON_MAC_ATTN BIT_26 +#define GRC_MODE_INT_ON_DMA_ATTN BIT_27 +#define GRC_MODE_INT_ON_FLOW_ATTN BIT_28 +#define GRC_MODE_4X_NIC_BASED_SEND_RINGS BIT_29 +#define GRC_MODE_MULTICAST_FRAME_ENABLE BIT_30 + + /* Misc configuration register. */ + T3_32BIT_REGISTER MiscCfg; +#define GRC_MISC_CFG_CORE_CLOCK_RESET BIT_0 +#define GRC_MISC_PRESCALAR_TIMER_MASK 0xfe +#define GRC_MISC_BD_ID_MASK 0x0001e000 +#define GRC_MISC_BD_ID_5700 0x0001e000 +#define GRC_MISC_BD_ID_5701 0x00000000 +#define GRC_MISC_BD_ID_5703 0x00000000 +#define GRC_MISC_BD_ID_5703S 0x00002000 +#define GRC_MISC_BD_ID_5702FE 0x00004000 +#define GRC_MISC_BD_ID_5704 0x00000000 +#define GRC_MISC_BD_ID_5704CIOBE 0x00004000 + + /* Miscellaneous local control register. */ + T3_32BIT_REGISTER LocalCtrl; +#define GRC_MISC_LOCAL_CTRL_INT_ACTIVE BIT_0 +#define GRC_MISC_LOCAL_CTRL_CLEAR_INT BIT_1 +#define GRC_MISC_LOCAL_CTRL_SET_INT BIT_2 +#define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN BIT_3 +#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0 BIT_8 +#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1 BIT_9 +#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2 BIT_10 +#define GRC_MISC_LOCAL_CTRL_GPIO_OE0 BIT_11 +#define GRC_MISC_LOCAL_CTRL_GPIO_OE1 BIT_12 +#define GRC_MISC_LOCAL_CTRL_GPIO_OE2 BIT_13 +#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 BIT_14 +#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 BIT_15 +#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2 BIT_16 +#define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY BIT_17 +#define GRC_MISC_LOCAL_CTRL_BANK_SELECT BIT_21 +#define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE BIT_22 + +#define GRC_MISC_MEMSIZE_256K 0 +#define GRC_MISC_MEMSIZE_512K (1 << 18) +#define GRC_MISC_MEMSIZE_1024K (2 << 18) +#define GRC_MISC_MEMSIZE_2048K (3 << 18) +#define GRC_MISC_MEMSIZE_4096K (4 << 18) +#define GRC_MISC_MEMSIZE_8192K (5 << 18) +#define GRC_MISC_MEMSIZE_16M (6 << 18) +#define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM BIT_24 + + T3_32BIT_REGISTER Timer; + + T3_32BIT_REGISTER RxCpuEvent; + T3_32BIT_REGISTER RxTimerRef; + T3_32BIT_REGISTER RxCpuSemaphore; + T3_32BIT_REGISTER RemoteRxCpuAttn; + + T3_32BIT_REGISTER TxCpuEvent; + T3_32BIT_REGISTER TxTimerRef; + T3_32BIT_REGISTER TxCpuSemaphore; + T3_32BIT_REGISTER RemoteTxCpuAttn; + + T3_64BIT_REGISTER MemoryPowerUp; + + T3_32BIT_REGISTER EepromAddr; +#define SEEPROM_ADDR_WRITE 0 +#define SEEPROM_ADDR_READ (1 << 31) +#define SEEPROM_ADDR_RW_MASK 0x80000000 +#define SEEPROM_ADDR_COMPLETE (1 << 30) +#define SEEPROM_ADDR_FSM_RESET (1 << 29) +#define SEEPROM_ADDR_DEV_ID(x) (x << 26) +#define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000 +#define SEEPROM_ADDR_START (1 << 25) +#define SEEPROM_ADDR_CLK_PERD(x) (x << 16) +#define SEEPROM_ADDR_ADDRESS(x) (x & 0xfffc) +#define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff + +#define SEEPROM_CLOCK_PERIOD 60 +#define SEEPROM_CHIP_SIZE (64 * 1024) + + T3_32BIT_REGISTER EepromData; + T3_32BIT_REGISTER EepromCtrl; + + T3_32BIT_REGISTER MdiCtrl; + T3_32BIT_REGISTER SepromDelay; + + /* Unused space. */ + LM_UINT8 Unused[948]; +} T3_GRC, *PT3_GRC; + +/******************************************************************************/ +/* NVRAM control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Cmd; +#define NVRAM_CMD_RESET BIT_0 +#define NVRAM_CMD_DONE BIT_3 +#define NVRAM_CMD_DO_IT BIT_4 +#define NVRAM_CMD_WR BIT_5 +#define NVRAM_CMD_RD BIT_NONE +#define NVRAM_CMD_ERASE BIT_6 +#define NVRAM_CMD_FIRST BIT_7 +#define NVRAM_CMD_LAST BIT_8 + + T3_32BIT_REGISTER Status; + T3_32BIT_REGISTER WriteData; + + T3_32BIT_REGISTER Addr; +#define NVRAM_ADDRESS_MASK 0xffffff + + T3_32BIT_REGISTER ReadData; + + /* Flash config 1 register. */ + T3_32BIT_REGISTER Config1; +#define FLASH_INTERFACE_ENABLE BIT_0 +#define FLASH_SSRAM_BUFFERRED_MODE BIT_1 +#define FLASH_PASS_THRU_MODE BIT_2 +#define FLASH_BIT_BANG_MODE BIT_3 +#define FLASH_COMPAT_BYPASS BIT_31 + + /* Buffered flash (Atmel: AT45DB011B) specific information */ +#define BUFFERED_FLASH_PAGE_POS 9 +#define BUFFERED_FLASH_BYTE_ADDR_MASK ((1<pMemView->OffsetName)) + +#define REG_WR(pDevice, OffsetName, Value32) \ + (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) && \ + (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) || \ + ((pDevice)->EnablePciXFix == FALSE)) ? \ + (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) + +#define MB_REG_RD(pDevice, OffsetName) \ + readl(&((pDevice)->pMemView->OffsetName)) + +#define MB_REG_WR(pDevice, OffsetName, Value32) \ + writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define REG_RD_OFFSET(pDevice, Offset) \ + readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset)) + +#define REG_WR_OFFSET(pDevice, Offset, Value32) \ + (((Offset >=0x200 ) && (Offset < 0x400)) || \ + ((pDevice)->EnablePciXFix == FALSE)) ? \ + (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \ + LM_RegWrInd(pDevice, Offset, Value32) + +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#else /* normal target access path below */ + +/* Register access. */ +#define REG_RD(pDevice, OffsetName) \ + readl(&((pDevice)->pMemView->OffsetName)) +#define REG_WR(pDevice, OffsetName, Value32) \ + writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define REG_RD_OFFSET(pDevice, Offset) \ + readl(((LM_UINT8 *) (pDevice)->pMemView + Offset)) +#define REG_WR_OFFSET(pDevice, Offset, Value32) \ + writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) + +/* There could be problem access the memory window directly. For now, */ +/* we have to go through the PCI configuration register. */ +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#endif /* PCIX_TARGET_WORKAROUND */ + +#endif /* Jimmy, merging */ + + /* Jimmy...rest of file is new stuff! */ +/******************************************************************************/ +/* NIC register read/write macros. */ +/******************************************************************************/ + +/* MAC register access. */ +LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register); +LM_VOID LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, + LM_UINT32 Value32); + +/* MAC memory access. */ +LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr); +LM_VOID LM_MemWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, + LM_UINT32 Value32); + +#define MB_REG_WR(pDevice, OffsetName, Value32) \ + ((pDevice)->UndiFix) ? \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600, \ + Value32) : \ + (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define MB_REG_RD(pDevice, OffsetName) \ + (((pDevice)->UndiFix) ? \ + LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) : \ + __raw_readl(&((pDevice)->pMemView->OffsetName))) + +#define REG_RD(pDevice, OffsetName) \ + (((pDevice)->UndiFix) ? \ + LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) : \ + __raw_readl(&((pDevice)->pMemView->OffsetName))) + +#if PCIX_TARGET_WORKAROUND + +#define REG_WR(pDevice, OffsetName, Value32) \ + ((pDevice)->EnablePciXFix == FALSE) ? \ + (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) + +#else + +#define REG_WR(pDevice, OffsetName, Value32) \ + __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#endif + +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#endif /* TIGON3_H */ diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c new file mode 100644 index 0000000000..ca6284b726 --- /dev/null +++ b/drivers/net/tsec.c @@ -0,0 +1,1590 @@ +/* + * Freescale Three Speed Ethernet Controller driver + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * Copyright 2004, 2007 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * author Andy Fleming + * + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_TSEC_ENET) +#include "tsec.h" +#include "miiphy.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define TX_BUF_CNT 2 + +static uint rxIdx; /* index of the current RX buffer */ +static uint txIdx; /* index of the current TX buffer */ + +typedef volatile struct rtxbd { + txbd8_t txbd[TX_BUF_CNT]; + rxbd8_t rxbd[PKTBUFSRX]; +} RTXBD; + +struct tsec_info_struct { + unsigned int phyaddr; + u32 flags; + unsigned int phyregidx; +}; + +/* The tsec_info structure contains 3 values which the + * driver uses to determine how to operate a given ethernet + * device. The information needed is: + * phyaddr - The address of the PHY which is attached to + * the given device. + * + * flags - This variable indicates whether the device + * supports gigabit speed ethernet, and whether it should be + * in reduced mode. + * + * phyregidx - This variable specifies which ethernet device + * controls the MII Management registers which are connected + * to the PHY. For now, only TSEC1 (index 0) has + * access to the PHYs, so all of the entries have "0". + * + * The values specified in the table are taken from the board's + * config file in include/configs/. When implementing a new + * board with ethernet capability, it is necessary to define: + * TSECn_PHY_ADDR + * TSECn_PHYIDX + * + * for n = 1,2,3, etc. And for FEC: + * FEC_PHY_ADDR + * FEC_PHYIDX + */ +static struct tsec_info_struct tsec_info[] = { +#ifdef CONFIG_TSEC1 + {TSEC1_PHY_ADDR, TSEC1_FLAGS, TSEC1_PHYIDX}, +#else + {0, 0, 0}, +#endif +#ifdef CONFIG_TSEC2 + {TSEC2_PHY_ADDR, TSEC2_FLAGS, TSEC2_PHYIDX}, +#else + {0, 0, 0}, +#endif +#ifdef CONFIG_MPC85XX_FEC + {FEC_PHY_ADDR, FEC_FLAGS, FEC_PHYIDX}, +#else +#ifdef CONFIG_TSEC3 + {TSEC3_PHY_ADDR, TSEC3_FLAGS, TSEC3_PHYIDX}, +#else + {0, 0, 0}, +#endif +#ifdef CONFIG_TSEC4 + {TSEC4_PHY_ADDR, TSEC4_FLAGS, TSEC4_PHYIDX}, +#else + {0, 0, 0}, +#endif /* CONFIG_TSEC4 */ +#endif /* CONFIG_MPC85XX_FEC */ +}; + +#define MAXCONTROLLERS (4) + +static int relocated = 0; + +static struct tsec_private *privlist[MAXCONTROLLERS]; + +#ifdef __GNUC__ +static RTXBD rtx __attribute__ ((aligned(8))); +#else +#error "rtx must be 64-bit aligned" +#endif + +static int tsec_send(struct eth_device *dev, + volatile void *packet, int length); +static int tsec_recv(struct eth_device *dev); +static int tsec_init(struct eth_device *dev, bd_t * bd); +static void tsec_halt(struct eth_device *dev); +static void init_registers(volatile tsec_t * regs); +static void startup_tsec(struct eth_device *dev); +static int init_phy(struct eth_device *dev); +void write_phy_reg(struct tsec_private *priv, uint regnum, uint value); +uint read_phy_reg(struct tsec_private *priv, uint regnum); +struct phy_info *get_phy_info(struct eth_device *dev); +void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); +static void adjust_link(struct eth_device *dev); +static void relocate_cmds(void); +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ + && !defined(BITBANGMII) +static int tsec_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value); +static int tsec_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value); +#endif +#ifdef CONFIG_MCAST_TFTP +static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); +#endif + +/* Initialize device structure. Returns success if PHY + * initialization succeeded (i.e. if it recognizes the PHY) + */ +int tsec_initialize(bd_t * bis, int index, char *devname) +{ + struct eth_device *dev; + int i; + struct tsec_private *priv; + + dev = (struct eth_device *)malloc(sizeof *dev); + + if (NULL == dev) + return 0; + + memset(dev, 0, sizeof *dev); + + priv = (struct tsec_private *)malloc(sizeof(*priv)); + + if (NULL == priv) + return 0; + + privlist[index] = priv; + priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index * TSEC_SIZE); + priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR + + tsec_info[index].phyregidx * + TSEC_SIZE); + + priv->phyaddr = tsec_info[index].phyaddr; + priv->flags = tsec_info[index].flags; + + sprintf(dev->name, devname); + dev->iobase = 0; + dev->priv = priv; + dev->init = tsec_init; + dev->halt = tsec_halt; + dev->send = tsec_send; + dev->recv = tsec_recv; +#ifdef CONFIG_MCAST_TFTP + dev->mcast = tsec_mcast_addr; +#endif + + /* Tell u-boot to get the addr from the env */ + for (i = 0; i < 6; i++) + dev->enetaddr[i] = 0; + + eth_register(dev); + + /* Reset the MAC */ + priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; + priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ + && !defined(BITBANGMII) + miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); +#endif + + /* Try to initialize PHY here, and return */ + return init_phy(dev); +} + +/* Initializes data structures and registers for the controller, + * and brings the interface up. Returns the link status, meaning + * that it returns success if the link is up, failure otherwise. + * This allows u-boot to find the first active controller. + */ +int tsec_init(struct eth_device *dev, bd_t * bd) +{ + uint tempval; + char tmpbuf[MAC_ADDR_LEN]; + int i; + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + /* Make sure the controller is stopped */ + tsec_halt(dev); + + /* Init MACCFG2. Defaults to GMII */ + regs->maccfg2 = MACCFG2_INIT_SETTINGS; + + /* Init ECNTRL */ + regs->ecntrl = ECNTRL_INIT_SETTINGS; + + /* Copy the station address into the address registers. + * Backwards, because little endian MACS are dumb */ + for (i = 0; i < MAC_ADDR_LEN; i++) { + tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; + } + regs->macstnaddr1 = *((uint *) (tmpbuf)); + + tempval = *((uint *) (tmpbuf + 4)); + + regs->macstnaddr2 = tempval; + + /* reset the indices to zero */ + rxIdx = 0; + txIdx = 0; + + /* Clear out (for the most part) the other registers */ + init_registers(regs); + + /* Ready the device for tx/rx */ + startup_tsec(dev); + + /* If there's no link, fail */ + return priv->link; + +} + +/* Write value to the device's PHY through the registers + * specified in priv, modifying the register specified in regnum. + * It will wait for the write to be done (or for a timeout to + * expire) before exiting + */ +void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) +{ + volatile tsec_t *regbase = priv->phyregs; + uint phyid = priv->phyaddr; + int timeout = 1000000; + + regbase->miimadd = (phyid << 8) | regnum; + regbase->miimcon = value; + asm("sync"); + + timeout = 1000000; + while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; +} + +/* Reads register regnum on the device's PHY through the + * registers specified in priv. It lowers and raises the read + * command, and waits for the data to become valid (miimind + * notvalid bit cleared), and the bus to cease activity (miimind + * busy bit cleared), and then returns the value + */ +uint read_phy_reg(struct tsec_private *priv, uint regnum) +{ + uint value; + volatile tsec_t *regbase = priv->phyregs; + uint phyid = priv->phyaddr; + + /* Put the address of the phy, and the register + * number into MIIMADD */ + regbase->miimadd = (phyid << 8) | regnum; + + /* Clear the command register, and wait */ + regbase->miimcom = 0; + asm("sync"); + + /* Initiate a read command, and wait */ + regbase->miimcom = MIIM_READ_COMMAND; + asm("sync"); + + /* Wait for the the indication that the read is done */ + while ((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ; + + /* Grab the value read from the PHY */ + value = regbase->miimstat; + + return value; +} + +/* Discover which PHY is attached to the device, and configure it + * properly. If the PHY is not recognized, then return 0 + * (failure). Otherwise, return 1 + */ +static int init_phy(struct eth_device *dev) +{ + struct tsec_private *priv = (struct tsec_private *)dev->priv; + struct phy_info *curphy; + volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR); + + /* Assign a Physical address to the TBI */ + regs->tbipa = CFG_TBIPA_VALUE; + regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE); + regs->tbipa = CFG_TBIPA_VALUE; + asm("sync"); + + /* Reset MII (due to new addresses) */ + priv->phyregs->miimcfg = MIIMCFG_RESET; + asm("sync"); + priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE; + asm("sync"); + while (priv->phyregs->miimind & MIIMIND_BUSY) ; + + if (0 == relocated) + relocate_cmds(); + + /* Get the cmd structure corresponding to the attached + * PHY */ + curphy = get_phy_info(dev); + + if (curphy == NULL) { + priv->phyinfo = NULL; + printf("%s: No PHY found\n", dev->name); + + return 0; + } + + priv->phyinfo = curphy; + + phy_run_commands(priv, priv->phyinfo->config); + + return 1; +} + +/* + * Returns which value to write to the control register. + * For 10/100, the value is slightly different + */ +uint mii_cr_init(uint mii_reg, struct tsec_private * priv) +{ + if (priv->flags & TSEC_GIGABIT) + return MIIM_CONTROL_INIT; + else + return MIIM_CR_INIT; +} + +/* Parse the status register for link, and then do + * auto-negotiation + */ +uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) +{ + /* + * Wait if the link is up, and autonegotiation is in progress + * (ie - we're capable and it's not done) + */ + mii_reg = read_phy_reg(priv, MIIM_STATUS); + if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE) + && !(mii_reg & PHY_BMSR_AUTN_COMP)) { + int i = 0; + + puts("Waiting for PHY auto negotiation to complete"); + while (!(mii_reg & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + priv->link = 0; + return 0; + } + + if ((i++ % 1000) == 0) { + putc('.'); + } + udelay(1000); /* 1 ms */ + mii_reg = read_phy_reg(priv, MIIM_STATUS); + } + puts(" done\n"); + priv->link = 1; + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (mii_reg & MIIM_STATUS_LINK) + priv->link = 1; + else + priv->link = 0; + } + + return 0; +} + +/* Generic function which updates the speed and duplex. If + * autonegotiation is enabled, it uses the AND of the link + * partner's advertised capabilities and our advertised + * capabilities. If autonegotiation is disabled, we use the + * appropriate bits in the control register. + * + * Stolen from Linux's mii.c and phy_device.c + */ +uint mii_parse_link(uint mii_reg, struct tsec_private *priv) +{ + /* We're using autonegotiation */ + if (mii_reg & PHY_BMSR_AUTN_ABLE) { + uint lpa = 0; + uint gblpa = 0; + + /* Check for gigabit capability */ + if (mii_reg & PHY_BMSR_EXT) { + /* We want a list of states supported by + * both PHYs in the link + */ + gblpa = read_phy_reg(priv, PHY_1000BTSR); + gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2; + } + + /* Set the baseline so we only have to set them + * if they're different + */ + priv->speed = 10; + priv->duplexity = 0; + + /* Check the gigabit fields */ + if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { + priv->speed = 1000; + + if (gblpa & PHY_1000BTSR_1000FD) + priv->duplexity = 1; + + /* We're done! */ + return 0; + } + + lpa = read_phy_reg(priv, PHY_ANAR); + lpa &= read_phy_reg(priv, PHY_ANLPAR); + + if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) { + priv->speed = 100; + + if (lpa & PHY_ANLPAR_TXFD) + priv->duplexity = 1; + + } else if (lpa & PHY_ANLPAR_10FD) + priv->duplexity = 1; + } else { + uint bmcr = read_phy_reg(priv, PHY_BMCR); + + priv->speed = 10; + priv->duplexity = 0; + + if (bmcr & PHY_BMCR_DPLX) + priv->duplexity = 1; + + if (bmcr & PHY_BMCR_1000_MBPS) + priv->speed = 1000; + else if (bmcr & PHY_BMCR_100_MBPS) + priv->speed = 100; + } + + return 0; +} + +/* + * Parse the BCM54xx status register for speed and duplex information. + * The linux sungem_phy has this information, but in a table format. + */ +uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv) +{ + + switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){ + + case 1: + printf("Enet starting in 10BT/HD\n"); + priv->duplexity = 0; + priv->speed = 10; + break; + + case 2: + printf("Enet starting in 10BT/FD\n"); + priv->duplexity = 1; + priv->speed = 10; + break; + + case 3: + printf("Enet starting in 100BT/HD\n"); + priv->duplexity = 0; + priv->speed = 100; + break; + + case 5: + printf("Enet starting in 100BT/FD\n"); + priv->duplexity = 1; + priv->speed = 100; + break; + + case 6: + printf("Enet starting in 1000BT/HD\n"); + priv->duplexity = 0; + priv->speed = 1000; + break; + + case 7: + printf("Enet starting in 1000BT/FD\n"); + priv->duplexity = 1; + priv->speed = 1000; + break; + + default: + printf("Auto-neg error, defaulting to 10BT/HD\n"); + priv->duplexity = 0; + priv->speed = 10; + break; + } + + return 0; + +} +/* Parse the 88E1011's status register for speed and duplex + * information + */ +uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) +{ + uint speed; + + mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); + + if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) && + !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { + int i = 0; + + puts("Waiting for PHY realtime link"); + while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { + /* Timeout reached ? */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + priv->link = 0; + break; + } + + if ((i++ % 1000) == 0) { + putc('.'); + } + udelay(1000); /* 1 ms */ + mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); + } + puts(" done\n"); + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (mii_reg & MIIM_88E1011_PHYSTAT_LINK) + priv->link = 1; + else + priv->link = 0; + } + + if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); + + switch (speed) { + case MIIM_88E1011_PHYSTAT_GBIT: + priv->speed = 1000; + break; + case MIIM_88E1011_PHYSTAT_100: + priv->speed = 100; + break; + default: + priv->speed = 10; + } + + return 0; +} + +/* Parse the cis8201's status register for speed and duplex + * information + */ +uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv) +{ + uint speed; + + if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED; + switch (speed) { + case MIIM_CIS8201_AUXCONSTAT_GBIT: + priv->speed = 1000; + break; + case MIIM_CIS8201_AUXCONSTAT_100: + priv->speed = 100; + break; + default: + priv->speed = 10; + break; + } + + return 0; +} + +/* Parse the vsc8244's status register for speed and duplex + * information + */ +uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv) +{ + uint speed; + + if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED; + switch (speed) { + case MIIM_VSC8244_AUXCONSTAT_GBIT: + priv->speed = 1000; + break; + case MIIM_VSC8244_AUXCONSTAT_100: + priv->speed = 100; + break; + default: + priv->speed = 10; + break; + } + + return 0; +} + +/* Parse the DM9161's status register for speed and duplex + * information + */ +uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv) +{ + if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) + priv->speed = 100; + else + priv->speed = 10; + + if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) + priv->duplexity = 1; + else + priv->duplexity = 0; + + return 0; +} + +/* + * Hack to write all 4 PHYs with the LED values + */ +uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv) +{ + uint phyid; + volatile tsec_t *regbase = priv->phyregs; + int timeout = 1000000; + + for (phyid = 0; phyid < 4; phyid++) { + regbase->miimadd = (phyid << 8) | mii_reg; + regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT; + asm("sync"); + + timeout = 1000000; + while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; + } + + return MIIM_CIS8204_SLEDCON_INIT; +} + +uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv) +{ + if (priv->flags & TSEC_REDUCED) + return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII; + else + return MIIM_CIS8204_EPHYCON_INIT; +} + +/* Initialized required registers to appropriate values, zeroing + * those we don't care about (unless zero is bad, in which case, + * choose a more appropriate value) + */ +static void init_registers(volatile tsec_t * regs) +{ + /* Clear IEVENT */ + regs->ievent = IEVENT_INIT_CLEAR; + + regs->imask = IMASK_INIT_CLEAR; + + regs->hash.iaddr0 = 0; + regs->hash.iaddr1 = 0; + regs->hash.iaddr2 = 0; + regs->hash.iaddr3 = 0; + regs->hash.iaddr4 = 0; + regs->hash.iaddr5 = 0; + regs->hash.iaddr6 = 0; + regs->hash.iaddr7 = 0; + + regs->hash.gaddr0 = 0; + regs->hash.gaddr1 = 0; + regs->hash.gaddr2 = 0; + regs->hash.gaddr3 = 0; + regs->hash.gaddr4 = 0; + regs->hash.gaddr5 = 0; + regs->hash.gaddr6 = 0; + regs->hash.gaddr7 = 0; + + regs->rctrl = 0x00000000; + + /* Init RMON mib registers */ + memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); + + regs->rmon.cam1 = 0xffffffff; + regs->rmon.cam2 = 0xffffffff; + + regs->mrblr = MRBLR_INIT_SETTINGS; + + regs->minflr = MINFLR_INIT_SETTINGS; + + regs->attr = ATTR_INIT_SETTINGS; + regs->attreli = ATTRELI_INIT_SETTINGS; + +} + +/* Configure maccfg2 based on negotiated speed and duplex + * reported by PHY handling code + */ +static void adjust_link(struct eth_device *dev) +{ + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + if (priv->link) { + if (priv->duplexity != 0) + regs->maccfg2 |= MACCFG2_FULL_DUPLEX; + else + regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX); + + switch (priv->speed) { + case 1000: + regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) + | MACCFG2_GMII); + break; + case 100: + case 10: + regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) + | MACCFG2_MII); + + /* Set R100 bit in all modes although + * it is only used in RGMII mode + */ + if (priv->speed == 100) + regs->ecntrl |= ECNTRL_R100; + else + regs->ecntrl &= ~(ECNTRL_R100); + break; + default: + printf("%s: Speed was bad\n", dev->name); + break; + } + + printf("Speed: %d, %s duplex\n", priv->speed, + (priv->duplexity) ? "full" : "half"); + + } else { + printf("%s: No link.\n", dev->name); + } +} + +/* Set up the buffers and their descriptors, and bring up the + * interface + */ +static void startup_tsec(struct eth_device *dev) +{ + int i; + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + /* Point to the buffer descriptors */ + regs->tbase = (unsigned int)(&rtx.txbd[txIdx]); + regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]); + + /* Initialize the Rx Buffer descriptors */ + for (i = 0; i < PKTBUFSRX; i++) { + rtx.rxbd[i].status = RXBD_EMPTY; + rtx.rxbd[i].length = 0; + rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; + } + rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; + + /* Initialize the TX Buffer Descriptors */ + for (i = 0; i < TX_BUF_CNT; i++) { + rtx.txbd[i].status = 0; + rtx.txbd[i].length = 0; + rtx.txbd[i].bufPtr = 0; + } + rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; + + /* Start up the PHY */ + if(priv->phyinfo) + phy_run_commands(priv, priv->phyinfo->startup); + + adjust_link(dev); + + /* Enable Transmit and Receive */ + regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN); + + /* Tell the DMA it is clear to go */ + regs->dmactrl |= DMACTRL_INIT_SETTINGS; + regs->tstat = TSTAT_CLEAR_THALT; + regs->rstat = RSTAT_CLEAR_RHALT; + regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); +} + +/* This returns the status bits of the device. The return value + * is never checked, and this is what the 8260 driver did, so we + * do the same. Presumably, this would be zero if there were no + * errors + */ +static int tsec_send(struct eth_device *dev, volatile void *packet, int length) +{ + int i; + int result = 0; + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + /* Find an empty buffer descriptor */ + for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { + if (i >= TOUT_LOOP) { + debug("%s: tsec: tx buffers full\n", dev->name); + return result; + } + } + + rtx.txbd[txIdx].bufPtr = (uint) packet; + rtx.txbd[txIdx].length = length; + rtx.txbd[txIdx].status |= + (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); + + /* Tell the DMA to go */ + regs->tstat = TSTAT_CLEAR_THALT; + + /* Wait for buffer to be transmitted */ + for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { + if (i >= TOUT_LOOP) { + debug("%s: tsec: tx error\n", dev->name); + return result; + } + } + + txIdx = (txIdx + 1) % TX_BUF_CNT; + result = rtx.txbd[txIdx].status & TXBD_STATS; + + return result; +} + +static int tsec_recv(struct eth_device *dev) +{ + int length; + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { + + length = rtx.rxbd[rxIdx].length; + + /* Send the packet up if there were no errors */ + if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { + NetReceive(NetRxPackets[rxIdx], length - 4); + } else { + printf("Got error %x\n", + (rtx.rxbd[rxIdx].status & RXBD_STATS)); + } + + rtx.rxbd[rxIdx].length = 0; + + /* Set the wrap bit if this is the last element in the list */ + rtx.rxbd[rxIdx].status = + RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); + + rxIdx = (rxIdx + 1) % PKTBUFSRX; + } + + if (regs->ievent & IEVENT_BSY) { + regs->ievent = IEVENT_BSY; + regs->rstat = RSTAT_CLEAR_RHALT; + } + + return -1; + +} + +/* Stop the interface */ +static void tsec_halt(struct eth_device *dev) +{ + struct tsec_private *priv = (struct tsec_private *)dev->priv; + volatile tsec_t *regs = priv->regs; + + regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); + regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS); + + while (!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))) ; + + regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN); + + /* Shut down the PHY, as needed */ + if(priv->phyinfo) + phy_run_commands(priv, priv->phyinfo->shutdown); +} + +struct phy_info phy_info_M88E1149S = { + 0x1410ca, + "Marvell 88E1149S", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {0x1d, 0x1f, NULL}, + {0x1e, 0x200c, NULL}, + {0x1d, 0x5, NULL}, + {0x1e, 0x0, NULL}, + {0x1e, 0x100, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_88E1011_PHY_STATUS, miim_read, + &mii_parse_88E1011_psr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */ +struct phy_info phy_info_BCM5461S = { + 0x02060c1, /* 5461 ID */ + "Broadcom BCM5461S", + 0, /* not clear to me what minor revisions we can shift away */ + (struct phy_cmd[]) { /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_BCM5464S = { + 0x02060b1, /* 5464 ID */ + "Broadcom BCM5464S", + 0, /* not clear to me what minor revisions we can shift away */ + (struct phy_cmd[]) { /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_M88E1011S = { + 0x01410c6, + "Marvell 88E1011S", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {0x1d, 0x1f, NULL}, + {0x1e, 0x200c, NULL}, + {0x1d, 0x5, NULL}, + {0x1e, 0x0, NULL}, + {0x1e, 0x100, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_88E1011_PHY_STATUS, miim_read, + &mii_parse_88E1011_psr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_M88E1111S = { + 0x01410cc, + "Marvell 88E1111S", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */ + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_88E1011_PHY_STATUS, miim_read, + &mii_parse_88E1011_psr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv) +{ + uint mii_data = read_phy_reg(priv, mii_reg); + + /* Setting MIIM_88E1145_PHY_EXT_CR */ + if (priv->flags & TSEC_REDUCED) + return mii_data | + MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY; + else + return mii_data; +} + +static struct phy_info phy_info_M88E1145 = { + 0x01410cd, + "Marvell 88E1145", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + + /* Errata E0, E1 */ + {29, 0x001b, NULL}, + {30, 0x418f, NULL}, + {29, 0x0016, NULL}, + {30, 0xa2da, NULL}, + + /* Configure the PHY */ + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, + NULL}, + {MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, NULL}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + {MIIM_88E1111_PHY_LED_CONTROL, + MIIM_88E1111_PHY_LED_DIRECT, NULL}, + /* Read the Status */ + {MIIM_88E1011_PHY_STATUS, miim_read, + &mii_parse_88E1011_psr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_cis8204 = { + 0x3f11, + "Cicada Cis8204", + 6, + (struct phy_cmd[]){ /* config */ + /* Override PHY config settings */ + {MIIM_CIS8201_AUX_CONSTAT, + MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, + /* Configure some basic stuff */ + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, + &mii_cis8204_fixled}, + {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, + &mii_cis8204_setmode}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Read the Status (2x to make sure link is right) */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_CIS8201_AUX_CONSTAT, miim_read, + &mii_parse_cis8201}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +/* Cicada 8201 */ +struct phy_info phy_info_cis8201 = { + 0xfc41, + "CIS8201", + 4, + (struct phy_cmd[]){ /* config */ + /* Override PHY config settings */ + {MIIM_CIS8201_AUX_CONSTAT, + MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, + /* Set up the interface mode */ + {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, + NULL}, + /* Configure some basic stuff */ + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Read the Status (2x to make sure link is right) */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_CIS8201_AUX_CONSTAT, miim_read, + &mii_parse_cis8201}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; +struct phy_info phy_info_VSC8244 = { + 0x3f1b, + "Vitesse VSC8244", + 6, + (struct phy_cmd[]){ /* config */ + /* Override PHY config settings */ + /* Configure some basic stuff */ + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Read the Status (2x to make sure link is right) */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_VSC8244_AUX_CONSTAT, miim_read, + &mii_parse_vsc8244}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info phy_info_dm9161 = { + 0x0181b88, + "Davicom DM9161E", + 4, + (struct phy_cmd[]){ /* config */ + {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL}, + /* Do not bypass the scrambler/descrambler */ + {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL}, + /* Clear 10BTCSR to default */ + {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, + NULL}, + /* Configure some basic stuff */ + {MIIM_CONTROL, MIIM_CR_INIT, NULL}, + /* Restart Auto Negotiation */ + {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_DM9161_SCSR, miim_read, + &mii_parse_dm9161_scsr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; +/* a generic flavor. */ +struct phy_info phy_info_generic = { + 0, + "Unknown/Generic PHY", + 32, + (struct phy_cmd[]) { /* config */ + {PHY_BMCR, PHY_BMCR_RESET, NULL}, + {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + {PHY_BMSR, miim_read, NULL}, + {PHY_BMSR, miim_read, &mii_parse_sr}, + {PHY_BMSR, miim_read, &mii_parse_link}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + } +}; + + +uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv) +{ + unsigned int speed; + if (priv->link) { + speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK; + + switch (speed) { + case MIIM_LXT971_SR2_10HDX: + priv->speed = 10; + priv->duplexity = 0; + break; + case MIIM_LXT971_SR2_10FDX: + priv->speed = 10; + priv->duplexity = 1; + break; + case MIIM_LXT971_SR2_100HDX: + priv->speed = 100; + priv->duplexity = 0; + break; + default: + priv->speed = 100; + priv->duplexity = 1; + } + } else { + priv->speed = 0; + priv->duplexity = 0; + } + + return 0; +} + +static struct phy_info phy_info_lxt971 = { + 0x0001378e, + "LXT971", + 4, + (struct phy_cmd[]){ /* config */ + {MIIM_CR, MIIM_CR_INIT, mii_cr_init}, /* autonegotiate */ + {miim_end,} + }, + (struct phy_cmd[]){ /* startup - enable interrupts */ + /* { 0x12, 0x00f2, NULL }, */ + {MIIM_STATUS, miim_read, NULL}, + {MIIM_STATUS, miim_read, &mii_parse_sr}, + {MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown - disable interrupts */ + {miim_end,} + }, +}; + +/* Parse the DP83865's link and auto-neg status register for speed and duplex + * information + */ +uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv) +{ + switch (mii_reg & MIIM_DP83865_SPD_MASK) { + + case MIIM_DP83865_SPD_1000: + priv->speed = 1000; + break; + + case MIIM_DP83865_SPD_100: + priv->speed = 100; + break; + + default: + priv->speed = 10; + break; + + } + + if (mii_reg & MIIM_DP83865_DPX_FULL) + priv->duplexity = 1; + else + priv->duplexity = 0; + + return 0; +} + +struct phy_info phy_info_dp83865 = { + 0x20005c7, + "NatSemi DP83865", + 4, + (struct phy_cmd[]){ /* config */ + {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the link and auto-neg status */ + {MIIM_DP83865_LANR, miim_read, + &mii_parse_dp83865_lanr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + +struct phy_info *phy_info[] = { + &phy_info_cis8204, + &phy_info_cis8201, + &phy_info_BCM5461S, + &phy_info_BCM5464S, + &phy_info_M88E1011S, + &phy_info_M88E1111S, + &phy_info_M88E1145, + &phy_info_M88E1149S, + &phy_info_dm9161, + &phy_info_lxt971, + &phy_info_VSC8244, + &phy_info_dp83865, + &phy_info_generic, + NULL +}; + +/* Grab the identifier of the device's PHY, and search through + * all of the known PHYs to see if one matches. If so, return + * it, if not, return NULL + */ +struct phy_info *get_phy_info(struct eth_device *dev) +{ + struct tsec_private *priv = (struct tsec_private *)dev->priv; + uint phy_reg, phy_ID; + int i; + struct phy_info *theInfo = NULL; + + /* Grab the bits from PHYIR1, and put them in the upper half */ + phy_reg = read_phy_reg(priv, MIIM_PHYIR1); + phy_ID = (phy_reg & 0xffff) << 16; + + /* Grab the bits from PHYIR2, and put them in the lower half */ + phy_reg = read_phy_reg(priv, MIIM_PHYIR2); + phy_ID |= (phy_reg & 0xffff); + + /* loop through all the known PHY types, and find one that */ + /* matches the ID we read from the PHY. */ + for (i = 0; phy_info[i]; i++) { + if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) { + theInfo = phy_info[i]; + break; + } + } + + if (theInfo == NULL) { + printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID); + return NULL; + } else { + debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID); + } + + return theInfo; +} + +/* Execute the given series of commands on the given device's + * PHY, running functions as necessary + */ +void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd) +{ + int i; + uint result; + volatile tsec_t *phyregs = priv->phyregs; + + phyregs->miimcfg = MIIMCFG_RESET; + + phyregs->miimcfg = MIIMCFG_INIT_VALUE; + + while (phyregs->miimind & MIIMIND_BUSY) ; + + for (i = 0; cmd->mii_reg != miim_end; i++) { + if (cmd->mii_data == miim_read) { + result = read_phy_reg(priv, cmd->mii_reg); + + if (cmd->funct != NULL) + (*(cmd->funct)) (result, priv); + + } else { + if (cmd->funct != NULL) + result = (*(cmd->funct)) (cmd->mii_reg, priv); + else + result = cmd->mii_data; + + write_phy_reg(priv, cmd->mii_reg, result); + + } + cmd++; + } +} + +/* Relocate the function pointers in the phy cmd lists */ +static void relocate_cmds(void) +{ + struct phy_cmd **cmdlistptr; + struct phy_cmd *cmd; + int i, j, k; + + for (i = 0; phy_info[i]; i++) { + /* First thing's first: relocate the pointers to the + * PHY command structures (the structs were done) */ + phy_info[i] = (struct phy_info *)((uint) phy_info[i] + + gd->reloc_off); + phy_info[i]->name += gd->reloc_off; + phy_info[i]->config = + (struct phy_cmd *)((uint) phy_info[i]->config + + gd->reloc_off); + phy_info[i]->startup = + (struct phy_cmd *)((uint) phy_info[i]->startup + + gd->reloc_off); + phy_info[i]->shutdown = + (struct phy_cmd *)((uint) phy_info[i]->shutdown + + gd->reloc_off); + + cmdlistptr = &phy_info[i]->config; + j = 0; + for (; cmdlistptr <= &phy_info[i]->shutdown; cmdlistptr++) { + k = 0; + for (cmd = *cmdlistptr; + cmd->mii_reg != miim_end; + cmd++) { + /* Only relocate non-NULL pointers */ + if (cmd->funct) + cmd->funct += gd->reloc_off; + + k++; + } + j++; + } + } + + relocated = 1; +} + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ + && !defined(BITBANGMII) + +struct tsec_private *get_priv_for_phy(unsigned char phyaddr) +{ + int i; + + for (i = 0; i < MAXCONTROLLERS; i++) { + if (privlist[i]->phyaddr == phyaddr) + return privlist[i]; + } + + return NULL; +} + +/* + * Read a MII PHY register. + * + * Returns: + * 0 on success + */ +static int tsec_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + unsigned short ret; + struct tsec_private *priv = get_priv_for_phy(addr); + + if (NULL == priv) { + printf("Can't read PHY at address %d\n", addr); + return -1; + } + + ret = (unsigned short)read_phy_reg(priv, reg); + *value = ret; + + return 0; +} + +/* + * Write a MII PHY register. + * + * Returns: + * 0 on success + */ +static int tsec_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + struct tsec_private *priv = get_priv_for_phy(addr); + + if (NULL == priv) { + printf("Can't write PHY at address %d\n", addr); + return -1; + } + + write_phy_reg(priv, reg, value); + + return 0; +} + +#endif + +#ifdef CONFIG_MCAST_TFTP + +/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ + +/* Set the appropriate hash bit for the given addr */ + +/* The algorithm works like so: + * 1) Take the Destination Address (ie the multicast address), and + * do a CRC on it (little endian), and reverse the bits of the + * result. + * 2) Use the 8 most significant bits as a hash into a 256-entry + * table. The table is controlled through 8 32-bit registers: + * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is + * gaddr7. This means that the 3 most significant bits in the + * hash index which gaddr register to use, and the 5 other bits + * indicate which bit (assuming an IBM numbering scheme, which + * for PowerPC (tm) is usually the case) in the tregister holds + * the entry. */ +static int +tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) +{ + struct tsec_private *priv = privlist[1]; + volatile tsec_t *regs = priv->regs; + volatile u32 *reg_array, value; + u8 result, whichbit, whichreg; + + result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); + whichbit = result & 0x1f; /* the 5 LSB = which bit to set */ + whichreg = result >> 5; /* the 3 MSB = which reg to set it in */ + value = (1 << (31-whichbit)); + + reg_array = &(regs->hash.gaddr0); + + if (set) { + reg_array[whichreg] |= value; + } else { + reg_array[whichreg] &= ~value; + } + return 0; +} +#endif /* Multicast TFTP ? */ + +#endif /* CONFIG_TSEC_ENET */ diff --git a/drivers/net/tsec.h b/drivers/net/tsec.h new file mode 100644 index 0000000000..2f0092ad59 --- /dev/null +++ b/drivers/net/tsec.h @@ -0,0 +1,563 @@ +/* + * tsec.h + * + * Driver for the Motorola Triple Speed Ethernet Controller + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * Copyright 2004, 2007 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * maintained by Xianghua Xiao (x.xiao@motorola.com) + * author Andy Fleming + * + */ + +#ifndef __TSEC_H +#define __TSEC_H + +#include +#include + +#ifndef CFG_TSEC1_OFFSET + #define CFG_TSEC1_OFFSET (0x24000) +#endif + +#define TSEC_SIZE 0x01000 + +/* FIXME: Should these be pushed back to 83xx and 85xx config files? */ +#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) + #define TSEC_BASE_ADDR (CFG_IMMR + CFG_TSEC1_OFFSET) +#elif defined(CONFIG_MPC83XX) + #define TSEC_BASE_ADDR (CFG_IMMR + CFG_TSEC1_OFFSET) +#endif + + +#define MAC_ADDR_LEN 6 + +/* #define TSEC_TIMEOUT 1000000 */ +#define TSEC_TIMEOUT 1000 +#define TOUT_LOOP 1000000 + +#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */ + +/* MAC register bits */ +#define MACCFG1_SOFT_RESET 0x80000000 +#define MACCFG1_RESET_RX_MC 0x00080000 +#define MACCFG1_RESET_TX_MC 0x00040000 +#define MACCFG1_RESET_RX_FUN 0x00020000 +#define MACCFG1_RESET_TX_FUN 0x00010000 +#define MACCFG1_LOOPBACK 0x00000100 +#define MACCFG1_RX_FLOW 0x00000020 +#define MACCFG1_TX_FLOW 0x00000010 +#define MACCFG1_SYNCD_RX_EN 0x00000008 +#define MACCFG1_RX_EN 0x00000004 +#define MACCFG1_SYNCD_TX_EN 0x00000002 +#define MACCFG1_TX_EN 0x00000001 + +#define MACCFG2_INIT_SETTINGS 0x00007205 +#define MACCFG2_FULL_DUPLEX 0x00000001 +#define MACCFG2_IF 0x00000300 +#define MACCFG2_GMII 0x00000200 +#define MACCFG2_MII 0x00000100 + +#define ECNTRL_INIT_SETTINGS 0x00001000 +#define ECNTRL_TBI_MODE 0x00000020 +#define ECNTRL_R100 0x00000008 +#define ECNTRL_SGMII_MODE 0x00000002 + +#define miim_end -2 +#define miim_read -1 + +#ifndef CFG_TBIPA_VALUE + #define CFG_TBIPA_VALUE 0x1f +#endif +#define MIIMCFG_INIT_VALUE 0x00000003 +#define MIIMCFG_RESET 0x80000000 + +#define MIIMIND_BUSY 0x00000001 +#define MIIMIND_NOTVALID 0x00000004 + +#define MIIM_CONTROL 0x00 +#define MIIM_CONTROL_RESET 0x00009140 +#define MIIM_CONTROL_INIT 0x00001140 +#define MIIM_CONTROL_RESTART 0x00001340 +#define MIIM_ANEN 0x00001000 + +#define MIIM_CR 0x00 +#define MIIM_CR_RST 0x00008000 +#define MIIM_CR_INIT 0x00001000 + +#define MIIM_STATUS 0x1 +#define MIIM_STATUS_AN_DONE 0x00000020 +#define MIIM_STATUS_LINK 0x0004 +#define PHY_BMSR_AUTN_ABLE 0x0008 +#define PHY_BMSR_AUTN_COMP 0x0020 + +#define MIIM_PHYIR1 0x2 +#define MIIM_PHYIR2 0x3 + +#define MIIM_ANAR 0x4 +#define MIIM_ANAR_INIT 0x1e1 + +#define MIIM_TBI_ANLPBPA 0x5 +#define MIIM_TBI_ANLPBPA_HALF 0x00000040 +#define MIIM_TBI_ANLPBPA_FULL 0x00000020 + +#define MIIM_TBI_ANEX 0x6 +#define MIIM_TBI_ANEX_NP 0x00000004 +#define MIIM_TBI_ANEX_PRX 0x00000002 + +#define MIIM_GBIT_CONTROL 0x9 +#define MIIM_GBIT_CONTROL_INIT 0xe00 + +/* Broadcom BCM54xx -- taken from linux sungem_phy */ +#define MIIM_BCM54xx_AUXSTATUS 0x19 +#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700 +#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8 + +/* Cicada Auxiliary Control/Status Register */ +#define MIIM_CIS8201_AUX_CONSTAT 0x1c +#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004 +#define MIIM_CIS8201_AUXCONSTAT_DUPLEX 0x0020 +#define MIIM_CIS8201_AUXCONSTAT_SPEED 0x0018 +#define MIIM_CIS8201_AUXCONSTAT_GBIT 0x0010 +#define MIIM_CIS8201_AUXCONSTAT_100 0x0008 + +/* Cicada Extended Control Register 1 */ +#define MIIM_CIS8201_EXT_CON1 0x17 +#define MIIM_CIS8201_EXTCON1_INIT 0x0000 + +/* Cicada 8204 Extended PHY Control Register 1 */ +#define MIIM_CIS8204_EPHY_CON 0x17 +#define MIIM_CIS8204_EPHYCON_INIT 0x0006 +#define MIIM_CIS8204_EPHYCON_RGMII 0x1100 + +/* Cicada 8204 Serial LED Control Register */ +#define MIIM_CIS8204_SLED_CON 0x1b +#define MIIM_CIS8204_SLEDCON_INIT 0x1115 + +#define MIIM_GBIT_CON 0x09 +#define MIIM_GBIT_CON_ADVERT 0x0e00 + +/* Entry for Vitesse VSC8244 regs starts here */ +/* Vitesse VSC8244 Auxiliary Control/Status Register */ +#define MIIM_VSC8244_AUX_CONSTAT 0x1c +#define MIIM_VSC8244_AUXCONSTAT_INIT 0x0000 +#define MIIM_VSC8244_AUXCONSTAT_DUPLEX 0x0020 +#define MIIM_VSC8244_AUXCONSTAT_SPEED 0x0018 +#define MIIM_VSC8244_AUXCONSTAT_GBIT 0x0010 +#define MIIM_VSC8244_AUXCONSTAT_100 0x0008 +#define MIIM_CONTROL_INIT_LOOPBACK 0x4000 + +/* Vitesse VSC8244 Extended PHY Control Register 1 */ +#define MIIM_VSC8244_EPHY_CON 0x17 +#define MIIM_VSC8244_EPHYCON_INIT 0x0006 + +/* Vitesse VSC8244 Serial LED Control Register */ +#define MIIM_VSC8244_LED_CON 0x1b +#define MIIM_VSC8244_LEDCON_INIT 0xF011 + +/* 88E1011 PHY Status Register */ +#define MIIM_88E1011_PHY_STATUS 0x11 +#define MIIM_88E1011_PHYSTAT_SPEED 0xc000 +#define MIIM_88E1011_PHYSTAT_GBIT 0x8000 +#define MIIM_88E1011_PHYSTAT_100 0x4000 +#define MIIM_88E1011_PHYSTAT_DUPLEX 0x2000 +#define MIIM_88E1011_PHYSTAT_SPDDONE 0x0800 +#define MIIM_88E1011_PHYSTAT_LINK 0x0400 + +#define MIIM_88E1011_PHY_SCR 0x10 +#define MIIM_88E1011_PHY_MDI_X_AUTO 0x0060 + +/* 88E1111 PHY LED Control Register */ +#define MIIM_88E1111_PHY_LED_CONTROL 24 +#define MIIM_88E1111_PHY_LED_DIRECT 0x4100 +#define MIIM_88E1111_PHY_LED_COMBINE 0x411C + +/* 88E1145 Extended PHY Specific Control Register */ +#define MIIM_88E1145_PHY_EXT_CR 20 +#define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 +#define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 + +#define MIIM_88E1145_PHY_PAGE 29 +#define MIIM_88E1145_PHY_CAL_OV 30 + + +/* DM9161 Control register values */ +#define MIIM_DM9161_CR_STOP 0x0400 +#define MIIM_DM9161_CR_RSTAN 0x1200 + +#define MIIM_DM9161_SCR 0x10 +#define MIIM_DM9161_SCR_INIT 0x0610 + +/* DM9161 Specified Configuration and Status Register */ +#define MIIM_DM9161_SCSR 0x11 +#define MIIM_DM9161_SCSR_100F 0x8000 +#define MIIM_DM9161_SCSR_100H 0x4000 +#define MIIM_DM9161_SCSR_10F 0x2000 +#define MIIM_DM9161_SCSR_10H 0x1000 + +/* DM9161 10BT Configuration/Status */ +#define MIIM_DM9161_10BTCSR 0x12 +#define MIIM_DM9161_10BTCSR_INIT 0x7800 + +/* LXT971 Status 2 registers */ +#define MIIM_LXT971_SR2 0x11 /* Status Register 2 */ +#define MIIM_LXT971_SR2_SPEED_MASK 0x4200 +#define MIIM_LXT971_SR2_10HDX 0x0000 /* 10 Mbit half duplex selected */ +#define MIIM_LXT971_SR2_10FDX 0x0200 /* 10 Mbit full duplex selected */ +#define MIIM_LXT971_SR2_100HDX 0x4000 /* 100 Mbit half duplex selected */ +#define MIIM_LXT971_SR2_100FDX 0x4200 /* 100 Mbit full duplex selected */ + +/* DP83865 Control register values */ +#define MIIM_DP83865_CR_INIT 0x9200 + +/* DP83865 Link and Auto-Neg Status Register */ +#define MIIM_DP83865_LANR 0x11 +#define MIIM_DP83865_SPD_MASK 0x0018 +#define MIIM_DP83865_SPD_1000 0x0010 +#define MIIM_DP83865_SPD_100 0x0008 +#define MIIM_DP83865_DPX_FULL 0x0002 + +#define MIIM_READ_COMMAND 0x00000001 + +#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN + +#define MINFLR_INIT_SETTINGS 0x00000040 + +#define DMACTRL_INIT_SETTINGS 0x000000c3 +#define DMACTRL_GRS 0x00000010 +#define DMACTRL_GTS 0x00000008 + +#define TSTAT_CLEAR_THALT 0x80000000 +#define RSTAT_CLEAR_RHALT 0x00800000 + + +#define IEVENT_INIT_CLEAR 0xffffffff +#define IEVENT_BABR 0x80000000 +#define IEVENT_RXC 0x40000000 +#define IEVENT_BSY 0x20000000 +#define IEVENT_EBERR 0x10000000 +#define IEVENT_MSRO 0x04000000 +#define IEVENT_GTSC 0x02000000 +#define IEVENT_BABT 0x01000000 +#define IEVENT_TXC 0x00800000 +#define IEVENT_TXE 0x00400000 +#define IEVENT_TXB 0x00200000 +#define IEVENT_TXF 0x00100000 +#define IEVENT_IE 0x00080000 +#define IEVENT_LC 0x00040000 +#define IEVENT_CRL 0x00020000 +#define IEVENT_XFUN 0x00010000 +#define IEVENT_RXB0 0x00008000 +#define IEVENT_GRSC 0x00000100 +#define IEVENT_RXF0 0x00000080 + +#define IMASK_INIT_CLEAR 0x00000000 +#define IMASK_TXEEN 0x00400000 +#define IMASK_TXBEN 0x00200000 +#define IMASK_TXFEN 0x00100000 +#define IMASK_RXFEN0 0x00000080 + + +/* Default Attribute fields */ +#define ATTR_INIT_SETTINGS 0x000000c0 +#define ATTRELI_INIT_SETTINGS 0x00000000 + + +/* TxBD status field bits */ +#define TXBD_READY 0x8000 +#define TXBD_PADCRC 0x4000 +#define TXBD_WRAP 0x2000 +#define TXBD_INTERRUPT 0x1000 +#define TXBD_LAST 0x0800 +#define TXBD_CRC 0x0400 +#define TXBD_DEF 0x0200 +#define TXBD_HUGEFRAME 0x0080 +#define TXBD_LATECOLLISION 0x0080 +#define TXBD_RETRYLIMIT 0x0040 +#define TXBD_RETRYCOUNTMASK 0x003c +#define TXBD_UNDERRUN 0x0002 +#define TXBD_STATS 0x03ff + +/* RxBD status field bits */ +#define RXBD_EMPTY 0x8000 +#define RXBD_RO1 0x4000 +#define RXBD_WRAP 0x2000 +#define RXBD_INTERRUPT 0x1000 +#define RXBD_LAST 0x0800 +#define RXBD_FIRST 0x0400 +#define RXBD_MISS 0x0100 +#define RXBD_BROADCAST 0x0080 +#define RXBD_MULTICAST 0x0040 +#define RXBD_LARGE 0x0020 +#define RXBD_NONOCTET 0x0010 +#define RXBD_SHORT 0x0008 +#define RXBD_CRCERR 0x0004 +#define RXBD_OVERRUN 0x0002 +#define RXBD_TRUNCATED 0x0001 +#define RXBD_STATS 0x003f + +typedef struct txbd8 +{ + ushort status; /* Status Fields */ + ushort length; /* Buffer length */ + uint bufPtr; /* Buffer Pointer */ +} txbd8_t; + +typedef struct rxbd8 +{ + ushort status; /* Status Fields */ + ushort length; /* Buffer Length */ + uint bufPtr; /* Buffer Pointer */ +} rxbd8_t; + +typedef struct rmon_mib +{ + /* Transmit and Receive Counters */ + uint tr64; /* Transmit and Receive 64-byte Frame Counter */ + uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */ + uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */ + uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */ + uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */ + uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */ + uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */ + /* Receive Counters */ + uint rbyt; /* Receive Byte Counter */ + uint rpkt; /* Receive Packet Counter */ + uint rfcs; /* Receive FCS Error Counter */ + uint rmca; /* Receive Multicast Packet (Counter) */ + uint rbca; /* Receive Broadcast Packet */ + uint rxcf; /* Receive Control Frame Packet */ + uint rxpf; /* Receive Pause Frame Packet */ + uint rxuo; /* Receive Unknown OP Code */ + uint raln; /* Receive Alignment Error */ + uint rflr; /* Receive Frame Length Error */ + uint rcde; /* Receive Code Error */ + uint rcse; /* Receive Carrier Sense Error */ + uint rund; /* Receive Undersize Packet */ + uint rovr; /* Receive Oversize Packet */ + uint rfrg; /* Receive Fragments */ + uint rjbr; /* Receive Jabber */ + uint rdrp; /* Receive Drop */ + /* Transmit Counters */ + uint tbyt; /* Transmit Byte Counter */ + uint tpkt; /* Transmit Packet */ + uint tmca; /* Transmit Multicast Packet */ + uint tbca; /* Transmit Broadcast Packet */ + uint txpf; /* Transmit Pause Control Frame */ + uint tdfr; /* Transmit Deferral Packet */ + uint tedf; /* Transmit Excessive Deferral Packet */ + uint tscl; /* Transmit Single Collision Packet */ + /* (0x2_n700) */ + uint tmcl; /* Transmit Multiple Collision Packet */ + uint tlcl; /* Transmit Late Collision Packet */ + uint txcl; /* Transmit Excessive Collision Packet */ + uint tncl; /* Transmit Total Collision */ + + uint res2; + + uint tdrp; /* Transmit Drop Frame */ + uint tjbr; /* Transmit Jabber Frame */ + uint tfcs; /* Transmit FCS Error */ + uint txcf; /* Transmit Control Frame */ + uint tovr; /* Transmit Oversize Frame */ + uint tund; /* Transmit Undersize Frame */ + uint tfrg; /* Transmit Fragments Frame */ + /* General Registers */ + uint car1; /* Carry Register One */ + uint car2; /* Carry Register Two */ + uint cam1; /* Carry Register One Mask */ + uint cam2; /* Carry Register Two Mask */ +} rmon_mib_t; + +typedef struct tsec_hash_regs +{ + uint iaddr0; /* Individual Address Register 0 */ + uint iaddr1; /* Individual Address Register 1 */ + uint iaddr2; /* Individual Address Register 2 */ + uint iaddr3; /* Individual Address Register 3 */ + uint iaddr4; /* Individual Address Register 4 */ + uint iaddr5; /* Individual Address Register 5 */ + uint iaddr6; /* Individual Address Register 6 */ + uint iaddr7; /* Individual Address Register 7 */ + uint res1[24]; + uint gaddr0; /* Group Address Register 0 */ + uint gaddr1; /* Group Address Register 1 */ + uint gaddr2; /* Group Address Register 2 */ + uint gaddr3; /* Group Address Register 3 */ + uint gaddr4; /* Group Address Register 4 */ + uint gaddr5; /* Group Address Register 5 */ + uint gaddr6; /* Group Address Register 6 */ + uint gaddr7; /* Group Address Register 7 */ + uint res2[24]; +} tsec_hash_t; + +typedef struct tsec +{ + /* General Control and Status Registers (0x2_n000) */ + uint res000[4]; + + uint ievent; /* Interrupt Event */ + uint imask; /* Interrupt Mask */ + uint edis; /* Error Disabled */ + uint res01c; + uint ecntrl; /* Ethernet Control */ + uint minflr; /* Minimum Frame Length */ + uint ptv; /* Pause Time Value */ + uint dmactrl; /* DMA Control */ + uint tbipa; /* TBI PHY Address */ + + uint res034[3]; + uint res040[48]; + + /* Transmit Control and Status Registers (0x2_n100) */ + uint tctrl; /* Transmit Control */ + uint tstat; /* Transmit Status */ + uint res108; + uint tbdlen; /* Tx BD Data Length */ + uint res110[5]; + uint ctbptr; /* Current TxBD Pointer */ + uint res128[23]; + uint tbptr; /* TxBD Pointer */ + uint res188[30]; + /* (0x2_n200) */ + uint res200; + uint tbase; /* TxBD Base Address */ + uint res208[42]; + uint ostbd; /* Out of Sequence TxBD */ + uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */ + uint res2b8[18]; + + /* Receive Control and Status Registers (0x2_n300) */ + uint rctrl; /* Receive Control */ + uint rstat; /* Receive Status */ + uint res308; + uint rbdlen; /* RxBD Data Length */ + uint res310[4]; + uint res320; + uint crbptr; /* Current Receive Buffer Pointer */ + uint res328[6]; + uint mrblr; /* Maximum Receive Buffer Length */ + uint res344[16]; + uint rbptr; /* RxBD Pointer */ + uint res388[30]; + /* (0x2_n400) */ + uint res400; + uint rbase; /* RxBD Base Address */ + uint res408[62]; + + /* MAC Registers (0x2_n500) */ + uint maccfg1; /* MAC Configuration #1 */ + uint maccfg2; /* MAC Configuration #2 */ + uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */ + uint hafdup; /* Half-duplex */ + uint maxfrm; /* Maximum Frame */ + uint res514; + uint res518; + + uint res51c; + + uint miimcfg; /* MII Management: Configuration */ + uint miimcom; /* MII Management: Command */ + uint miimadd; /* MII Management: Address */ + uint miimcon; /* MII Management: Control */ + uint miimstat; /* MII Management: Status */ + uint miimind; /* MII Management: Indicators */ + + uint res538; + + uint ifstat; /* Interface Status */ + uint macstnaddr1; /* Station Address, part 1 */ + uint macstnaddr2; /* Station Address, part 2 */ + uint res548[46]; + + /* (0x2_n600) */ + uint res600[32]; + + /* RMON MIB Registers (0x2_n680-0x2_n73c) */ + rmon_mib_t rmon; + uint res740[48]; + + /* Hash Function Registers (0x2_n800) */ + tsec_hash_t hash; + + uint res900[128]; + + /* Pattern Registers (0x2_nb00) */ + uint resb00[62]; + uint attr; /* Default Attribute Register */ + uint attreli; /* Default Attribute Extract Length and Index */ + + /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */ + uint resc00[256]; +} tsec_t; + +#define TSEC_GIGABIT (1) + +/* This flag currently only has + * meaning if we're using the eTSEC */ +#define TSEC_REDUCED (1 << 1) + +struct tsec_private { + volatile tsec_t *regs; + volatile tsec_t *phyregs; + struct phy_info *phyinfo; + uint phyaddr; + u32 flags; + uint link; + uint duplexity; + uint speed; +}; + + +/* + * struct phy_cmd: A command for reading or writing a PHY register + * + * mii_reg: The register to read or write + * + * mii_data: For writes, the value to put in the register. + * A value of -1 indicates this is a read. + * + * funct: A function pointer which is invoked for each command. + * For reads, this function will be passed the value read + * from the PHY, and process it. + * For writes, the result of this function will be written + * to the PHY register + */ +struct phy_cmd { + uint mii_reg; + uint mii_data; + uint (*funct) (uint mii_reg, struct tsec_private* priv); +}; + +/* struct phy_info: a structure which defines attributes for a PHY + * + * id will contain a number which represents the PHY. During + * startup, the driver will poll the PHY to find out what its + * UID--as defined by registers 2 and 3--is. The 32-bit result + * gotten from the PHY will be shifted right by "shift" bits to + * discard any bits which may change based on revision numbers + * unimportant to functionality + * + * The struct phy_cmd entries represent pointers to an arrays of + * commands which tell the driver what to do to the PHY. + */ +struct phy_info { + uint id; + char *name; + uint shift; + /* Called to configure the PHY, and modify the controller + * based on the results */ + struct phy_cmd *config; + + /* Called when starting up the controller */ + struct phy_cmd *startup; + + /* Called when bringing down the controller */ + struct phy_cmd *shutdown; +}; + +#endif /* __TSEC_H */ diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c new file mode 100644 index 0000000000..524e9daa4c --- /dev/null +++ b/drivers/net/tsi108_eth.c @@ -0,0 +1,1036 @@ +/*********************************************************************** + * + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Description: + * Ethernet interface for Tundra TSI108 bridge chip + * + ***********************************************************************/ + +#include + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_TSI108_ETH) + +#if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2) +#error "CONFIG_TSI108_ETH_NUM_PORTS must be defined as 1 or 2" +#endif + +#include +#include +#include +#include + +#ifdef DEBUG +#define TSI108_ETH_DEBUG 7 +#else +#define TSI108_ETH_DEBUG 0 +#endif + +#if TSI108_ETH_DEBUG > 0 +#define debug_lev(lev, fmt, args...) \ +if (lev <= TSI108_ETH_DEBUG) \ +printf ("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) +#else +#define debug_lev(lev, fmt, args...) do{}while(0) +#endif + +#define RX_PRINT_ERRORS +#define TX_PRINT_ERRORS + +#define ETH_BASE (CFG_TSI108_CSR_BASE + 0x6000) + +#define ETH_PORT_OFFSET 0x400 + +#define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset)))) + +#define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000) +#define MAC_CONFIG_1_TX_ENABLE (0x00000001) +#define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002) +#define MAC_CONFIG_1_RX_ENABLE (0x00000004) +#define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008) +#define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010) +#define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020) +#define MAC_CONFIG_1_LOOP_BACK (0x00000100) +#define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000) +#define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000) +#define MAC_CONFIG_1_RESET_TX_MAC (0x00040000) +#define MAC_CONFIG_1_RESET_RX_MAC (0x00080000) +#define MAC_CONFIG_1_SIM_RESET (0x40000000) +#define MAC_CONFIG_1_SOFT_RESET (0x80000000) + +#define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004) +#define MAC_CONFIG_2_FULL_DUPLEX (0x00000001) +#define MAC_CONFIG_2_CRC_ENABLE (0x00000002) +#define MAC_CONFIG_2_PAD_CRC (0x00000004) +#define MAC_CONFIG_2_LENGTH_CHECK (0x00000010) +#define MAC_CONFIG_2_HUGE_FRAME (0x00000020) +#define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8) +#define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12) +#define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */ +#define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */ + +#define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010) + +#define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020) +#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7) +#define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010) +#define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020) +#define MII_MGMT_CONFIG_RESET_MGMT (0x80000000) + +#define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024) +#define MII_MGMT_COMMAND_READ_CYCLE (0x00000001) +#define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002) + +#define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028) +#define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c) +#define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030) + +#define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034) +#define MII_MGMT_INDICATORS_BUSY (0x00000001) +#define MII_MGMT_INDICATORS_SCAN (0x00000002) +#define MII_MGMT_INDICATORS_NOT_VALID (0x00000004) + +#define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c) +#define INTERFACE_STATUS_LINK_FAIL (0x00000008) +#define INTERFACE_STATUS_EXCESS_DEFER (0x00000200) + +#define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040) +#define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044) + +#define reg_PORT_CONTROL(base) __REG32(base, 0x00000200) +#define PORT_CONTROL_PRI (0x00000001) +#define PORT_CONTROL_BPT (0x00010000) +#define PORT_CONTROL_SPD (0x00040000) +#define PORT_CONTROL_RBC (0x00080000) +#define PORT_CONTROL_PRB (0x00200000) +#define PORT_CONTROL_DIS (0x00400000) +#define PORT_CONTROL_TBI (0x00800000) +#define PORT_CONTROL_STE (0x10000000) +#define PORT_CONTROL_ZOR (0x20000000) +#define PORT_CONTROL_CLR (0x40000000) +#define PORT_CONTROL_SRT (0x80000000) + +#define reg_TX_CONFIG(base) __REG32(base, 0x00000220) +#define TX_CONFIG_START_Q (0x00000003) +#define TX_CONFIG_EHP (0x00400000) +#define TX_CONFIG_CHP (0x00800000) +#define TX_CONFIG_RST (0x80000000) + +#define reg_TX_CONTROL(base) __REG32(base, 0x00000224) +#define TX_CONTROL_GO (0x00008000) +#define TX_CONTROL_MP (0x01000000) +#define TX_CONTROL_EAI (0x20000000) +#define TX_CONTROL_ABT (0x40000000) +#define TX_CONTROL_EII (0x80000000) + +#define reg_TX_STATUS(base) __REG32(base, 0x00000228) +#define TX_STATUS_QUEUE_USABLE (0x0000000f) +#define TX_STATUS_CURR_Q (0x00000300) +#define TX_STATUS_ACT (0x00008000) +#define TX_STATUS_QUEUE_IDLE (0x000f0000) +#define TX_STATUS_EOQ_PENDING (0x0f000000) + +#define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c) +#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f) +#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00) +#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230) + +#define reg_TX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000270) +#define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define TX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define TX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274) + +#define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278) +#define TX_ERROR_STATUS (0x00000278) +#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010) +#define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020) +#define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040) +#define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080) +#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000) +#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000) +#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000) + +#define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280) +#define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define TX_QUEUE_0_CONFIG_AM (0x00004000) +#define TX_QUEUE_0_CONFIG_GVI (0x00008000) +#define TX_QUEUE_0_CONFIG_EEI (0x00010000) +#define TX_QUEUE_0_CONFIG_ELI (0x00020000) +#define TX_QUEUE_0_CONFIG_ENI (0x00040000) +#define TX_QUEUE_0_CONFIG_ESI (0x00080000) +#define TX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284) +#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define OCN_PORT_HLP 0 /* HLP Interface */ +#define OCN_PORT_PCI_X 1 /* PCI-X Interface */ +#define OCN_PORT_PROCESSOR_MASTER 2 /* Processor Interface (master) */ +#define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */ +#define OCN_PORT_MEMORY 4 /* Memory Controller */ +#define OCN_PORT_DMA 5 /* DMA Controller */ +#define OCN_PORT_ETHERNET 6 /* Ethernet Controller */ +#define OCN_PORT_PRINT 7 /* Print Engine Interface */ + +#define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288) + +#define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c) +#define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000) + +#define reg_RX_CONFIG(base) __REG32(base, 0x00000320) +#define RX_CONFIG_DEF_Q (0x00000003) +#define RX_CONFIG_EMF (0x00000100) +#define RX_CONFIG_EUF (0x00000200) +#define RX_CONFIG_BFE (0x00000400) +#define RX_CONFIG_MFE (0x00000800) +#define RX_CONFIG_UFE (0x00001000) +#define RX_CONFIG_SE (0x00002000) +#define RX_CONFIG_ABF (0x00200000) +#define RX_CONFIG_APE (0x00400000) +#define RX_CONFIG_CHP (0x00800000) +#define RX_CONFIG_RST (0x80000000) + +#define reg_RX_CONTROL(base) __REG32(base, 0x00000324) +#define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f) +#define GE_E0_RX_CONTROL_GO (0x00008000) +#define GE_E0_RX_CONTROL_EAI (0x20000000) +#define GE_E0_RX_CONTROL_ABT (0x40000000) +#define GE_E0_RX_CONTROL_EII (0x80000000) + +#define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c) +#define RX_EXTENDED_STATUS (0x0000032c) +#define RX_EXTENDED_STATUS_EOQ (0x0000000f) +#define RX_EXTENDED_STATUS_EOQ_0 (0x00000001) +#define RX_EXTENDED_STATUS_EOF (0x00000f00) +#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330) + +#define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370) +#define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define RX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define RX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374) + +#define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380) +#define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define RX_QUEUE_0_CONFIG_AM (0x00004000) +#define RX_QUEUE_0_CONFIG_EEI (0x00010000) +#define RX_QUEUE_0_CONFIG_ELI (0x00020000) +#define RX_QUEUE_0_CONFIG_ENI (0x00040000) +#define RX_QUEUE_0_CONFIG_ESI (0x00080000) +#define RX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384) +#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388) + +#define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c) +#define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000) + +/* + * PHY register definitions + */ +/* the first 15 PHY registers are standard. */ +#define PHY_CTRL_REG 0 /* Control Register */ +#define PHY_STATUS_REG 1 /* Status Regiser */ +#define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */ +#define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */ +#define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */ +#define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */ + +/* + * PHY Register bit masks. + */ +#define PHY_CTRL_RESET (1 << 15) +#define PHY_CTRL_LOOPBACK (1 << 14) +#define PHY_CTRL_SPEED0 (1 << 13) +#define PHY_CTRL_AN_EN (1 << 12) +#define PHY_CTRL_PWR_DN (1 << 11) +#define PHY_CTRL_ISOLATE (1 << 10) +#define PHY_CTRL_RESTART_AN (1 << 9) +#define PHY_CTRL_FULL_DUPLEX (1 << 8) +#define PHY_CTRL_CT_EN (1 << 7) +#define PHY_CTRL_SPEED1 (1 << 6) + +#define PHY_STAT_100BASE_T4 (1 << 15) +#define PHY_STAT_100BASE_X_FD (1 << 14) +#define PHY_STAT_100BASE_X_HD (1 << 13) +#define PHY_STAT_10BASE_T_FD (1 << 12) +#define PHY_STAT_10BASE_T_HD (1 << 11) +#define PHY_STAT_100BASE_T2_FD (1 << 10) +#define PHY_STAT_100BASE_T2_HD (1 << 9) +#define PHY_STAT_EXT_STAT (1 << 8) +#define PHY_STAT_RESERVED (1 << 7) +#define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */ +#define PHY_STAT_AN_COMPLETE (1 << 5) +#define PHY_STAT_REM_FAULT (1 << 4) +#define PHY_STAT_AN_CAP (1 << 3) +#define PHY_STAT_LINK_UP (1 << 2) +#define PHY_STAT_JABBER (1 << 1) +#define PHY_STAT_EXT_CAP (1 << 0) + +#define TBI_CONTROL_2 0x11 +#define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001 +#define TBI_CONTROL_2_ENABLE_WRAP 0x0002 +#define TBI_CONTROL_2_G_MII_MODE 0x0010 +#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020 +#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100 +#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000 +#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000 +#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000 +#define TBI_CONTROL_2_SOFT_RESET 0x8000 + +/* marvel specific */ +#define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */ +#define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */ +#define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */ + +/* + * MARVELL 88E1111 PHY register bit masks + */ +/* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */ + +#define SPEC_STAT_SPEED_MASK (3 << 14) +#define SPEC_STAT_FULL_DUP (1 << 13) +#define SPEC_STAT_PAGE_RCVD (1 << 12) +#define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */ +#define SPEC_STAT_LINK_UP (1 << 10) +#define SPEC_STAT_CABLE_LEN_MASK (7 << 7)/* Cable Length (100/1000 modes only) */ +#define SPEC_STAT_MDIX (1 << 6) +#define SPEC_STAT_POLARITY (1 << 1) +#define SPEC_STAT_JABBER (1 << 0) + +#define SPEED_1000 (2 << 14) +#define SPEED_100 (1 << 14) +#define SPEED_10 (0 << 14) + +#define TBI_ADDR 0x1E /* Ten Bit Interface address */ + +/* negotiated link parameters */ +#define LINK_SPEED_UNKNOWN 0 +#define LINK_SPEED_10 1 +#define LINK_SPEED_100 2 +#define LINK_SPEED_1000 3 + +#define LINK_DUPLEX_UNKNOWN 0 +#define LINK_DUPLEX_HALF 1 +#define LINK_DUPLEX_FULL 2 + +static unsigned int phy_address[] = { 8, 9 }; + +#define vuint32 volatile u32 + +/* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte) + * This structure is accessed by the ethernet DMA engine which means it + * MUST be in LITTLE ENDIAN format */ +struct dma_descriptor { + vuint32 start_addr0; /* buffer address, least significant bytes. */ + vuint32 start_addr1; /* buffer address, most significant bytes. */ + vuint32 next_descr_addr0;/* next descriptor address, least significant bytes. Must be 64-bit aligned. */ + vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */ + vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */ + vuint32 config_status; /* Configuration/Status. */ + vuint32 reserved1; /* reserved to make the descriptor cache line aligned. */ + vuint32 reserved2; /* reserved to make the descriptor cache line aligned. */ +}; + +/* last next descriptor address flag */ +#define DMA_DESCR_LAST (1 << 31) + +/* TX DMA descriptor config status bits */ +#define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */ +#define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */ +#define DMA_DESCR_TX_PFVLAN (1 << 2) +#define DMA_DESCR_TX_HUGE (1 << 3) +#define DMA_DESCR_TX_PAD (1 << 4) +#define DMA_DESCR_TX_CRC (1 << 5) +#define DMA_DESCR_TX_DESCR_INT (1 << 14) +#define DMA_DESCR_TX_RETRY_COUNT 0x000F0000 +#define DMA_DESCR_TX_ONE_COLLISION (1 << 20) +#define DMA_DESCR_TX_LATE_COLLISION (1 << 24) +#define DMA_DESCR_TX_UNDERRUN (1 << 25) +#define DMA_DESCR_TX_RETRY_LIMIT (1 << 26) +#define DMA_DESCR_TX_OK (1 << 30) +#define DMA_DESCR_TX_OWNER (1 << 31) + +/* RX DMA descriptor status bits */ +#define DMA_DESCR_RX_EOF (1 << 0) +#define DMA_DESCR_RX_SOF (1 << 1) +#define DMA_DESCR_RX_VTF (1 << 2) +#define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3) +#define DMA_DESCR_RX_SHORT_FRAME (1 << 4) +#define DMA_DESCR_RX_HASH_MATCH (1 << 7) +#define DMA_DESCR_RX_BAD_FRAME (1 << 8) +#define DMA_DESCR_RX_OVERRUN (1 << 9) +#define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11) +#define DMA_DESCR_RX_CRC_ERROR (1 << 12) +#define DMA_DESCR_RX_DESCR_INT (1 << 13) +#define DMA_DESCR_RX_OWNER (1 << 15) + +#define RX_BUFFER_SIZE PKTSIZE +#define NUM_RX_DESC PKTBUFSRX + +static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32))); + +static struct dma_descriptor rx_descr_array[NUM_RX_DESC] + __attribute__ ((aligned(32))); + +static struct dma_descriptor *rx_descr_current; + +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis); +static int tsi108_eth_send (struct eth_device *dev, + volatile void *packet, int length); +static int tsi108_eth_recv (struct eth_device *dev); +static void tsi108_eth_halt (struct eth_device *dev); +static unsigned int read_phy (unsigned int base, + unsigned int phy_addr, unsigned int phy_reg); +static void write_phy (unsigned int base, + unsigned int phy_addr, + unsigned int phy_reg, unsigned int phy_data); + +#if TSI108_ETH_DEBUG > 100 +/* + * print phy debug infomation + */ +static void dump_phy_regs (unsigned int phy_addr) +{ + int i; + + printf ("PHY %d registers\n", phy_addr); + for (i = 0; i <= 30; i++) { + printf ("%2d 0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i)); + } + printf ("\n"); + +} +#else +#define dump_phy_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void tx_diag_regs (unsigned int base) +{ + int i; + unsigned long dummy; + + printf ("TX diagnostics registers\n"); + reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI; + udelay (1000); + dummy = reg_TX_DIAGNOSTIC_DATA(base); + for (i = 0x00; i <= 0x05; i++) { + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + } + reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI; + udelay (1000); + dummy = reg_TX_DIAGNOSTIC_DATA(base); + for (i = 0x40; i <= 0x47; i++) { + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + } + printf ("\n"); + +} +#else +#define tx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void rx_diag_regs (unsigned int base) +{ + int i; + unsigned long dummy; + + printf ("RX diagnostics registers\n"); + reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI; + udelay (1000); + dummy = reg_RX_DIAGNOSTIC_DATA(base); + for (i = 0x00; i <= 0x05; i++) { + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + } + reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI; + udelay (1000); + dummy = reg_RX_DIAGNOSTIC_DATA(base); + for (i = 0x08; i <= 0x0a; i++) { + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + } + printf ("\n"); + +} +#else +#define rx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void debug_mii_regs (unsigned int base) +{ + printf ("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base)); + printf ("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base)); + printf ("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base)); + printf ("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base)); + printf ("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base)); + printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); + printf ("\n"); + +} +#else +#define debug_mii_regs(base) do{}while(0) +#endif + +/* + * Wait until the phy bus is non-busy + */ +static void phy_wait (unsigned int base, unsigned int condition) +{ + int timeout; + + timeout = 0; + while (reg_MII_MGMT_INDICATORS(base) & condition) { + udelay (10); + if (++timeout > 10000) { + printf ("ERROR: timeout waiting for phy bus (%d)\n", + condition); + break; + } + } +} + +/* + * read phy register + */ +static unsigned int read_phy (unsigned int base, + unsigned int phy_addr, unsigned int phy_reg) +{ + unsigned int value; + + phy_wait (base, MII_MGMT_INDICATORS_BUSY); + + reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + + /* Ensure that the Read Cycle bit is cleared prior to next read cycle */ + reg_MII_MGMT_COMMAND(base) = 0; + + /* start the read */ + reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE; + + /* wait for the read to complete */ + phy_wait (base, + MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY); + + value = reg_MII_MGMT_STATUS(base); + + reg_MII_MGMT_COMMAND(base) = 0; + + return value; +} + +/* + * write phy register + */ +static void write_phy (unsigned int base, + unsigned int phy_addr, + unsigned int phy_reg, unsigned int phy_data) +{ + phy_wait (base, MII_MGMT_INDICATORS_BUSY); + + reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + + /* Ensure that the Read Cycle bit is cleared prior to next cycle */ + reg_MII_MGMT_COMMAND(base) = 0; + + /* start the write */ + reg_MII_MGMT_CONTROL(base) = phy_data; +} + +/* + * configure the marvell 88e1111 phy + */ +static int marvell_88e_phy_config (struct eth_device *dev, int *speed, + int *duplex) +{ + unsigned long base; + unsigned long phy_addr; + unsigned int phy_status; + unsigned int phy_spec_status; + int timeout; + int phy_speed; + int phy_duplex; + unsigned int value; + + phy_speed = LINK_SPEED_UNKNOWN; + phy_duplex = LINK_DUPLEX_UNKNOWN; + + base = dev->iobase; + phy_addr = (unsigned long)dev->priv; + + /* Take the PHY out of reset. */ + write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); + + /* Wait for the reset process to complete. */ + udelay (10); + timeout = 0; + while ((phy_status = + read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { + udelay (10); + if (++timeout > 10000) { + printf ("ERROR: timeout waiting for phy reset\n"); + break; + } + } + + /* TBI Configuration. */ + write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | + TBI_CONTROL_2_RECEIVE_CLOCK_SELECT); + /* Wait for the link to be established. */ + timeout = 0; + do { + udelay (20000); + phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG); + if (++timeout > 100) { + debug_lev(1, "ERROR: unable to establish link!!!\n"); + break; + } + } while ((phy_status & PHY_STAT_LINK_UP) == 0); + + if ((phy_status & PHY_STAT_LINK_UP) == 0) + return 0; + + value = 0; + phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + if (phy_spec_status & SPEC_STAT_RESOLVED) { + switch (phy_spec_status & SPEC_STAT_SPEED_MASK) { + case SPEED_1000: + phy_speed = LINK_SPEED_1000; + value |= PHY_CTRL_SPEED1; + break; + case SPEED_100: + phy_speed = LINK_SPEED_100; + value |= PHY_CTRL_SPEED0; + break; + case SPEED_10: + phy_speed = LINK_SPEED_10; + break; + } + if (phy_spec_status & SPEC_STAT_FULL_DUP) { + phy_duplex = LINK_DUPLEX_FULL; + value |= PHY_CTRL_FULL_DUPLEX; + } else + phy_duplex = LINK_DUPLEX_HALF; + } + /* set TBI speed */ + write_phy (base, TBI_ADDR, PHY_CTRL_REG, value); + write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); + +#if TSI108_ETH_DEBUG > 0 + printf ("%s link is up", dev->name); + phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + if (phy_spec_status & SPEC_STAT_RESOLVED) { + switch (phy_speed) { + case LINK_SPEED_1000: + printf (", 1000 Mbps"); + break; + case LINK_SPEED_100: + printf (", 100 Mbps"); + break; + case LINK_SPEED_10: + printf (", 10 Mbps"); + break; + } + if (phy_duplex == LINK_DUPLEX_FULL) + printf (", Full duplex"); + else + printf (", Half duplex"); + } + printf ("\n"); +#endif + + dump_phy_regs (TBI_ADDR); + if (speed) + *speed = phy_speed; + if (duplex) + *duplex = phy_duplex; + + return 1; +} + +/* + * External interface + * + * register the tsi108 ethernet controllers with the multi-ethernet system + */ +int tsi108_eth_initialize (bd_t * bis) +{ + struct eth_device *dev; + int index; + + for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { + dev = (struct eth_device *)malloc(sizeof(struct eth_device)); + + sprintf (dev->name, "TSI108_eth%d", index); + + dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); + dev->priv = (void *)(phy_address[index]); + dev->init = tsi108_eth_probe; + dev->halt = tsi108_eth_halt; + dev->send = tsi108_eth_send; + dev->recv = tsi108_eth_recv; + + eth_register(dev); + } + return index; +} + +/* + * probe for and initialize a single ethernet interface + */ +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis) +{ + unsigned long base; + unsigned long value; + int index; + struct dma_descriptor *tx_descr; + struct dma_descriptor *rx_descr; + int speed; + int duplex; + + base = dev->iobase; + + reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT; + + /* Bring DMA/FIFO out of reset. */ + reg_TX_CONFIG(base) = 0x00000000; + reg_RX_CONFIG(base) = 0x00000000; + + reg_TX_THRESHOLDS(base) = (192 << 16) | 192; + reg_RX_THRESHOLDS(base) = (192 << 16) | 112; + + /* Bring MAC out of reset. */ + reg_MAC_CONFIG_1(base) = 0x00000000; + + /* DMA MAC configuration. */ + reg_MAC_CONFIG_1(base) = + MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE; + + reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE; + reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE; + + /* Note: Early tsi108 manual did not have correct byte order + * for the station address.*/ + reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) | + (dev->enetaddr[4] << 16) | + (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0); + + reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | + (dev->enetaddr[0] << 16); + + if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) + return 0; + + value = + MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | + MAC_CONFIG_2_CRC_ENABLE; + if (speed == LINK_SPEED_1000) + value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); + else { + value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); + reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; + } + if (duplex == LINK_DUPLEX_FULL) { + value |= MAC_CONFIG_2_FULL_DUPLEX; + reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; + } else + reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; + reg_MAC_CONFIG_2(base) = value; + + reg_RX_CONFIG(base) = RX_CONFIG_SE; + reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; + reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + + /* initialize the RX DMA descriptors */ + rx_descr = &rx_descr_array[0]; + rx_descr_current = rx_descr; + for (index = 0; index < NUM_RX_DESC; index++) { + /* make sure the receive buffers are not in cache */ + invalidate_dcache_range((unsigned long)NetRxPackets[index], + (unsigned long)NetRxPackets[index] + + RX_BUFFER_SIZE); + rx_descr->start_addr0 = + cpu_to_le32((vuint32) NetRxPackets[index]); + rx_descr->start_addr1 = 0; + rx_descr->next_descr_addr0 = + cpu_to_le32((vuint32) (rx_descr + 1)); + rx_descr->next_descr_addr1 = 0; + rx_descr->vlan_byte_count = 0; + rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | + DMA_DESCR_RX_OWNER); + rx_descr++; + } + rx_descr--; + rx_descr->next_descr_addr0 = 0; + rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + /* Push the descriptors to RAM so the ethernet DMA can see them */ + invalidate_dcache_range((unsigned long)rx_descr_array, + (unsigned long)rx_descr_array + + sizeof(rx_descr_array)); + + /* enable RX queue */ + reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01; + reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current; + /* enable receive DMA */ + reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; + + reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; + reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + + /* initialize the TX DMA descriptor */ + tx_descr = &tx_descriptor; + + tx_descr->start_addr0 = 0; + tx_descr->start_addr1 = 0; + tx_descr->next_descr_addr0 = 0; + tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + tx_descr->vlan_byte_count = 0; + tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK | + DMA_DESCR_TX_SOF | + DMA_DESCR_TX_EOF); + /* enable TX queue */ + reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01; + + return 1; +} + +/* + * send a packet + */ +static int tsi108_eth_send (struct eth_device *dev, + volatile void *packet, int length) +{ + unsigned long base; + int timeout; + struct dma_descriptor *tx_descr; + unsigned long status; + + base = dev->iobase; + tx_descr = &tx_descriptor; + + /* Wait until the last packet has been transmitted. */ + timeout = 0; + do { + /* make sure we see the changes made by the DMA engine */ + invalidate_dcache_range((unsigned long)tx_descr, + (unsigned long)tx_descr + + sizeof(struct dma_descriptor)); + + if (timeout != 0) + udelay (15); + if (++timeout > 10000) { + tx_diag_regs(base); + debug_lev(1, + "ERROR: timeout waiting for last transmit packet to be sent\n"); + return 0; + } + } while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER)); + + status = le32_to_cpu(tx_descr->config_status); + if ((status & DMA_DESCR_TX_OK) == 0) { +#ifdef TX_PRINT_ERRORS + printf ("TX packet error: 0x%08x\n %s%s%s%s\n", status, + status & DMA_DESCR_TX_OK ? "tx error, " : "", + status & DMA_DESCR_TX_RETRY_LIMIT ? + "retry limit reached, " : "", + status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "", + status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, " + : ""); +#endif + } + + debug_lev (9, "sending packet %d\n", length); + tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); + tx_descr->start_addr1 = 0; + tx_descr->next_descr_addr0 = 0; + tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + tx_descr->vlan_byte_count = cpu_to_le32(length); + tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER | + DMA_DESCR_TX_CRC | + DMA_DESCR_TX_PAD | + DMA_DESCR_TX_SOF | + DMA_DESCR_TX_EOF); + + invalidate_dcache_range((unsigned long)tx_descr, + (unsigned long)tx_descr + + sizeof(struct dma_descriptor)); + + invalidate_dcache_range((unsigned long)packet, + (unsigned long)packet + length); + + reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr; + reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID; + + return length; +} + +/* + * Check for received packets and send them up the protocal stack + */ +static int tsi108_eth_recv (struct eth_device *dev) +{ + struct dma_descriptor *rx_descr; + unsigned long base; + int length = 0; + unsigned long status; + volatile uchar *buffer; + + base = dev->iobase; + + /* make sure we see the changes made by the DMA engine */ + invalidate_dcache_range ((unsigned long)rx_descr_array, + (unsigned long)rx_descr_array + + sizeof(rx_descr_array)); + + /* process all of the received packets */ + rx_descr = rx_descr_current; + while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) { + /* check for error */ + status = le32_to_cpu(rx_descr->config_status); + if (status & DMA_DESCR_RX_BAD_FRAME) { +#ifdef RX_PRINT_ERRORS + printf ("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", + status, + status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " + : "", + status & DMA_DESCR_RX_SHORT_FRAME ? "too short, " + : "", + status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " : + "", + status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "", + status & DMA_DESCR_RX_MAX_FRAME_LEN ? + "max length, " : "", + status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " : + ""); +#endif + } else { + length = + le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF; + + /*** process packet ***/ + buffer = + (volatile uchar + *)(le32_to_cpu (rx_descr->start_addr0)); + NetReceive (buffer, length); + + invalidate_dcache_range ((unsigned long)buffer, + (unsigned long)buffer + + RX_BUFFER_SIZE); + } + /* Give this buffer back to the DMA engine */ + rx_descr->vlan_byte_count = 0; + rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) | + DMA_DESCR_RX_OWNER); + /* move descriptor pointer forward */ + rx_descr = + (struct dma_descriptor + *)(le32_to_cpu (rx_descr->next_descr_addr0)); + if (rx_descr == 0) + rx_descr = &rx_descr_array[0]; + } + /* remember where we are for next time */ + rx_descr_current = rx_descr; + + /* If the DMA engine has reached the end of the queue + * start over at the begining */ + if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) { + + reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0; + reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0]; + reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; + } + + return length; +} + +/* + * disable an ethernet interface + */ +static void tsi108_eth_halt (struct eth_device *dev) +{ + unsigned long base; + + base = dev->iobase; + + /* Put DMA/FIFO into reset state. */ + reg_TX_CONFIG(base) = TX_CONFIG_RST; + reg_RX_CONFIG(base) = RX_CONFIG_RST; + + /* Put MAC into reset state. */ + reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET; +} + +#endif diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c new file mode 100644 index 0000000000..1267c5798f --- /dev/null +++ b/drivers/net/uli526x.c @@ -0,0 +1,996 @@ +/* + * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Roy Zang , Sep, 2007 + * + * Description: + * ULI 526x Ethernet port driver. + * Based on the Linux driver: drivers/net/tulip/uli526x.c + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +/* some kernel function compatible define */ + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_ULI526X) + +#undef DEBUG + +/* Board/System/Debug information/definition */ +#define ULI_VENDOR_ID 0x10B9 +#define ULI5261_DEVICE_ID 0x5261 +#define ULI5263_DEVICE_ID 0x5263 +/* ULi M5261 ID*/ +#define PCI_ULI5261_ID ULI5261_DEVICE_ID << 16 | ULI_VENDOR_ID +/* ULi M5263 ID*/ +#define PCI_ULI5263_ID ULI5263_DEVICE_ID << 16 | ULI_VENDOR_ID + +#define ULI526X_IO_SIZE 0x100 +#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */ +#define RX_DESC_CNT PKTBUFSRX /* Allocated Rx descriptors */ +#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */ +#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */ +#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT) +#define TX_BUF_ALLOC 0x300 +#define RX_ALLOC_SIZE PKTSIZE +#define ULI526X_RESET 1 +#define CR0_DEFAULT 0 +#define CR6_DEFAULT 0x22200000 +#define CR7_DEFAULT 0x180c1 +#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */ +#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */ +#define MAX_PACKET_SIZE 1514 +#define ULI5261_MAX_MULTICAST 14 +#define RX_COPY_SIZE 100 +#define MAX_CHECK_PACKET 0x8000 + +#define ULI526X_10MHF 0 +#define ULI526X_100MHF 1 +#define ULI526X_10MFD 4 +#define ULI526X_100MFD 5 +#define ULI526X_AUTO 8 + +#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */ +#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */ +#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */ +#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */ +#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */ +#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */ + +/* CR9 definition: SROM/MII */ +#define CR9_SROM_READ 0x4800 +#define CR9_SRCS 0x1 +#define CR9_SRCLK 0x2 +#define CR9_CRDOUT 0x8 +#define SROM_DATA_0 0x0 +#define SROM_DATA_1 0x4 +#define PHY_DATA_1 0x20000 +#define PHY_DATA_0 0x00000 +#define MDCLKH 0x10000 + +#define PHY_POWER_DOWN 0x800 + +#define SROM_V41_CODE 0x14 + +#define SROM_CLK_WRITE(data, ioaddr) do { \ + outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \ + udelay(5); \ + outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK, ioaddr); \ + udelay(5); \ + outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \ + udelay(5); \ + } while (0) + +/* Structure/enum declaration */ + +struct tx_desc { + u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ + char *tx_buf_ptr; /* Data for us */ + struct tx_desc *next_tx_desc; +}; + +struct rx_desc { + u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ + char *rx_buf_ptr; /* Data for us */ + struct rx_desc *next_rx_desc; +}; + +struct uli526x_board_info { + u32 chip_id; /* Chip vendor/Device ID */ + pci_dev_t pdev; + + long ioaddr; /* I/O base address */ + u32 cr0_data; + u32 cr5_data; + u32 cr6_data; + u32 cr7_data; + u32 cr15_data; + + /* pointer for memory physical address */ + dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */ + dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */ + dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */ + dma_addr_t first_tx_desc_dma; + dma_addr_t first_rx_desc_dma; + + /* descriptor pointer */ + unsigned char *buf_pool_ptr; /* Tx buffer pool memory */ + unsigned char *buf_pool_start; /* Tx buffer pool align dword */ + unsigned char *desc_pool_ptr; /* descriptor pool memory */ + struct tx_desc *first_tx_desc; + struct tx_desc *tx_insert_ptr; + struct tx_desc *tx_remove_ptr; + struct rx_desc *first_rx_desc; + struct rx_desc *rx_ready_ptr; /* packet come pointer */ + unsigned long tx_packet_cnt; /* transmitted packet count */ + + u16 PHY_reg4; /* Saved Phyxcer register 4 value */ + + u8 media_mode; /* user specify media mode */ + u8 op_mode; /* real work dedia mode */ + u8 phy_addr; + + /* NIC SROM data */ + unsigned char srom[128]; +}; + +enum uli526x_offsets { + DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20, + DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48, + DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70, + DCR15 = 0x78 +}; + +enum uli526x_CR6_bits { + CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80, + CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000, + CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000 +}; + +/* Global variable declaration -- */ + +static unsigned char uli526x_media_mode = ULI526X_AUTO; + +static struct tx_desc desc_pool_array[DESC_ALL_CNT + 0x20] + __attribute__ ((aligned(32))); +static char buf_pool[TX_BUF_ALLOC * TX_DESC_CNT + 4]; + +/* For module input parameter */ +static int mode = 8; + +/* function declaration -- */ +static int uli526x_start_xmit(struct eth_device *dev, + volatile void *packet, int length); +static const struct ethtool_ops netdev_ethtool_ops; +static u16 read_srom_word(long, int); +static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); +static void allocate_rx_buffer(struct uli526x_board_info *); +static void update_cr6(u32, unsigned long); +static u16 phy_read(unsigned long, u8, u8, u32); +static u16 phy_readby_cr10(unsigned long, u8, u8); +static void phy_write(unsigned long, u8, u8, u16, u32); +static void phy_writeby_cr10(unsigned long, u8, u8, u16); +static void phy_write_1bit(unsigned long, u32, u32); +static u16 phy_read_1bit(unsigned long, u32); +static int uli526x_rx_packet(struct eth_device *); +static void uli526x_free_tx_pkt(struct eth_device *, + struct uli526x_board_info *); +static void uli526x_reuse_buf(struct rx_desc *); +static void uli526x_init(struct eth_device *); +static void uli526x_set_phyxcer(struct uli526x_board_info *); + + +static int uli526x_init_one(struct eth_device *, bd_t *); +static void uli526x_disable(struct eth_device *); +static void set_mac_addr(struct eth_device *); + +static struct pci_device_id uli526x_pci_tbl[] = { + { ULI_VENDOR_ID, ULI5261_DEVICE_ID}, /* 5261 device */ + { ULI_VENDOR_ID, ULI5263_DEVICE_ID}, /* 5263 device */ + {} +}; + +/* ULI526X network board routine */ + +/* + * Search ULI526X board, register it + */ + +int uli526x_initialize(bd_t *bis) +{ + pci_dev_t devno; + int card_number = 0; + struct eth_device *dev; + struct uli526x_board_info *db; /* board information structure */ + + u32 iobase; + int idx = 0; + + while (1) { + /* Find PCI device */ + devno = pci_find_devices(uli526x_pci_tbl, idx++); + if (devno < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + dev = (struct eth_device *)malloc(sizeof *dev); + sprintf(dev->name, "uli526x#%d\n", card_number); + db = (struct uli526x_board_info *) + malloc(sizeof(struct uli526x_board_info)); + + dev->priv = db; + db->pdev = devno; + dev->iobase = iobase; + + dev->init = uli526x_init_one; + dev->halt = uli526x_disable; + dev->send = uli526x_start_xmit; + dev->recv = uli526x_rx_packet; + + /* init db */ + db->ioaddr = dev->iobase; + /* get chip id */ + + pci_read_config_dword(devno, PCI_VENDOR_ID, &db->chip_id); +#ifdef DEBUG + printf("uli526x: uli526x @0x%x\n", iobase); + printf("uli526x: chip_id%x\n", db->chip_id); +#endif + eth_register(dev); + card_number++; + pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); + udelay(10 * 1000); + } + return card_number; +} + +static int uli526x_init_one(struct eth_device *dev, bd_t *bis) +{ + + struct uli526x_board_info *db = dev->priv; + int i; + + switch (mode) { + case ULI526X_10MHF: + case ULI526X_100MHF: + case ULI526X_10MFD: + case ULI526X_100MFD: + uli526x_media_mode = mode; + break; + default: + uli526x_media_mode = ULI526X_AUTO; + break; + } + + /* Allocate Tx/Rx descriptor memory */ + db->desc_pool_ptr = (uchar *)&desc_pool_array[0]; + db->desc_pool_dma_ptr = (dma_addr_t)&desc_pool_array[0]; + if (db->desc_pool_ptr == NULL) + return 0; + + db->buf_pool_ptr = &buf_pool[0]; + db->buf_pool_dma_ptr = (dma_addr_t)&buf_pool[0]; + if (db->buf_pool_ptr == NULL) + return 0; + + db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr; + db->first_tx_desc_dma = db->desc_pool_dma_ptr; + + db->buf_pool_start = db->buf_pool_ptr; + db->buf_pool_dma_start = db->buf_pool_dma_ptr; + +#ifdef DEBUG + printf("%s(): db->ioaddr= 0x%x\n", + __FUNCTION__, db->ioaddr); + printf("%s(): media_mode= 0x%x\n", + __FUNCTION__, uli526x_media_mode); + printf("%s(): db->desc_pool_ptr= 0x%x\n", + __FUNCTION__, db->desc_pool_ptr); + printf("%s(): db->desc_pool_dma_ptr= 0x%x\n", + __FUNCTION__, db->desc_pool_dma_ptr); + printf("%s(): db->buf_pool_ptr= 0x%x\n", + __FUNCTION__, db->buf_pool_ptr); + printf("%s(): db->buf_pool_dma_ptr= 0x%x\n", + __FUNCTION__, db->buf_pool_dma_ptr); +#endif + + /* read 64 word srom data */ + for (i = 0; i < 64; i++) + ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, + i)); + + /* Set Node address */ + if (((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0) + /* SROM absent, so write MAC address to ID Table */ + set_mac_addr(dev); + else { /*Exist SROM*/ + for (i = 0; i < 6; i++) + dev->enetaddr[i] = db->srom[20 + i]; + } +#ifdef DEBUG + for (i = 0; i < 6; i++) + printf("%c%02x", i ? ':' : ' ', dev->enetaddr[i]); +#endif + db->PHY_reg4 = 0x1e0; + + /* system variable init */ + db->cr6_data = CR6_DEFAULT ; + db->cr6_data |= ULI526X_TXTH_256; + db->cr0_data = CR0_DEFAULT; + uli526x_init(dev); + return 1; +} + +static void uli526x_disable(struct eth_device *dev) +{ +#ifdef DEBUG + printf("uli526x_disable\n"); +#endif + struct uli526x_board_info *db = dev->priv; + + if (!((inl(db->ioaddr + DCR12)) & 0x8)) { + /* Reset & stop ULI526X board */ + outl(ULI526X_RESET, db->ioaddr + DCR0); + udelay(5); + phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id); + + /* reset the board */ + db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */ + update_cr6(db->cr6_data, dev->iobase); + outl(0, dev->iobase + DCR7); /* Disable Interrupt */ + outl(inl(dev->iobase + DCR5), dev->iobase + DCR5); + } +} + +/* Initialize ULI526X board + * Reset ULI526X board + * Initialize TX/Rx descriptor chain structure + * Send the set-up frame + * Enable Tx/Rx machine + */ + +static void uli526x_init(struct eth_device *dev) +{ + + struct uli526x_board_info *db = dev->priv; + u8 phy_tmp; + u16 phy_value; + u16 phy_reg_reset; + + /* Reset M526x MAC controller */ + outl(ULI526X_RESET, db->ioaddr + DCR0); /* RESET MAC */ + udelay(100); + outl(db->cr0_data, db->ioaddr + DCR0); + udelay(5); + + /* Phy addr : In some boards,M5261/M5263 phy address != 1 */ + db->phy_addr = 1; + db->tx_packet_cnt = 0; + for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) { + /* peer add */ + phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id); + if (phy_value != 0xffff && phy_value != 0) { + db->phy_addr = phy_tmp; + break; + } + } + +#ifdef DEBUG + printf("%s(): db->ioaddr= 0x%x\n", __FUNCTION__, db->ioaddr); + printf("%s(): db->phy_addr= 0x%x\n", __FUNCTION__, db->phy_addr); +#endif + if (phy_tmp == 32) + printf("Can not find the phy address!!!"); + + /* Parser SROM and media mode */ + db->media_mode = uli526x_media_mode; + + if (!(inl(db->ioaddr + DCR12) & 0x8)) { + /* Phyxcer capability setting */ + phy_reg_reset = phy_read(db->ioaddr, + db->phy_addr, 0, db->chip_id); + phy_reg_reset = (phy_reg_reset | 0x8000); + phy_write(db->ioaddr, db->phy_addr, 0, + phy_reg_reset, db->chip_id); + udelay(500); + + /* Process Phyxcer Media Mode */ + uli526x_set_phyxcer(db); + } + /* Media Mode Process */ + if (!(db->media_mode & ULI526X_AUTO)) + db->op_mode = db->media_mode; /* Force Mode */ + + /* Initialize Transmit/Receive decriptor and CR3/4 */ + uli526x_descriptor_init(db, db->ioaddr); + + /* Init CR6 to program M526X operation */ + update_cr6(db->cr6_data, db->ioaddr); + + /* Init CR7, interrupt active bit */ + db->cr7_data = CR7_DEFAULT; + outl(db->cr7_data, db->ioaddr + DCR7); + + /* Init CR15, Tx jabber and Rx watchdog timer */ + outl(db->cr15_data, db->ioaddr + DCR15); + + /* Enable ULI526X Tx/Rx function */ + db->cr6_data |= CR6_RXSC | CR6_TXSC; + update_cr6(db->cr6_data, db->ioaddr); + while (!(inl(db->ioaddr + DCR12) & 0x8)) + udelay(10); +} + +/* + * Hardware start transmission. + * Send a packet to media from the upper layer. + */ + +static int uli526x_start_xmit(struct eth_device *dev, + volatile void *packet, int length) +{ + struct uli526x_board_info *db = dev->priv; + struct tx_desc *txptr; + unsigned int len = length; + /* Too large packet check */ + if (len > MAX_PACKET_SIZE) { + printf(": big packet = %d\n", len); + return 0; + } + + /* No Tx resource check, it never happen nromally */ + if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) { + printf("No Tx resource %ld\n", db->tx_packet_cnt); + return 0; + } + + /* Disable NIC interrupt */ + outl(0, dev->iobase + DCR7); + + /* transmit this packet */ + txptr = db->tx_insert_ptr; + memcpy((char *)txptr->tx_buf_ptr, (char *)packet, (int)length); + txptr->tdes1 = cpu_to_le32(0xe1000000 | length); + + /* Point to next transmit free descriptor */ + db->tx_insert_ptr = txptr->next_tx_desc; + + /* Transmit Packet Process */ + if ((db->tx_packet_cnt < TX_DESC_CNT)) { + txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */ + db->tx_packet_cnt++; /* Ready to send */ + outl(0x1, dev->iobase + DCR1); /* Issue Tx polling */ + } + + /* Got ULI526X status */ + db->cr5_data = inl(db->ioaddr + DCR5); + outl(db->cr5_data, db->ioaddr + DCR5); + +#ifdef TX_DEBUG + printf("%s(): length = 0x%x\n", __FUNCTION__, length); + printf("%s(): cr5_data=%x\n", __FUNCTION__, db->cr5_data); +#endif + + outl(db->cr7_data, dev->iobase + DCR7); + uli526x_free_tx_pkt(dev, db); + + return length; +} + +/* + * Free TX resource after TX complete + */ + +static void uli526x_free_tx_pkt(struct eth_device *dev, + struct uli526x_board_info *db) +{ + struct tx_desc *txptr; + u32 tdes0; + + txptr = db->tx_remove_ptr; + while (db->tx_packet_cnt) { + tdes0 = le32_to_cpu(txptr->tdes0); + /* printf(DRV_NAME ": tdes0=%x\n", tdes0); */ + if (tdes0 & 0x80000000) + break; + + /* A packet sent completed */ + db->tx_packet_cnt--; + + if (tdes0 != 0x7fffffff) { +#ifdef TX_DEBUG + printf("%s()tdes0=%x\n", __FUNCTION__, tdes0); +#endif + if (tdes0 & TDES0_ERR_MASK) { + if (tdes0 & 0x0002) { /* UnderRun */ + if (!(db->cr6_data & CR6_SFT)) { + db->cr6_data = db->cr6_data | + CR6_SFT; + update_cr6(db->cr6_data, + db->ioaddr); + } + } + } + } + + txptr = txptr->next_tx_desc; + }/* End of while */ + + /* Update TX remove pointer to next */ + db->tx_remove_ptr = txptr; +} + + +/* + * Receive the come packet and pass to upper layer + */ + +static int uli526x_rx_packet(struct eth_device *dev) +{ + struct uli526x_board_info *db = dev->priv; + struct rx_desc *rxptr; + int rxlen = 0; + u32 rdes0; + + rxptr = db->rx_ready_ptr; + + rdes0 = le32_to_cpu(rxptr->rdes0); +#ifdef RX_DEBUG + printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0); +#endif + if (!(rdes0 & 0x80000000)) { /* packet owner check */ + if ((rdes0 & 0x300) != 0x300) { + /* A packet without First/Last flag */ + /* reuse this buf */ + printf("A packet without First/Last flag"); + uli526x_reuse_buf(rxptr); + } else { + /* A packet with First/Last flag */ + rxlen = ((rdes0 >> 16) & 0x3fff) - 4; +#ifdef RX_DEBUG + printf("%s(): rxlen =%x\n", __FUNCTION__, rxlen); +#endif + /* error summary bit check */ + if (rdes0 & 0x8000) { + /* This is a error packet */ + printf("Eroor: rdes0: %lx\n", rdes0); + } + + if (!(rdes0 & 0x8000) || + ((db->cr6_data & CR6_PM) && (rxlen > 6))) { + +#ifdef RX_DEBUG + printf("%s(): rx_skb_ptr =%x\n", + __FUNCTION__, rxptr->rx_buf_ptr); + printf("%s(): rxlen =%x\n", + __FUNCTION__, rxlen); + + printf("%s(): buf addr =%x\n", + __FUNCTION__, rxptr->rx_buf_ptr); + printf("%s(): rxlen =%x\n", + __FUNCTION__, rxlen); + int i; + for (i = 0; i < 0x20; i++) + printf("%s(): data[%x] =%x\n", + __FUNCTION__, i, rxptr->rx_buf_ptr[i]); +#endif + + NetReceive(rxptr->rx_buf_ptr, rxlen); + uli526x_reuse_buf(rxptr); + + } else { + /* Reuse SKB buffer when the packet is error */ + printf("Reuse buffer, rdes0"); + uli526x_reuse_buf(rxptr); + } + } + + rxptr = rxptr->next_rx_desc; + } + + db->rx_ready_ptr = rxptr; + return rxlen; +} + +/* + * Reuse the RX buffer + */ + +static void uli526x_reuse_buf(struct rx_desc *rxptr) +{ + + if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) + rxptr->rdes0 = cpu_to_le32(0x80000000); + else + printf("Buffer reuse method error"); +} +/* + * Initialize transmit/Receive descriptor + * Using Chain structure, and allocate Tx/Rx buffer + */ + +static void uli526x_descriptor_init(struct uli526x_board_info *db, + unsigned long ioaddr) +{ + struct tx_desc *tmp_tx; + struct rx_desc *tmp_rx; + unsigned char *tmp_buf; + dma_addr_t tmp_tx_dma, tmp_rx_dma; + dma_addr_t tmp_buf_dma; + int i; + /* tx descriptor start pointer */ + db->tx_insert_ptr = db->first_tx_desc; + db->tx_remove_ptr = db->first_tx_desc; + + outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */ + + /* rx descriptor start pointer */ + db->first_rx_desc = (void *)db->first_tx_desc + + sizeof(struct tx_desc) * TX_DESC_CNT; + db->first_rx_desc_dma = db->first_tx_desc_dma + + sizeof(struct tx_desc) * TX_DESC_CNT; + db->rx_ready_ptr = db->first_rx_desc; + outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */ +#ifdef DEBUG + printf("%s(): db->first_tx_desc= 0x%x\n", + __FUNCTION__, db->first_tx_desc); + printf("%s(): db->first_rx_desc_dma= 0x%x\n", + __FUNCTION__, db->first_rx_desc_dma); +#endif + /* Init Transmit chain */ + tmp_buf = db->buf_pool_start; + tmp_buf_dma = db->buf_pool_dma_start; + tmp_tx_dma = db->first_tx_desc_dma; + for (tmp_tx = db->first_tx_desc, i = 0; + i < TX_DESC_CNT; i++, tmp_tx++) { + tmp_tx->tx_buf_ptr = tmp_buf; + tmp_tx->tdes0 = cpu_to_le32(0); + tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */ + tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma); + tmp_tx_dma += sizeof(struct tx_desc); + tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma); + tmp_tx->next_tx_desc = tmp_tx + 1; + tmp_buf = tmp_buf + TX_BUF_ALLOC; + tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC; + } + (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma); + tmp_tx->next_tx_desc = db->first_tx_desc; + + /* Init Receive descriptor chain */ + tmp_rx_dma = db->first_rx_desc_dma; + for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; + i++, tmp_rx++) { + tmp_rx->rdes0 = cpu_to_le32(0); + tmp_rx->rdes1 = cpu_to_le32(0x01000600); + tmp_rx_dma += sizeof(struct rx_desc); + tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma); + tmp_rx->next_rx_desc = tmp_rx + 1; + } + (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma); + tmp_rx->next_rx_desc = db->first_rx_desc; + + /* pre-allocate Rx buffer */ + allocate_rx_buffer(db); +} + +/* + * Update CR6 value + * Firstly stop ULI526X, then written value and start + */ + +static void update_cr6(u32 cr6_data, unsigned long ioaddr) +{ + + outl(cr6_data, ioaddr + DCR6); + udelay(5); +} + +/* + * Allocate rx buffer, + */ + +static void allocate_rx_buffer(struct uli526x_board_info *db) +{ + int index; + struct rx_desc *rxptr; + rxptr = db->first_rx_desc; + u32 addr; + + for (index = 0; index < RX_DESC_CNT; index++) { + addr = (u32)NetRxPackets[index]; + addr += (16 - (addr & 15)); + rxptr->rx_buf_ptr = (char *) addr; + rxptr->rdes2 = cpu_to_le32(addr); + rxptr->rdes0 = cpu_to_le32(0x80000000); +#ifdef DEBUG + printf("%s(): Number 0x%x:\n", __FUNCTION__, index); + printf("%s(): addr 0x%x:\n", __FUNCTION__, addr); + printf("%s(): rxptr address = 0x%x\n", __FUNCTION__, rxptr); + printf("%s(): rxptr buf address = 0x%x\n", \ + __FUNCTION__, rxptr->rx_buf_ptr); + printf("%s(): rdes2 = 0x%x\n", __FUNCTION__, rxptr->rdes2); +#endif + rxptr = rxptr->next_rx_desc; + } +} + +/* + * Read one word data from the serial ROM + */ + +static u16 read_srom_word(long ioaddr, int offset) +{ + int i; + u16 srom_data = 0; + long cr9_ioaddr = ioaddr + DCR9; + + outl(CR9_SROM_READ, cr9_ioaddr); + outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); + + /* Send the Read Command 110b */ + SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr); + SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr); + SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr); + + /* Send the offset */ + for (i = 5; i >= 0; i--) { + srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0; + SROM_CLK_WRITE(srom_data, cr9_ioaddr); + } + + outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); + + for (i = 16; i > 0; i--) { + outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr); + udelay(5); + srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) + ? 1 : 0); + outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); + udelay(5); + } + + outl(CR9_SROM_READ, cr9_ioaddr); + return srom_data; +} + +/* + * Set 10/100 phyxcer capability + * AUTO mode : phyxcer register4 is NIC capability + * Force mode: phyxcer register4 is the force media + */ + +static void uli526x_set_phyxcer(struct uli526x_board_info *db) +{ + u16 phy_reg; + + /* Phyxcer capability setting */ + phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0; + + if (db->media_mode & ULI526X_AUTO) { + /* AUTO Mode */ + phy_reg |= db->PHY_reg4; + } else { + /* Force Mode */ + switch (db->media_mode) { + case ULI526X_10MHF: phy_reg |= 0x20; break; + case ULI526X_10MFD: phy_reg |= 0x40; break; + case ULI526X_100MHF: phy_reg |= 0x80; break; + case ULI526X_100MFD: phy_reg |= 0x100; break; + } + + } + + /* Write new capability to Phyxcer Reg4 */ + if (!(phy_reg & 0x01e0)) { + phy_reg |= db->PHY_reg4; + db->media_mode |= ULI526X_AUTO; + } + phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id); + + /* Restart Auto-Negotiation */ + phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id); + udelay(50); +} + +/* + * Write a word to Phy register + */ + +static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, + u16 phy_data, u32 chip_id) +{ + u16 i; + unsigned long ioaddr; + + if (chip_id == PCI_ULI5263_ID) { + phy_writeby_cr10(iobase, phy_addr, offset, phy_data); + return; + } + /* M5261/M5263 Chip */ + ioaddr = iobase + DCR9; + + /* Send 33 synchronization clock to Phy controller */ + for (i = 0; i < 35; i++) + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + + /* Send start command(01) to Phy */ + phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + + /* Send write command(01) to Phy */ + phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + + /* Send Phy address */ + for (i = 0x10; i > 0; i = i >> 1) + phy_write_1bit(ioaddr, phy_addr & i ? + PHY_DATA_1 : PHY_DATA_0, chip_id); + + /* Send register address */ + for (i = 0x10; i > 0; i = i >> 1) + phy_write_1bit(ioaddr, offset & i ? + PHY_DATA_1 : PHY_DATA_0, chip_id); + + /* written trasnition */ + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); + + /* Write a word data to PHY controller */ + for (i = 0x8000; i > 0; i >>= 1) + phy_write_1bit(ioaddr, phy_data & i ? + PHY_DATA_1 : PHY_DATA_0, chip_id); +} + +/* + * Read a word data from phy register + */ + +static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id) +{ + int i; + u16 phy_data; + unsigned long ioaddr; + + if (chip_id == PCI_ULI5263_ID) + return phy_readby_cr10(iobase, phy_addr, offset); + /* M5261/M5263 Chip */ + ioaddr = iobase + DCR9; + + /* Send 33 synchronization clock to Phy controller */ + for (i = 0; i < 35; i++) + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + + /* Send start command(01) to Phy */ + phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + + /* Send read command(10) to Phy */ + phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); + phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); + + /* Send Phy address */ + for (i = 0x10; i > 0; i = i >> 1) + phy_write_1bit(ioaddr, phy_addr & i ? + PHY_DATA_1 : PHY_DATA_0, chip_id); + + /* Send register address */ + for (i = 0x10; i > 0; i = i >> 1) + phy_write_1bit(ioaddr, offset & i ? + PHY_DATA_1 : PHY_DATA_0, chip_id); + + /* Skip transition state */ + phy_read_1bit(ioaddr, chip_id); + + /* read 16bit data */ + for (phy_data = 0, i = 0; i < 16; i++) { + phy_data <<= 1; + phy_data |= phy_read_1bit(ioaddr, chip_id); + } + + return phy_data; +} + +static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset) +{ + unsigned long ioaddr, cr10_value; + + ioaddr = iobase + DCR10; + cr10_value = phy_addr; + cr10_value = (cr10_value<<5) + offset; + cr10_value = (cr10_value<<16) + 0x08000000; + outl(cr10_value, ioaddr); + udelay(1); + while (1) { + cr10_value = inl(ioaddr); + if (cr10_value & 0x10000000) + break; + } + return (cr10_value&0x0ffff); +} + +static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, + u8 offset, u16 phy_data) +{ + unsigned long ioaddr, cr10_value; + + ioaddr = iobase + DCR10; + cr10_value = phy_addr; + cr10_value = (cr10_value<<5) + offset; + cr10_value = (cr10_value<<16) + 0x04000000 + phy_data; + outl(cr10_value, ioaddr); + udelay(1); +} +/* + * Write one bit data to Phy Controller + */ + +static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id) +{ + outl(phy_data , ioaddr); /* MII Clock Low */ + udelay(1); + outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */ + udelay(1); + outl(phy_data , ioaddr); /* MII Clock Low */ + udelay(1); +} + +/* + * Read one bit phy data from PHY controller + */ + +static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id) +{ + u16 phy_data; + + outl(0x50000 , ioaddr); + udelay(1); + phy_data = (inl(ioaddr) >> 19) & 0x1; + outl(0x40000 , ioaddr); + udelay(1); + + return phy_data; +} + +/* + * Set MAC address to ID Table + */ + +static void set_mac_addr(struct eth_device *dev) +{ + int i; + u16 addr; + struct uli526x_board_info *db = dev->priv; + outl(0x10000, db->ioaddr + DCR0); /* Diagnosis mode */ + /* Reset dianostic pointer port */ + outl(0x1c0, db->ioaddr + DCR13); + outl(0, db->ioaddr + DCR14); /* Clear reset port */ + outl(0x10, db->ioaddr + DCR14); /* Reset ID Table pointer */ + outl(0, db->ioaddr + DCR14); /* Clear reset port */ + outl(0, db->ioaddr + DCR13); /* Clear CR13 */ + /* Select ID Table access port */ + outl(0x1b0, db->ioaddr + DCR13); + /* Read MAC address from CR14 */ + for (i = 0; i < 3; i++) { + addr = dev->enetaddr[2 * i] | (dev->enetaddr[2 * i + 1] << 8); + outl(addr, db->ioaddr + DCR14); + } + /* write end */ + outl(0, db->ioaddr + DCR13); /* Clear CR13 */ + outl(0, db->ioaddr + DCR0); /* Clear CR0 */ + udelay(10); + return; +} +#endif diff --git a/drivers/netarm_eth.c b/drivers/netarm_eth.c deleted file mode 100644 index a99ee5da2e..0000000000 --- a/drivers/netarm_eth.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2004 IMMS gGmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * author(s): Thomas Elste, - * (some parts derived from uCLinux Netarm Ethernet Driver) - */ - - -#include - -#ifdef CONFIG_DRIVER_NETARMETH -#include -#include -#include "netarm_eth.h" -#include - - -#if defined(CONFIG_CMD_NET) - -static int na_mii_poll_busy (void); - -static void na_get_mac_addr (void) -{ - unsigned short p[3]; - char *m_addr; - char ethaddr[20]; - - m_addr = (char *) p; - - p[0] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_1); - p[1] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_2); - p[2] = (unsigned short) GET_EADDR (NETARM_ETH_SAL_STATION_ADDR_3); - - sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", - m_addr[0], m_addr[1], - m_addr[2], m_addr[3], m_addr[4], m_addr[5]); - - printf ("HW-MAC Address: %s\n", ethaddr); - - /* set env, todo: check if already an adress is set */ - setenv ("ethaddr", ethaddr); -} - - -static void na_mii_write (int reg, int value) -{ - int mii_addr; - - /* Select register */ - mii_addr = CFG_ETH_PHY_ADDR + reg; - SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr); - /* Write value */ - SET_EADDR (NETARM_ETH_MII_WRITE, value); - na_mii_poll_busy (); -} - -static unsigned int na_mii_read (int reg) -{ - int mii_addr, val; - - /* Select register */ - mii_addr = CFG_ETH_PHY_ADDR + reg; - SET_EADDR (NETARM_ETH_MII_ADDR, mii_addr); - /* do one management cycle */ - SET_EADDR (NETARM_ETH_MII_CMD, - GET_EADDR (NETARM_ETH_MII_CMD) | NETARM_ETH_MIIC_RSTAT); - na_mii_poll_busy (); - /* Return read value */ - val = GET_EADDR (NETARM_ETH_MII_READ); - return val; -} - -static int na_mii_poll_busy (void) -{ - /* arm simple, non interrupt dependent timer */ - reset_timer_masked (); - while (get_timer_masked () < NA_MII_POLL_BUSY_DELAY) { - if (!(GET_EADDR (NETARM_ETH_MII_IND) & NETARM_ETH_MIII_BUSY)) { - return 1; - } - } - printf ("na_mii_busy timeout\n"); - return (0); -} - -static int na_mii_identify_phy (void) -{ - int id_reg_a = 0; - - /* get phy id register */ - id_reg_a = na_mii_read (MII_PHY_ID); - - if (id_reg_a == 0x0043) { - /* This must be an Enable or a Lucent LU3X31 PHY chip */ - return 1; - } else if (id_reg_a == 0x0013) { - /* it is an Intel LXT971A */ - return 1; - } - return (0); -} - -static int na_mii_negotiate (void) -{ - int i = 0; - - /* Enable auto-negotiation */ - na_mii_write (MII_PHY_AUTONEGADV, 0x01e1); - /* FIXME: 0x01E1 is 100Mb half and full duplex, 0x0061 is 10Mb only */ - /* Restart auto-negotiation */ - na_mii_write (MII_PHY_CONTROL, 0x1200); - - /* status register is 0xffff after setting the autoneg restart bit */ - while (na_mii_read (MII_PHY_STATUS) == 0xffff) { - i++; - } - - /* na_mii_read uses the timer already, so we can't use it again for - timeout checking. - Instead we just try some times. - */ - for (i = 0; i < 40000; i++) { - if ((na_mii_read (MII_PHY_STATUS) & 0x0024) == 0x0024) { - return 0; - } - } - /* - printf("*Warning* autonegotiation timeout, status: 0x%x\n",na_mii_read(MII_PHY_STATUS)); - */ - return (1); -} - -static unsigned int na_mii_check_speed (void) -{ - unsigned int status; - - /* Read Status register */ - status = na_mii_read (MII_PHY_STATUS); - /* Check link status. If 0, default to 100 Mbps. */ - if ((status & 0x0004) == 0) { - printf ("*Warning* no link detected, set default speed to 100Mbs\n"); - return 1; - } else { - if ((na_mii_read (17) & 0x4000) != 0) { - printf ("100Mbs link detected\n"); - return 1; - } else { - printf ("10Mbs link detected\n"); - return 0; - } - } - return 0; -} - -static int reset_eth (void) -{ - int pt; - - na_get_mac_addr (); - pt = na_mii_identify_phy (); - - /* reset the phy */ - na_mii_write (MII_PHY_CONTROL, 0x8000); - reset_timer_masked (); - while (get_timer_masked () < NA_MII_NEGOTIATE_DELAY) { - if ((na_mii_read (MII_PHY_STATUS) & 0x8000) == 0) { - break; - } - } - if (get_timer_masked () >= NA_MII_NEGOTIATE_DELAY) - printf ("phy reset timeout\n"); - - /* set the PCS reg */ - SET_EADDR (NETARM_ETH_PCS_CFG, NETARM_ETH_PCSC_CLKS_25M | - NETARM_ETH_PCSC_ENJAB | NETARM_ETH_PCSC_NOCFR); - - na_mii_negotiate (); - na_mii_check_speed (); - - /* Delay 10 millisecond. (Maybe this should be 1 second.) */ - udelay (10000); - - /* Turn receive on. - Enable statistics register autozero on read. - Do not insert MAC address on transmit. - Do not enable special test modes. */ - SET_EADDR (NETARM_ETH_STL_CFG, - (NETARM_ETH_STLC_AUTOZ | NETARM_ETH_STLC_RXEN)); - - /* Set the inter-packet gap delay to 0.96us for MII. - The NET+ARM H/W Reference Guide indicates that the Back-to-back IPG - Gap Timer Register should be set to 0x15 and the Non Back-to-back IPG - Gap Timer Register should be set to 0x00000C12 for the MII PHY. */ - SET_EADDR (NETARM_ETH_B2B_IPG_GAP_TMR, 0x15); - SET_EADDR (NETARM_ETH_NB2B_IPG_GAP_TMR, 0x00000C12); - - /* Add CRC to end of packets. - Pad packets to minimum length of 64 bytes. - Allow unlimited length transmit packets. - Receive all broadcast packets. - NOTE: Multicast addressing is NOT enabled here currently. */ - SET_EADDR (NETARM_ETH_MAC_CFG, - (NETARM_ETH_MACC_CRCEN | - NETARM_ETH_MACC_PADEN | NETARM_ETH_MACC_HUGEN)); - SET_EADDR (NETARM_ETH_SAL_FILTER, NETARM_ETH_SALF_BROAD); - - /* enable fifos */ - SET_EADDR (NETARM_ETH_GEN_CTRL, - (NETARM_ETH_GCR_ERX | NETARM_ETH_GCR_ETX)); - - return (0); -} - - -extern int eth_init (bd_t * bd) -{ - reset_eth (); - return 0; -} - -extern void eth_halt (void) -{ - SET_EADDR (NETARM_ETH_GEN_CTRL, 0); -} - -/* Get a data block via Ethernet */ -extern int eth_rx (void) -{ - int i; - unsigned short rxlen; - unsigned int *addr; - unsigned int rxstatus, lastrxlen; - char *pa; - - /* RXBR is 1, data block was received */ - if ((GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXBR) == 0) - return 0; - - /* get status register and the length of received block */ - rxstatus = GET_EADDR (NETARM_ETH_RX_STAT); - rxlen = (rxstatus & NETARM_ETH_RXSTAT_SIZE) >> 16; - - if (rxlen == 0) - return 0; - - /* clear RXBR to make fifo available */ - SET_EADDR (NETARM_ETH_GEN_STAT, - GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_RXBR); - - /* clear TXBC to make fifo available */ - /* According to NETARM50 data manual you just have to clear - RXBR but that has no effect. Only after clearing TXBC the - Fifo becomes readable. */ - SET_EADDR (NETARM_ETH_GEN_STAT, - GET_EADDR (NETARM_ETH_GEN_STAT) & ~NETARM_ETH_GST_TXBC); - - addr = (unsigned int *) NetRxPackets[0]; - pa = (char *) NetRxPackets[0]; - - /* read the fifo */ - for (i = 0; i < rxlen / 4; i++) { - *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1); - addr++; - } - - if (GET_EADDR (NETARM_ETH_GEN_STAT) & NETARM_ETH_GST_RXREGR) { - /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */ - lastrxlen = - (GET_EADDR (NETARM_ETH_GEN_STAT) & - NETARM_ETH_GST_RXFDB) >> 28; - *addr = GET_EADDR (NETARM_ETH_FIFO_DAT1); - switch (lastrxlen) { - case 1: - *addr &= 0xff000000; - break; - case 2: - *addr &= 0xffff0000; - break; - case 3: - *addr &= 0xffffff00; - break; - } - } - - /* Pass the packet up to the protocol layers. */ - NetReceive (NetRxPackets[0], rxlen); - - return rxlen; -} - -/* Send a data block via Ethernet. */ -extern int eth_send (volatile void *packet, int length) -{ - int i, length32; - char *pa; - unsigned int *pa32, lastp = 0, rest; - - pa = (char *) packet; - pa32 = (unsigned int *) packet; - length32 = length / 4; - rest = length % 4; - - /* make sure there's no garbage in the last word */ - switch (rest) { - case 0: - lastp = pa32[length32]; - length32--; - break; - case 1: - lastp = pa32[length32] & 0x000000ff; - break; - case 2: - lastp = pa32[length32] & 0x0000ffff; - break; - case 3: - lastp = pa32[length32] & 0x00ffffff; - break; - } - - /* write to the fifo */ - for (i = 0; i < length32; i++) - SET_EADDR (NETARM_ETH_FIFO_DAT1, pa32[i]); - - /* the last word is written to an extra register, this - starts the transmission */ - SET_EADDR (NETARM_ETH_FIFO_DAT2, lastp); - - /* NETARM_ETH_TXSTAT_TXOK should be checked, to know if the transmission - went fine. But we can't use the timer for a timeout loop because - of it is used already in upper layers. So we just try some times. */ - i = 0; - while (i < 50000) { - if ((GET_EADDR (NETARM_ETH_TX_STAT) & NETARM_ETH_TXSTAT_TXOK) - == NETARM_ETH_TXSTAT_TXOK) - return 0; - i++; - } - - printf ("eth_send timeout\n"); - return 1; -} - -#endif /* COMMANDS & CFG_NET */ - -#endif /* CONFIG_DRIVER_NETARMETH */ diff --git a/drivers/netarm_eth.h b/drivers/netarm_eth.h deleted file mode 100644 index 8edab82da3..0000000000 --- a/drivers/netarm_eth.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2003 IMMS gGmbH - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * author(s): Thomas Elste, - */ - -#include -#include - -#ifdef CONFIG_DRIVER_NETARMETH - -#define SET_EADDR(ad,val) *(volatile unsigned int*)(ad + NETARM_ETH_MODULE_BASE) = val -#define GET_EADDR(ad) (*(volatile unsigned int*)(ad + NETARM_ETH_MODULE_BASE)) - -#define NA_MII_POLL_BUSY_DELAY 900 - -/* MII negotiation timeout value - 500 jiffies = 5 seconds */ -#define NA_MII_NEGOTIATE_DELAY 30 - -/* Registers in the physical layer chip */ -#define MII_PHY_CONTROL 0 -#define MII_PHY_STATUS 1 -#define MII_PHY_ID 2 -#define MII_PHY_AUTONEGADV 4 - -#endif /* CONFIG_DRIVER_NETARMETH */ diff --git a/drivers/netconsole.c b/drivers/netconsole.c deleted file mode 100644 index 69089f92ce..0000000000 --- a/drivers/netconsole.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -#ifdef CONFIG_NETCONSOLE - -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -static char input_buffer[512]; -static int input_size = 0; /* char count in input buffer */ -static int input_offset = 0; /* offset to valid chars in input buffer */ -static int input_recursion = 0; -static int output_recursion = 0; -static int net_timeout; -static uchar nc_ether[6]; /* server enet address */ -static IPaddr_t nc_ip; /* server ip */ -static short nc_port; /* source/target port */ -static const char *output_packet; /* used by first send udp */ -static int output_packet_len = 0; - -static void nc_wait_arp_handler (uchar * pkt, unsigned dest, unsigned src, - unsigned len) -{ - NetState = NETLOOP_SUCCESS; /* got arp reply - quit net loop */ -} - -static void nc_handler (uchar * pkt, unsigned dest, unsigned src, - unsigned len) -{ - if (input_size) - NetState = NETLOOP_SUCCESS; /* got input - quit net loop */ -} - -static void nc_timeout (void) -{ - NetState = NETLOOP_SUCCESS; -} - -void NcStart (void) -{ - if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) { - /* going to check for input packet */ - NetSetHandler (nc_handler); - NetSetTimeout (net_timeout, nc_timeout); - } else { - /* send arp request */ - uchar *pkt; - NetSetHandler (nc_wait_arp_handler); - pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; - memcpy (pkt, output_packet, output_packet_len); - NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len); - } -} - -int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len) -{ - int end, chunk; - - if (dest != nc_port || !len) - return 0; /* not for us */ - - if (input_size == sizeof input_buffer) - return 1; /* no space */ - if (len > sizeof input_buffer - input_size) - len = sizeof input_buffer - input_size; - - end = input_offset + input_size; - if (end > sizeof input_buffer) - end -= sizeof input_buffer; - - chunk = len; - if (end + len > sizeof input_buffer) { - chunk = sizeof input_buffer - end; - memcpy(input_buffer, pkt + chunk, len - chunk); - } - memcpy (input_buffer + end, pkt, chunk); - - input_size += len; - - return 1; -} - -static void nc_send_packet (const char *buf, int len) -{ - struct eth_device *eth; - int inited = 0; - uchar *pkt; - uchar *ether; - IPaddr_t ip; - - if ((eth = eth_get_dev ()) == NULL) { - return; - } - - if (!memcmp (nc_ether, NetEtherNullAddr, 6)) { - if (eth->state == ETH_STATE_ACTIVE) - return; /* inside net loop */ - output_packet = buf; - output_packet_len = len; - NetLoop (NETCONS); /* wait for arp reply and send packet */ - output_packet_len = 0; - return; - } - - if (eth->state != ETH_STATE_ACTIVE) { - if (eth_init (gd->bd) < 0) - return; - inited = 1; - } - pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; - memcpy (pkt, buf, len); - ether = nc_ether; - ip = nc_ip; - NetSendUDPPacket (ether, ip, nc_port, nc_port, len); - - if (inited) - eth_halt (); -} - -int nc_start (void) -{ - int netmask, our_ip; - - nc_port = 6666; /* default port */ - - if (getenv ("ncip")) { - char *p; - - nc_ip = getenv_IPaddr ("ncip"); - if (!nc_ip) - return -1; /* ncip is 0.0.0.0 */ - if ((p = strchr (getenv ("ncip"), ':')) != NULL) - nc_port = simple_strtoul (p + 1, NULL, 10); - } else - nc_ip = ~0; /* ncip is not set */ - - our_ip = getenv_IPaddr ("ipaddr"); - netmask = getenv_IPaddr ("netmask"); - - if (nc_ip == ~0 || /* 255.255.255.255 */ - ((netmask & our_ip) == (netmask & nc_ip) && /* on the same net */ - (netmask | nc_ip) == ~0)) /* broadcast to our net */ - memset (nc_ether, 0xff, sizeof nc_ether); - else - memset (nc_ether, 0, sizeof nc_ether); /* force arp request */ - - return 0; -} - -void nc_putc (char c) -{ - if (output_recursion) - return; - output_recursion = 1; - - nc_send_packet (&c, 1); - - output_recursion = 0; -} - -void nc_puts (const char *s) -{ - int len; - - if (output_recursion) - return; - output_recursion = 1; - - if ((len = strlen (s)) > 512) - len = 512; - - nc_send_packet (s, len); - - output_recursion = 0; -} - -int nc_getc (void) -{ - uchar c; - - input_recursion = 1; - - net_timeout = 0; /* no timeout */ - while (!input_size) - NetLoop (NETCONS); - - input_recursion = 0; - - c = input_buffer[input_offset++]; - - if (input_offset >= sizeof input_buffer) - input_offset -= sizeof input_buffer; - input_size--; - - return c; -} - -int nc_tstc (void) -{ - struct eth_device *eth; - - if (input_recursion) - return 0; - - if (input_size) - return 1; - - eth = eth_get_dev (); - if (eth && eth->state == ETH_STATE_ACTIVE) - return 0; /* inside net loop */ - - input_recursion = 1; - - net_timeout = 1; - NetLoop (NETCONS); /* kind of poll */ - - input_recursion = 0; - - return input_size != 0; -} - -int drv_nc_init (void) -{ - device_t dev; - int rc; - - memset (&dev, 0, sizeof (dev)); - - strcpy (dev.name, "nc"); - dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; - dev.start = nc_start; - dev.putc = nc_putc; - dev.puts = nc_puts; - dev.getc = nc_getc; - dev.tstc = nc_tstc; - - rc = device_register (&dev); - - return (rc == 0) ? 1 : rc; -} - -#endif /* CONFIG_NETCONSOLE */ diff --git a/drivers/nicext.h b/drivers/nicext.h deleted file mode 100644 index 4074972c07..0000000000 --- a/drivers/nicext.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** - * Copyright(c) 2000-2001 Broadcom Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation. - * - * Name: nicext.h - * - * Description: Broadcom Network Interface Card Extension (NICE) is an - * extension to Linux NET device kernel mode drivers. - * NICE is designed to provide additional functionalities, - * such as receive packet intercept. To support Broadcom NICE, - * the network device driver can be modified by adding an - * device ioctl handler and by indicating receiving packets - * to the NICE receive handler. Broadcom NICE will only be - * enabled by a NICE-aware intermediate driver, such as - * Broadcom Advanced Server Program Driver (BASP). When NICE - * is not enabled, the modified network device drivers - * functions exactly as other non-NICE aware drivers. - * - * Author: Frankie Fan - * - * Created: September 17, 2000 - * - ****************************************************************************/ -#ifndef _nicext_h_ -#define _nicext_h_ - -/* - * ioctl for NICE - */ -#define SIOCNICE SIOCDEVPRIVATE+7 - -/* - * SIOCNICE: - * - * The following structure needs to be less than IFNAMSIZ (16 bytes) because - * we're overloading ifreq.ifr_ifru. - * - * If 16 bytes is not enough, we should consider relaxing this because - * this is no field after ifr_ifru in the ifreq structure. But we may - * run into future compatiability problem in case of changing struct ifreq. - */ -struct nice_req -{ - __u32 cmd; - - union - { -#ifdef __KERNEL__ - /* cmd = NICE_CMD_SET_RX or NICE_CMD_GET_RX */ - struct - { - void (*nrqus1_rx)( struct sk_buff*, void* ); - void* nrqus1_ctx; - } nrqu_nrqus1; - - /* cmd = NICE_CMD_QUERY_SUPPORT */ - struct - { - __u32 nrqus2_magic; - __u32 nrqus2_support_rx:1; - __u32 nrqus2_support_vlan:1; - __u32 nrqus2_support_get_speed:1; - } nrqu_nrqus2; -#endif - - /* cmd = NICE_CMD_GET_SPEED */ - struct - { - unsigned int nrqus3_speed; /* 0 if link is down, */ - /* otherwise speed in Mbps */ - } nrqu_nrqus3; - - /* cmd = NICE_CMD_BLINK_LED */ - struct - { - unsigned int nrqus4_blink_time; /* blink duration in seconds */ - } nrqu_nrqus4; - - } nrq_nrqu; -}; - -#define nrq_rx nrq_nrqu.nrqu_nrqus1.nrqus1_rx -#define nrq_ctx nrq_nrqu.nrqu_nrqus1.nrqus1_ctx -#define nrq_support_rx nrq_nrqu.nrqu_nrqus2.nrqus2_support_rx -#define nrq_magic nrq_nrqu.nrqu_nrqus2.nrqus2_magic -#define nrq_support_vlan nrq_nrqu.nrqu_nrqus2.nrqus2_support_vlan -#define nrq_support_get_speed nrq_nrqu.nrqu_nrqus2.nrqus2_support_get_speed -#define nrq_speed nrq_nrqu.nrqu_nrqus3.nrqus3_speed -#define nrq_blink_time nrq_nrqu.nrqu_nrqus4.nrqus4_blink_time - -/* - * magic constants - */ -#define NICE_REQUESTOR_MAGIC 0x4543494E /* NICE in ascii */ -#define NICE_DEVICE_MAGIC 0x4E494345 /* ECIN in ascii */ - -/* - * command field - */ -#define NICE_CMD_QUERY_SUPPORT 0x00000001 -#define NICE_CMD_SET_RX 0x00000002 -#define NICE_CMD_GET_RX 0x00000003 -#define NICE_CMD_GET_SPEED 0x00000004 -#define NICE_CMD_BLINK_LED 0x00000005 - -#endif /* _nicext_h_ */ diff --git a/drivers/ns7520_eth.c b/drivers/ns7520_eth.c deleted file mode 100644 index a5a20dfd72..0000000000 --- a/drivers/ns7520_eth.c +++ /dev/null @@ -1,859 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2005 by Videon Central, Inc. - * - * $Id$ - * @Author: Arthur Shipkowski - * @Descr: Ethernet driver for the NS7520. Uses polled Ethernet, like - * the older netarmeth driver. Note that attempting to filter - * broadcast and multicast out in the SAFR register will cause - * bad things due to released errata. - * @References: [1] NS7520 Hardware Reference, December 2003 - * [2] Intel LXT971 Datasheet #249414 Rev. 02 - * - ***********************************************************************/ - -#include - -#if defined(CONFIG_DRIVER_NS7520_ETHERNET) - -#include /* NetSendPacket */ -#include -#include - -#include "ns7520_eth.h" /* for Ethernet and PHY */ - -/** - * Send an error message to the terminal. - */ -#define ERROR(x) \ -do { \ - char *__foo = strrchr(__FILE__, '/'); \ - \ - printf("%s: %d: %s(): ", (__foo == NULL ? __FILE__ : (__foo + 1)), \ - __LINE__, __FUNCTION__); \ - printf x; printf("\n"); \ -} while (0); - -/* some definition to make transistion to linux easier */ - -#define NS7520_DRIVER_NAME "eth" -#define KERN_WARNING "Warning:" -#define KERN_ERR "Error:" -#define KERN_INFO "Info:" - -#if 1 -# define DEBUG -#endif - -#ifdef DEBUG -# define printk printf - -# define DEBUG_INIT 0x0001 -# define DEBUG_MINOR 0x0002 -# define DEBUG_RX 0x0004 -# define DEBUG_TX 0x0008 -# define DEBUG_INT 0x0010 -# define DEBUG_POLL 0x0020 -# define DEBUG_LINK 0x0040 -# define DEBUG_MII 0x0100 -# define DEBUG_MII_LOW 0x0200 -# define DEBUG_MEM 0x0400 -# define DEBUG_ERROR 0x4000 -# define DEBUG_ERROR_CRIT 0x8000 - -static int nDebugLvl = DEBUG_ERROR_CRIT; - -# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \ - printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 ) -# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \ - printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 ) -# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\ - printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 ) -# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\ - printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0) -# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \ - printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0); -# define ASSERT( expr, func ) if( !( expr ) ) { \ - printf( "Assertion failed! %s:line %d %s\n", \ - (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \ - func } -#else /* DEBUG */ -# define printk(...) -# define DEBUG_ARGS0( FLG, a0 ) -# define DEBUG_ARGS1( FLG, a0, a1 ) -# define DEBUG_ARGS2( FLG, a0, a1, a2 ) -# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) -# define DEBUG_FN( n ) -# define ASSERT(expr, func) -#endif /* DEBUG */ - -#define NS7520_MII_NEG_DELAY (5*CFG_HZ) /* in s */ -#define TX_TIMEOUT (5*CFG_HZ) /* in s */ -#define RX_STALL_WORKAROUND_CNT 100 - -static int ns7520_eth_reset(void); - -static void ns7520_link_auto_negotiate(void); -static void ns7520_link_update_egcr(void); -static void ns7520_link_print_changed(void); - -/* the PHY stuff */ - -static char ns7520_mii_identify_phy(void); -static unsigned short ns7520_mii_read(unsigned short uiRegister); -static void ns7520_mii_write(unsigned short uiRegister, - unsigned short uiData); -static unsigned int ns7520_mii_get_clock_divisor(unsigned int - unMaxMDIOClk); -static unsigned int ns7520_mii_poll_busy(void); - -static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; -static unsigned int uiLastLinkStatus; -static PhyType phyDetected = PHY_NONE; - -/*********************************************************************** - * @Function: eth_init - * @Return: -1 on failure otherwise 0 - * @Descr: Initializes the ethernet engine and uses either FS Forth's default - * MAC addr or the one in environment - ***********************************************************************/ - -int eth_init(bd_t * pbis) -{ - unsigned char aucMACAddr[6]; - char *pcTmp = getenv("ethaddr"); - char *pcEnd; - int i; - - DEBUG_FN(DEBUG_INIT); - - /* no need to check for hardware */ - - if (!ns7520_eth_reset()) - return -1; - - if (NULL == pcTmp) - return -1; - - for (i = 0; i < 6; i++) { - aucMACAddr[i] = - pcTmp ? simple_strtoul(pcTmp, &pcEnd, 16) : 0; - pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd; - } - - /* configure ethernet address */ - - *get_eth_reg_addr(NS7520_ETH_SA1) = - aucMACAddr[5] << 8 | aucMACAddr[4]; - *get_eth_reg_addr(NS7520_ETH_SA2) = - aucMACAddr[3] << 8 | aucMACAddr[2]; - *get_eth_reg_addr(NS7520_ETH_SA3) = - aucMACAddr[1] << 8 | aucMACAddr[0]; - - /* enable hardware */ - - *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN; - *get_eth_reg_addr(NS7520_ETH_SUPP) = NS7520_ETH_SUPP_JABBER; - *get_eth_reg_addr(NS7520_ETH_MAC1) = NS7520_ETH_MAC1_RXEN; - - /* the linux kernel may give packets < 60 bytes, for example arp */ - *get_eth_reg_addr(NS7520_ETH_MAC2) = NS7520_ETH_MAC2_CRCEN | - NS7520_ETH_MAC2_PADEN | NS7520_ETH_MAC2_HUGE; - - /* Broadcast/multicast allowed; if you don't set this even unicast chokes */ - /* Based on NS7520 errata documentation */ - *get_eth_reg_addr(NS7520_ETH_SAFR) = - NS7520_ETH_SAFR_BROAD | NS7520_ETH_SAFR_PRM; - - /* enable receive and transmit FIFO, use 10/100 Mbps MII */ - *get_eth_reg_addr(NS7520_ETH_EGCR) |= - NS7520_ETH_EGCR_ETXWM_75 | - NS7520_ETH_EGCR_ERX | - NS7520_ETH_EGCR_ERXREG | - NS7520_ETH_EGCR_ERXBR | NS7520_ETH_EGCR_ETX; - - return 0; -} - -/*********************************************************************** - * @Function: eth_send - * @Return: -1 on timeout otherwise 1 - * @Descr: sends one frame by DMA - ***********************************************************************/ - -int eth_send(volatile void *pPacket, int nLen) -{ - int i, length32, retval = 1; - char *pa; - unsigned int *pa32, lastp = 0, rest; - unsigned int status; - - pa = (char *) pPacket; - pa32 = (unsigned int *) pPacket; - length32 = nLen / 4; - rest = nLen % 4; - - /* make sure there's no garbage in the last word */ - switch (rest) { - case 0: - lastp = pa32[length32 - 1]; - length32--; - break; - case 1: - lastp = pa32[length32] & 0x000000ff; - break; - case 2: - lastp = pa32[length32] & 0x0000ffff; - break; - case 3: - lastp = pa32[length32] & 0x00ffffff; - break; - } - - while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) & - NS7520_ETH_EGSR_TXREGE) - == 0) { - } - - /* write to the fifo */ - for (i = 0; i < length32; i++) - *get_eth_reg_addr(NS7520_ETH_FIFO) = pa32[i]; - - /* the last word is written to an extra register, this - starts the transmission */ - *get_eth_reg_addr(NS7520_ETH_FIFOL) = lastp; - - /* Wait for it to be done */ - while ((*get_eth_reg_addr(NS7520_ETH_EGSR) & NS7520_ETH_EGSR_TXBC) - == 0) { - } - status = (*get_eth_reg_addr(NS7520_ETH_ETSR)); - *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_TXBC; /* Clear it now */ - - if (status & NS7520_ETH_ETSR_TXOK) { - retval = 0; /* We're OK! */ - } else if (status & NS7520_ETH_ETSR_TXDEF) { - printf("Deferred, we'll see.\n"); - retval = 0; - } else if (status & NS7520_ETH_ETSR_TXAL) { - printf("Late collision error, %d collisions.\n", - (*get_eth_reg_addr(NS7520_ETH_ETSR)) & - NS7520_ETH_ETSR_TXCOLC); - } else if (status & NS7520_ETH_ETSR_TXAEC) { - printf("Excessive collisions: %d\n", - (*get_eth_reg_addr(NS7520_ETH_ETSR)) & - NS7520_ETH_ETSR_TXCOLC); - } else if (status & NS7520_ETH_ETSR_TXAED) { - printf("Excessive deferral on xmit.\n"); - } else if (status & NS7520_ETH_ETSR_TXAUR) { - printf("Packet underrun.\n"); - } else if (status & NS7520_ETH_ETSR_TXAJ) { - printf("Jumbo packet error.\n"); - } else { - printf("Error: Should never get here.\n"); - } - - return (retval); -} - -/*********************************************************************** - * @Function: eth_rx - * @Return: size of last frame in bytes or 0 if no frame available - * @Descr: gives one frame to U-Boot which has been copied by DMA engine already - * to NetRxPackets[ 0 ]. - ***********************************************************************/ - -int eth_rx(void) -{ - int i; - unsigned short rxlen; - unsigned short totrxlen = 0; - unsigned int *addr; - unsigned int rxstatus, lastrxlen; - char *pa; - - /* If RXBR is 1, data block was received */ - while (((*get_eth_reg_addr(NS7520_ETH_EGSR)) & - NS7520_ETH_EGSR_RXBR) == NS7520_ETH_EGSR_RXBR) { - - /* get status register and the length of received block */ - rxstatus = *get_eth_reg_addr(NS7520_ETH_ERSR); - rxlen = (rxstatus & NS7520_ETH_ERSR_RXSIZE) >> 16; - - /* clear RXBR to make fifo available */ - *get_eth_reg_addr(NS7520_ETH_EGSR) = NS7520_ETH_EGSR_RXBR; - - if (rxstatus & NS7520_ETH_ERSR_ROVER) { - printf("Receive overrun, resetting FIFO.\n"); - *get_eth_reg_addr(NS7520_ETH_EGCR) &= - ~NS7520_ETH_EGCR_ERX; - udelay(20); - *get_eth_reg_addr(NS7520_ETH_EGCR) |= - NS7520_ETH_EGCR_ERX; - } - if (rxlen == 0) { - printf("Nothing.\n"); - return 0; - } - - addr = (unsigned int *) NetRxPackets[0]; - pa = (char *) NetRxPackets[0]; - - /* read the fifo */ - for (i = 0; i < rxlen / 4; i++) { - *addr = *get_eth_reg_addr(NS7520_ETH_FIFO); - addr++; - } - - if ((*get_eth_reg_addr(NS7520_ETH_EGSR)) & - NS7520_ETH_EGSR_RXREGR) { - /* RXFDB indicates wether the last word is 1,2,3 or 4 bytes long */ - lastrxlen = - ((*get_eth_reg_addr(NS7520_ETH_EGSR)) & - NS7520_ETH_EGSR_RXFDB_MA) >> 28; - *addr = *get_eth_reg_addr(NS7520_ETH_FIFO); - switch (lastrxlen) { - case 1: - *addr &= 0xff000000; - break; - case 2: - *addr &= 0xffff0000; - break; - case 3: - *addr &= 0xffffff00; - break; - } - } - - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[0], rxlen - 4); - totrxlen += rxlen - 4; - } - - return totrxlen; -} - -/*********************************************************************** - * @Function: eth_halt - * @Return: n/a - * @Descr: stops the ethernet engine - ***********************************************************************/ - -void eth_halt(void) -{ - DEBUG_FN(DEBUG_INIT); - - *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_RXEN; - *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~(NS7520_ETH_EGCR_ERX | - NS7520_ETH_EGCR_ERXDMA | - NS7520_ETH_EGCR_ERXREG | - NS7520_ETH_EGCR_ERXBR | - NS7520_ETH_EGCR_ETX | - NS7520_ETH_EGCR_ETXDMA); -} - -/*********************************************************************** - * @Function: ns7520_eth_reset - * @Return: 0 on failure otherwise 1 - * @Descr: resets the ethernet interface and the PHY, - * performs auto negotiation or fixed modes - ***********************************************************************/ - -static int ns7520_eth_reset(void) -{ - DEBUG_FN(DEBUG_MINOR); - - /* Reset important registers */ - *get_eth_reg_addr(NS7520_ETH_EGCR) = 0; /* Null it out! */ - *get_eth_reg_addr(NS7520_ETH_MAC1) &= NS7520_ETH_MAC1_SRST; - *get_eth_reg_addr(NS7520_ETH_MAC2) = 0; - /* Reset MAC */ - *get_eth_reg_addr(NS7520_ETH_EGCR) |= NS7520_ETH_EGCR_MAC_RES; - udelay(5); - *get_eth_reg_addr(NS7520_ETH_EGCR) &= ~NS7520_ETH_EGCR_MAC_RES; - - /* reset and initialize PHY */ - - *get_eth_reg_addr(NS7520_ETH_MAC1) &= ~NS7520_ETH_MAC1_SRST; - - /* we don't support hot plugging of PHY, therefore we don't reset - phyDetected and nPhyMaxMdioClock here. The risk is if the setting is - incorrect the first open - may detect the PHY correctly but succeding will fail - For reseting the PHY and identifying we have to use the standard - MDIO CLOCK value 2.5 MHz only after hardware reset - After having identified the PHY we will do faster */ - - *get_eth_reg_addr(NS7520_ETH_MCFG) = - ns7520_mii_get_clock_divisor(nPhyMaxMdioClock); - - /* reset PHY */ - ns7520_mii_write(PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET); - ns7520_mii_write(PHY_COMMON_CTRL, 0); - - udelay(3000); /* [2] p.70 says at least 300us reset recovery time. */ - - /* MII clock has been setup to default, ns7520_mii_identify_phy should - work for all */ - - if (!ns7520_mii_identify_phy()) { - printk(KERN_ERR NS7520_DRIVER_NAME - ": Unsupported PHY, aborting\n"); - return 0; - } - - /* now take the highest MDIO clock possible after detection */ - *get_eth_reg_addr(NS7520_ETH_MCFG) = - ns7520_mii_get_clock_divisor(nPhyMaxMdioClock); - - /* PHY has been detected, so there can be no abort reason and we can - finish initializing ethernet */ - - uiLastLinkStatus = 0xff; /* undefined */ - - ns7520_link_auto_negotiate(); - - if (phyDetected == PHY_LXT971A) - /* set LED2 to link mode */ - ns7520_mii_write(PHY_LXT971_LED_CFG, - (PHY_LXT971_LED_CFG_LINK_ACT << - PHY_LXT971_LED_CFG_SHIFT_LED2) | - (PHY_LXT971_LED_CFG_TRANSMIT << - PHY_LXT971_LED_CFG_SHIFT_LED1)); - - return 1; -} - -/*********************************************************************** - * @Function: ns7520_link_auto_negotiate - * @Return: void - * @Descr: performs auto-negotation of link. - ***********************************************************************/ - -static void ns7520_link_auto_negotiate(void) -{ - unsigned long ulStartJiffies; - unsigned short uiStatus; - - DEBUG_FN(DEBUG_LINK); - - /* run auto-negotation */ - /* define what we are capable of */ - ns7520_mii_write(PHY_COMMON_AUTO_ADV, - PHY_COMMON_AUTO_ADV_100BTXFD | - PHY_COMMON_AUTO_ADV_100BTX | - PHY_COMMON_AUTO_ADV_10BTFD | - PHY_COMMON_AUTO_ADV_10BT | - PHY_COMMON_AUTO_ADV_802_3); - /* start auto-negotiation */ - ns7520_mii_write(PHY_COMMON_CTRL, - PHY_COMMON_CTRL_AUTO_NEG | - PHY_COMMON_CTRL_RES_AUTO); - - /* wait for completion */ - - ulStartJiffies = get_timer(0); - while (get_timer(0) < ulStartJiffies + NS7520_MII_NEG_DELAY) { - uiStatus = ns7520_mii_read(PHY_COMMON_STAT); - if ((uiStatus & - (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) - == - (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) { - /* lucky we are, auto-negotiation succeeded */ - ns7520_link_print_changed(); - ns7520_link_update_egcr(); - return; - } - } - - DEBUG_ARGS0(DEBUG_LINK, "auto-negotiation timed out\n"); - /* ignore invalid link settings */ -} - -/*********************************************************************** - * @Function: ns7520_link_update_egcr - * @Return: void - * @Descr: updates the EGCR and MAC2 link status after mode change or - * auto-negotation - ***********************************************************************/ - -static void ns7520_link_update_egcr(void) -{ - unsigned int unEGCR; - unsigned int unMAC2; - unsigned int unIPGT; - - DEBUG_FN(DEBUG_LINK); - - unEGCR = *get_eth_reg_addr(NS7520_ETH_EGCR); - unMAC2 = *get_eth_reg_addr(NS7520_ETH_MAC2); - unIPGT = - *get_eth_reg_addr(NS7520_ETH_IPGT) & ~NS7520_ETH_IPGT_IPGT; - - unEGCR &= ~NS7520_ETH_EGCR_EFULLD; - unMAC2 &= ~NS7520_ETH_MAC2_FULLD; - if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE) - == PHY_LXT971_STAT2_DUPLEX_MODE) { - unEGCR |= NS7520_ETH_EGCR_EFULLD; - unMAC2 |= NS7520_ETH_MAC2_FULLD; - unIPGT |= 0x15; /* see [1] p. 167 */ - } else - unIPGT |= 0x12; /* see [1] p. 167 */ - - *get_eth_reg_addr(NS7520_ETH_MAC2) = unMAC2; - *get_eth_reg_addr(NS7520_ETH_EGCR) = unEGCR; - *get_eth_reg_addr(NS7520_ETH_IPGT) = unIPGT; -} - -/*********************************************************************** - * @Function: ns7520_link_print_changed - * @Return: void - * @Descr: checks whether the link status has changed and if so prints - * the new mode - ***********************************************************************/ - -static void ns7520_link_print_changed(void) -{ - unsigned short uiStatus; - unsigned short uiControl; - - DEBUG_FN(DEBUG_LINK); - - uiControl = ns7520_mii_read(PHY_COMMON_CTRL); - - if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == - PHY_COMMON_CTRL_AUTO_NEG) { - /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */ - uiStatus = ns7520_mii_read(PHY_COMMON_STAT); - - if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) { - printk(KERN_WARNING NS7520_DRIVER_NAME - ": link down\n"); - /* @TODO Linux: carrier_off */ - } else { - /* @TODO Linux: carrier_on */ - if (phyDetected == PHY_LXT971A) { - uiStatus = - ns7520_mii_read(PHY_LXT971_STAT2); - uiStatus &= - (PHY_LXT971_STAT2_100BTX | - PHY_LXT971_STAT2_DUPLEX_MODE | - PHY_LXT971_STAT2_AUTO_NEG); - - /* mask out all uninteresting parts */ - } - /* other PHYs must store there link information in - uiStatus as PHY_LXT971 */ - } - } else { - /* mode has been forced, so uiStatus should be the same as the - last link status, enforce printing */ - uiStatus = uiLastLinkStatus; - uiLastLinkStatus = 0xff; - } - - if (uiStatus != uiLastLinkStatus) { - /* save current link status */ - uiLastLinkStatus = uiStatus; - - /* print new link status */ - - printk(KERN_INFO NS7520_DRIVER_NAME - ": link mode %i Mbps %s duplex %s\n", - (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10, - (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" : - "half", - (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" : - ""); - } -} - -/*********************************************************************** - * the MII low level stuff - ***********************************************************************/ - -/*********************************************************************** - * @Function: ns7520_mii_identify_phy - * @Return: 1 if supported PHY has been detected otherwise 0 - * @Descr: checks for supported PHY and prints the IDs. - ***********************************************************************/ - -static char ns7520_mii_identify_phy(void) -{ - unsigned short uiID1; - unsigned short uiID2; - unsigned char *szName; - char cRes = 0; - - DEBUG_FN(DEBUG_MII); - - phyDetected = (PhyType) uiID1 = ns7520_mii_read(PHY_COMMON_ID1); - - switch (phyDetected) { - case PHY_LXT971A: - szName = "LXT971A"; - uiID2 = ns7520_mii_read(PHY_COMMON_ID2); - nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK; - cRes = 1; - break; - case PHY_NONE: - default: - /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong - address or reset sets the wrong NS7520_ETH_MCFG_CLKS */ - - uiID2 = 0; - szName = "unknown"; - nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; - phyDetected = PHY_NONE; - } - - printk(KERN_INFO NS7520_DRIVER_NAME - ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName); - - return cRes; -} - -/*********************************************************************** - * @Function: ns7520_mii_read - * @Return: the data read from PHY register uiRegister - * @Descr: the data read may be invalid if timed out. If so, a message - * is printed but the invalid data is returned. - * The fixed device address is being used. - ***********************************************************************/ - -static unsigned short ns7520_mii_read(unsigned short uiRegister) -{ - DEBUG_FN(DEBUG_MII_LOW); - - /* write MII register to be read */ - *get_eth_reg_addr(NS7520_ETH_MADR) = - CONFIG_PHY_ADDR << 8 | uiRegister; - - *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ; - - if (!ns7520_mii_poll_busy()) - printk(KERN_WARNING NS7520_DRIVER_NAME - ": MII still busy in read\n"); - /* continue to read */ - - *get_eth_reg_addr(NS7520_ETH_MCMD) = 0; - - return (unsigned short) (*get_eth_reg_addr(NS7520_ETH_MRDD)); -} - -/*********************************************************************** - * @Function: ns7520_mii_write - * @Return: nothing - * @Descr: writes the data to the PHY register. In case of a timeout, - * no special handling is performed but a message printed - * The fixed device address is being used. - ***********************************************************************/ - -static void ns7520_mii_write(unsigned short uiRegister, - unsigned short uiData) -{ - DEBUG_FN(DEBUG_MII_LOW); - - /* write MII register to be written */ - *get_eth_reg_addr(NS7520_ETH_MADR) = - CONFIG_PHY_ADDR << 8 | uiRegister; - - *get_eth_reg_addr(NS7520_ETH_MWTD) = uiData; - - if (!ns7520_mii_poll_busy()) { - printf(KERN_WARNING NS7520_DRIVER_NAME - ": MII still busy in write\n"); - } -} - -/*********************************************************************** - * @Function: ns7520_mii_get_clock_divisor - * @Return: the clock divisor that should be used in NS7520_ETH_MCFG_CLKS - * @Descr: if no clock divisor can be calculated for the - * current SYSCLK and the maximum MDIO Clock, a warning is printed - * and the greatest divisor is taken - ***********************************************************************/ - -static unsigned int ns7520_mii_get_clock_divisor(unsigned int unMaxMDIOClk) -{ - struct { - unsigned int unSysClkDivisor; - unsigned int unClks; /* field for NS7520_ETH_MCFG_CLKS */ - } PHYClockDivisors[] = { - { - 4, NS7520_ETH_MCFG_CLKS_4}, { - 6, NS7520_ETH_MCFG_CLKS_6}, { - 8, NS7520_ETH_MCFG_CLKS_8}, { - 10, NS7520_ETH_MCFG_CLKS_10}, { - 14, NS7520_ETH_MCFG_CLKS_14}, { - 20, NS7520_ETH_MCFG_CLKS_20}, { - 28, NS7520_ETH_MCFG_CLKS_28} - }; - - int nIndexSysClkDiv; - int nArraySize = - sizeof(PHYClockDivisors) / sizeof(PHYClockDivisors[0]); - unsigned int unClks = NS7520_ETH_MCFG_CLKS_28; /* defaults to - greatest div */ - - DEBUG_FN(DEBUG_INIT); - - for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize; - nIndexSysClkDiv++) { - /* find first sysclock divisor that isn't higher than 2.5 MHz - clock */ - if (NETARM_XTAL_FREQ / - PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <= - unMaxMDIOClk) { - unClks = PHYClockDivisors[nIndexSysClkDiv].unClks; - break; - } - } - - DEBUG_ARGS2(DEBUG_INIT, - "Taking MDIO Clock bit mask 0x%0x for max clock %i\n", - unClks, unMaxMDIOClk); - - /* return greatest divisor */ - return unClks; -} - -/*********************************************************************** - * @Function: ns7520_mii_poll_busy - * @Return: 0 if timed out otherwise the remaing timeout - * @Descr: waits until the MII has completed a command or it times out - * code may be interrupted by hard interrupts. - * It is not checked what happens on multiple actions when - * the first is still being busy and we timeout. - ***********************************************************************/ - -static unsigned int ns7520_mii_poll_busy(void) -{ - unsigned int unTimeout = 1000; - - DEBUG_FN(DEBUG_MII_LOW); - - while (((*get_eth_reg_addr(NS7520_ETH_MIND) & NS7520_ETH_MIND_BUSY) - == NS7520_ETH_MIND_BUSY) && unTimeout) - unTimeout--; - - return unTimeout; -} - -/* ---------------------------------------------------------------------------- - * Net+ARM ethernet MII functionality. - */ -#if defined(CONFIG_MII) - -/** - * Maximum MII address we support - */ -#define MII_ADDRESS_MAX (31) - -/** - * Maximum MII register address we support - */ -#define MII_REGISTER_MAX (31) - -/** - * Ethernet MII interface return values for public functions. - */ -enum mii_status { - MII_STATUS_SUCCESS = 0, - MII_STATUS_FAILURE = 1, -}; - -/** - * Read a 16-bit value from an MII register. - */ -extern int ns7520_miiphy_read(char *devname, unsigned char const addr, - unsigned char const reg, unsigned short *const value) -{ - int ret = MII_STATUS_FAILURE; - - /* Parameter checks */ - if (addr > MII_ADDRESS_MAX) { - ERROR(("invalid addr, 0x%02X", addr)); - goto miiphy_read_failed_0; - } - - if (reg > MII_REGISTER_MAX) { - ERROR(("invalid reg, 0x%02X", reg)); - goto miiphy_read_failed_0; - } - - if (value == NULL) { - ERROR(("NULL value")); - goto miiphy_read_failed_0; - } - - DEBUG_FN(DEBUG_MII_LOW); - - /* write MII register to be read */ - *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg; - - *get_eth_reg_addr(NS7520_ETH_MCMD) = NS7520_ETH_MCMD_READ; - - if (!ns7520_mii_poll_busy()) - printk(KERN_WARNING NS7520_DRIVER_NAME - ": MII still busy in read\n"); - /* continue to read */ - - *get_eth_reg_addr(NS7520_ETH_MCMD) = 0; - - *value = (*get_eth_reg_addr(NS7520_ETH_MRDD)); - ret = MII_STATUS_SUCCESS; - /* Fall through */ - - miiphy_read_failed_0: - return (ret); -} - -/** - * Write a 16-bit value to an MII register. - */ -extern int ns7520_miiphy_write(char *devname, unsigned char const addr, - unsigned char const reg, unsigned short const value) -{ - int ret = MII_STATUS_FAILURE; - - /* Parameter checks */ - if (addr > MII_ADDRESS_MAX) { - ERROR(("invalid addr, 0x%02X", addr)); - goto miiphy_write_failed_0; - } - - if (reg > MII_REGISTER_MAX) { - ERROR(("invalid reg, 0x%02X", reg)); - goto miiphy_write_failed_0; - } - - /* write MII register to be written */ - *get_eth_reg_addr(NS7520_ETH_MADR) = (addr << 8) | reg; - - *get_eth_reg_addr(NS7520_ETH_MWTD) = value; - - if (!ns7520_mii_poll_busy()) { - printf(KERN_WARNING NS7520_DRIVER_NAME - ": MII still busy in write\n"); - } - - ret = MII_STATUS_SUCCESS; - /* Fall through */ - - miiphy_write_failed_0: - return (ret); -} -#endif /* defined(CONFIG_MII) */ -#endif /* CONFIG_DRIVER_NS7520_ETHERNET */ - -int ns7520_miiphy_initialize(bd_t *bis) -{ -#if defined(CONFIG_DRIVER_NS7520_ETHERNET) -#if defined(CONFIG_MII) - miiphy_register("ns7520phy", ns7520_miiphy_read, ns7520_miiphy_write); -#endif -#endif - return 0; -} diff --git a/drivers/ns8382x.c b/drivers/ns8382x.c deleted file mode 100644 index f8b143a01a..0000000000 --- a/drivers/ns8382x.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - ns8382x.c: A U-Boot driver for the NatSemi DP8382[01]. - ported by: Mark A. Rakes (mark_rakes@vivato.net) - - Adapted from: - 1. an Etherboot driver for DP8381[56] written by: - Copyright (C) 2001 Entity Cyber, Inc. - - This development of this Etherboot driver was funded by - Sicom Systems: http://www.sicompos.com/ - - Author: Marty Connor (mdc@thinguin.org) - Adapted from a Linux driver which was written by Donald Becker - - This software may be used and distributed according to the terms - of the GNU Public License (GPL), incorporated herein by reference. - - 2. A Linux driver by Donald Becker, ns820.c: - Written/copyright 1999-2002 by Donald Becker. - - This software may be used and distributed according to the terms of - the GNU General Public License (GPL), incorporated herein by reference. - Drivers based on or derived from this code fall under the GPL and must - retain the authorship, copyright and license notice. This file is not - a complete program and may only be used when the entire operating - system is licensed under the GPL. License for under other terms may be - available. Contact the original author for details. - - The original author may be reached as becker@scyld.com, or at - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Support information and updates available at - http://www.scyld.com/network/netsemi.html - - Datasheets available from: - http://www.national.com/pf/DP/DP83820.html - http://www.national.com/pf/DP/DP83821.html -*/ - -/* Revision History - * October 2002 mar 1.0 - * Initial U-Boot Release. - * Tested with Netgear GA622T (83820) - * and SMC9452TX (83821) - * NOTE: custom boards with these chips may (likely) require - * a programmed EEPROM device (if present) in order to work - * correctly. -*/ - -/* Includes */ -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_NS8382X) - -/* defines */ -#define DSIZE 0x00000FFF -#define ETH_ALEN 6 -#define CRC_SIZE 4 -#define TOUT_LOOP 500000 -#define TX_BUF_SIZE 1536 -#define RX_BUF_SIZE 1536 -#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ - -enum register_offsets { - ChipCmd = 0x00, - ChipConfig = 0x04, - EECtrl = 0x08, - IntrMask = 0x14, - IntrEnable = 0x18, - TxRingPtr = 0x20, - TxRingPtrHi = 0x24, - TxConfig = 0x28, - RxRingPtr = 0x30, - RxRingPtrHi = 0x34, - RxConfig = 0x38, - PriQueue = 0x3C, - RxFilterAddr = 0x48, - RxFilterData = 0x4C, - ClkRun = 0xCC, - PCIPM = 0x44, -}; - -enum ChipCmdBits { - ChipReset = 0x100, - RxReset = 0x20, - TxReset = 0x10, - RxOff = 0x08, - RxOn = 0x04, - TxOff = 0x02, - TxOn = 0x01 -}; - -enum ChipConfigBits { - LinkSts = 0x80000000, - GigSpeed = 0x40000000, - HundSpeed = 0x20000000, - FullDuplex = 0x10000000, - TBIEn = 0x01000000, - Mode1000 = 0x00400000, - T64En = 0x00004000, - D64En = 0x00001000, - M64En = 0x00000800, - PhyRst = 0x00000400, - PhyDis = 0x00000200, - ExtStEn = 0x00000100, - BEMode = 0x00000001, -}; -#define SpeedStatus_Polarity ( GigSpeed | HundSpeed | FullDuplex) - -enum TxConfig_bits { - TxDrthMask = 0x000000ff, - TxFlthMask = 0x0000ff00, - TxMxdmaMask = 0x00700000, - TxMxdma_8 = 0x00100000, - TxMxdma_16 = 0x00200000, - TxMxdma_32 = 0x00300000, - TxMxdma_64 = 0x00400000, - TxMxdma_128 = 0x00500000, - TxMxdma_256 = 0x00600000, - TxMxdma_512 = 0x00700000, - TxMxdma_1024 = 0x00000000, - TxCollRetry = 0x00800000, - TxAutoPad = 0x10000000, - TxMacLoop = 0x20000000, - TxHeartIgn = 0x40000000, - TxCarrierIgn = 0x80000000 -}; - -enum RxConfig_bits { - RxDrthMask = 0x0000003e, - RxMxdmaMask = 0x00700000, - RxMxdma_8 = 0x00100000, - RxMxdma_16 = 0x00200000, - RxMxdma_32 = 0x00300000, - RxMxdma_64 = 0x00400000, - RxMxdma_128 = 0x00500000, - RxMxdma_256 = 0x00600000, - RxMxdma_512 = 0x00700000, - RxMxdma_1024 = 0x00000000, - RxAcceptLenErr = 0x04000000, - RxAcceptLong = 0x08000000, - RxAcceptTx = 0x10000000, - RxStripCRC = 0x20000000, - RxAcceptRunt = 0x40000000, - RxAcceptErr = 0x80000000, -}; - -/* Bits in the RxMode register. */ -enum rx_mode_bits { - RxFilterEnable = 0x80000000, - AcceptAllBroadcast = 0x40000000, - AcceptAllMulticast = 0x20000000, - AcceptAllUnicast = 0x10000000, - AcceptPerfectMatch = 0x08000000, -}; - -typedef struct _BufferDesc { - u32 link; - u32 bufptr; - vu_long cmdsts; - u32 extsts; /*not used here */ -} BufferDesc; - -/* Bits in network_desc.status */ -enum desc_status_bits { - DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000, - DescNoCRC = 0x10000000, DescPktOK = 0x08000000, - DescSizeMask = 0xfff, - - DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000, - DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000, - DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000, - DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000, - - DescRxAbort = 0x04000000, DescRxOver = 0x02000000, - DescRxDest = 0x01800000, DescRxLong = 0x00400000, - DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000, - DescRxCRC = 0x00080000, DescRxAlign = 0x00040000, - DescRxLoop = 0x00020000, DesRxColl = 0x00010000, -}; - -/* Bits in MEAR */ -enum mii_reg_bits { - MDIO_ShiftClk = 0x0040, - MDIO_EnbOutput = 0x0020, - MDIO_Data = 0x0010, -}; - -/* PHY Register offsets. */ -enum phy_reg_offsets { - BMCR = 0x00, - BMSR = 0x01, - PHYIDR1 = 0x02, - PHYIDR2 = 0x03, - ANAR = 0x04, - KTCR = 0x09, -}; - -/* basic mode control register bits */ -enum bmcr_bits { - Bmcr_Reset = 0x8000, - Bmcr_Loop = 0x4000, - Bmcr_Speed0 = 0x2000, - Bmcr_AutoNegEn = 0x1000, /*if set ignores Duplex, Speed[01] */ - Bmcr_RstAutoNeg = 0x0200, - Bmcr_Duplex = 0x0100, - Bmcr_Speed1 = 0x0040, - Bmcr_Force10H = 0x0000, - Bmcr_Force10F = 0x0100, - Bmcr_Force100H = 0x2000, - Bmcr_Force100F = 0x2100, - Bmcr_Force1000H = 0x0040, - Bmcr_Force1000F = 0x0140, -}; - -/* auto negotiation advertisement register */ -enum anar_bits { - anar_adv_100F = 0x0100, - anar_adv_100H = 0x0080, - anar_adv_10F = 0x0040, - anar_adv_10H = 0x0020, - anar_ieee_8023 = 0x0001, -}; - -/* 1K-base T control register */ -enum ktcr_bits { - ktcr_adv_1000H = 0x0100, - ktcr_adv_1000F = 0x0200, -}; - -/* Globals */ -static u32 SavedClkRun; -static unsigned int cur_rx; -static unsigned int rx_config; -static unsigned int tx_config; - -/* Note: transmit and receive buffers and descriptors must be - long long word aligned */ -static BufferDesc txd __attribute__ ((aligned(8))); -static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(8))); -static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(8))); -static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] - __attribute__ ((aligned(8))); - -/* Function Prototypes */ -static int mdio_read(struct eth_device *dev, int phy_id, int addr); -static void mdio_write(struct eth_device *dev, int phy_id, int addr, int value); -static void mdio_sync(struct eth_device *dev, u32 offset); -static int ns8382x_init(struct eth_device *dev, bd_t * bis); -static void ns8382x_reset(struct eth_device *dev); -static void ns8382x_init_rxfilter(struct eth_device *dev); -static void ns8382x_init_txd(struct eth_device *dev); -static void ns8382x_init_rxd(struct eth_device *dev); -static void ns8382x_set_rx_mode(struct eth_device *dev); -static void ns8382x_check_duplex(struct eth_device *dev); -static int ns8382x_send(struct eth_device *dev, volatile void *packet, - int length); -static int ns8382x_poll(struct eth_device *dev); -static void ns8382x_disable(struct eth_device *dev); - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83820}, - {} -}; - -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) - -static inline int -INW(struct eth_device *dev, u_long addr) -{ - return le16_to_cpu(*(vu_short *) (addr + dev->iobase)); -} - -static int -INL(struct eth_device *dev, u_long addr) -{ - return le32_to_cpu(*(vu_long *) (addr + dev->iobase)); -} - -static inline void -OUTW(struct eth_device *dev, int command, u_long addr) -{ - *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command); -} - -static inline void -OUTL(struct eth_device *dev, int command, u_long addr) -{ - *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command); -} - -/* Function: ns8382x_initialize - * Description: Retrieves the MAC address of the card, and sets up some - * globals required by other routines, and initializes the NIC, making it - * ready to send and receive packets. - * Side effects: initializes ns8382xs, ready to recieve packets. - * Returns: int: number of cards found - */ - -int -ns8382x_initialize(bd_t * bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase, status; - int i, idx = 0; - u32 phyAddress; - u32 tmp; - u32 chip_config; - - while (1) { /* Find PCI device(s) */ - if ((devno = pci_find_devices(supported, idx++)) < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); - iobase &= ~0x3; /* 1: unused and 0:I/O Space Indicator */ - -#ifdef NS8382X_DEBUG - printf("ns8382x: NatSemi dp8382x @ 0x%x\n", iobase); -#endif - - pci_write_config_dword(devno, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword(devno, PCI_COMMAND, &status); - if (!(status & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEM access.\n"); - continue; - } else if (!(status & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); - continue; - } - - dev = (struct eth_device *) malloc(sizeof *dev); - - sprintf(dev->name, "dp8382x#%d", card_number); - dev->iobase = bus_to_phys(iobase); - dev->priv = (void *) devno; - dev->init = ns8382x_init; - dev->halt = ns8382x_disable; - dev->send = ns8382x_send; - dev->recv = ns8382x_poll; - - /* ns8382x has a non-standard PM control register - * in PCI config space. Some boards apparently need - * to be brought to D0 in this manner. */ - pci_read_config_dword(devno, PCIPM, &tmp); - if (tmp & (0x03 | 0x100)) { /* D0 state, disable PME assertion */ - u32 newtmp = tmp & ~(0x03 | 0x100); - pci_write_config_dword(devno, PCIPM, newtmp); - } - - /* get MAC address */ - for (i = 0; i < 3; i++) { - u32 data; - char *mac = (char *)&dev->enetaddr[i * 2]; - - OUTL(dev, i * 2, RxFilterAddr); - data = INL(dev, RxFilterData); - *mac++ = data; - *mac++ = data >> 8; - } - /* get PHY address, can't be zero */ - for (phyAddress = 1; phyAddress < 32; phyAddress++) { - u32 rev, phy1; - - phy1 = mdio_read(dev, phyAddress, PHYIDR1); - if (phy1 == 0x2000) { /*check for 83861/91 */ - rev = mdio_read(dev, phyAddress, PHYIDR2); - if ((rev & ~(0x000f)) == 0x00005c50 || - (rev & ~(0x000f)) == 0x00005c60) { -#ifdef NS8382X_DEBUG - printf("phy rev is %x\n", rev); - printf("phy address is %x\n", - phyAddress); -#endif - break; - } - } - } - - /* set phy to autonegotiate && advertise everything */ - mdio_write(dev, phyAddress, KTCR, - (ktcr_adv_1000H | ktcr_adv_1000F)); - mdio_write(dev, phyAddress, ANAR, - (anar_adv_100F | anar_adv_100H | anar_adv_10H | - anar_adv_10F | anar_ieee_8023)); - mdio_write(dev, phyAddress, BMCR, 0x0); /*restore */ - mdio_write(dev, phyAddress, BMCR, - (Bmcr_AutoNegEn | Bmcr_RstAutoNeg)); - /* Reset the chip to erase any previous misconfiguration. */ - OUTL(dev, (ChipReset), ChipCmd); - - chip_config = INL(dev, ChipConfig); - /* reset the phy */ - OUTL(dev, (chip_config | PhyRst), ChipConfig); - /* power up and initialize transceiver */ - OUTL(dev, (chip_config & ~(PhyDis)), ChipConfig); - - mdio_sync(dev, EECtrl); -#ifdef NS8382X_DEBUG - { - u32 chpcfg = - INL(dev, ChipConfig) ^ SpeedStatus_Polarity; - - printf("%s: Transceiver 10%s %s duplex.\n", dev->name, - (chpcfg & GigSpeed) ? "00" : (chpcfg & HundSpeed) - ? "0" : "", - chpcfg & FullDuplex ? "full" : "half"); - printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, - dev->enetaddr[0], dev->enetaddr[1], - dev->enetaddr[2], dev->enetaddr[3], - dev->enetaddr[4], dev->enetaddr[5]); - } -#endif - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. */ - SavedClkRun = INL(dev, ClkRun); - OUTL(dev, SavedClkRun & ~0x100, ClkRun); - - eth_register(dev); - - card_number++; - - pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x60); - - udelay(10 * 1000); - } - return card_number; -} - -/* MII transceiver control section. - Read and write MII registers using software-generated serial MDIO - protocol. See the MII specifications or DP83840A data sheet for details. - - The maximum data clock rate is 2.5 Mhz. To meet minimum timing we - must flush writes to the PCI bus with a PCI read. */ -#define mdio_delay(mdio_addr) INL(dev, mdio_addr) - -#define MDIO_EnbIn (0) -#define MDIO_WRITE0 (MDIO_EnbOutput) -#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput) - -/* Generate the preamble required for initial synchronization and - a few older transceivers. */ -static void -mdio_sync(struct eth_device *dev, u32 offset) -{ - int bits = 32; - - /* Establish sync by sending at least 32 logic ones. */ - while (--bits >= 0) { - OUTL(dev, MDIO_WRITE1, offset); - mdio_delay(offset); - OUTL(dev, MDIO_WRITE1 | MDIO_ShiftClk, offset); - mdio_delay(offset); - } -} - -static int -mdio_read(struct eth_device *dev, int phy_id, int addr) -{ - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | addr; - int i, retval = 0; - - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - - OUTL(dev, dataval, EECtrl); - mdio_delay(EECtrl); - OUTL(dev, dataval | MDIO_ShiftClk, EECtrl); - mdio_delay(EECtrl); - } - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - OUTL(dev, MDIO_EnbIn, EECtrl); - mdio_delay(EECtrl); - retval = - (retval << 1) | ((INL(dev, EECtrl) & MDIO_Data) ? 1 : 0); - OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl); - mdio_delay(EECtrl); - } - return (retval >> 1) & 0xffff; -} - -static void -mdio_write(struct eth_device *dev, int phy_id, int addr, int value) -{ - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (addr << 18) | value; - int i; - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - - OUTL(dev, dataval, EECtrl); - mdio_delay(EECtrl); - OUTL(dev, dataval | MDIO_ShiftClk, EECtrl); - mdio_delay(EECtrl); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - OUTL(dev, MDIO_EnbIn, EECtrl); - mdio_delay(EECtrl); - OUTL(dev, MDIO_EnbIn | MDIO_ShiftClk, EECtrl); - mdio_delay(EECtrl); - } - return; -} - -/* Function: ns8382x_init - * Description: resets the ethernet controller chip and configures - * registers and data structures required for sending and receiving packets. - * Arguments: struct eth_device *dev: NIC data structure - * returns: int. - */ - -static int -ns8382x_init(struct eth_device *dev, bd_t * bis) -{ - u32 config; - - ns8382x_reset(dev); - - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. */ - OUTL(dev, SavedClkRun & ~0x100, ClkRun); - - ns8382x_init_rxfilter(dev); - ns8382x_init_txd(dev); - ns8382x_init_rxd(dev); - - /*set up ChipConfig */ - config = INL(dev, ChipConfig); - /*turn off 64 bit ops && Ten-bit interface - * && big-endian mode && extended status */ - config &= ~(TBIEn | Mode1000 | T64En | D64En | M64En | BEMode | PhyDis | ExtStEn); - OUTL(dev, config, ChipConfig); - - /* Configure the PCI bus bursts and FIFO thresholds. */ - tx_config = TxCarrierIgn | TxHeartIgn | TxAutoPad - | TxCollRetry | TxMxdma_1024 | (0x1002); - rx_config = RxMxdma_1024 | 0x20; -#ifdef NS8382X_DEBUG - printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config); - printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config); -#endif - OUTL(dev, tx_config, TxConfig); - OUTL(dev, rx_config, RxConfig); - - /*turn off priority queueing */ - OUTL(dev, 0x0, PriQueue); - - ns8382x_check_duplex(dev); - ns8382x_set_rx_mode(dev); - - OUTL(dev, (RxOn | TxOn), ChipCmd); - return 1; -} - -/* Function: ns8382x_reset - * Description: soft resets the controller chip - * Arguments: struct eth_device *dev: NIC data structure - * Returns: void. - */ -static void -ns8382x_reset(struct eth_device *dev) -{ - OUTL(dev, ChipReset, ChipCmd); - while (INL(dev, ChipCmd)) - /*wait until done */ ; - OUTL(dev, 0, IntrMask); - OUTL(dev, 0, IntrEnable); -} - -/* Function: ns8382x_init_rxfilter - * Description: sets receive filter address to our MAC address - * Arguments: struct eth_device *dev: NIC data structure - * returns: void. - */ - -static void -ns8382x_init_rxfilter(struct eth_device *dev) -{ - int i; - - for (i = 0; i < ETH_ALEN; i += 2) { - OUTL(dev, i, RxFilterAddr); - OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8), - RxFilterData); - } -} - -/* Function: ns8382x_init_txd - * Description: initializes the Tx descriptor - * Arguments: struct eth_device *dev: NIC data structure - * returns: void. - */ - -static void -ns8382x_init_txd(struct eth_device *dev) -{ - txd.link = (u32) 0; - txd.bufptr = cpu_to_le32((u32) & txb[0]); - txd.cmdsts = (u32) 0; - txd.extsts = (u32) 0; - - OUTL(dev, 0x0, TxRingPtrHi); - OUTL(dev, phys_to_bus((u32)&txd), TxRingPtr); -#ifdef NS8382X_DEBUG - printf("ns8382x_init_txd: TX descriptor register loaded with: %#08X (&txd: %p)\n", - INL(dev, TxRingPtr), &txd); -#endif -} - -/* Function: ns8382x_init_rxd - * Description: initializes the Rx descriptor ring - * Arguments: struct eth_device *dev: NIC data structure - * Returns: void. - */ - -static void -ns8382x_init_rxd(struct eth_device *dev) -{ - int i; - - OUTL(dev, 0x0, RxRingPtrHi); - - cur_rx = 0; - for (i = 0; i < NUM_RX_DESC; i++) { - rxd[i].link = - cpu_to_le32((i + 1 < - NUM_RX_DESC) ? (u32) & rxd[i + - 1] : (u32) & - rxd[0]); - rxd[i].extsts = cpu_to_le32((u32) 0x0); - rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE); - rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]); -#ifdef NS8382X_DEBUG - printf - ("ns8382x_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n", - i, &rxd[i], le32_to_cpu(rxd[i].link), - le32_to_cpu(rxd[i].cmdsts), le32_to_cpu(rxd[i].bufptr)); -#endif - } - OUTL(dev, phys_to_bus((u32) & rxd), RxRingPtr); - -#ifdef NS8382X_DEBUG - printf("ns8382x_init_rxd: RX descriptor register loaded with: %X\n", - INL(dev, RxRingPtr)); -#endif -} - -/* Function: ns8382x_set_rx_mode - * Description: - * sets the receive mode to accept all broadcast packets and packets - * with our MAC address, and reject all multicast packets. - * Arguments: struct eth_device *dev: NIC data structure - * Returns: void. - */ - -static void -ns8382x_set_rx_mode(struct eth_device *dev) -{ - u32 rx_mode = 0x0; - /*spec says RxFilterEnable has to be 0 for rest of - * this stuff to be properly configured. Linux driver - * seems to support this*/ -/* OUTL(dev, rx_mode, RxFilterAddr);*/ - rx_mode = (RxFilterEnable | AcceptAllBroadcast | AcceptPerfectMatch); - OUTL(dev, rx_mode, RxFilterAddr); - printf("ns8382x_set_rx_mode: set to %X\n", rx_mode); - /*now we turn RxFilterEnable back on */ - /*rx_mode |= RxFilterEnable; - OUTL(dev, rx_mode, RxFilterAddr);*/ -} - -static void -ns8382x_check_duplex(struct eth_device *dev) -{ - int gig = 0; - int hun = 0; - int duplex = 0; - int config = (INL(dev, ChipConfig) ^ SpeedStatus_Polarity); - - duplex = (config & FullDuplex) ? 1 : 0; - gig = (config & GigSpeed) ? 1 : 0; - hun = (config & HundSpeed) ? 1 : 0; -#ifdef NS8382X_DEBUG - printf("%s: Setting 10%s %s-duplex based on negotiated link" - " capability.\n", dev->name, (gig) ? "00" : (hun) ? "0" : "", - duplex ? "full" : "half"); -#endif - if (duplex) { - rx_config |= RxAcceptTx; - tx_config |= (TxCarrierIgn | TxHeartIgn); - } else { - rx_config &= ~RxAcceptTx; - tx_config &= ~(TxCarrierIgn | TxHeartIgn); - } -#ifdef NS8382X_DEBUG - printf("%s: Resetting TxConfig Register %#08X\n", dev->name, tx_config); - printf("%s: Resetting RxConfig Register %#08X\n", dev->name, rx_config); -#endif - OUTL(dev, tx_config, TxConfig); - OUTL(dev, rx_config, RxConfig); - - /*if speed is 10 or 100, remove MODE1000, - * if it's 1000, then set it */ - config = INL(dev, ChipConfig); - if (gig) - config |= Mode1000; - else - config &= ~Mode1000; - -#ifdef NS8382X_DEBUG - printf("%s: %setting Mode1000\n", dev->name, (gig) ? "S" : "Uns"); -#endif - OUTL(dev, config, ChipConfig); -} - -/* Function: ns8382x_send - * Description: transmits a packet and waits for completion or timeout. - * Returns: void. */ -static int -ns8382x_send(struct eth_device *dev, volatile void *packet, int length) -{ - u32 i, status = 0; - vu_long tx_stat = 0; - - /* Stop the transmitter */ - OUTL(dev, TxOff, ChipCmd); -#ifdef NS8382X_DEBUG - printf("ns8382x_send: sending %d bytes\n", (int)length); -#endif - - /* set the transmit buffer descriptor and enable Transmit State Machine */ - txd.link = cpu_to_le32(0x0); - txd.bufptr = cpu_to_le32(phys_to_bus((u32)packet)); - txd.extsts = cpu_to_le32(0x0); - txd.cmdsts = cpu_to_le32(DescOwn | length); - - /* load Transmit Descriptor Register */ - OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr); -#ifdef NS8382X_DEBUG - printf("ns8382x_send: TX descriptor register loaded with: %#08X\n", - INL(dev, TxRingPtr)); - printf("\ttxd.link:%X\tbufp:%X\texsts:%X\tcmdsts:%X\n", - le32_to_cpu(txd.link), le32_to_cpu(txd.bufptr), - le32_to_cpu(txd.extsts), le32_to_cpu(txd.cmdsts)); -#endif - /* restart the transmitter */ - OUTL(dev, TxOn, ChipCmd); - - for (i = 0; (tx_stat = le32_to_cpu(txd.cmdsts)) & DescOwn; i++) { - if (i >= TOUT_LOOP) { - printf ("%s: tx error buffer not ready: txd.cmdsts %#X\n", - dev->name, tx_stat); - goto Done; - } - } - - if (!(tx_stat & DescPktOK)) { - printf("ns8382x_send: Transmit error, Tx status %X.\n", tx_stat); - goto Done; - } -#ifdef NS8382X_DEBUG - printf("ns8382x_send: tx_stat: %#08X\n", tx_stat); -#endif - - status = 1; - Done: - return status; -} - -/* Function: ns8382x_poll - * Description: checks for a received packet and returns it if found. - * Arguments: struct eth_device *dev: NIC data structure - * Returns: 1 if packet was received. - * 0 if no packet was received. - * Side effects: - * Returns (copies) the packet to the array dev->packet. - * Returns the length of the packet. - */ - -static int -ns8382x_poll(struct eth_device *dev) -{ - int retstat = 0; - int length = 0; - vu_long rx_status = le32_to_cpu(rxd[cur_rx].cmdsts); - - if (!(rx_status & (u32) DescOwn)) - return retstat; -#ifdef NS8382X_DEBUG - printf("ns8382x_poll: got a packet: cur_rx:%u, status:%lx\n", - cur_rx, rx_status); -#endif - length = (rx_status & DSIZE) - CRC_SIZE; - - if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) { - /* corrupted packet received */ - printf("ns8382x_poll: Corrupted packet, status:%lx\n", rx_status); - retstat = 0; - } else { - /* give packet to higher level routine */ - NetReceive((rxb + cur_rx * RX_BUF_SIZE), length); - retstat = 1; - } - - /* return the descriptor and buffer to receive ring */ - rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE); - rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]); - - if (++cur_rx == NUM_RX_DESC) - cur_rx = 0; - - /* re-enable the potentially idle receive state machine */ - OUTL(dev, RxOn, ChipCmd); - - return retstat; -} - -/* Function: ns8382x_disable - * Description: Turns off interrupts and stops Tx and Rx engines - * Arguments: struct eth_device *dev: NIC data structure - * Returns: void. - */ - -static void -ns8382x_disable(struct eth_device *dev) -{ - /* Disable interrupts using the mask. */ - OUTL(dev, 0, IntrMask); - OUTL(dev, 0, IntrEnable); - - /* Stop the chip's Tx and Rx processes. */ - OUTL(dev, (RxOff | TxOff), ChipCmd); - - /* Restore PME enable bit */ - OUTL(dev, SavedClkRun, ClkRun); -} - -#endif diff --git a/drivers/ns9750_eth.c b/drivers/ns9750_eth.c deleted file mode 100644 index 067ff8efab..0000000000 --- a/drivers/ns9750_eth.c +++ /dev/null @@ -1,797 +0,0 @@ -/*********************************************************************** - * - * Copyright (C) 2004 by FS Forth-Systeme GmbH. - * All rights reserved. - * - * $Id: ns9750_eth.c,v 1.2 2004/02/24 14:09:39 mpietrek Exp $ - * @Author: Markus Pietrek - * @Descr: Ethernet driver for the NS9750. Uses DMA Engine with polling - * interrupt status. But interrupts are not enabled. - * Only one tx buffer descriptor and the RXA buffer descriptor are used - * Currently no transmit lockup handling is included. eth_send has a 5s - * timeout for sending frames. No retransmits are performed when an - * error occurs. - * @References: [1] NS9750 Hardware Reference, December 2003 - * [2] Intel LXT971 Datasheet #249414 Rev. 02 - * [3] NS7520 Linux Ethernet Driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - ***********************************************************************/ - -#include -#include /* NetSendPacket */ - -#include "ns9750_eth.h" /* for Ethernet and PHY */ - -#ifdef CONFIG_DRIVER_NS9750_ETHERNET - -/* some definition to make transistion to linux easier */ - -#define NS9750_DRIVER_NAME "eth" -#define KERN_WARNING "Warning:" -#define KERN_ERR "Error:" -#define KERN_INFO "Info:" - -#if 0 -# define DEBUG -#endif - -#ifdef DEBUG -# define printk printf - -# define DEBUG_INIT 0x0001 -# define DEBUG_MINOR 0x0002 -# define DEBUG_RX 0x0004 -# define DEBUG_TX 0x0008 -# define DEBUG_INT 0x0010 -# define DEBUG_POLL 0x0020 -# define DEBUG_LINK 0x0040 -# define DEBUG_MII 0x0100 -# define DEBUG_MII_LOW 0x0200 -# define DEBUG_MEM 0x0400 -# define DEBUG_ERROR 0x4000 -# define DEBUG_ERROR_CRIT 0x8000 - -static int nDebugLvl = DEBUG_ERROR_CRIT; - -# define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \ - printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 ) -# define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \ - printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 ) -# define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\ - printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 ) -# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\ - printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0) -# define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \ - printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0); -# define ASSERT( expr, func ) if( !( expr ) ) { \ - printf( "Assertion failed! %s:line %d %s\n", \ - (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \ - func } -#else /* DEBUG */ -# define printk(...) -# define DEBUG_ARGS0( FLG, a0 ) -# define DEBUG_ARGS1( FLG, a0, a1 ) -# define DEBUG_ARGS2( FLG, a0, a1, a2 ) -# define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) -# define DEBUG_FN( n ) -# define ASSERT(expr, func) -#endif /* DEBUG */ - -#define NS9750_MII_NEG_DELAY (5*CFG_HZ) /* in s */ -#define TX_TIMEOUT (5*CFG_HZ) /* in s */ - -/* @TODO move it to eeprom.h */ -#define FS_EEPROM_AUTONEG_MASK 0x7 -#define FS_EEPROM_AUTONEG_SPEED_MASK 0x1 -#define FS_EEPROM_AUTONEG_SPEED_10 0x0 -#define FS_EEPROM_AUTONEG_SPEED_100 0x1 -#define FS_EEPROM_AUTONEG_DUPLEX_MASK 0x2 -#define FS_EEPROM_AUTONEG_DUPLEX_HALF 0x0 -#define FS_EEPROM_AUTONEG_DUPLEX_FULL 0x2 -#define FS_EEPROM_AUTONEG_ENABLE_MASK 0x4 -#define FS_EEPROM_AUTONEG_DISABLE 0x0 -#define FS_EEPROM_AUTONEG_ENABLE 0x4 - -/* buffer descriptors taken from [1] p.306 */ -typedef struct -{ - unsigned int* punSrc; - unsigned int unLen; /* 11 bits */ - unsigned int* punDest; /* unused */ - union { - unsigned int unReg; - struct { - unsigned uStatus : 16; - unsigned uRes : 12; - unsigned uFull : 1; - unsigned uEnable : 1; - unsigned uInt : 1; - unsigned uWrap : 1; - } bits; - } s; -} rx_buffer_desc_t; - -typedef struct -{ - unsigned int* punSrc; - unsigned int unLen; /* 10 bits */ - unsigned int* punDest; /* unused */ - union { - unsigned int unReg; /* only 32bit accesses may done to NS9750 - * eth engine */ - struct { - unsigned uStatus : 16; - unsigned uRes : 12; - unsigned uFull : 1; - unsigned uLast : 1; - unsigned uInt : 1; - unsigned uWrap : 1; - } bits; - } s; -} tx_buffer_desc_t; - -static int ns9750_eth_reset( void ); - -static void ns9750_link_force( void ); -static void ns9750_link_auto_negotiate( void ); -static void ns9750_link_update_egcr( void ); -static void ns9750_link_print_changed( void ); - -/* the PHY stuff */ - -static char ns9750_mii_identify_phy( void ); -static unsigned short ns9750_mii_read( unsigned short uiRegister ); -static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData ); -static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk ); -static unsigned int ns9750_mii_poll_busy( void ); - -static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; -static unsigned char ucLinkMode = FS_EEPROM_AUTONEG_ENABLE; -static unsigned int uiLastLinkStatus; -static PhyType phyDetected = PHY_NONE; - -/* we use only one tx buffer descriptor */ -static tx_buffer_desc_t* pTxBufferDesc = - (tx_buffer_desc_t*) get_eth_reg_addr( NS9750_ETH_TXBD ); - -/* we use only one rx buffer descriptor of the 4 */ -static rx_buffer_desc_t aRxBufferDesc[ 4 ]; - -/*********************************************************************** - * @Function: eth_init - * @Return: -1 on failure otherwise 0 - * @Descr: Initializes the ethernet engine and uses either FS Forth's default - * MAC addr or the one in environment - ***********************************************************************/ - -int eth_init (bd_t * pbis) -{ - /* This default MAC Addr is reserved by FS Forth-Systeme for the case of - EEPROM failures */ - unsigned char aucMACAddr[6] = { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 }; - char *pcTmp = getenv ("ethaddr"); - char *pcEnd; - int i; - - DEBUG_FN (DEBUG_INIT); - - /* no need to check for hardware */ - - if (!ns9750_eth_reset ()) - return -1; - - if (pcTmp != NULL) - for (i = 0; i < 6; i++) { - aucMACAddr[i] = - pcTmp ? simple_strtoul (pcTmp, &pcEnd, - 16) : 0; - pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd; - } - - /* configure ethernet address */ - - *get_eth_reg_addr (NS9750_ETH_SA1) = - aucMACAddr[5] << 8 | aucMACAddr[4]; - *get_eth_reg_addr (NS9750_ETH_SA2) = - aucMACAddr[3] << 8 | aucMACAddr[2]; - *get_eth_reg_addr (NS9750_ETH_SA3) = - aucMACAddr[1] << 8 | aucMACAddr[0]; - - /* enable hardware */ - - *get_eth_reg_addr (NS9750_ETH_MAC1) = NS9750_ETH_MAC1_RXEN; - - /* the linux kernel may give packets < 60 bytes, for example arp */ - *get_eth_reg_addr (NS9750_ETH_MAC2) = NS9750_ETH_MAC2_CRCEN | - NS9750_ETH_MAC2_PADEN | NS9750_ETH_MAC2_HUGE; - - /* enable receive and transmit FIFO, use 10/100 Mbps MII */ - *get_eth_reg_addr (NS9750_ETH_EGCR1) = - NS9750_ETH_EGCR1_ETXWM | - NS9750_ETH_EGCR1_ERX | - NS9750_ETH_EGCR1_ERXDMA | - NS9750_ETH_EGCR1_ETX | - NS9750_ETH_EGCR1_ETXDMA | NS9750_ETH_EGCR1_ITXA; - - /* prepare DMA descriptors */ - for (i = 0; i < 4; i++) { - aRxBufferDesc[i].punSrc = 0; - aRxBufferDesc[i].unLen = 0; - aRxBufferDesc[i].s.bits.uWrap = 1; - aRxBufferDesc[i].s.bits.uInt = 1; - aRxBufferDesc[i].s.bits.uEnable = 0; - aRxBufferDesc[i].s.bits.uFull = 0; - } - - /* NetRxPackets[ 0 ] is initialized before eth_init is called and never - changes. NetRxPackets is 32bit aligned */ - aRxBufferDesc[0].punSrc = (unsigned int *) NetRxPackets[0]; - aRxBufferDesc[0].s.bits.uEnable = 1; - aRxBufferDesc[0].unLen = 1522; /* as stated in [1] p.307 */ - - *get_eth_reg_addr (NS9750_ETH_RXAPTR) = - (unsigned int) &aRxBufferDesc[0]; - - /* [1] Tab. 221 states less than 5us */ - *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_ERXINIT; - while (! - (*get_eth_reg_addr (NS9750_ETH_EGSR) & NS9750_ETH_EGSR_RXINIT)) - /* wait for finish */ - udelay (1); - - /* @TODO do we need to clear RXINIT? */ - *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_ERXINIT; - - *get_eth_reg_addr (NS9750_ETH_RXFREE) = 0x1; - - return 0; -} - -/*********************************************************************** - * @Function: eth_send - * @Return: -1 on timeout otherwise 1 - * @Descr: sends one frame by DMA - ***********************************************************************/ - -int eth_send (volatile void *pPacket, int nLen) -{ - ulong ulTimeout; - - DEBUG_FN (DEBUG_TX); - - /* clear old status values */ - *get_eth_reg_addr (NS9750_ETH_EINTR) &= - *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_TX_MA; - - /* prepare Tx Descriptors */ - - pTxBufferDesc->punSrc = (unsigned int *) pPacket; /* pPacket is 32bit - * aligned */ - pTxBufferDesc->unLen = nLen; - /* only 32bit accesses allowed. wrap, full, interrupt and enabled to 1 */ - pTxBufferDesc->s.unReg = 0xf0000000; - /* pTxBufferDesc is the first possible buffer descriptor */ - *get_eth_reg_addr (NS9750_ETH_TXPTR) = 0x0; - - /* enable processor for next frame */ - - *get_eth_reg_addr (NS9750_ETH_EGCR2) &= ~NS9750_ETH_EGCR2_TCLER; - *get_eth_reg_addr (NS9750_ETH_EGCR2) |= NS9750_ETH_EGCR2_TCLER; - - ulTimeout = get_timer (0); - - DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, - "Waiting for transmission to finish\n"); - while (! - (*get_eth_reg_addr (NS9750_ETH_EINTR) & - (NS9750_ETH_EINTR_TXDONE | NS9750_ETH_EINTR_TXERR))) { - /* do nothing, wait for completion */ - if (get_timer (0) - ulTimeout > TX_TIMEOUT) { - DEBUG_ARGS0 (DEBUG_TX, "Transmit Timed out\n"); - return -1; - } - } - DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, "transmitted...\n"); - - return 0; -} - -/*********************************************************************** - * @Function: eth_rx - * @Return: size of last frame in bytes or 0 if no frame available - * @Descr: gives one frame to U-Boot which has been copied by DMA engine already - * to NetRxPackets[ 0 ]. - ***********************************************************************/ - -int eth_rx (void) -{ - int nLen = 0; - unsigned int unStatus; - - unStatus = - *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_RX_MA; - - if (!unStatus) - /* no packet available, return immediately */ - return 0; - - DEBUG_FN (DEBUG_RX); - - /* unLen always < max(nLen) and discard checksum */ - nLen = (int) aRxBufferDesc[0].unLen - 4; - - /* acknowledge status register */ - *get_eth_reg_addr (NS9750_ETH_EINTR) = unStatus; - - aRxBufferDesc[0].unLen = 1522; - aRxBufferDesc[0].s.bits.uFull = 0; - - /* Buffer A descriptor available again */ - *get_eth_reg_addr (NS9750_ETH_RXFREE) |= 0x1; - - /* NetReceive may call eth_send. Due to a possible bug of the NS9750 we - * have to acknowledge the received frame before sending a new one */ - if (unStatus & NS9750_ETH_EINTR_RXDONEA) - NetReceive (NetRxPackets[0], nLen); - - return nLen; -} - -/*********************************************************************** - * @Function: eth_halt - * @Return: n/a - * @Descr: stops the ethernet engine - ***********************************************************************/ - -void eth_halt (void) -{ - DEBUG_FN (DEBUG_INIT); - - *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_RXEN; - *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~(NS9750_ETH_EGCR1_ERX | - NS9750_ETH_EGCR1_ERXDMA | - NS9750_ETH_EGCR1_ETX | - NS9750_ETH_EGCR1_ETXDMA); -} - -/*********************************************************************** - * @Function: ns9750_eth_reset - * @Return: 0 on failure otherwise 1 - * @Descr: resets the ethernet interface and the PHY, - * performs auto negotiation or fixed modes - ***********************************************************************/ - -static int ns9750_eth_reset (void) -{ - DEBUG_FN (DEBUG_MINOR); - - /* Reset MAC */ - *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_MAC_HRST; - udelay (5); /* according to [1], p.322 */ - *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_MAC_HRST; - - /* reset and initialize PHY */ - - *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_SRST; - - /* we don't support hot plugging of PHY, therefore we don't reset - phyDetected and nPhyMaxMdioClock here. The risk is if the setting is - incorrect the first open - may detect the PHY correctly but succeding will fail - For reseting the PHY and identifying we have to use the standard - MDIO CLOCK value 2.5 MHz only after hardware reset - After having identified the PHY we will do faster */ - - *get_eth_reg_addr (NS9750_ETH_MCFG) = - ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); - - /* reset PHY */ - ns9750_mii_write (PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET); - ns9750_mii_write (PHY_COMMON_CTRL, 0); - - /* @TODO check time */ - udelay (3000); /* [2] p.70 says at least 300us reset recovery time. But - go sure, it didn't worked stable at higher timer - frequencies under LxNETES-2.x */ - - /* MII clock has been setup to default, ns9750_mii_identify_phy should - work for all */ - - if (!ns9750_mii_identify_phy ()) { - printk (KERN_ERR NS9750_DRIVER_NAME - ": Unsupported PHY, aborting\n"); - return 0; - } - - /* now take the highest MDIO clock possible after detection */ - *get_eth_reg_addr (NS9750_ETH_MCFG) = - ns9750_mii_get_clock_divisor (nPhyMaxMdioClock); - - - /* PHY has been detected, so there can be no abort reason and we can - finish initializing ethernet */ - - uiLastLinkStatus = 0xff; /* undefined */ - - if ((ucLinkMode & FS_EEPROM_AUTONEG_ENABLE_MASK) == - FS_EEPROM_AUTONEG_DISABLE) - /* use parameters defined */ - ns9750_link_force (); - else - ns9750_link_auto_negotiate (); - - if (phyDetected == PHY_LXT971A) - /* set LED2 to link mode */ - ns9750_mii_write (PHY_LXT971_LED_CFG, - PHY_LXT971_LED_CFG_LINK_ACT << - PHY_LXT971_LED_CFG_SHIFT_LED2); - - return 1; -} - -/*********************************************************************** - * @Function: ns9750_link_force - * @Return: void - * @Descr: configures eth and MII to use the link mode defined in - * ucLinkMode - ***********************************************************************/ - -static void ns9750_link_force (void) -{ - unsigned short uiControl; - - DEBUG_FN (DEBUG_LINK); - - uiControl = ns9750_mii_read (PHY_COMMON_CTRL); - uiControl &= ~(PHY_COMMON_CTRL_SPD_MA | - PHY_COMMON_CTRL_AUTO_NEG | PHY_COMMON_CTRL_DUPLEX); - - uiLastLinkStatus = 0; - - if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) == - FS_EEPROM_AUTONEG_SPEED_100) { - uiControl |= PHY_COMMON_CTRL_SPD_100; - uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX; - } else - uiControl |= PHY_COMMON_CTRL_SPD_10; - - if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) == - FS_EEPROM_AUTONEG_DUPLEX_FULL) { - uiControl |= PHY_COMMON_CTRL_DUPLEX; - uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE; - } - - ns9750_mii_write (PHY_COMMON_CTRL, uiControl); - - ns9750_link_print_changed (); - ns9750_link_update_egcr (); -} - -/*********************************************************************** - * @Function: ns9750_link_auto_negotiate - * @Return: void - * @Descr: performs auto-negotation of link. - ***********************************************************************/ - -static void ns9750_link_auto_negotiate (void) -{ - unsigned long ulStartJiffies; - unsigned short uiStatus; - - DEBUG_FN (DEBUG_LINK); - - /* run auto-negotation */ - /* define what we are capable of */ - ns9750_mii_write (PHY_COMMON_AUTO_ADV, - PHY_COMMON_AUTO_ADV_100BTXFD | - PHY_COMMON_AUTO_ADV_100BTX | - PHY_COMMON_AUTO_ADV_10BTFD | - PHY_COMMON_AUTO_ADV_10BT | - PHY_COMMON_AUTO_ADV_802_3); - /* start auto-negotiation */ - ns9750_mii_write (PHY_COMMON_CTRL, - PHY_COMMON_CTRL_AUTO_NEG | - PHY_COMMON_CTRL_RES_AUTO); - - /* wait for completion */ - - ulStartJiffies = get_ticks (); - while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) { - uiStatus = ns9750_mii_read (PHY_COMMON_STAT); - if ((uiStatus & - (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) == - (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) { - /* lucky we are, auto-negotiation succeeded */ - ns9750_link_print_changed (); - ns9750_link_update_egcr (); - return; - } - } - - DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n"); - /* ignore invalid link settings */ -} - -/*********************************************************************** - * @Function: ns9750_link_update_egcr - * @Return: void - * @Descr: updates the EGCR and MAC2 link status after mode change or - * auto-negotation - ***********************************************************************/ - -static void ns9750_link_update_egcr (void) -{ - unsigned int unEGCR; - unsigned int unMAC2; - unsigned int unIPGT; - - DEBUG_FN (DEBUG_LINK); - - unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1); - unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2); - unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA; - - unMAC2 &= ~NS9750_ETH_MAC2_FULLD; - if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE) - == PHY_LXT971_STAT2_DUPLEX_MODE) { - unMAC2 |= NS9750_ETH_MAC2_FULLD; - unIPGT |= 0x15; /* see [1] p. 339 */ - } else - unIPGT |= 0x12; /* see [1] p. 339 */ - - *get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2; - *get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR; - *get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT; -} - -/*********************************************************************** - * @Function: ns9750_link_print_changed - * @Return: void - * @Descr: checks whether the link status has changed and if so prints - * the new mode - ***********************************************************************/ - -static void ns9750_link_print_changed (void) -{ - unsigned short uiStatus; - unsigned short uiControl; - - DEBUG_FN (DEBUG_LINK); - - uiControl = ns9750_mii_read (PHY_COMMON_CTRL); - - if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) == - PHY_COMMON_CTRL_AUTO_NEG) { - /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */ - uiStatus = ns9750_mii_read (PHY_COMMON_STAT); - - if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) { - printk (KERN_WARNING NS9750_DRIVER_NAME - ": link down\n"); - /* @TODO Linux: carrier_off */ - } else { - /* @TODO Linux: carrier_on */ - if (phyDetected == PHY_LXT971A) { - uiStatus = ns9750_mii_read (PHY_LXT971_STAT2); - uiStatus &= (PHY_LXT971_STAT2_100BTX | - PHY_LXT971_STAT2_DUPLEX_MODE | - PHY_LXT971_STAT2_AUTO_NEG); - - /* mask out all uninteresting parts */ - } - /* other PHYs must store there link information in - uiStatus as PHY_LXT971 */ - } - } else { - /* mode has been forced, so uiStatus should be the same as the - last link status, enforce printing */ - uiStatus = uiLastLinkStatus; - uiLastLinkStatus = 0xff; - } - - if (uiStatus != uiLastLinkStatus) { - /* save current link status */ - uiLastLinkStatus = uiStatus; - - /* print new link status */ - - printk (KERN_INFO NS9750_DRIVER_NAME - ": link mode %i Mbps %s duplex %s\n", - (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10, - (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" : - "half", - (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" : - ""); - } -} - -/*********************************************************************** - * the MII low level stuff - ***********************************************************************/ - -/*********************************************************************** - * @Function: ns9750_mii_identify_phy - * @Return: 1 if supported PHY has been detected otherwise 0 - * @Descr: checks for supported PHY and prints the IDs. - ***********************************************************************/ - -static char ns9750_mii_identify_phy (void) -{ - unsigned short uiID1; - unsigned short uiID2; - unsigned char *szName; - char cRes = 0; - - DEBUG_FN (DEBUG_MII); - - phyDetected = (PhyType) uiID1 = ns9750_mii_read (PHY_COMMON_ID1); - - switch (phyDetected) { - case PHY_LXT971A: - szName = "LXT971A"; - uiID2 = ns9750_mii_read (PHY_COMMON_ID2); - nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK; - cRes = 1; - break; - case PHY_NONE: - default: - /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong - address or reset sets the wrong NS9750_ETH_MCFG_CLKS */ - - uiID2 = 0; - szName = "unknown"; - nPhyMaxMdioClock = PHY_MDIO_MAX_CLK; - phyDetected = PHY_NONE; - } - - printk (KERN_INFO NS9750_DRIVER_NAME - ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName); - - return cRes; -} - -/*********************************************************************** - * @Function: ns9750_mii_read - * @Return: the data read from PHY register uiRegister - * @Descr: the data read may be invalid if timed out. If so, a message - * is printed but the invalid data is returned. - * The fixed device address is being used. - ***********************************************************************/ - -static unsigned short ns9750_mii_read (unsigned short uiRegister) -{ - DEBUG_FN (DEBUG_MII_LOW); - - /* write MII register to be read */ - *get_eth_reg_addr (NS9750_ETH_MADR) = - NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; - - *get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ; - - if (!ns9750_mii_poll_busy ()) - printk (KERN_WARNING NS9750_DRIVER_NAME - ": MII still busy in read\n"); - /* continue to read */ - - *get_eth_reg_addr (NS9750_ETH_MCMD) = 0; - - return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD)); -} - - -/*********************************************************************** - * @Function: ns9750_mii_write - * @Return: nothing - * @Descr: writes the data to the PHY register. In case of a timeout, - * no special handling is performed but a message printed - * The fixed device address is being used. - ***********************************************************************/ - -static void ns9750_mii_write (unsigned short uiRegister, - unsigned short uiData) -{ - DEBUG_FN (DEBUG_MII_LOW); - - /* write MII register to be written */ - *get_eth_reg_addr (NS9750_ETH_MADR) = - NS9750_ETH_PHY_ADDRESS << 8 | uiRegister; - - *get_eth_reg_addr (NS9750_ETH_MWTD) = uiData; - - if (!ns9750_mii_poll_busy ()) { - printf (KERN_WARNING NS9750_DRIVER_NAME - ": MII still busy in write\n"); - } -} - - -/*********************************************************************** - * @Function: ns9750_mii_get_clock_divisor - * @Return: the clock divisor that should be used in NS9750_ETH_MCFG_CLKS - * @Descr: if no clock divisor can be calculated for the - * current SYSCLK and the maximum MDIO Clock, a warning is printed - * and the greatest divisor is taken - ***********************************************************************/ - -static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk) -{ - struct { - unsigned int unSysClkDivisor; - unsigned int unClks; /* field for NS9750_ETH_MCFG_CLKS */ - } PHYClockDivisors[] = { - { - 4, NS9750_ETH_MCFG_CLKS_4}, { - 6, NS9750_ETH_MCFG_CLKS_6}, { - 8, NS9750_ETH_MCFG_CLKS_8}, { - 10, NS9750_ETH_MCFG_CLKS_10}, { - 20, NS9750_ETH_MCFG_CLKS_20}, { - 30, NS9750_ETH_MCFG_CLKS_30}, { - 40, NS9750_ETH_MCFG_CLKS_40} - }; - - int nIndexSysClkDiv; - int nArraySize = - sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]); - unsigned int unClks = NS9750_ETH_MCFG_CLKS_40; /* defaults to - greatest div */ - - DEBUG_FN (DEBUG_INIT); - - for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize; - nIndexSysClkDiv++) { - /* find first sysclock divisor that isn't higher than 2.5 MHz - clock */ - if (AHB_CLK_FREQ / - PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <= - unMaxMDIOClk) { - unClks = PHYClockDivisors[nIndexSysClkDiv].unClks; - break; - } - } - - DEBUG_ARGS2 (DEBUG_INIT, - "Taking MDIO Clock bit mask 0x%0x for max clock %i\n", - unClks, unMaxMDIOClk); - - /* return greatest divisor */ - return unClks; -} - -/*********************************************************************** - * @Function: ns9750_mii_poll_busy - * @Return: 0 if timed out otherwise the remaing timeout - * @Descr: waits until the MII has completed a command or it times out - * code may be interrupted by hard interrupts. - * It is not checked what happens on multiple actions when - * the first is still being busy and we timeout. - ***********************************************************************/ - -static unsigned int ns9750_mii_poll_busy (void) -{ - unsigned int unTimeout = 10000; - - DEBUG_FN (DEBUG_MII_LOW); - - while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY) - == NS9750_ETH_MIND_BUSY) && unTimeout) - unTimeout--; - - return unTimeout; -} - -#endif /* CONFIG_DRIVER_NS9750_ETHERNET */ diff --git a/drivers/pcnet.c b/drivers/pcnet.c deleted file mode 100644 index 2af0e8f244..0000000000 --- a/drivers/pcnet.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de. - * - * This driver for AMD PCnet network controllers is derived from the - * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#if 0 -#define PCNET_DEBUG_LEVEL 0 /* 0=off, 1=init, 2=rx/tx */ -#endif - -#if PCNET_DEBUG_LEVEL > 0 -#define PCNET_DEBUG1(fmt,args...) printf (fmt ,##args) -#if PCNET_DEBUG_LEVEL > 1 -#define PCNET_DEBUG2(fmt,args...) printf (fmt ,##args) -#else -#define PCNET_DEBUG2(fmt,args...) -#endif -#else -#define PCNET_DEBUG1(fmt,args...) -#define PCNET_DEBUG2(fmt,args...) -#endif - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_PCNET) - -#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975) -#error "Macro for PCnet chip version is not defined!" -#endif - -/* - * Set the number of Tx and Rx buffers, using Log_2(# buffers). - * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. - * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). - */ -#define PCNET_LOG_TX_BUFFERS 0 -#define PCNET_LOG_RX_BUFFERS 2 - -#define TX_RING_SIZE (1 << (PCNET_LOG_TX_BUFFERS)) -#define TX_RING_LEN_BITS ((PCNET_LOG_TX_BUFFERS) << 12) - -#define RX_RING_SIZE (1 << (PCNET_LOG_RX_BUFFERS)) -#define RX_RING_LEN_BITS ((PCNET_LOG_RX_BUFFERS) << 4) - -#define PKT_BUF_SZ 1544 - -/* The PCNET Rx and Tx ring descriptors. */ -struct pcnet_rx_head { - u32 base; - s16 buf_length; - s16 status; - u32 msg_length; - u32 reserved; -}; - -struct pcnet_tx_head { - u32 base; - s16 length; - s16 status; - u32 misc; - u32 reserved; -}; - -/* The PCNET 32-Bit initialization block, described in databook. */ -struct pcnet_init_block { - u16 mode; - u16 tlen_rlen; - u8 phys_addr[6]; - u16 reserved; - u32 filter[2]; - /* Receive and transmit ring base, along with extra bits. */ - u32 rx_ring; - u32 tx_ring; - u32 reserved2; -}; - -typedef struct pcnet_priv { - struct pcnet_rx_head rx_ring[RX_RING_SIZE]; - struct pcnet_tx_head tx_ring[TX_RING_SIZE]; - struct pcnet_init_block init_block; - /* Receive Buffer space */ - unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; - int cur_rx; - int cur_tx; -} pcnet_priv_t; - -static pcnet_priv_t *lp; - -/* Offsets from base I/O address for WIO mode */ -#define PCNET_RDP 0x10 -#define PCNET_RAP 0x12 -#define PCNET_RESET 0x14 -#define PCNET_BDP 0x16 - -static u16 pcnet_read_csr (struct eth_device *dev, int index) -{ - outw (index, dev->iobase+PCNET_RAP); - return inw (dev->iobase+PCNET_RDP); -} - -static void pcnet_write_csr (struct eth_device *dev, int index, u16 val) -{ - outw (index, dev->iobase+PCNET_RAP); - outw (val, dev->iobase+PCNET_RDP); -} - -static u16 pcnet_read_bcr (struct eth_device *dev, int index) -{ - outw (index, dev->iobase+PCNET_RAP); - return inw (dev->iobase+PCNET_BDP); -} - -static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val) -{ - outw (index, dev->iobase+PCNET_RAP); - outw (val, dev->iobase+PCNET_BDP); -} - -static void pcnet_reset (struct eth_device *dev) -{ - inw (dev->iobase+PCNET_RESET); -} - -static int pcnet_check (struct eth_device *dev) -{ - outw (88, dev->iobase+PCNET_RAP); - return (inw (dev->iobase+PCNET_RAP) == 88); -} - -static int pcnet_init( struct eth_device* dev, bd_t *bis); -static int pcnet_send (struct eth_device* dev, volatile void *packet, - int length); -static int pcnet_recv (struct eth_device* dev); -static void pcnet_halt (struct eth_device* dev); -static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num); - -#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a)) -#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a))) - -static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, - { } -}; - - -int pcnet_initialize(bd_t *bis) -{ - pci_dev_t devbusfn; - struct eth_device* dev; - u16 command, status; - int dev_nr = 0; - - PCNET_DEBUG1("\npcnet_initialize...\n"); - - for (dev_nr = 0; ; dev_nr++) { - - /* - * Find the PCnet PCI device(s). - */ - if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) { - break; - } - - /* - * Allocate and pre-fill the device structure. - */ - dev = (struct eth_device*) malloc(sizeof *dev); - dev->priv = (void *)devbusfn; - sprintf(dev->name, "pcnet#%d", dev_nr); - - /* - * Setup the PCI device. - */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (unsigned int *)&dev->iobase); - dev->iobase &= ~0xf; - - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ", - dev->name, devbusfn, dev->iobase); - - command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; - pci_write_config_word(devbusfn, PCI_COMMAND, command); - pci_read_config_word(devbusfn, PCI_COMMAND, &status); - if ((status & command) != command) { - printf("%s: Couldn't enable IO access or Bus Mastering\n", - dev->name); - free(dev); - continue; - } - - pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); - - /* - * Probe the PCnet chip. - */ - if (pcnet_probe(dev, bis, dev_nr) < 0) { - free(dev); - continue; - } - - /* - * Setup device structure and register the driver. - */ - dev->init = pcnet_init; - dev->halt = pcnet_halt; - dev->send = pcnet_send; - dev->recv = pcnet_recv; - - eth_register(dev); - } - - udelay(10 * 1000); - - return dev_nr; -} - -static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr) -{ - int chip_version; - char *chipname; -#ifdef PCNET_HAS_PROM - int i; -#endif - - /* Reset the PCnet controller */ - pcnet_reset(dev); - - /* Check if register access is working */ - if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { - printf("%s: CSR register access check failed\n", dev->name); - return -1; - } - - /* Identify the chip */ - chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16); - if ((chip_version & 0xfff) != 0x003) - return -1; - chip_version = (chip_version >> 12) & 0xffff; - switch (chip_version) { -#ifdef CONFIG_PCNET_79C973 - case 0x2625: - chipname = "PCnet/FAST III 79C973"; /* PCI */ - break; -#endif -#ifdef CONFIG_PCNET_79C975 - case 0x2627: - chipname = "PCnet/FAST III 79C975"; /* PCI */ - break; -#endif - default: - printf("%s: PCnet version %#x not supported\n", - dev->name, chip_version); - return -1; - } - - PCNET_DEBUG1("AMD %s\n", chipname); - -#ifdef PCNET_HAS_PROM - /* - * In most chips, after a chip reset, the ethernet address is read from - * the station address PROM at the base address and programmed into the - * "Physical Address Registers" CSR12-14. - */ - for (i = 0; i < 3; i++) { - unsigned int val; - val = pcnet_read_csr(dev, i+12) & 0x0ffff; - /* There may be endianness issues here. */ - dev->enetaddr[2*i ] = val & 0x0ff; - dev->enetaddr[2*i+1] = (val >> 8) & 0x0ff; - } -#endif /* PCNET_HAS_PROM */ - - return 0; -} - -static int pcnet_init(struct eth_device* dev, bd_t *bis) -{ - int i, val; - u32 addr; - - PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); - - /* Switch pcnet to 32bit mode */ - pcnet_write_bcr (dev, 20, 2); - -#ifdef CONFIG_PN62 - /* Setup LED registers */ - val = pcnet_read_bcr (dev, 2) | 0x1000; - pcnet_write_bcr (dev, 2, val); /* enable LEDPE */ - pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */ - pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */ - pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */ - pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */ -#endif - - /* Set/reset autoselect bit */ - val = pcnet_read_bcr (dev, 2) & ~2; - val |= 2; - pcnet_write_bcr (dev, 2, val); - - /* Enable auto negotiate, setup, disable fd */ - val = pcnet_read_bcr(dev, 32) & ~0x98; - val |= 0x20; - pcnet_write_bcr(dev, 32, val); - - /* - * We only maintain one structure because the drivers will never - * be used concurrently. In 32bit mode the RX and TX ring entries - * must be aligned on 16-byte boundaries. - */ - if (lp == NULL) { - addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10); - addr = (addr + 0xf) & ~0xf; - lp = (pcnet_priv_t *)addr; - } - - lp->init_block.mode = cpu_to_le16(0x0000); - lp->init_block.filter[0] = 0x00000000; - lp->init_block.filter[1] = 0x00000000; - - /* - * Initialize the Rx ring. - */ - lp->cur_rx = 0; - for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]); - lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); - lp->rx_ring[i].status = cpu_to_le16(0x8000); - PCNET_DEBUG1("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n", - i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length, - lp->rx_ring[i].status); - } - - /* - * Initialize the Tx ring. The Tx buffer address is filled in as - * needed, but we do need to clear the upper ownership bit. - */ - lp->cur_tx = 0; - for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_ring[i].base = 0; - lp->tx_ring[i].status = 0; - } - - /* - * Setup Init Block. - */ - PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->init_block); - - for (i = 0; i < 6; i++) { - lp->init_block.phys_addr[i] = dev->enetaddr[i]; - PCNET_DEBUG1(" %02x", lp->init_block.phys_addr[i]); - } - - lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | - RX_RING_LEN_BITS); - lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring); - lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring); - - PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", - lp->init_block.tlen_rlen, - lp->init_block.rx_ring, lp->init_block.tx_ring); - - /* - * Tell the controller where the Init Block is located. - */ - addr = PCI_TO_MEM(dev, &lp->init_block); - pcnet_write_csr(dev, 1, addr & 0xffff); - pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); - - pcnet_write_csr (dev, 4, 0x0915); - pcnet_write_csr (dev, 0, 0x0001); /* start */ - - /* Wait for Init Done bit */ - for (i = 10000; i > 0; i--) { - if (pcnet_read_csr (dev, 0) & 0x0100) - break; - udelay(10); - } - if (i <= 0) { - printf("%s: TIMEOUT: controller init failed\n", dev->name); - pcnet_reset (dev); - return 0; - } - - /* - * Finally start network controller operation. - */ - pcnet_write_csr (dev, 0, 0x0002); - - return 1; -} - -static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len) -{ - int i, status; - struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx]; - - PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet); - - /* Wait for completion by testing the OWN bit */ - for (i = 1000; i > 0; i--) { - status = le16_to_cpu(entry->status); - if ((status & 0x8000) == 0) - break; - udelay(100); - PCNET_DEBUG2("."); - } - if (i <= 0) { - printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", - dev->name, lp->cur_tx, status); - pkt_len = 0; - goto failure; - } - - /* - * Setup Tx ring. Caution: the write order is important here, - * set the status with the "ownership" bits last. - */ - status = 0x8300; - entry->length = le16_to_cpu(-pkt_len); - entry->misc = 0x00000000; - entry->base = PCI_TO_MEM_LE(dev, packet); - entry->status = le16_to_cpu(status); - - /* Trigger an immediate send poll. */ - pcnet_write_csr (dev, 0, 0x0008); - - failure: - if (++lp->cur_tx >= TX_RING_SIZE) - lp->cur_tx = 0; - - PCNET_DEBUG2("done\n"); - return pkt_len; -} - -static int pcnet_recv(struct eth_device* dev) -{ - struct pcnet_rx_head *entry; - int pkt_len = 0; - u16 status; - - while (1) { - entry = &lp->rx_ring[lp->cur_rx]; - /* - * If we own the next entry, it's a new packet. Send it up. - */ - if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) { - break; - } - status >>= 8; - - if (status != 0x03) { /* There was an error. */ - - printf("%s: Rx%d", dev->name, lp->cur_rx); - PCNET_DEBUG1(" (status=0x%x)", status); - if (status & 0x20) printf(" Frame"); - if (status & 0x10) printf(" Overflow"); - if (status & 0x08) printf(" CRC"); - if (status & 0x04) printf(" Fifo"); - printf(" Error\n"); - entry->status &= le16_to_cpu(0x03ff); - - } else { - - pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4; - if (pkt_len < 60) { - printf("%s: Rx%d: invalid packet length %d\n", - dev->name, lp->cur_rx, pkt_len); - } else { - NetReceive(lp->rx_buf[lp->cur_rx], pkt_len); - PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n", - lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]); - } - } - entry->status |= cpu_to_le16(0x8000); - - if (++lp->cur_rx >= RX_RING_SIZE) - lp->cur_rx = 0; - } - return pkt_len; -} - -static void pcnet_halt(struct eth_device* dev) -{ - int i; - - PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name); - - /* Reset the PCnet controller */ - pcnet_reset (dev); - - /* Wait for Stop bit */ - for (i = 1000; i > 0; i--) { - if (pcnet_read_csr (dev, 0) & 0x4) - break; - udelay(10); - } - if (i <= 0) { - printf("%s: TIMEOUT: controller reset failed\n", dev->name); - } -} - -#endif diff --git a/drivers/plb2800_eth.c b/drivers/plb2800_eth.c deleted file mode 100644 index 0ae5d808a6..0000000000 --- a/drivers/plb2800_eth.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * PLB2800 internal switch ethernet driver. - * - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -#if defined(CONFIG_CMD_NET) \ - && defined(CONFIG_NET_MULTI) && defined(CONFIG_PLB2800_ETHER) - -#include -#include -#include - - -#define NUM_RX_DESC PKTBUFSRX -#define TOUT_LOOP 1000000 - -#define LONG_REF(addr) (*((volatile unsigned long*)addr)) - -#define CMAC_CRX_CTRL LONG_REF(0xb800c870) -#define CMAC_CTX_CTRL LONG_REF(0xb800c874) -#define SYS_MAC_ADDR_0 LONG_REF(0xb800c878) -#define SYS_MAC_ADDR_1 LONG_REF(0xb800c87c) -#define MIPS_H_MASK LONG_REF(0xB800C810) - -#define MA_LEARN LONG_REF(0xb8008004) -#define DA_LOOKUP LONG_REF(0xb8008008) - -#define CMAC_CRX_CTRL_PD 0x00000001 -#define CMAC_CRX_CTRL_CG 0x00000002 -#define CMAC_CRX_CTRL_PL_SHIFT 2 -#define CMAC_CRIT 0x0 -#define CMAC_NON_CRIT 0x1 -#define MBOX_STAT_ID_SHF 28 -#define MBOX_STAT_CP 0x80000000 -#define MBOX_STAT_MB 0x00000001 -#define EN_MA_LEARN 0x02000000 -#define EN_DA_LKUP 0x01000000 -#define MA_DEST_SHF 11 -#define DA_DEST_SHF 11 -#define DA_STATE_SHF 19 -#define TSTAMP_MS 0x00000000 -#define SW_H_MBOX4_MASK 0x08000000 -#define SW_H_MBOX3_MASK 0x04000000 -#define SW_H_MBOX2_MASK 0x02000000 -#define SW_H_MBOX1_MASK 0x01000000 - -typedef volatile struct { - unsigned int stat; - unsigned int cmd; - unsigned int cnt; - unsigned int adr; -} mailbox_t; - -#define MBOX_REG(mb) ((mailbox_t*)(0xb800c830+(mb<<4))) - -typedef volatile struct { - unsigned int word0; - unsigned int word1; - unsigned int word2; -} mbhdr_t; - -#define MBOX_MEM(mb) ((void*)(0xb800a000+((3-mb)<<11))) - - -static int plb2800_eth_init(struct eth_device *dev, bd_t * bis); -static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, - int length); -static int plb2800_eth_recv(struct eth_device *dev); -static void plb2800_eth_halt(struct eth_device *dev); - -static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr); -static unsigned char * plb2800_get_mac_addr(void); - -static int rx_new; -static int mac_addr_set = 0; - - -int plb2800_eth_initialize(bd_t * bis) -{ - struct eth_device *dev; - ulong temp; - -#ifdef DEBUG - printf("Entered plb2800_eth_initialize()\n"); -#endif - - if (!(dev = (struct eth_device *) malloc (sizeof *dev))) - { - printf("Failed to allocate memory\n"); - return 0; - } - memset(dev, 0, sizeof(*dev)); - - sprintf(dev->name, "PLB2800 Switch"); - dev->init = plb2800_eth_init; - dev->halt = plb2800_eth_halt; - dev->send = plb2800_eth_send; - dev->recv = plb2800_eth_recv; - - eth_register(dev); - - /* bug fix */ - *(ulong *)0xb800e800 = 0x838; - - /* Set MBOX ownership */ - temp = CMAC_CRIT << MBOX_STAT_ID_SHF; - MBOX_REG(0)->stat = temp; - MBOX_REG(1)->stat = temp; - - temp = CMAC_NON_CRIT << MBOX_STAT_ID_SHF; - MBOX_REG(2)->stat = temp; - MBOX_REG(3)->stat = temp; - - plb2800_set_mac_addr(dev, plb2800_get_mac_addr()); - - /* Disable all Mbox interrupt */ - temp = MIPS_H_MASK; - temp &= ~ (SW_H_MBOX1_MASK | SW_H_MBOX2_MASK | SW_H_MBOX3_MASK | SW_H_MBOX4_MASK) ; - MIPS_H_MASK = temp; - -#ifdef DEBUG - printf("Leaving plb2800_eth_initialize()\n"); -#endif - - return 1; -} - -static int plb2800_eth_init(struct eth_device *dev, bd_t * bis) -{ -#ifdef DEBUG - printf("Entering plb2800_eth_init()\n"); -#endif - - plb2800_set_mac_addr(dev, dev->enetaddr); - - rx_new = 0; - -#ifdef DEBUG - printf("Leaving plb2800_eth_init()\n"); -#endif - - return 0; -} - - -static int plb2800_eth_send(struct eth_device *dev, volatile void *packet, - int length) -{ - int i; - int res = -1; - u32 temp; - mailbox_t * mb = MBOX_REG(0); - char * mem = MBOX_MEM(0); - -#ifdef DEBUG - printf("Entered plb2800_eth_send()\n"); -#endif - - if (length <= 0) - { - printf ("%s: bad packet size: %d\n", dev->name, length); - goto Done; - } - - if (length < 64) - { - length = 64; - } - - temp = CMAC_CRX_CTRL_CG | ((length + 4) << CMAC_CRX_CTRL_PL_SHIFT); - -#ifdef DEBUG - printf("0 mb->stat = 0x%x\n", mb->stat); -#endif - - for(i = 0; mb->stat & (MBOX_STAT_CP | MBOX_STAT_MB); i++) - { - if (i >= TOUT_LOOP) - { - printf("%s: tx buffer not ready\n", dev->name); - printf("1 mb->stat = 0x%x\n", mb->stat); - goto Done; - } - } - - /* For some strange reason, memcpy doesn't work, here! - */ - do - { - int words = (length >> 2) + 1; - unsigned int* dst = (unsigned int*)(mem); - unsigned int* src = (unsigned int*)(packet); - for (i = 0; i < words; i++) - { - *dst = *src; - dst++; - src++; - }; - } while(0); - - CMAC_CRX_CTRL = temp; - mb->cmd = MBOX_STAT_CP; - -#ifdef DEBUG - printf("2 mb->stat = 0x%x\n", mb->stat); -#endif - - res = length; -Done: - -#ifdef DEBUG - printf("Leaving plb2800_eth_send()\n"); -#endif - - return res; -} - - -static int plb2800_eth_recv(struct eth_device *dev) -{ - int length = 0; - mailbox_t * mbox = MBOX_REG(3); - unsigned char * hdr = MBOX_MEM(3); - unsigned int stat; - -#ifdef DEBUG - printf("Entered plb2800_eth_recv()\n"); -#endif - - for (;;) - { - stat = mbox->stat; - - if (!(stat & MBOX_STAT_CP)) - { - break; - } - - length = ((*(hdr + 6) & 0x3f) << 8) + *(hdr + 7); - memcpy((void *)NetRxPackets[rx_new], hdr + 12, length); - - stat &= ~MBOX_STAT_CP; - mbox->stat = stat; -#ifdef DEBUG - { - int i; - for (i=0;i -#include -#include "rtl8019.h" -#include - -#ifdef CONFIG_DRIVER_RTL8019 - -#if defined(CONFIG_CMD_NET) - - -/* packet page register access functions */ - - -static unsigned char get_reg (unsigned int regno) -{ - return (*(unsigned char *) regno); -} - - -static void put_reg (unsigned int regno, unsigned char val) -{ - *(volatile unsigned char *) regno = val; -} - -static void eth_reset (void) -{ - unsigned char ucTemp; - - /* reset NIC */ - ucTemp = get_reg (RTL8019_RESET); - put_reg (RTL8019_RESET, ucTemp); - put_reg (RTL8019_INTERRUPTSTATUS, 0xff); - udelay (2000); /* wait for 2ms */ -} - -void rtl8019_get_enetaddr (uchar * addr) -{ - unsigned char i; - unsigned char temp; - - eth_reset (); - - put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); - put_reg (RTL8019_DATACONFIGURATION, 0x48); - put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); - put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00); - put_reg (RTL8019_REMOTEBYTECOUNT0, 12); - put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); - put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); - printf ("MAC: "); - for (i = 0; i < 6; i++) { - temp = get_reg (RTL8019_DMA_DATA); - *addr++ = temp; - temp = get_reg (RTL8019_DMA_DATA); - printf ("%x:", temp); - } - - while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40)); - printf ("\b \n"); - put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); - put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); - put_reg (RTL8019_COMMAND, RTL8019_PAGE0); -} - - -void eth_halt (void) -{ - put_reg (RTL8019_COMMAND, 0x01); -} - -int eth_init (bd_t * bd) -{ - eth_reset (); - put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); - put_reg (RTL8019_DATACONFIGURATION, 0x48); - put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); - put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); - put_reg (RTL8019_RECEIVECONFIGURATION, 0x00); /*00; */ - put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); - put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02); - put_reg (RTL8019_PAGESTART, RTL8019_PSTART); - put_reg (RTL8019_BOUNDARY, RTL8019_PSTART); - put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP); - put_reg (RTL8019_INTERRUPTSTATUS, 0xff); - put_reg (RTL8019_INTERRUPTMASK, 0x11); /*b; */ - put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP); - put_reg (RTL8019_PHYSICALADDRESS0, bd->bi_enetaddr[0]); - put_reg (RTL8019_PHYSICALADDRESS1, bd->bi_enetaddr[1]); - put_reg (RTL8019_PHYSICALADDRESS2, bd->bi_enetaddr[2]); - put_reg (RTL8019_PHYSICALADDRESS3, bd->bi_enetaddr[3]); - put_reg (RTL8019_PHYSICALADDRESS4, bd->bi_enetaddr[4]); - put_reg (RTL8019_PHYSICALADDRESS5, bd->bi_enetaddr[5]); - put_reg (RTL8019_MULTIADDRESS0, 0x00); - put_reg (RTL8019_MULTIADDRESS1, 0x00); - put_reg (RTL8019_MULTIADDRESS2, 0x00); - put_reg (RTL8019_MULTIADDRESS3, 0x00); - put_reg (RTL8019_MULTIADDRESS4, 0x00); - put_reg (RTL8019_MULTIADDRESS5, 0x00); - put_reg (RTL8019_MULTIADDRESS6, 0x00); - put_reg (RTL8019_MULTIADDRESS7, 0x00); - put_reg (RTL8019_CURRENT, RTL8019_PSTART); - put_reg (RTL8019_COMMAND, RTL8019_PAGE0); - put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); /*58; */ - - return 0; -} - - -static unsigned char nic_to_pc (void) -{ - unsigned char rec_head_status; - unsigned char next_packet_pointer; - unsigned char packet_length0; - unsigned char packet_length1; - unsigned short rxlen = 0; - unsigned int i = 4; - unsigned char current_point; - unsigned char *addr; - - /* - * The RTL8019's first 4B is packet status,page of next packet - * and packet length(2B).So we receive the fist 4B. - */ - put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); - put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); - put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); - put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04); - - put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); - - rec_head_status = get_reg (RTL8019_DMA_DATA); - next_packet_pointer = get_reg (RTL8019_DMA_DATA); - packet_length0 = get_reg (RTL8019_DMA_DATA); - packet_length1 = get_reg (RTL8019_DMA_DATA); - - put_reg (RTL8019_COMMAND, RTL8019_PAGE0); - /*Packet length is in two 8bit registers */ - rxlen = packet_length1; - rxlen = (((rxlen << 8) & 0xff00) + packet_length0); - rxlen -= 4; - - if (rxlen > PKTSIZE_ALIGN + PKTALIGN) - printf ("packet too big!\n"); - - /*Receive the packet */ - put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04); - put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); - - put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff)); - put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff)); - - - put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); - - for (addr = (unsigned char *) NetRxPackets[0], i = rxlen; i > 0; i--) - *addr++ = get_reg (RTL8019_DMA_DATA); - /* Pass the packet up to the protocol layers. */ - NetReceive (NetRxPackets[0], rxlen); - - while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); /* wait for the op. */ - - /* - * To test whether the packets are all received,get the - * location of current point - */ - put_reg (RTL8019_COMMAND, RTL8019_PAGE1); - current_point = get_reg (RTL8019_CURRENT); - put_reg (RTL8019_COMMAND, RTL8019_PAGE0); - put_reg (RTL8019_BOUNDARY, next_packet_pointer); - return current_point; -} - -/* Get a data block via Ethernet */ -extern int eth_rx (void) -{ - unsigned char temp, current_point; - - put_reg (RTL8019_COMMAND, RTL8019_PAGE0); - - while (1) { - temp = get_reg (RTL8019_INTERRUPTSTATUS); - - if (temp & 0x90) { - /*overflow */ - put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); - udelay (2000); - put_reg (RTL8019_REMOTEBYTECOUNT0, 0); - put_reg (RTL8019_REMOTEBYTECOUNT1, 0); - put_reg (RTL8019_TRANSMITCONFIGURATION, 2); - do { - current_point = nic_to_pc (); - } while (get_reg (RTL8019_BOUNDARY) != current_point); - - put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); - } - - if (temp & 0x1) { - /*packet received */ - do { - put_reg (RTL8019_INTERRUPTSTATUS, 0x01); - current_point = nic_to_pc (); - } while (get_reg (RTL8019_BOUNDARY) != current_point); - } - - if (!(temp & 0x1)) - return 0; - /* done and exit. */ - } -} - -/* Send a data block via Ethernet. */ -extern int eth_send (volatile void *packet, int length) -{ - volatile unsigned char *p; - unsigned int pn; - - pn = length; - p = (volatile unsigned char *) packet; - - while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT); - - put_reg (RTL8019_REMOTESTARTADDRESS0, 0); - put_reg (RTL8019_REMOTESTARTADDRESS1, RTL8019_TPSTART); - put_reg (RTL8019_REMOTEBYTECOUNT0, (pn & 0xff)); - put_reg (RTL8019_REMOTEBYTECOUNT1, ((pn >> 8) & 0xff)); - - put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR); - while (pn > 0) { - put_reg (RTL8019_DMA_DATA, *p++); - pn--; - } - - pn = length; - - while (pn < 60) { /*Padding */ - put_reg (RTL8019_DMA_DATA, 0); - pn++; - } - - while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); - - put_reg (RTL8019_INTERRUPTSTATUS, 0x40); - put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); - put_reg (RTL8019_TRANSMITBYTECOUNT0, (pn & 0xff)); - put_reg (RTL8019_TRANSMITBYTECOUNT1, ((pn >> 8 & 0xff))); - put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT); - - return 0; -} - -#endif /* COMMANDS & CFG_NET */ - -#endif /* CONFIG_DRIVER_RTL8019 */ diff --git a/drivers/rtl8019.h b/drivers/rtl8019.h deleted file mode 100644 index 38116ad845..0000000000 --- a/drivers/rtl8019.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Realtek 8019AS Ethernet - * (C) Copyright 2002-2003 - * Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* - * This code works in 8bit mode. - * If you need to work in 16bit mode, PLS change it! - */ - -#include -#include - - -#ifdef CONFIG_DRIVER_RTL8019 - -#define RTL8019_REG_00 (RTL8019_BASE + 0x00) -#define RTL8019_REG_01 (RTL8019_BASE + 0x01) -#define RTL8019_REG_02 (RTL8019_BASE + 0x02) -#define RTL8019_REG_03 (RTL8019_BASE + 0x03) -#define RTL8019_REG_04 (RTL8019_BASE + 0x04) -#define RTL8019_REG_05 (RTL8019_BASE + 0x05) -#define RTL8019_REG_06 (RTL8019_BASE + 0x06) -#define RTL8019_REG_07 (RTL8019_BASE + 0x07) -#define RTL8019_REG_08 (RTL8019_BASE + 0x08) -#define RTL8019_REG_09 (RTL8019_BASE + 0x09) -#define RTL8019_REG_0a (RTL8019_BASE + 0x0a) -#define RTL8019_REG_0b (RTL8019_BASE + 0x0b) -#define RTL8019_REG_0c (RTL8019_BASE + 0x0c) -#define RTL8019_REG_0d (RTL8019_BASE + 0x0d) -#define RTL8019_REG_0e (RTL8019_BASE + 0x0e) -#define RTL8019_REG_0f (RTL8019_BASE + 0x0f) -#define RTL8019_REG_10 (RTL8019_BASE + 0x10) -#define RTL8019_REG_1f (RTL8019_BASE + 0x1f) - -#define RTL8019_COMMAND RTL8019_REG_00 -#define RTL8019_PAGESTART RTL8019_REG_01 -#define RTL8019_PAGESTOP RTL8019_REG_02 -#define RTL8019_BOUNDARY RTL8019_REG_03 -#define RTL8019_TRANSMITSTATUS RTL8019_REG_04 -#define RTL8019_TRANSMITPAGE RTL8019_REG_04 -#define RTL8019_TRANSMITBYTECOUNT0 RTL8019_REG_05 -#define RTL8019_NCR RTL8019_REG_05 -#define RTL8019_TRANSMITBYTECOUNT1 RTL8019_REG_06 -#define RTL8019_INTERRUPTSTATUS RTL8019_REG_07 -#define RTL8019_CURRENT RTL8019_REG_07 -#define RTL8019_REMOTESTARTADDRESS0 RTL8019_REG_08 -#define RTL8019_CRDMA0 RTL8019_REG_08 -#define RTL8019_REMOTESTARTADDRESS1 RTL8019_REG_09 -#define RTL8019_CRDMA1 RTL8019_REG_09 -#define RTL8019_REMOTEBYTECOUNT0 RTL8019_REG_0a -#define RTL8019_REMOTEBYTECOUNT1 RTL8019_REG_0b -#define RTL8019_RECEIVESTATUS RTL8019_REG_0c -#define RTL8019_RECEIVECONFIGURATION RTL8019_REG_0c -#define RTL8019_TRANSMITCONFIGURATION RTL8019_REG_0d -#define RTL8019_FAE_TALLY RTL8019_REG_0d -#define RTL8019_DATACONFIGURATION RTL8019_REG_0e -#define RTL8019_CRC_TALLY RTL8019_REG_0e -#define RTL8019_INTERRUPTMASK RTL8019_REG_0f -#define RTL8019_MISS_PKT_TALLY RTL8019_REG_0f -#define RTL8019_PHYSICALADDRESS0 RTL8019_REG_01 -#define RTL8019_PHYSICALADDRESS1 RTL8019_REG_02 -#define RTL8019_PHYSICALADDRESS2 RTL8019_REG_03 -#define RTL8019_PHYSICALADDRESS3 RTL8019_REG_04 -#define RTL8019_PHYSICALADDRESS4 RTL8019_REG_05 -#define RTL8019_PHYSICALADDRESS5 RTL8019_REG_06 -#define RTL8019_MULTIADDRESS0 RTL8019_REG_08 -#define RTL8019_MULTIADDRESS1 RTL8019_REG_09 -#define RTL8019_MULTIADDRESS2 RTL8019_REG_0a -#define RTL8019_MULTIADDRESS3 RTL8019_REG_0b -#define RTL8019_MULTIADDRESS4 RTL8019_REG_0c -#define RTL8019_MULTIADDRESS5 RTL8019_REG_0d -#define RTL8019_MULTIADDRESS6 RTL8019_REG_0e -#define RTL8019_MULTIADDRESS7 RTL8019_REG_0f -#define RTL8019_DMA_DATA RTL8019_REG_10 -#define RTL8019_RESET RTL8019_REG_1f - - -#define RTL8019_PAGE0 0x22 -#define RTL8019_PAGE1 0x62 -#define RTL8019_PAGE0DMAWRITE 0x12 -#define RTL8019_PAGE2DMAWRITE 0x92 -#define RTL8019_REMOTEDMAWR 0x12 -#define RTL8019_REMOTEDMARD 0x0A -#define RTL8019_ABORTDMAWR 0x32 -#define RTL8019_ABORTDMARD 0x2A -#define RTL8019_PAGE0STOP 0x21 -#define RTL8019_PAGE1STOP 0x61 -#define RTL8019_TRANSMIT 0x26 -#define RTL8019_TXINPROGRESS 0x04 -#define RTL8019_SEND 0x1A - -#define RTL8019_PSTART 0x4c -#define RTL8019_PSTOP 0x80 -#define RTL8019_TPSTART 0x40 - - -#endif /*end of CONFIG_DRIVER_RTL8019*/ diff --git a/drivers/rtl8139.c b/drivers/rtl8139.c deleted file mode 100644 index 2367180057..0000000000 --- a/drivers/rtl8139.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * rtl8139.c : U-Boot driver for the RealTek RTL8139 - * - * Masami Komiya (mkomiya@sonare.it) - * - * Most part is taken from rtl8139.c of etherboot - * - */ - -/* rtl8139.c - etherboot driver for the Realtek 8139 chipset - - ported from the linux driver written by Donald Becker - by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - changes to the original driver: - - removed support for interrupts, switching to polling mode (yuck!) - - removed support for the 8129 chip (external MII) - -*/ - -/*********************************************************************/ -/* Revision History */ -/*********************************************************************/ - -/* - 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap) - Put in virt_to_bus calls to allow Etherboot relocation. - - 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap) - Following email from Hyun-Joon Cha, added a disable routine, otherwise - NIC remains live and can crash the kernel later. - - 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub) - Shuffled things around, removed the leftovers from the 8129 support - that was in the Linux driver and added a bit more 8139 definitions. - Moved the 8K receive buffer to a fixed, available address outside the - 0x98000-0x9ffff range. This is a bit of a hack, but currently the only - way to make room for the Etherboot features that need substantial amounts - of code like the ANSI console support. Currently the buffer is just below - 0x10000, so this even conforms to the tagged boot image specification, - which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My - interpretation of this "reserved" is that Etherboot may do whatever it - likes, as long as its environment is kept intact (like the BIOS - variables). Hopefully fixed rtl_poll() once and for all. The symptoms - were that if Etherboot was left at the boot menu for several minutes, the - first eth_poll failed. Seems like I am the only person who does this. - First of all I fixed the debugging code and then set out for a long bug - hunting session. It took me about a week full time work - poking around - various places in the driver, reading Don Becker's and Jeff Garzik's Linux - driver and even the FreeBSD driver (what a piece of crap!) - and - eventually spotted the nasty thing: the transmit routine was acknowledging - each and every interrupt pending, including the RxOverrun and RxFIFIOver - interrupts. This confused the RTL8139 thoroughly. It destroyed the - Rx ring contents by dumping the 2K FIFO contents right where we wanted to - get the next packet. Oh well, what fun. - - 18 Jan 2000 mdc@thinguin.org (Marty Connor) - Drastically simplified error handling. Basically, if any error - in transmission or reception occurs, the card is reset. - Also, pointed all transmit descriptors to the same buffer to - save buffer space. This should decrease driver size and avoid - corruption because of exceeding 32K during runtime. - - 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) - rtl_poll was quite broken: it used the RxOK interrupt flag instead - of the RxBufferEmpty flag which often resulted in very bad - transmission performace - below 1kBytes/s. - -*/ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_RTL8139) - -#define TICKS_PER_SEC CFG_HZ -#define TICKS_PER_MS (TICKS_PER_SEC/1000) - -#define RTL_TIMEOUT (1*TICKS_PER_SEC) - -#define ETH_FRAME_LEN 1514 -#define ETH_ALEN 6 -#define ETH_ZLEN 60 - -/* PCI Tuning Parameters - Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ -#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ -#define TX_DMA_BURST 4 /* Calculate as 16<priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) - -/* Symbolic offsets to registers. */ -enum RTL8139_registers { - MAC0=0, /* Ethernet hardware address. */ - MAR0=8, /* Multicast filter. */ - TxStatus0=0x10, /* Transmit status (four 32bit registers). */ - TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ - RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, - ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, - IntrMask=0x3C, IntrStatus=0x3E, - TxConfig=0x40, RxConfig=0x44, - Timer=0x48, /* general-purpose counter. */ - RxMissed=0x4C, /* 24 bits valid, write clears. */ - Cfg9346=0x50, Config0=0x51, Config1=0x52, - TimerIntrReg=0x54, /* intr if gp counter reaches this value */ - MediaStatus=0x58, - Config3=0x59, - MultiIntr=0x5C, - RevisionID=0x5E, /* revision of the RTL8139 chip */ - TxSummary=0x60, - MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, - NWayExpansion=0x6A, - DisconnectCnt=0x6C, FalseCarrierCnt=0x6E, - NWayTestReg=0x70, - RxCnt=0x72, /* packet received counter */ - CSCR=0x74, /* chip status and configuration register */ - PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80, /* undocumented */ - /* from 0x84 onwards are a number of power management/wakeup frame - * definitions we will probably never need to know about. */ -}; - -enum ChipCmdBits { - CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, }; - -/* Interrupt register bits, using my own meaningful names. */ -enum IntrStatusBits { - PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000, - RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10, - TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01, -}; -enum TxStatusBits { - TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000, - TxOutOfWindow=0x20000000, TxAborted=0x40000000, - TxCarrierLost=0x80000000, -}; -enum RxStatusBits { - RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000, - RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004, - RxBadAlign=0x0002, RxStatusOK=0x0001, -}; - -enum MediaStatusBits { - MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08, - MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01, -}; - -enum MIIBMCRBits { - BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000, - BMCRRestartNWay=0x0200, BMCRDuplex=0x0100, -}; - -enum CSCRBits { - CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, - CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, - CSCR_LinkDownCmd=0x0f3c0, -}; - -/* Bits in RxConfig. */ -enum rx_mode_bits { - RxCfgWrap=0x80, - AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, - AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, -}; - -static int ioaddr; -static unsigned int cur_rx,cur_tx; - -/* The RTL8139 can only transmit from a contiguous, aligned memory block. */ -static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); -static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); - -static int rtl8139_probe(struct eth_device *dev, bd_t *bis); -static int read_eeprom(int location, int addr_len); -static void rtl_reset(struct eth_device *dev); -static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length); -static int rtl_poll(struct eth_device *dev); -static void rtl_disable(struct eth_device *dev); -#ifdef CONFIG_MCAST_TFTP/* This driver already accepts all b/mcast */ -static int rtl_bcast_addr (struct eth_device *dev, u8 bcast_mac, u8 set) -{ - return (0); -} -#endif - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139}, - {PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139}, - {} -}; - -int rtl8139_initialize(bd_t *bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase; - int idx=0; - - while(1){ - /* Find RTL8139 */ - if ((devno = pci_find_devices(supported, idx++)) < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); - iobase &= ~0xf; - - debug ("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - - dev = (struct eth_device *)malloc(sizeof *dev); - - sprintf (dev->name, "RTL8139#%d", card_number); - - dev->priv = (void *) devno; - dev->iobase = (int)bus_to_phys(iobase); - dev->init = rtl8139_probe; - dev->halt = rtl_disable; - dev->send = rtl_transmit; - dev->recv = rtl_poll; -#ifdef CONFIG_MCAST_TFTP - dev->mcast = rtl_bcast_addr; -#endif - - eth_register (dev); - - card_number++; - - pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); - - udelay (10 * 1000); - } - - return card_number; -} - -static int rtl8139_probe(struct eth_device *dev, bd_t *bis) -{ - int i; - int speed10, fullduplex; - int addr_len; - unsigned short *ap = (unsigned short *)dev->enetaddr; - - ioaddr = dev->iobase; - - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + Config1); - - addr_len = read_eeprom(0,8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu (read_eeprom(i + 7, addr_len)); - - speed10 = inb(ioaddr + MediaStatus) & MSRSpeed10; - fullduplex = inw(ioaddr + MII_BMCR) & BMCRDuplex; - - rtl_reset(dev); - - if (inb(ioaddr + MediaStatus) & MSRLinkFail) { - printf("Cable not connected or other link failure\n"); - return(0); - } - - return 1; -} - -/* Serial EEPROM section. */ - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 -#define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) - -/* - Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. -*/ - -#define eeprom_delay() inl(ee_addr) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) -#define EE_ERASE_CMD (7) - -static int read_eeprom(int location, int addr_len) -{ - int i; - unsigned int retval = 0; - long ee_addr = ioaddr + Cfg9346; - int read_cmd = location | (EE_READ_CMD << addr_len); - - outb(EE_ENB & ~EE_CS, ee_addr); - outb(EE_ENB, ee_addr); - eeprom_delay(); - - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outb(EE_ENB | dataval, ee_addr); - eeprom_delay(); - outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - } - outb(EE_ENB, ee_addr); - eeprom_delay(); - - for (i = 16; i > 0; i--) { - outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); - outb(EE_ENB, ee_addr); - eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - outb(~EE_CS, ee_addr); - eeprom_delay(); - return retval; -} - -static const unsigned int rtl8139_rx_config = - (RX_BUF_LEN_IDX << 11) | - (RX_FIFO_THRESH << 13) | - (RX_DMA_BURST << 8); - -static void set_rx_mode(struct eth_device *dev) { - unsigned int mc_filter[2]; - int rx_mode; - /* !IFF_PROMISC */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - - outl(rtl8139_rx_config | rx_mode, ioaddr + RxConfig); - - outl(mc_filter[0], ioaddr + MAR0 + 0); - outl(mc_filter[1], ioaddr + MAR0 + 4); -} - -static void rtl_reset(struct eth_device *dev) -{ - int i; - - outb(CmdReset, ioaddr + ChipCmd); - - cur_rx = 0; - cur_tx = 0; - - /* Give the chip 10ms to finish the reset. */ - for (i=0; i<100; ++i){ - if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; - udelay (100); /* wait 100us */ - } - - - for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], ioaddr + MAC0 + i); - - /* Must enable Tx/Rx before setting transfer thresholds! */ - outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); - outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8), - ioaddr + RxConfig); /* accept no frames yet! */ - outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); - - /* The Linux driver changes Config1 here to use a different LED pattern - * for half duplex or full/autodetect duplex (for full/autodetect, the - * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses - * TX/RX, Link100, Link10). This is messy, because it doesn't match - * the inscription on the mounting bracket. It should not be changed - * from the configuration EEPROM default, because the card manufacturer - * should have set that to match the card. */ - -#ifdef DEBUG_RX - printf("rx ring address is %X\n",(unsigned long)rx_ring); -#endif - outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf); - - /* If we add multicast support, the MAR0 register would have to be - * initialized to 0xffffffffffffffff (two 32 bit accesses). Etherboot - * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast. */ - - outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); - - outl(rtl8139_rx_config, ioaddr + RxConfig); - - /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + RxMissed); - - /* set_rx_mode */ - set_rx_mode(dev); - - /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, ioaddr + IntrMask); -} - -static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length) -{ - unsigned int status, to; - unsigned long txstatus; - unsigned int len = length; - - ioaddr = dev->iobase; - - memcpy((char *)tx_buffer, (char *)packet, (int)length); - -#ifdef DEBUG_TX - printf("sending %d bytes\n", len); -#endif - - /* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 - * bytes are sent automatically for the FCS, totalling to 64 bytes). */ - while (len < ETH_ZLEN) { - tx_buffer[len++] = '\0'; - } - - outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); - outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, - ioaddr + TxStatus0 + cur_tx*4); - - to = currticks() + RTL_TIMEOUT; - - do { - status = inw(ioaddr + IntrStatus); - /* Only acknlowledge interrupt sources we can properly handle - * here - the RxOverflow/RxFIFOOver MUST be handled in the - * rtl_poll() function. */ - outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); - if ((status & (TxOK | TxErr | PCIErr)) != 0) break; - } while (currticks() < to); - - txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); - - if (status & TxOK) { - cur_tx = (cur_tx + 1) % NUM_TX_DESC; -#ifdef DEBUG_TX - printf("tx done (%d ticks), status %hX txstatus %X\n", - to-currticks(), status, txstatus); -#endif - return length; - } else { -#ifdef DEBUG_TX - printf("tx timeout/error (%d ticks), status %hX txstatus %X\n", - currticks()-to, status, txstatus); -#endif - rtl_reset(dev); - - return 0; - } -} - -static int rtl_poll(struct eth_device *dev) -{ - unsigned int status; - unsigned int ring_offs; - unsigned int rx_size, rx_status; - int length=0; - - ioaddr = dev->iobase; - - if (inb(ioaddr + ChipCmd) & RxBufEmpty) { - return 0; - } - - status = inw(ioaddr + IntrStatus); - /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); - -#ifdef DEBUG_RX - printf("rtl_poll: int %hX ", status); -#endif - - ring_offs = cur_rx % RX_BUF_LEN; - rx_status = *(unsigned int*)KSEG1ADDR((rx_ring + ring_offs)); - rx_size = rx_status >> 16; - rx_status &= 0xffff; - - if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) || - (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { - printf("rx error %hX\n", rx_status); - rtl_reset(dev); /* this clears all interrupts still pending */ - return 0; - } - - /* Received a good packet */ - length = rx_size - 4; /* no one cares about the FCS */ - if (ring_offs+4+rx_size-4 > RX_BUF_LEN) { - int semi_count = RX_BUF_LEN - ring_offs - 4; - unsigned char rxdata[RX_BUF_LEN]; - - memcpy(rxdata, rx_ring + ring_offs + 4, semi_count); - memcpy(&(rxdata[semi_count]), rx_ring, rx_size-4-semi_count); - - NetReceive(rxdata, length); -#ifdef DEBUG_RX - printf("rx packet %d+%d bytes", semi_count,rx_size-4-semi_count); -#endif - } else { - NetReceive(rx_ring + ring_offs + 4, length); -#ifdef DEBUG_RX - printf("rx packet %d bytes", rx_size-4); -#endif - } - - cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - outw(cur_rx - 16, ioaddr + RxBufPtr); - /* See RTL8139 Programming Guide V0.1 for the official handling of - * Rx overflow situations. The document itself contains basically no - * usable information, except for a few exception handling rules. */ - outw(status & (RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus); - return length; -} - -static void rtl_disable(struct eth_device *dev) -{ - int i; - - ioaddr = dev->iobase; - - /* reset the chip */ - outb(CmdReset, ioaddr + ChipCmd); - - /* Give the chip 10ms to finish the reset. */ - for (i=0; i<100; ++i){ - if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; - udelay (100); /* wait 100us */ - } -} -#endif diff --git a/drivers/rtl8169.c b/drivers/rtl8169.c deleted file mode 100644 index 63ea2cca9b..0000000000 --- a/drivers/rtl8169.c +++ /dev/null @@ -1,888 +0,0 @@ -/* - * rtl8169.c : U-Boot driver for the RealTek RTL8169 - * - * Masami Komiya (mkomiya@sonare.it) - * - * Most part is taken from r8169.c of etherboot - * - */ - -/************************************************************************** -* r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit -* Written 2003 by Timothy Legge -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* Portions of this code based on: -* r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver -* for Linux kernel 2.4.x. -* -* Written 2002 ShuChen -* See Linux Driver for full information -* -* Linux Driver Version 1.27a, 10.02.2002 -* -* Thanks to: -* Jean Chen of RealTek Semiconductor Corp. for -* providing the evaluation NIC used to develop -* this driver. RealTek's support for Etherboot -* is appreciated. -* -* REVISION HISTORY: -* ================ -* -* v1.0 11-26-2003 timlegge Initial port of Linux driver -* v1.5 01-17-2004 timlegge Initial driver output cleanup -* -* Indent Options: indent -kr -i8 -***************************************************************************/ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_RTL8169) - -#undef DEBUG_RTL8169 -#undef DEBUG_RTL8169_TX -#undef DEBUG_RTL8169_RX - -#define drv_version "v1.5" -#define drv_date "01-17-2004" - -static u32 ioaddr; - -/* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - -#define currticks() get_timer(0) -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) - -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* MAC address length*/ -#define MAC_ADDR_LEN 6 - -/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -#define TX_FIFO_THRESH 256 /* In bytes */ - -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define NUM_TX_DESC 1 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 4 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define RX_BUF_LEN 8192 - -#define RTL_MIN_IO_SIZE 0x80 -#define TX_TIMEOUT (6*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE -#define ETH_ALEN MAC_ADDR_LEN -#define ETH_ZLEN 60 - -enum RTL8169_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - TxDescStartAddr = 0x20, - TxHDescStartAddr = 0x28, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4C, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5C, - PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6A, - PHYstatus = 0x6C, - RxMaxSize = 0xDA, - CPlusCmd = 0xE0, - RxDescStartAddr = 0xE4, - EarlyTxThres = 0xEC, - FuncEvent = 0xF0, - FuncEventMask = 0xF4, - FuncPresetState = 0xF8, - FuncForceEvent = 0xFC, -}; - -enum RTL8169_register_content { - /*InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x80, - RxFIFOOver = 0x40, - RxUnderrun = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, - - /*RxStatusDesc */ - RxRES = 0x00200000, - RxCRC = 0x00080000, - RxRUNT = 0x00100000, - RxRWT = 0x00400000, - - /*ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /*Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - - /*rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /*RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /*TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /*rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /*GIGABIT_PHY_registers */ - PHY_CTRL_REG = 0, - PHY_STAT_REG = 1, - PHY_AUTO_NEGO_REG = 4, - PHY_1000_CTRL_REG = 9, - - /*GIGABIT_PHY_REG_BIT */ - PHY_Restart_Auto_Nego = 0x0200, - PHY_Enable_Auto_Nego = 0x1000, - - /* PHY_STAT_REG = 1; */ - PHY_Auto_Neco_Comp = 0x0020, - - /* PHY_AUTO_NEGO_REG = 4; */ - PHY_Cap_10_Half = 0x0020, - PHY_Cap_10_Full = 0x0040, - PHY_Cap_100_Half = 0x0080, - PHY_Cap_100_Full = 0x0100, - - /* PHY_1000_CTRL_REG = 9; */ - PHY_Cap_1000_Full = 0x0200, - - PHY_Cap_Null = 0x0, - - /*_MediaType*/ - _10_Half = 0x01, - _10_Full = 0x02, - _100_Half = 0x04, - _100_Full = 0x08, - _1000_Full = 0x10, - - /*_TBICSRBit*/ - TBILinkOK = 0x02000000, -}; - -static struct { - const char *name; - u8 version; /* depend on RTL8169 docs */ - u32 RxConfigMask; /* should clear the bits supported by this chip */ -} rtl_chip_info[] = { - {"RTL-8169", 0x00, 0xff7e1880,}, - {"RTL-8169", 0x04, 0xff7e1880,}, -}; - -enum _DescStatusBit { - OWNbit = 0x80000000, - EORbit = 0x40000000, - FSbit = 0x20000000, - LSbit = 0x10000000, -}; - -struct TxDesc { - u32 status; - u32 vlan_tag; - u32 buf_addr; - u32 buf_Haddr; -}; - -struct RxDesc { - u32 status; - u32 vlan_tag; - u32 buf_addr; - u32 buf_Haddr; -}; - -/* Define the TX Descriptor */ -static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256]; -/* __attribute__ ((aligned(256))); */ - -/* Create a static buffer of size RX_BUF_SZ for each -TX Descriptor. All descriptors point to a -part of this buffer */ -static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE]; - -/* Define the RX Descriptor */ -static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256]; - /* __attribute__ ((aligned(256))); */ - -/* Create a static buffer of size RX_BUF_SZ for each -RX Descriptor All descriptors point to a -part of this buffer */ -static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; - -struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ - int chipset; - unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - unsigned long dirty_tx; - unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */ - unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */ - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ - unsigned char *RxBufferRings; /* Index of Rx Buffer */ - unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */ - unsigned char *Tx_skbuff[NUM_TX_DESC]; -} tpx; - -static struct rtl8169_private *tpc; - -static const u16 rtl8169_intr_mask = - SYSErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | - TxOK | RxErr | RxOK; -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_REALTEK, 0x8169}, - {} -}; - -void mdio_write(int RegAddr, int value) -{ - int i; - - RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); - udelay(1000); - - for (i = 2000; i > 0; i--) { - /* Check if the RTL8169 has completed writing to the specified MII register */ - if (!(RTL_R32(PHYAR) & 0x80000000)) { - break; - } else { - udelay(100); - } - } -} - -int mdio_read(int RegAddr) -{ - int i, value = -1; - - RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); - udelay(1000); - - for (i = 2000; i > 0; i--) { - /* Check if the RTL8169 has completed retrieving data from the specified MII register */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = (int) (RTL_R32(PHYAR) & 0xFFFF); - break; - } else { - udelay(100); - } - } - return value; -} - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -static int rtl8169_init_board(struct eth_device *dev) -{ - int i; - u32 tmp; - -#ifdef DEBUG_RTL8169 - printf ("%s\n", __FUNCTION__); -#endif - ioaddr = dev->iobase; - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - else - udelay(10); - - /* identify chip attached to board */ - tmp = RTL_R32(TxConfig); - tmp = ((tmp & 0x7c000000) + ((tmp & 0x00800000) << 2)) >> 24; - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--){ - if (tmp == rtl_chip_info[i].version) { - tpc->chipset = i; - goto match; - } - } - - /* if unknown chip, assume array element #0, original RTL-8169 in this case */ - printf("PCI device %s: unknown chip version, assuming RTL-8169\n", dev->name); - printf("PCI device: TxConfig = 0x%hX\n", (unsigned long) RTL_R32(TxConfig)); - tpc->chipset = 0; - -match: - return 0; -} - -/************************************************************************** -RECV - Receive a frame -***************************************************************************/ -static int rtl_recv(struct eth_device *dev) -{ - /* return true if there's an ethernet packet ready to read */ - /* nic->packet should contain data on return */ - /* nic->packetlen should contain length of data */ - int cur_rx; - int length = 0; - -#ifdef DEBUG_RTL8169_RX - printf ("%s\n", __FUNCTION__); -#endif - ioaddr = dev->iobase; - - cur_rx = tpc->cur_rx; - if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) { - if (!(tpc->RxDescArray[cur_rx].status & RxRES)) { - unsigned char rxdata[RX_BUF_LEN]; - length = (int) (tpc->RxDescArray[cur_rx]. - status & 0x00001FFF) - 4; - - memcpy(rxdata, tpc->RxBufferRing[cur_rx], length); - NetReceive(rxdata, length); - - if (cur_rx == NUM_RX_DESC - 1) - tpc->RxDescArray[cur_rx].status = - (OWNbit | EORbit) + RX_BUF_SIZE; - else - tpc->RxDescArray[cur_rx].status = - OWNbit + RX_BUF_SIZE; - tpc->RxDescArray[cur_rx].buf_addr = - virt_to_bus(tpc->RxBufferRing[cur_rx]); - } else { - puts("Error Rx"); - } - cur_rx = (cur_rx + 1) % NUM_RX_DESC; - tpc->cur_rx = cur_rx; - return 1; - - } - tpc->cur_rx = cur_rx; - return (0); /* initially as this is called to flush the input */ -} - -#define HZ 1000 -/************************************************************************** -SEND - Transmit a frame -***************************************************************************/ -static int rtl_send(struct eth_device *dev, volatile void *packet, int length) -{ - /* send the packet to destination */ - - u32 to; - u8 *ptxb; - int entry = tpc->cur_tx % NUM_TX_DESC; - u32 len = length; - -#ifdef DEBUG_RTL8169_TX - int stime = currticks(); - printf ("%s\n", __FUNCTION__); - printf("sending %d bytes\n", len); -#endif - - ioaddr = dev->iobase; - - /* point to the current txb incase multiple tx_rings are used */ - ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; - memcpy(ptxb, (char *)packet, (int)length); - - while (len < ETH_ZLEN) - ptxb[len++] = '\0'; - - tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb); - if (entry != (NUM_TX_DESC - 1)) { - tpc->TxDescArray[entry].status = - (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ? - len : ETH_ZLEN); - } else { - tpc->TxDescArray[entry].status = - (OWNbit | EORbit | FSbit | LSbit) | - ((len > ETH_ZLEN) ? length : ETH_ZLEN); - } - RTL_W8(TxPoll, 0x40); /* set polling bit */ - - tpc->cur_tx++; - to = currticks() + TX_TIMEOUT; - while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ - - if (currticks() >= to) { -#ifdef DEBUG_RTL8169_TX - puts ("tx timeout/error\n"); - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); -#endif - return 0; - } else { -#ifdef DEBUG_RTL8169_TX - puts("tx done\n"); -#endif - return length; - } -} - -static void rtl8169_set_rx_mode(struct eth_device *dev) -{ - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - -#ifdef DEBUG_RTL8169 - printf ("%s\n", __FUNCTION__); -#endif - - /* IFF_ALLMULTI */ - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - - tmp = rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tpc->chipset].RxConfigMask); - - RTL_W32(RxConfig, tmp); - RTL_W32(MAR0 + 0, mc_filter[0]); - RTL_W32(MAR0 + 4, mc_filter[1]); -} - -static void rtl8169_hw_start(struct eth_device *dev) -{ - u32 i; - -#ifdef DEBUG_RTL8169 - int stime = currticks(); - printf ("%s\n", __FUNCTION__); -#endif - -#if 0 - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 1000; i > 0; i--) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - else - udelay(10); - } -#endif - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - RTL_W8(EarlyTxThres, EarlyTxThld); - - /* For gigabit rtl8169 */ - RTL_W16(RxMaxSize, RxPacketMaxSize); - - /* Set Rx Config register */ - i = rtl8169_rx_config | (RTL_R32(RxConfig) & - rtl_chip_info[tpc->chipset].RxConfigMask); - RTL_W32(RxConfig, i); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - - tpc->cur_rx = 0; - - RTL_W32(TxDescStartAddr, virt_to_le32desc(tpc->TxDescArray)); - RTL_W32(RxDescStartAddr, virt_to_le32desc(tpc->RxDescArray)); - RTL_W8(Cfg9346, Cfg9346_Lock); - udelay(10); - - RTL_W32(RxMissed, 0); - - rtl8169_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - -#ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); -#endif -} - -static void rtl8169_init_ring(struct eth_device *dev) -{ - int i; - -#ifdef DEBUG_RTL8169 - int stime = currticks(); - printf ("%s\n", __FUNCTION__); -#endif - - tpc->cur_rx = 0; - tpc->cur_tx = 0; - tpc->dirty_tx = 0; - memset(tpc->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); - memset(tpc->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); - - for (i = 0; i < NUM_TX_DESC; i++) { - tpc->Tx_skbuff[i] = &txb[i]; - } - - for (i = 0; i < NUM_RX_DESC; i++) { - if (i == (NUM_RX_DESC - 1)) - tpc->RxDescArray[i].status = - (OWNbit | EORbit) + RX_BUF_SIZE; - else - tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE; - - tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; - tpc->RxDescArray[i].buf_addr = - virt_to_bus(tpc->RxBufferRing[i]); - } - -#ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); -#endif -} - -/************************************************************************** -RESET - Finish setting up the ethernet interface -***************************************************************************/ -static void rtl_reset(struct eth_device *dev, bd_t *bis) -{ - int i; - u8 diff; - u32 TxPhyAddr, RxPhyAddr; - -#ifdef DEBUG_RTL8169 - int stime = currticks(); - printf ("%s\n", __FUNCTION__); -#endif - - tpc->TxDescArrays = tx_ring; - if (tpc->TxDescArrays == 0) - puts("Allot Error"); - /* Tx Desscriptor needs 256 bytes alignment; */ - TxPhyAddr = virt_to_bus(tpc->TxDescArrays); - diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); - TxPhyAddr += diff; - tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff); - - tpc->RxDescArrays = rx_ring; - /* Rx Desscriptor needs 256 bytes alignment; */ - RxPhyAddr = virt_to_bus(tpc->RxDescArrays); - diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); - RxPhyAddr += diff; - tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff); - - if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) { - puts("Allocate RxDescArray or TxDescArray failed\n"); - return; - } - - rtl8169_init_ring(dev); - rtl8169_hw_start(dev); - /* Construct a perfect filter frame with the mac address as first match - * and broadcast for all others */ - for (i = 0; i < 192; i++) - txb[i] = 0xFF; - - txb[0] = dev->enetaddr[0]; - txb[1] = dev->enetaddr[1]; - txb[2] = dev->enetaddr[2]; - txb[3] = dev->enetaddr[3]; - txb[4] = dev->enetaddr[4]; - txb[5] = dev->enetaddr[5]; - -#ifdef DEBUG_RTL8169 - printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime); -#endif -} - -/************************************************************************** -HALT - Turn off ethernet interface -***************************************************************************/ -static void rtl_halt(struct eth_device *dev) -{ - int i; - -#ifdef DEBUG_RTL8169 - printf ("%s\n", __FUNCTION__); -#endif - - ioaddr = dev->iobase; - - /* Stop the chip's Tx and Rx DMA processes. */ - RTL_W8(ChipCmd, 0x00); - - /* Disable interrupts by clearing the interrupt mask. */ - RTL_W16(IntrMask, 0x0000); - - RTL_W32(RxMissed, 0); - - tpc->TxDescArrays = NULL; - tpc->RxDescArrays = NULL; - tpc->TxDescArray = NULL; - tpc->RxDescArray = NULL; - for (i = 0; i < NUM_RX_DESC; i++) { - tpc->RxBufferRing[i] = NULL; - } -} - -/************************************************************************** -INIT - Look for an adapter, this routine's visible to the outside -***************************************************************************/ - -#define board_found 1 -#define valid_link 0 -static int rtl_init(struct eth_device *dev, bd_t *bis) -{ - static int board_idx = -1; - static int printed_version = 0; - int i, rc; - int option = -1, Cap10_100 = 0, Cap1000 = 0; - -#ifdef DEBUG_RTL8169 - printf ("%s\n", __FUNCTION__); -#endif - - ioaddr = dev->iobase; - - board_idx++; - - printed_version = 1; - - /* point to private storage */ - tpc = &tpx; - - rc = rtl8169_init_board(dev); - if (rc) - return rc; - - /* Get MAC address. FIXME: read EEPROM */ - for (i = 0; i < MAC_ADDR_LEN; i++) - dev->enetaddr[i] = RTL_R8(MAC0 + i); - -#ifdef DEBUG_RTL8169 - printf("MAC Address"); - for (i = 0; i < MAC_ADDR_LEN; i++) - printf(":%02x", dev->enetaddr[i]); - putc('\n'); -#endif - -#ifdef DEBUG_RTL8169 - /* Print out some hardware info */ - printf("%s: at ioaddr 0x%x\n", dev->name, ioaddr); -#endif - - /* if TBI is not endbled */ - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(PHY_AUTO_NEGO_REG); - - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - /* Force RTL8169 in 10/100/1000 Full/Half mode. */ - if (option > 0) { -#ifdef DEBUG_RTL8169 - printf("%s: Force-mode Enabled.\n", dev->name); -#endif - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_Null; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; - } - mdio_write(PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); /* leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ - mdio_write(PHY_1000_CTRL_REG, Cap1000); - } else { -#ifdef DEBUG_RTL8169 - printf("%s: Auto-negotiation Enabled.\n", - dev->name); -#endif - /* enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged */ - mdio_write(PHY_AUTO_NEGO_REG, - PHY_Cap_10_Half | PHY_Cap_10_Full | - PHY_Cap_100_Half | PHY_Cap_100_Full | - (val & 0x1F)); - - /* enable 1000 Full Mode */ - mdio_write(PHY_1000_CTRL_REG, PHY_Cap_1000_Full); - - } - - /* Enable auto-negotiation and restart auto-nigotiation */ - mdio_write(PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - udelay(100); - - /* wait for auto-negotiation process */ - for (i = 10000; i > 0; i--) { - /* check if auto-negotiation complete */ - if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) { - udelay(100); - option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { -#ifdef DEBUG_RTL8169 - printf("%s: 1000Mbps Full-duplex operation.\n", - dev->name); -#endif - } else { -#ifdef DEBUG_RTL8169 - printf - ("%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); -#endif - } - break; - } else { - udelay(100); - } - } /* end for-loop to wait for auto-negotiation process */ - - } else { - udelay(100); -#ifdef DEBUG_RTL8169 - printf - ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", - dev->name, - (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); -#endif - } - - return 1; -} - -int rtl8169_initialize(bd_t *bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - u32 iobase; - int idx=0; - - while(1){ - /* Find RTL8169 */ - if ((devno = pci_find_devices(supported, idx++)) < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); - iobase &= ~0xf; - - debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase); - - dev = (struct eth_device *)malloc(sizeof *dev); - - sprintf (dev->name, "RTL8169#%d", card_number); - - dev->priv = (void *) devno; - dev->iobase = (int)bus_to_phys(iobase); - - dev->init = rtl_reset; - dev->halt = rtl_halt; - dev->send = rtl_send; - dev->recv = rtl_recv; - - eth_register (dev); - - rtl_init(dev, bis); - - card_number++; - } - return card_number; -} - -#endif diff --git a/drivers/s3c4510b_eth.c b/drivers/s3c4510b_eth.c deleted file mode 100644 index 3d9066abea..0000000000 --- a/drivers/s3c4510b_eth.c +++ /dev/null @@ -1,246 +0,0 @@ -/*********************************************************************** - * - * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) - * Curt Brune - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Description: Ethernet interface for Samsung S3C4510B SoC - */ - -#include - -#ifdef CONFIG_DRIVER_S3C4510_ETH - -#include -#include -#include -#include "s3c4510b_eth.h" - -static TX_FrameDescriptor txFDbase[ETH_MaxTxFrames]; -static MACFrame txFrameBase[ETH_MaxTxFrames]; -static RX_FrameDescriptor rxFDbase[PKTBUFSRX]; -static ETH m_eth; - -static s32 TxFDinit( ETH *eth) { - - s32 i; - MACFrame *txFrmBase; - - /* disable cache for access to the TX buffers */ - txFrmBase = (MACFrame *)( (u32)txFrameBase | CACHE_DISABLE_MASK); - - /* store start of Tx descriptors and set current */ - eth->m_curTX_FD = (TX_FrameDescriptor *) ((u32)txFDbase | CACHE_DISABLE_MASK); - eth->m_baseTX_FD = eth->m_curTX_FD; - - for ( i = 0; i < ETH_MaxTxFrames; i++) { - eth->m_baseTX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)&txFrmBase[i]; - eth->m_baseTX_FD[i].m_frameDataPtr.bf.owner = 0x0; /* CPU owner */ - eth->m_baseTX_FD[i].m_opt.ui = 0x0; - eth->m_baseTX_FD[i].m_status.ui = 0x0; - eth->m_baseTX_FD[i].m_nextFD = ð->m_baseTX_FD[i+1]; - } - - /* make the list circular */ - eth->m_baseTX_FD[i-1].m_nextFD = ð->m_baseTX_FD[0]; - - PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD); - - return 0; -} - -static s32 RxFDinit( ETH *eth) { - - s32 i; - /* MACFrame *rxFrmBase; */ - - /* disable cache for access to the RX buffers */ - /* rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */ - - /* store start of Rx descriptors and set current */ - eth->m_curRX_FD = (RX_FrameDescriptor *)((u32)rxFDbase | CACHE_DISABLE_MASK); - eth->m_baseRX_FD = eth->m_curRX_FD; - for ( i = 0; i < PKTBUFSRX; i++) { - eth->m_baseRX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)NetRxPackets[i] | CACHE_DISABLE_MASK; - eth->m_baseRX_FD[i].m_frameDataPtr.bf.owner = 0x1; /* BDMA owner */ - eth->m_baseRX_FD[i].m_reserved = 0x0; - eth->m_baseRX_FD[i].m_status.ui = 0x0; - eth->m_baseRX_FD[i].m_nextFD = ð->m_baseRX_FD[i+1]; - } - - /* make the list circular */ - eth->m_baseRX_FD[i-1].m_nextFD = ð->m_baseRX_FD[0]; - - PUT_REG( REG_BDMARXPTR, (u32)eth->m_curRX_FD); - - return 0; -} - -/* - * Public u-boot interface functions below - */ - -int eth_init(bd_t *bis) -{ - - ETH *eth = &m_eth; - - /* store our MAC address */ - eth->m_mac = bis->bi_enetaddr; - - /* setup DBMA and MAC */ - PUT_REG( REG_BDMARXCON, ETH_BRxRS); /* reset BDMA RX machine */ - PUT_REG( REG_BDMATXCON, ETH_BTxRS); /* reset BDMA TX machine */ - PUT_REG( REG_MACCON , ETH_SwReset); /* reset MAC machine */ - PUT_REG( REG_BDMARXLSZ, sizeof(MACFrame)); - PUT_REG( REG_MACCON , 0); /* reset MAC machine */ - - /* init frame descriptors */ - TxFDinit( eth); - RxFDinit( eth); - - /* init the CAM with our MAC address */ - PUT_REG( REG_CAM_BASE, (eth->m_mac[0] << 24) | - (eth->m_mac[1] << 16) | - (eth->m_mac[2] << 8) | - (eth->m_mac[3])); - PUT_REG( REG_CAM_BASE + 0x4, (eth->m_mac[4] << 24) | - (eth->m_mac[5] << 16)); - - /* enable CAM address 1 -- the MAC we just loaded */ - PUT_REG( REG_CAMEN, 0x1); - - PUT_REG( REG_CAMCON, - ETH_BroadAcc | /* accept broadcast packetes */ - ETH_CompEn); /* enable compare mode (check against the CAM) */ - - /* configure the BDMA Transmitter control */ - PUT_REG( REG_BDMATXCON, - ETH_BTxBRST | /* BDMA Tx burst size 16 words */ - ETH_BTxMSL110 | /* BDMA Tx wait to fill 6/8 of the BDMA */ - ETH_BTxSTSKO | /* BDMA Tx interrupt(Stop) on non-owner TX FD */ - ETH_BTxEn); /* BDMA Tx Enable */ - - /* configure the MAC Transmitter control */ - PUT_REG( REG_MACTXCON, - ETH_EnComp | /* interrupt when the MAC transmits or discards packet */ - ETH_TxEn); /* MAC transmit enable */ - - /* configure the BDMA Receiver control */ - PUT_REG( REG_BDMARXCON, - ETH_BRxBRST | /* BDMA Rx Burst Size 16 words */ - ETH_BRxSTSKO | /* BDMA Rx interrupt(Stop) on non-owner RX FD */ - ETH_BRxMAINC | /* BDMA Rx Memory Address increment */ - ETH_BRxDIE | /* BDMA Rx Every Received Frame Interrupt Enable */ - ETH_BRxNLIE | /* BDMA Rx NULL List Interrupt Enable */ - ETH_BRxNOIE | /* BDMA Rx Not Owner Interrupt Enable */ - ETH_BRxLittle | /* BDMA Rx Little endian */ - ETH_BRxEn); /* BDMA Rx Enable */ - - /* configure the MAC Receiver control */ - PUT_REG( REG_MACRXCON, - ETH_RxEn); /* MAC ETH_RxEn */ - - return 0; - -} - -/* Send a packet */ -s32 eth_send(volatile void *packet, s32 length) -{ - - u32 i; - ETH *eth = &m_eth; - - if ( eth->m_curTX_FD->m_frameDataPtr.bf.owner) { - printf("eth_send(): TX Frame. CPU not owner.\n"); - return -1; - } - - /* copy user data into frame data pointer */ - memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)), - (void *)packet, - length); - - /* Set TX Frame flags */ - eth->m_curTX_FD->m_opt.bf.widgetAlign = 0; - eth->m_curTX_FD->m_opt.bf.frameDataDir = 1; - eth->m_curTX_FD->m_opt.bf.littleEndian = 1; - eth->m_curTX_FD->m_opt.bf.macTxIrqEnbl = 1; - eth->m_curTX_FD->m_opt.bf.no_crc = 0; - eth->m_curTX_FD->m_opt.bf.no_padding = 0; - - /* Set TX Frame length */ - eth->m_curTX_FD->m_status.bf.len = length; - - /* Change ownership to BDMA */ - eth->m_curTX_FD->m_frameDataPtr.bf.owner = 1; - - /* Enable MAC and BDMA Tx control register */ - SET_REG( REG_BDMATXCON, ETH_BTxEn); - SET_REG( REG_MACTXCON, ETH_TxEn); - - /* poll on TX completion status */ - while ( !eth->m_curTX_FD->m_status.bf.complete) { - /* sleep */ - for ( i = 0; i < 0x10000; i ++); - } - - /* Change the Tx frame descriptor for next use */ - eth->m_curTX_FD = eth->m_curTX_FD->m_nextFD; - - return 0; -} - -/* Check for received packets */ -s32 eth_rx (void) -{ - s32 nLen = 0; - ETH *eth = &m_eth; - - /* check if packet ready */ - if ( (GET_REG( REG_BDMASTAT)) & ETH_S_BRxRDF) { - /* process all waiting packets */ - while ( !eth->m_curRX_FD->m_frameDataPtr.bf.owner) { - nLen = eth->m_curRX_FD->m_status.bf.len; - /* call back u-boot -- may call eth_send() */ - NetReceive ((u8 *)eth->m_curRX_FD->m_frameDataPtr.ui, nLen); - /* set owner back to CPU */ - eth->m_curRX_FD->m_frameDataPtr.bf.owner = 1; - /* clear status */ - eth->m_curRX_FD->m_status.ui = 0x0; - /* advance to next descriptor */ - eth->m_curRX_FD = eth->m_curRX_FD->m_nextFD; - /* clear received frame bit */ - PUT_REG( REG_BDMASTAT, ETH_S_BRxRDF); - } - } - - return nLen; -} - -/* Halt ethernet engine */ -void eth_halt(void) -{ - /* disable MAC */ - PUT_REG( REG_MACCON, ETH_HaltReg); -} - -#endif diff --git a/drivers/s3c4510b_eth.h b/drivers/s3c4510b_eth.h deleted file mode 100644 index cbddba71a4..0000000000 --- a/drivers/s3c4510b_eth.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifndef __S3C4510B_ETH_H -#define __S3C4510B_ETH_H -/* - * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) - * Curt Brune - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * MODULE: $Id:$ - * Description: Ethernet interface - * Runtime Env: ARM7TDMI - * Change History: - * 03-02-04 Create (Curt Brune) curt@cucy.com - * - */ - -#define __packed __attribute__ ((packed)) - -#define ETH_MAC_ADDR_SIZE (6) /* dst,src addr is 6bytes each */ -#define ETH_MaxTxFrames (16) /* Max number of Tx Frames */ - -/* Buffered DMA Receiver Control Register */ -#define ETH_BRxBRST 0x0000F /* BDMA Rx Burst Size * BRxBRST */ - /* = Burst Data Size 16 */ -#define ETH_BRxSTSKO 0x00020 /* BDMA Rx Stop/Skip Frame or Interrupt(=1) */ - /* case of not OWNER the current Frame */ -#define ETH_BRxMAINC 0x00040 /* BDMA Rx Memory Address Inc/Dec */ -#define ETH_BRxDIE 0x00080 /* BDMA Rx Every Received Frame Interrupt Enable */ -#define ETH_BRxNLIE 0x00100 /* BDMA Rx NULL List Interrupt Enable */ -#define ETH_BRxNOIE 0x00200 /* BDMA Rx Not Owner Interrupt Enable */ -#define ETH_BRxMSOIE 0x00400 /* BDMA Rx Maximum Size over Interrupr Enable */ -#define ETH_BRxLittle 0x00800 /* BDMA Rx Big/Little Endian */ -#define ETH_BRxBig 0x00000 /* BDMA Rx Big/Little Endian */ -#define ETH_BRxWA01 0x01000 /* BDMA Rx Word Alignment- one invalid byte */ -#define ETH_BRxWA10 0x02000 /* BDMA Rx Word Alignment- two invalid byte */ -#define ETH_BRxWA11 0x03000 /* BDMA Rx Word Alignment- three invalid byte */ -#define ETH_BRxEn 0x04000 /* BDMA Rx Enable */ -#define ETH_BRxRS 0x08000 /* BDMA Rx Reset */ -#define ETH_RxEmpty 0x10000 /* BDMA Rx Buffer empty interrupt */ -#define ETH_BRxEarly 0x20000 /* BDMA Rx Early notify Interrupt */ - -/* Buffered DMA Trasmit Control Register(BDMATXCON) */ -#define ETH_BTxBRST 0x0000F /* BDMA Tx Burst Size = 16 */ -#define ETH_BTxSTSKO 0x00020 /* BDMA Tx Stop/Skip Frame or Interrupt in case */ - /* of not Owner the current frame */ -#define ETH_BTxCPIE 0x00080 /* BDMA Tx Complete to send control */ - /* packet Enable */ -#define ETH_BTxNOIE 0x00200 /* BDMA Tx Buffer Not Owner */ -#define ETH_BTxEmpty 0x00400 /* BDMA Tx Buffer Empty Interrupt */ - -/* BDMA Tx buffer can be moved to the MAC Tx IO when the new frame comes in. */ -#define ETH_BTxMSL000 0x00000 /* No wait to fill the BDMA */ -#define ETH_BTxMSL001 0x00800 /* wait to fill 1/8 of the BDMA */ -#define ETH_BTxMSL010 0x01000 /* wait to fill 2/8 of the BDMA */ -#define ETH_BTxMSL011 0x01800 /* wait to fill 3/8 of the BDMA */ -#define ETH_BTxMSL100 0x02000 /* wait to fill 4/8 of the BDMA */ -#define ETH_BTxMSL101 0x02800 /* wait to fill 5/8 of the BDMA */ -#define ETH_BTxMSL110 0x03000 /* wait to fill 6/8 of the BDMA */ -#define ETH_BTxMSL111 0x03800 /* wait to fill 7/8 of the BDMA */ -#define ETH_BTxEn 0x04000 /* BDMA Tx Enable */ -#define ETH_BTxRS 0x08000 /* BDMA Tx Reset */ - -/* BDMA Status Register */ -#define ETH_S_BRxRDF 0x00001 /* BDMA Rx Done Every Received Frame */ -#define ETH_S_BRxNL 0x00002 /* BDMA Rx NULL List */ -#define ETH_S_BRxNO 0x00004 /* BDMA Rx Not Owner */ -#define ETH_S_BRxMSO 0x00008 /* BDMA Rx Maximum Size Over */ -#define ETH_S_BRxEmpty 0x00010 /* BDMA Rx Buffer Empty */ -#define ETH_S_BRxSEarly 0x00020 /* Early Notify */ -#define ETH_S_BRxFRF 0x00080 /* One more frame data in BDMA receive buffer */ -#define ETH_S_BTxCCP 0x10000 /* BDMA Tx Complete to send Control Packet */ -#define ETH_S_BTxNL 0x20000 /* BDMA Tx Null List */ -#define ETH_S_BTxNO 0x40000 /* BDMA Tx Not Owner */ -#define ETH_S_BTxEmpty 0x100000 /* BDMA Tx Buffer Empty */ - -/* MAC Control Register */ -#define ETH_HaltReg 0x0001 /* stop transmission and reception */ - /* after completion of any current packets */ -#define ETH_HaltImm 0x0002 /* Stop transmission and reception immediately */ -#define ETH_SwReset 0x0004 /* reset all Ethernet controller state machines */ - /* and FIFOs */ -#define ETH_FullDup 0x0008 /* allow transmission to begin while reception */ - /* is occurring */ -#define ETH_MACLoop 0x0010 /* MAC loopback */ -#define ETH_ConnM00 0x0000 /* Automatic-default */ -#define ETH_ConnM01 0x0020 /* Force 10Mbits endec */ -#define ETH_ConnM10 0x0040 /* Force MII (rate determined by MII clock */ -#define ETH_MIIOFF 0x0040 /* Force MII (rate determined by MII clock */ -#define ETH_Loop10 0x0080 /* Loop 10Mbps */ -#define ETH_MissRoll 0x0400 /* Missed error counter rolled over */ -#define ETH_MDCOFF 0x1000 /* MII Station Management Clock Off */ -#define ETH_EnMissRoll 0x2000 /* Interrupt when missed error counter rolls */ - /* over */ -#define ETH_Link10 0x8000 /* Link status 10Mbps */ - -/* CAM control register(CAMCON) */ -#define ETH_StationAcc 0x0001 /* Accept any packet with a unicast station */ - /* address */ -#define ETH_GroupAcc 0x0002 /* Accept any packet with multicast-group */ - /* station address */ -#define ETH_BroadAcc 0x0004 /* Accept any packet with a broadcast station */ - /* address */ -#define ETH_NegCAM 0x0008 /* 0: Accept packets CAM recognizes, */ - /* reject others */ - /* 1: reject packets CAM recognizes, */ - /* accept others */ -#define ETH_CompEn 0x0010 /* Compare Enable mode */ - -/* Transmit Control Register(MACTXCON) */ -#define ETH_TxEn 0x0001 /* transmit Enable */ -#define ETH_TxHalt 0x0002 /* Transmit Halt Request */ -#define ETH_NoPad 0x0004 /* suppress Padding */ -#define ETH_NoCRC 0x0008 /* Suppress CRC */ -#define ETH_FBack 0x0010 /* Fast Back-off */ -#define ETH_NoDef 0x0020 /* Disable the defer counter */ -#define ETH_SdPause 0x0040 /* Send Pause */ -#define ETH_MII10En 0x0080 /* MII 10Mbps mode enable */ -#define ETH_EnUnder 0x0100 /* Enable Underrun */ -#define ETH_EnDefer 0x0200 /* Enable Deferral */ -#define ETH_EnNCarr 0x0400 /* Enable No Carrier */ -#define ETH_EnExColl 0x0800 /* interrupt if 16 collision occur */ - /* in the same packet */ -#define ETH_EnLateColl 0x1000 /* interrupt if collision occurs after */ - /* 512 bit times(64 bytes times) */ -#define ETH_EnTxPar 0x2000 /* interrupt if the MAC transmit FIFO */ - /* has a parity error */ -#define ETH_EnComp 0x4000 /* interrupt when the MAC transmits or */ - /* discards one packet */ - -/* Transmit Status Register(MACTXSTAT) */ -#define ETH_ExColl 0x0010 /* Excessive collision */ -#define ETH_TxDeffered 0x0020 /* set if 16 collisions occur for same packet */ -#define ETH_Paused 0x0040 /* packet waited because of pause during */ - /* transmission */ -#define ETH_IntTx 0x0080 /* set if transmission of packet causes an */ - /* interrupt condiftion */ -#define ETH_Under 0x0100 /* MAC transmit FIFO becomes empty during */ - /* transmission */ -#define ETH_Defer 0x0200 /* MAC defers for MAC deferral */ -#define ETH_NCarr 0x0400 /* No carrier sense detected during the */ - /* transmission of a packet */ -#define ETH_SQE 0x0800 /* Signal Quality Error */ -#define ETH_LateColl 0x1000 /* a collision occures after 512 bit times */ -#define ETH_TxPar 0x2000 /* MAC transmit FIFO has detected a parity error */ -#define ETH_Comp 0x4000 /* MAC transmit or discards one packet */ -#define ETH_TxHalted 0x8000 /* Transmission was halted by clearing */ - /* TxEn or Halt immedite */ - -/* Receive Control Register (MACRXCON) */ -#define ETH_RxEn 0x0001 -#define ETH_RxHalt 0x0002 -#define ETH_LongEn 0x0004 -#define ETH_ShortEn 0x0008 -#define ETH_StripCRC 0x0010 -#define ETH_PassCtl 0x0020 -#define ETH_IgnoreCRC 0x0040 -#define ETH_EnAlign 0x0100 -#define ETH_EnCRCErr 0x0200 -#define ETH_EnOver 0x0400 -#define ETH_EnLongErr 0x0800 -#define ETH_EnRxPar 0x2000 -#define ETH_EnGood 0x4000 - -/* Receive Status Register(MACRXSTAT) */ -#define ETH_MCtlRecd 0x0020 -#define ETH_MIntRx 0x0040 -#define ETH_MRx10Stat 0x0080 -#define ETH_MAllignErr 0x0100 -#define ETH_MCRCErr 0x0200 -#define ETH_MOverflow 0x0400 -#define ETH_MLongErr 0x0800 -#define ETH_MRxPar 0x2000 -#define ETH_MRxGood 0x4000 -#define ETH_MRxHalted 0x8000 - -/* type of ethernet packets */ -#define ETH_TYPE_ARP (0x0806) -#define ETH_TYPE_IP (0x0800) - -#define ETH_HDR_SIZE (14) - -/* bit field for frame data pointer word */ -typedef struct __BF_FrameDataPtr { - u32 dataPtr:31; - u32 owner: 1; -} BF_FrameDataPtr; - -typedef union _FrameDataPtr { - u32 ui; - BF_FrameDataPtr bf; -} FrameDataPtr; - -typedef struct __BF_TX_Options { - u32 no_padding: 1; - u32 no_crc: 1; - u32 macTxIrqEnbl: 1; - u32 littleEndian: 1; - u32 frameDataDir: 1; - u32 widgetAlign: 2; - u32 reserved:25; -} BF_TX_Options; - -typedef union _TX_Options { - u32 ui; - BF_TX_Options bf; -} TX_Options; - -typedef struct __BF_RX_Status { - u32 len:16; /* frame length */ - u32 reserved1: 3; - u32 overMax: 1; - u32 reserved2: 1; - u32 ctrlRcv: 1; - u32 intRx: 1; - u32 rx10stat: 1; - u32 alignErr: 1; - u32 crcErr: 1; - u32 overFlow: 1; - u32 longErr: 1; - u32 reserved3: 1; - u32 parityErr: 1; - u32 good: 1; - u32 halted: 1; -} BF_RX_Status; - -typedef union _RX_Status { - u32 ui; - BF_RX_Status bf; -} RX_Status; - -typedef struct __BF_TX_Status { - u32 len:16; /* frame length */ - u32 txCollCnt: 4; - u32 exColl: 1; - u32 txDefer: 1; - u32 paused: 1; - u32 intTx: 1; - u32 underRun: 1; - u32 defer: 1; - u32 noCarrier: 1; - u32 SQErr: 1; - u32 lateColl: 1; - u32 parityErr: 1; - u32 complete: 1; - u32 halted: 1; -} BF_TX_Status; - -typedef union _TX_Status { - u32 ui; - BF_TX_Status bf; -} TX_Status; - -/* TX descriptor structure */ -typedef struct __TX_FrameDescriptor { - volatile FrameDataPtr m_frameDataPtr; - TX_Options m_opt; - volatile TX_Status m_status; - struct __TX_FrameDescriptor *m_nextFD; -} TX_FrameDescriptor; - -/* RX descriptor structure */ -typedef struct __RX_FrameDescriptor { - volatile FrameDataPtr m_frameDataPtr; - u32 m_reserved; - volatile RX_Status m_status; - struct __RX_FrameDescriptor *m_nextFD; -} RX_FrameDescriptor; - -/* MAC Frame Structure */ -typedef struct __MACFrame { - u8 m_dstAddr[6] __packed; - u8 m_srcAddr[6] __packed; - u16 m_lengthOrType __packed; - u8 m_payload[1506] __packed; -} MACFrame; - -/* Ethernet Control block */ -typedef struct __ETH { - TX_FrameDescriptor *m_curTX_FD; /* pointer to current TX frame descriptor */ - TX_FrameDescriptor *m_baseTX_FD; /* pointer to base TX frame descriptor */ - RX_FrameDescriptor *m_curRX_FD; /* pointer to current RX frame descriptor */ - RX_FrameDescriptor *m_baseRX_FD; /* pointer to base RX frame descriptor */ - u8 *m_mac; /* pointer to our MAC address */ -} ETH; - -#endif diff --git a/drivers/sk98lin/Makefile b/drivers/sk98lin/Makefile deleted file mode 100644 index a7d4a3b7a7..0000000000 --- a/drivers/sk98lin/Makefile +++ /dev/null @@ -1,120 +0,0 @@ -# -# (C) Copyright 2003-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# -# File: drivers/sk98lin/Makefile -# -# Makefile for the SysKonnect SK-98xx device driver. -# - -include $(TOPDIR)/config.mk - -LIB := $(obj)libsk98lin.a - -COBJS-y += skge.o -COBJS-y += skaddr.o -COBJS-y += skgehwt.o -COBJS-y += skgeinit.o -COBJS-y += skgepnmi.o -COBJS-y += skgesirq.o -COBJS-y += ski2c.o -COBJS-y += sklm80.o -COBJS-y += skqueue.o -COBJS-y += skrlmt.o -COBJS-y += sktimer.o -COBJS-y += skvpd.o -COBJS-y += skxmac2.o -COBJS-y += skcsum.o -#COBJS-y += skproc.o - -COBJS-y += uboot_skb.o -COBJS-y += uboot_drv.o - -COBJS := $(COBJS-y) -SRCS := $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) - -# DBGDEF = \ -# -DDEBUG - -ifdef DEBUG -DBGDEF += \ --DSK_DEBUG_CHKMOD=0x00000000L \ --DSK_DEBUG_CHKCAT=0x00000000L -endif - - -# **** possible debug modules for SK_DEBUG_CHKMOD ***************** -# SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -# SK_DBGMOD_VPD 0x00000008L /* VPD module */ -# SK_DBGMOD_I2C 0x00000010L /* I2C module */ -# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -# SK_DBGMOD_DRV 0x00010000L /* DRV module */ - -# **** possible debug categories for SK_DEBUG_CHKCAT ************** -# *** common modules *** -# SK_DBGCAT_INIT 0x00000001L module/driver initialization -# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL) -# SK_DBGCAT_ERR 0x00000004L error handling paths -# SK_DBGCAT_TX 0x00000008L transmit path -# SK_DBGCAT_RX 0x00000010L receive path -# SK_DBGCAT_IRQ 0x00000020L general IRQ handling -# SK_DBGCAT_QUEUE 0x00000040L any queue management -# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump -# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump - -# *** driver (file skge.c) *** -# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points -# SK_DBGCAT_DRV_??? 0x00020000 not used -# SK_DBGCAT_DRV_MCA 0x00040000 multicast -# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path -# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path -# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime -# SK_DBGCAT_DRV_??? 0x00400000 not used -# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode -# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames -# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions -# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources -# SK_DBGCAT_DRV_EVENT 0x08000000 driver events - -EXTRA_CFLAGS += -I. -DSK_USE_CSUM $(DBGDEF) - -CFLAGS += $(EXTRA_CFLAGS) -HOST_CFLAGS += $(EXTRA_CFLAGS) - - -all: $(LIB) - -$(LIB): $(obj).depend $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/drivers/sk98lin/h/lm80.h b/drivers/sk98lin/h/lm80.h deleted file mode 100644 index 981a4cab02..0000000000 --- a/drivers/sk98lin/h/lm80.h +++ /dev/null @@ -1,197 +0,0 @@ -/****************************************************************************** - * - * Name: lm80.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2002/04/25 11:04:10 $ - * Purpose: Contains all defines for the LM80 Chip - * (National Semiconductor). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: lm80.h,v $ - * Revision 1.4 2002/04/25 11:04:10 rschmidt - * Editorial changes - * - * Revision 1.3 1999/11/22 13:41:19 cgoos - * Changed license header to GPL. - * - * Revision 1.2 1999/03/12 13:26:51 malthoff - * remove __STDC__. - * - * Revision 1.1 1998/06/19 09:28:31 malthoff - * created. - * - * - ******************************************************************************/ - -#ifndef __INC_LM80_H -#define __INC_LM80_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * LM80 register definition - * - * All registers are 8 bit wide - */ -#define LM80_CFG 0x00 /* Configuration Register */ -#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ -#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */ -#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */ -#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */ -#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */ -#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */ - /* 0x07 - 0x1f reserved */ - /* current values */ -#define LM80_VT0_IN 0x20 /* current Voltage 0 value */ -#define LM80_VT1_IN 0x21 /* current Voltage 1 value */ -#define LM80_VT2_IN 0x22 /* current Voltage 2 value */ -#define LM80_VT3_IN 0x23 /* current Voltage 3 value */ -#define LM80_VT4_IN 0x24 /* current Voltage 4 value */ -#define LM80_VT5_IN 0x25 /* current Voltage 5 value */ -#define LM80_VT6_IN 0x26 /* current Voltage 6 value */ -#define LM80_TEMP_IN 0x27 /* current Temperature value */ -#define LM80_FAN1_IN 0x28 /* current Fan 1 count */ -#define LM80_FAN2_IN 0x29 /* current Fan 2 count */ - /* limit values */ -#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */ -#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */ -#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */ -#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */ -#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */ -#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */ -#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */ -#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */ -#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */ -#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */ -#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */ -#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */ -#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */ -#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */ -#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */ -#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */ -#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */ -#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */ -#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ -#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -/* - * LM80 bit definitions - */ - -/* LM80_CFG Configuration Register */ -#define LM80_CFG_START (1<<0) /* start monitoring operation */ -#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */ -#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */ -#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */ -#define LM80_CFG_RESET (1<<4) /* signals a reset */ -#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */ -#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */ -#define LM80_CFG_INIT (1<<7) /* restore power on defaults */ - -/* LM80_ISRC_1 Interrupt Status Register 1 */ -/* LM80_IMSK_1 Interrupt Mask Register 1 */ -#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */ -#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */ -#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */ -#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */ -#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */ -#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */ -#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */ -#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */ - -/* LM80_ISRC_2 Interrupt Status Register 2 */ -/* LM80_IMSK_2 Interrupt Mask Register 2 */ -#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ -#define LM80_IS_BTI (1<<1) /* state of BTI# pin */ -#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */ -#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */ -#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */ -#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */ - /* bit 6 and 7 are reserved in LM80_ISRC_2 */ -#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */ -#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */ - -/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */ -#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */ -#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */ -#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */ -#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */ -#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/ -#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */ - -/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */ -#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ -#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */ -#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */ -#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/ -#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */ -#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */ - - /* 0x07 - 0x1f reserved */ -/* LM80_VT0_IN current Voltage 0 value */ -/* LM80_VT1_IN current Voltage 1 value */ -/* LM80_VT2_IN current Voltage 2 value */ -/* LM80_VT3_IN current Voltage 3 value */ -/* LM80_VT4_IN current Voltage 4 value */ -/* LM80_VT5_IN current Voltage 5 value */ -/* LM80_VT6_IN current Voltage 6 value */ -/* LM80_TEMP_IN current temperature value */ -/* LM80_FAN1_IN current Fan 1 count */ -/* LM80_FAN2_IN current Fan 2 count */ -/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */ -/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */ -/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */ -/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */ -/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */ -/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */ -/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */ -/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */ -/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */ -/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */ -/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */ -/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */ -/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */ -/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */ -/* LM80_THOT_LIM_UP hot temperature limit (high) */ -/* LM80_THOT_LIM_LO hot temperature limit (low) */ -/* LM80_TOS_LIM_UP OS temperature limit (high) */ -/* LM80_TOS_LIM_LO OS temperature limit (low) */ -/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */ -/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -#define LM80_ADDR 0x28 /* LM80 default addr */ - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_LM80_H */ diff --git a/drivers/sk98lin/h/skaddr.h b/drivers/sk98lin/h/skaddr.h deleted file mode 100644 index 711f873e7f..0000000000 --- a/drivers/sk98lin/h/skaddr.h +++ /dev/null @@ -1,425 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.26 $ - * Date: $Date: 2002/11/15 07:24:42 $ - * Purpose: Header file for Address Management (MC, UC, Prom). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skaddr.h,v $ - * Revision 1.26 2002/11/15 07:24:42 tschilli - * SK_ADDR_EQUAL macro fixed. - * - * Revision 1.25 2002/06/10 13:55:18 tschilli - * Changes for handling YUKON. - * All changes are internally and not visible to the programmer - * using this module. - * - * Revision 1.24 2001/01/22 13:41:34 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.23 2000/08/10 11:27:50 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * - * Revision 1.22 2000/08/07 11:10:40 rassmann - * Editorial changes. - * - * Revision 1.21 2000/05/04 09:39:59 rassmann - * Editorial changes. - * Corrected multicast address hashing. - * - * Revision 1.20 1999/11/22 13:46:14 cgoos - * Changed license header to GPL. - * Allowing overwrite for SK_ADDR_EQUAL. - * - * Revision 1.19 1999/05/28 10:56:07 rassmann - * Editorial changes. - * - * Revision 1.18 1999/04/06 17:22:04 rassmann - * Added private "ActivePort". - * - * Revision 1.17 1999/01/14 16:18:19 rassmann - * Corrected multicast initialization. - * - * Revision 1.16 1999/01/04 10:30:36 rassmann - * SkAddrOverride only possible after SK_INIT_IO phase. - * - * Revision 1.15 1998/12/29 13:13:11 rassmann - * An address override is now preserved in the SK_INIT_IO phase. - * All functions return an int now. - * Extended parameter checking. - * - * Revision 1.14 1998/11/24 12:39:45 rassmann - * Reserved multicast entry for BPDU address. - * 13 multicast entries left for protocol. - * - * Revision 1.13 1998/11/13 17:24:32 rassmann - * Changed return value of SkAddrOverride to int. - * - * Revision 1.12 1998/11/13 16:56:19 rassmann - * Added macro SK_ADDR_COMPARE. - * Changed return type of SkAddrOverride to SK_BOOL. - * - * Revision 1.11 1998/10/28 18:16:35 rassmann - * Avoiding I/Os before SK_INIT_RUN level. - * Aligning InexactFilter. - * - * Revision 1.10 1998/10/22 11:39:10 rassmann - * Corrected signed/unsigned mismatches. - * - * Revision 1.9 1998/10/15 15:15:49 rassmann - * Changed Flags Parameters from SK_U8 to int. - * Checked with lint. - * - * Revision 1.8 1998/09/24 19:15:12 rassmann - * Code cleanup. - * - * Revision 1.7 1998/09/18 20:22:13 rassmann - * Added HW access. - * - * Revision 1.6 1998/09/04 19:40:20 rassmann - * Interface enhancements. - * - * Revision 1.5 1998/09/04 12:40:57 rassmann - * Interface cleanup. - * - * Revision 1.4 1998/09/04 12:14:13 rassmann - * Interface cleanup. - * - * Revision 1.3 1998/09/02 16:56:40 rassmann - * Updated interface. - * - * Revision 1.2 1998/08/27 14:26:09 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:31:08 rassmann - * First public version. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses and promiscuous mode - * on GEnesis adapters. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKADDR_H -#define __INC_SKADDR_H - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */ -#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */ - -/* ----- Common return values ----- */ - -#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */ -#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */ -#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */ - -/* ----- Clear/Add flag bits ----- */ - -#define SK_ADDR_PERMANENT 1 /* RLMT Address */ - -/* ----- Additional Clear flag bits ----- */ - -#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */ - -/* ----- Override flag bits ----- */ - -#define SK_ADDR_LOGICAL_ADDRESS 0 -#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */ -#define SK_ADDR_PHYSICAL_ADDRESS 1 -#define SK_ADDR_CLEAR_LOGICAL 2 -#define SK_ADDR_SET_LOGICAL 4 - -/* ----- Override return values ----- */ - -#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS) -#define SK_ADDR_DUPLICATE_ADDRESS 1 -#define SK_ADDR_MULTICAST_ADDRESS 2 - -/* ----- Partitioning of excact match table ----- */ - -#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */ - -#define SK_ADDR_FIRST_MATCH_RLMT 1 -#define SK_ADDR_LAST_MATCH_RLMT 2 -#define SK_ADDR_FIRST_MATCH_DRV 3 -#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1) - -/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */ - -#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */ -#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */ - -/* ----- Additional SkAddrMcAdd return values ----- */ - -#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */ -#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */ -#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */ - -/* Promiscuous mode bits ----- */ - -#define SK_PROM_MODE_NONE 0 /* Normal receive. */ -#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */ -#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */ -/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */ - -/* Macros */ - -#if 0 -#ifndef SK_ADDR_EQUAL -/* - * "&" instead of "&&" allows better optimization on IA-64. - * The replacement is safe here, as all bytes exist. - */ -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ - (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ - (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ - (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ - (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ - (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ -#endif /* 0 */ - -#ifndef SK_ADDR_EQUAL -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ - (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ - (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ - (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ - (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ - (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U16 *)&(((SK_U8 *)(A1))[4]) == *(SK_U16 *)&(((SK_U8 *)(A2))[4])) && \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ - -/* typedefs *******************************************************************/ - -typedef struct s_MacAddr { - SK_U8 a[SK_MAC_ADDR_LEN]; -} SK_MAC_ADDR; - - -/* SK_FILTER is used to ensure alignment of the filter. */ -typedef union s_InexactFilter { - SK_U8 Bytes[8]; - SK_U64 Val; /* Dummy entry for alignment only. */ -} SK_FILTER64; - - -typedef struct s_AddrNet SK_ADDR_NET; - - -typedef struct s_AddrPort { - -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */ - int PromMode; /* Promiscuous Mode. */ - -/* ----- Private part ----- */ - - SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - - SK_U32 FirstExactMatchRlmt; - SK_U32 NextExactMatchRlmt; - SK_U32 FirstExactMatchDrv; - SK_U32 NextExactMatchDrv; - SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES]; - SK_FILTER64 InexactFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */ -} SK_ADDR_PORT; - - -struct s_AddrNet { -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */ - -/* ----- Private part ----- */ - - SK_U32 ActivePort; /* View of module ADDR. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - SK_U16 Align02; -}; - - -typedef struct s_Addr { - -/* ----- Public part (read-only) ----- */ - - SK_ADDR_NET Net[SK_MAX_NETS]; - SK_ADDR_PORT Port[SK_MAX_MACS]; - -/* ----- Private part ----- */ -} SK_ADDR; - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* Functions provided by SkAddr */ - -/* ANSI/C++ compliant function prototypes */ - -extern int SkAddrInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkAddrMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrXmacMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrGmacMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrXmacMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrGmacMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrXmacMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrGmacMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrOverride( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pNewAddr, - int Flags); - -extern int SkAddrPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -extern int SkAddrXmacPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -extern int SkAddrGmacPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -extern int SkAddrSwap( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 FromPortNumber, - SK_U32 ToPortNumber); - -#else /* defined(SK_KR_PROTO)) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKADDR_H */ diff --git a/drivers/sk98lin/h/skcsum.h b/drivers/sk98lin/h/skcsum.h deleted file mode 100644 index 2acae329e3..0000000000 --- a/drivers/sk98lin/h/skcsum.h +++ /dev/null @@ -1,261 +0,0 @@ -/****************************************************************************** - * - * Name: skcsum.h - * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) - * Version: $Revision: 1.9 $ - * Date: $Date: 2001/02/06 11:21:39 $ - * Purpose: Store/verify Internet checksum in send/receive packets. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skcsum.h,v $ - * Revision 1.9 2001/02/06 11:21:39 rassmann - * Editorial changes. - * - * Revision 1.8 2001/02/06 11:15:36 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.7 2000/06/29 13:17:05 rassmann - * Corrected reception of a packet with UDP checksum == 0 (which means there - * is no UDP checksum). - * - * Revision 1.6 2000/02/28 12:33:44 cgoos - * Changed C++ style comments to C style. - * - * Revision 1.5 2000/02/21 12:10:05 cgoos - * Fixed license comment. - * - * Revision 1.4 2000/02/21 11:08:37 cgoos - * Merged changes back into common source. - * - * Revision 1.1 1999/07/26 14:47:49 mkarl - * changed from common source to windows specific source - * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and - * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester - * changes for Tx csum offload - * - * Revision 1.2 1998/09/04 12:16:34 mhaveman - * Checked in for Stephan to allow compilation. - * -Added definition SK_CSUM_EVENT_CLEAR_PROTO_STATS to clear statistic - * -Added prototype for SkCsEvent() - * - * Revision 1.1 1998/09/01 15:36:53 swolf - * initial revision - * - * 01-Sep-1998 sw Created. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * Public header file for the "GEnesis" common module "CSUM". - * - * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" - * and is the code name of this SysKonnect project. - * - * Compilation Options: - * - * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an - * empty module. - * - * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id - * definitions. In this case, all SKCS_PROTO_xxx definitions must be made - * external. - * - * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status - * definitions. In this case, all SKCS_STATUS_xxx definitions must be made - * external. - * - * Include File Hierarchy: - * - * "h/skcsum.h" - * "h/sktypes.h" - * "h/skqueue.h" - * - ******************************************************************************/ - -#ifndef __INC_SKCSUM_H -#define __INC_SKCSUM_H - -#include "h/sktypes.h" -#include "h/skqueue.h" - -/* defines ********************************************************************/ - -/* - * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user - * overwrite. - */ -#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */ -#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */ -#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */ -#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */ - -/* Indices for protocol statistics. */ -#define SKCS_PROTO_STATS_IP 0 -#define SKCS_PROTO_STATS_UDP 1 -#define SKCS_PROTO_STATS_TCP 2 -#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */ -#endif /* !SKCS_OVERWRITE_PROTO */ - -/* - * Define the default SKCS_STATUS type and values if no user overwrite. - * - * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. - * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. - * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. - * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame - * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). - * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). - * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). - * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). - * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. - * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. - * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. - */ -#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */ -#define SKCS_STATUS int /* Define status type. */ - -#define SKCS_STATUS_UNKNOWN_IP_VERSION 1 -#define SKCS_STATUS_IP_CSUM_ERROR 2 -#define SKCS_STATUS_IP_FRAGMENT 3 -#define SKCS_STATUS_IP_CSUM_OK 4 -#define SKCS_STATUS_TCP_CSUM_ERROR 5 -#define SKCS_STATUS_UDP_CSUM_ERROR 6 -#define SKCS_STATUS_TCP_CSUM_OK 7 -#define SKCS_STATUS_UDP_CSUM_OK 8 -/* needed for Microsoft */ -#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9 -#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10 -/* UDP checksum may be omitted */ -#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11 -#endif /* !SKCS_OVERWRITE_STATUS */ - -/* Clear protocol statistics event. */ -#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1 - -/* - * Add two values in one's complement. - * - * Note: One of the two input values may be "longer" than 16-bit, but then the - * resulting sum may be 17 bits long. In this case, add zero to the result using - * SKCS_OC_ADD() again. - * - * Result = Value1 + Value2 - */ -#define SKCS_OC_ADD(Result, Value1, Value2) { \ - unsigned long Sum; \ - \ - Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \ - /* Add-in any carry. */ \ - (Result) = (Sum & 0xffff) + (Sum >> 16); \ -} - -/* - * Subtract two values in one's complement. - * - * Result = Value1 - Value2 - */ -#define SKCS_OC_SUB(Result, Value1, Value2) \ - SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff) - -/* typedefs *******************************************************************/ - -/* - * SKCS_PROTO_STATS - The CSUM protocol statistics structure. - * - * There is one instance of this structure for each protocol supported. - */ -typedef struct s_CsProtocolStatistics { - SK_U64 RxOkCts; /* Receive checksum ok. */ - SK_U64 RxUnableCts; /* Unable to verify receive checksum. */ - SK_U64 RxErrCts; /* Receive checksum error. */ - SK_U64 TxOkCts; /* Transmit checksum ok. */ - SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */ -} SKCS_PROTO_STATS; - -/* - * s_Csum - The CSUM module context structure. - */ -typedef struct s_Csum { - /* Enabled receive SK_PROTO_XXX bit flags. */ - unsigned ReceiveFlags[SK_MAX_NETS]; -#ifdef TX_CSUM - unsigned TransmitFlags[SK_MAX_NETS]; -#endif /* TX_CSUM */ - - /* The protocol statistics structure; one per supported protocol. */ - SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS]; -} SK_CSUM; - -/* - * SKCS_PACKET_INFO - The packet information structure. - */ -typedef struct s_CsPacketInfo { - /* Bit field specifiying the desired/found protocols. */ - unsigned ProtocolFlags; - - /* Length of complete IP header, including any option fields. */ - unsigned IpHeaderLength; - - /* IP header checksum. */ - unsigned IpHeaderChecksum; - - /* TCP/UDP pseudo header checksum. */ - unsigned PseudoHeaderChecksum; -} SKCS_PACKET_INFO; - -/* function prototypes ********************************************************/ - -#ifndef SkCsCalculateChecksum -extern unsigned SkCsCalculateChecksum( - void *pData, - unsigned Length); -#endif - -extern int SkCsEvent( - SK_AC *pAc, - SK_IOC Ioc, - SK_U32 Event, - SK_EVPARA Param); - -extern SKCS_STATUS SkCsGetReceiveInfo( - SK_AC *pAc, - void *pIpHeader, - unsigned Checksum1, - unsigned Checksum2, - int NetNumber); - -extern void SkCsGetSendInfo( - SK_AC *pAc, - void *pIpHeader, - SKCS_PACKET_INFO *pPacketInfo, - int NetNumber); - -extern void SkCsSetReceiveFlags( - SK_AC *pAc, - unsigned ReceiveFlags, - unsigned *pChecksum1Offset, - unsigned *pChecksum2Offset, - int NetNumber); - -#endif /* __INC_SKCSUM_H */ diff --git a/drivers/sk98lin/h/skdebug.h b/drivers/sk98lin/h/skdebug.h deleted file mode 100644 index cf5b5ad332..0000000000 --- a/drivers/sk98lin/h/skdebug.h +++ /dev/null @@ -1,119 +0,0 @@ -/****************************************************************************** - * - * Name: skdebug.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.12 $ - * Date: $Date: 2002/07/15 15:37:13 $ - * Purpose: SK specific DEBUG support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skdebug.h,v $ - * Revision 1.12 2002/07/15 15:37:13 rschmidt - * Power Management support - * Editorial changes - * - * Revision 1.11 2002/04/25 11:04:39 rschmidt - * Editorial changes - * - * Revision 1.10 1999/11/22 13:47:40 cgoos - * Changed license header to GPL. - * - * Revision 1.9 1999/09/14 14:02:43 rwahl - * Added SK_DBGMOD_PECP. - * - * Revision 1.8 1998/11/25 08:31:54 gklug - * fix: no C++ comments allowed in common sources - * - * Revision 1.7 1998/11/24 16:47:24 swolf - * Driver may now define its own SK_DBG_MSG() (eg. in "h/skdrv1st.h"). - * - * Revision 1.6 1998/10/28 10:23:55 rassmann - * ADDED SK_DBGMOD_ADDR. - * - * Revision 1.5 1998/10/22 09:43:55 gklug - * add: CSUM module - * - * Revision 1.4 1998/10/01 07:54:44 gklug - * add: PNMI debug module - * - * Revision 1.3 1998/09/18 08:32:34 afischer - * Macros changed according ssr-spec.: - * SK_DBG_MODCHK -> SK_DBG_CHKMOD - * SK_DBG_CATCHK -> SK_DBG_CHKCAT - * - * Revision 1.2 1998/07/03 14:38:25 malthoff - * Add category SK_DBGCAT_FATAL. - * - * Revision 1.1 1998/06/19 13:39:01 malthoff - * created. - * - * - ******************************************************************************/ - -#ifndef __INC_SKDEBUG_H -#define __INC_SKDEBUG_H - -#ifdef DEBUG -#ifndef SK_DBG_MSG -#define SK_DBG_MSG(pAC,comp,cat,arg) \ - if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ - ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ - SK_DBG_PRINTF arg ; \ - } -#endif -#else -#define SK_DBG_MSG(pAC,comp,lev,arg) -#endif - -/* PLS NOTE: - * ========= - * Due to any restrictions of kernel printf routines do not use other - * format identifiers as: %x %d %c %s . - * Never use any combined format identifiers such as: %lx %ld in your - * printf - argument (arg) because some OS specific kernel printfs may - * only support some basic identifiers. - */ - -/* Debug modules */ - -#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -#define SK_DBGMOD_VPD 0x00000008L /* VPD module */ -#define SK_DBGMOD_I2C 0x00000010L /* I2C module */ -#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -#define SK_DBGMOD_PECP 0x00000100L /* PECP module */ -#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */ - -/* Debug events */ - -#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */ -#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */ -#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */ -#define SK_DBGCAT_TX 0x00000008L /* transmit path */ -#define SK_DBGCAT_RX 0x00000010L /* receive path */ -#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */ -#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */ -#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */ -#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */ - -#endif /* __INC_SKDEBUG_H */ diff --git a/drivers/sk98lin/h/skdrv1st.h b/drivers/sk98lin/h/skdrv1st.h deleted file mode 100644 index af34d7b96f..0000000000 --- a/drivers/sk98lin/h/skdrv1st.h +++ /dev/null @@ -1,264 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv1st.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: First header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skdrv1st.h,v $ - * Revision 1.11 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.10 2002/10/02 12:46:02 mlindner - * Add: Support for Yukon - * - * Revision 1.9.2.2 2001/12/07 12:06:42 mlindner - * Fix: malloc -> slab changes - * - * Revision 1.9.2.1 2001/03/12 16:50:59 mlindner - * chg: kernel 2.4 adaption - * - * Revision 1.9 2001/01/22 14:16:04 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * Revision 1.8 2000/02/21 12:19:18 cgoos - * Added default for SK_DEBUG_CHKMOD/_CHKCAT - * - * Revision 1.7 1999/11/22 13:50:00 cgoos - * Changed license header to GPL. - * Added overwrite for several functions. - * Removed linux 2.0.x definitions. - * Removed PCI vendor ID definition (now in kernel). - * - * Revision 1.6 1999/07/27 08:03:33 cgoos - * Changed SK_IN/OUT macros to readX/writeX instead of memory - * accesses (necessary for ALPHA). - * - * Revision 1.5 1999/07/23 12:10:21 cgoos - * Removed SK_RLMT_SLOW_LOOKAHEAD define. - * - * Revision 1.4 1999/07/14 12:31:13 cgoos - * Added SK_RLMT_SLOW_LOOKAHEAD define. - * - * Revision 1.3 1999/04/07 10:12:54 cgoos - * Added check for KERNEL and OPTIMIZATION defines. - * - * Revision 1.2 1999/03/01 08:51:47 cgoos - * Fixed pcibios_read/write definitions. - * - * Revision 1.1 1999/02/16 07:40:49 cgoos - * First version. - * - * - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the first include file of the driver, which includes all - * neccessary system header files and some of the GEnesis header files. - * It also defines some basic items. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV1ST_H -#define __INC_SKDRV1ST_H - -#if 0 -/* Check kernel version */ -#include -#if (LINUX_VERSION_CODE > 0x020300) -#endif -#endif - -typedef struct s_AC SK_AC; - -/* override some default functions with optimized linux functions */ - -#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2) -#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4) -#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8) -#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),2) - -#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) - -#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) - - -#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) -#warning You must compile this file with the correct options! -#warning See the last lines of the source file. -#error You must compile this driver with "-O". -#endif - -#if 0 -#include -#endif -#include -#if 0 -#include -#endif -#include -#if 0 -#include -#include -#include -#include -#include -#endif -#include -#include -#include -#if 0 -#include -#include -#include - -#include -#include -#include -#endif - -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/skdebug.h" -#include "h/lm80.h" -#include "h/xmac_ii.h" - -#include "u-boot_compat.h" - -#ifdef __LITTLE_ENDIAN -#define SK_LITTLE_ENDIAN -#else -#define SK_BIG_ENDIAN -#endif - -#if 0 -#define SK_NET_DEVICE net_device -#else -#define SK_NET_DEVICE eth_device -#endif - - -/* we use gethrtime(), return unit: nanoseconds */ -#if 0 -#define SK_TICKS_PER_SEC HZ -#else -#define SK_TICKS_PER_SEC CFG_HZ -#endif - -#define SK_MEM_MAPPED_IO - -/* #define SK_RLMT_SLOW_LOOKAHEAD */ - -#define SK_MAX_MACS 2 -#define SK_MAX_NETS 2 - -#define SK_IOC char* - -typedef struct s_DrvRlmtMbuf SK_MBUF; - -#define SK_CONST64 INT64_C -#define SK_CONSTU64 UINT64_C - -#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size) -#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size) -#define SK_MEMSET(dest,val,size) memset(dest,val,size) -#define SK_STRLEN(pStr) strlen((char*)(pStr)) -#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size) -#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2)) - -/* macros to access the adapter */ -#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) -#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) -#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) -#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a))) -#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a))) -#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a))) - -#define int8_t char -#define int16_t short -#define int32_t long -#define int64_t long long -#define uint8_t u_char -#define uint16_t u_short -#define uint32_t u_long -#define uint64_t unsigned long long -#define t_scalar_t int -#define t_uscalar_t unsigned int -#define uintptr_t unsigned long - -#define __CONCAT__(A,B) A##B - -#define INT32_C(a) __CONCAT__(a,L) -#define INT64_C(a) __CONCAT__(a,LL) -#define UINT32_C(a) __CONCAT__(a,UL) -#define UINT64_C(a) __CONCAT__(a,ULL) - -#ifdef DEBUG -#define SK_DBG_PRINTF printk -#ifndef SK_DEBUG_CHKMOD -#define SK_DEBUG_CHKMOD 0 -#endif -#ifndef SK_DEBUG_CHKCAT -#define SK_DEBUG_CHKCAT 0 -#endif -/* those come from the makefile */ -#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD) -#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT) - -extern void SkDbgPrintf(const char *format,...); - -#define SK_DBGMOD_DRV 0x00010000 - -/**** possible driver debug categories ********************************/ -#define SK_DBGCAT_DRV_ENTRY 0x00010000 -#define SK_DBGCAT_DRV_SAP 0x00020000 -#define SK_DBGCAT_DRV_MCA 0x00040000 -#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 -#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 -#define SK_DBGCAT_DRV_PROGRESS 0x00200000 -#define SK_DBGCAT_DRV_MSG 0x00400000 -#define SK_DBGCAT_DRV_PROM 0x00800000 -#define SK_DBGCAT_DRV_TX_FRAME 0x01000000 -#define SK_DBGCAT_DRV_ERROR 0x02000000 -#define SK_DBGCAT_DRV_INT_SRC 0x04000000 -#define SK_DBGCAT_DRV_EVENT 0x08000000 - -#endif - -#define SK_ERR_LOG SkErrorLog - -extern void SkErrorLog(SK_AC*, int, int, char*); - -#endif diff --git a/drivers/sk98lin/h/skdrv2nd.h b/drivers/sk98lin/h/skdrv2nd.h deleted file mode 100644 index a311827aa7..0000000000 --- a/drivers/sk98lin/h/skdrv2nd.h +++ /dev/null @@ -1,561 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv2nd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: Second header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skdrv2nd.h,v $ - * Revision 1.15 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.14 2003/02/25 13:26:26 mlindner - * Add: Support for various vendors - * - * Revision 1.13 2002/10/02 12:46:02 mlindner - * Add: Support for Yukon - * - * Revision 1.12.2.2 2001/09/05 12:14:50 mlindner - * add: New hardware revision int - * - * Revision 1.12.2.1 2001/03/12 16:50:59 mlindner - * chg: kernel 2.4 adaption - * - * Revision 1.12 2001/03/01 12:52:15 mlindner - * Fixed ring size - * - * Revision 1.11 2001/02/19 13:28:02 mlindner - * Changed PNMI parameter values - * - * Revision 1.10 2001/01/22 14:16:04 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * Revision 1.1 2000/10/05 19:46:50 phargrov - * Add directory src/vipk_devs_nonlbl/vipk_sk98lin/ - * This is the SysKonnect SK-98xx Gigabit Ethernet driver, - * contributed by SysKonnect. - * - * Revision 1.9 2000/02/21 10:39:55 cgoos - * Added flag for jumbo support usage. - * - * Revision 1.8 1999/11/22 13:50:44 cgoos - * Changed license header to GPL. - * Fixed two comments. - * - * Revision 1.7 1999/09/28 12:38:21 cgoos - * Added CheckQueue to SK_AC. - * - * Revision 1.6 1999/07/27 08:04:05 cgoos - * Added checksumming variables to SK_AC. - * - * Revision 1.5 1999/03/29 12:33:26 cgoos - * Rreversed to fine lock granularity. - * - * Revision 1.4 1999/03/15 12:14:02 cgoos - * Added DriverLock to SK_AC. - * Removed other locks. - * - * Revision 1.3 1999/03/01 08:52:27 cgoos - * Changed pAC->PciDev declaration. - * - * Revision 1.2 1999/02/18 10:57:14 cgoos - * Removed SkDrvTimeStamp prototype. - * Fixed SkGeOsGetTime prototype. - * - * Revision 1.1 1999/02/16 07:41:01 cgoos - * First version. - * - * - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the second include file of the driver, which includes all other - * neccessary files and defines all structures and constants used by the - * driver and the common modules. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV2ND_H -#define __INC_SKDRV2ND_H - -#include "h/skqueue.h" -#include "h/skgehwt.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skgepnmi.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skaddr.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skrlmt.h" -#include "h/skgedrv.h" - -#define SK_PCI_ISCOMPLIANT(result, pdev) { \ - result = SK_FALSE; /* default */ \ - /* 3Com (0x10b7) */ \ - if (pdev->vendor == 0x10b7) { \ - /* Gigabit Ethernet Adapter (0x1700) */ \ - if ((pdev->device == 0x1700)) { \ - result = SK_TRUE; \ - } \ - /* SysKonnect (0x1148) */ \ - } else if (pdev->vendor == 0x1148) { \ - /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */ \ - /* SK-98xx V2 Gigabit Ethernet Adapter (0x4320) */ \ - if ((pdev->device == 0x4300) || \ - (pdev->device == 0x4320)) { \ - result = SK_TRUE; \ - } \ - /* D-Link (0x1186) */ \ - } else if (pdev->vendor == 0x1186) { \ - /* Gigabit Ethernet Adapter (0x4c00) */ \ - if ((pdev->device == 0x4c00)) { \ - result = SK_TRUE; \ - } \ - /* CNet (0x1371) */ \ - } else if (pdev->vendor == 0x1371) { \ - /* GigaCard Network Adapter (0x434e) */ \ - if ((pdev->device == 0x434e)) { \ - result = SK_TRUE; \ - } \ - /* Linksys (0x1737) */ \ - } else if (pdev->vendor == 0x1737) { \ - /* Gigabit Network Adapter (0x1032) */ \ - /* Gigabit Network Adapter (0x1064) */ \ - if ((pdev->device == 0x1032) || \ - (pdev->device == 0x1064)) { \ - result = SK_TRUE; \ - } \ - } else { \ - result = SK_FALSE; \ - } \ -} - - -extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); -extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); -extern SK_U64 SkOsGetTime(SK_AC*); -extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); -extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); -extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); -extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32); -extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); -extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); -extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); - -struct s_DrvRlmtMbuf { - SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ - SK_U8 *pData; /* Data buffer (virtually contig.). */ - unsigned Size; /* Data buffer size. */ - unsigned Length; /* Length of packet (<= Size). */ - SK_U32 PortIdx; /* Receiving/transmitting port. */ -#ifdef SK_RLMT_MBUF_PRIVATE - SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ -#endif /* SK_RLMT_MBUF_PRIVATE */ - struct sk_buff *pOs; /* Pointer to message block */ -}; - - -/* - * ioctl definitions - */ -#define SK_IOCTL_BASE (SIOCDEVPRIVATE) -#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) -#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) -#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) - -typedef struct s_IOCTL SK_GE_IOCTL; - -struct s_IOCTL { - char* pData; - unsigned int Len; -}; - - -/* - * define sizes of descriptor rings in bytes - */ - -#if 0 -#define TX_RING_SIZE (8*1024) -#define RX_RING_SIZE (24*1024) -#else -#define TX_RING_SIZE (10 * 40) -#define RX_RING_SIZE (10 * 40) -#endif - -/* - * Buffer size for ethernet packets - */ -#define ETH_BUF_SIZE 1540 -#define ETH_MAX_MTU 1514 -#define ETH_MIN_MTU 60 -#define ETH_MULTICAST_BIT 0x01 -#define SK_JUMBO_MTU 9000 - -/* - * transmit priority selects the queue: LOW=asynchron, HIGH=synchron - */ -#define TX_PRIO_LOW 0 -#define TX_PRIO_HIGH 1 - -/* - * alignment of rx/tx descriptors - */ -#define DESCR_ALIGN 8 - -/* - * definitions for pnmi. TODO - */ -#define SK_DRIVER_RESET(pAC, IoC) 0 -#define SK_DRIVER_SENDEVENT(pAC, IoC) 0 -#define SK_DRIVER_SELFTEST(pAC, IoC) 0 -/* For get mtu you must add an own function */ -#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0 -#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0 -#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0 - - -/* TX and RX descriptors *****************************************************/ - -typedef struct s_RxD RXD; /* the receive descriptor */ - -struct s_RxD { - volatile SK_U32 RBControl; /* Receive Buffer Control */ - SK_U32 VNextRxd; /* Next receive descriptor,low dword */ - SK_U32 VDataLow; /* Receive buffer Addr, low dword */ - SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ - SK_U32 FrameStat; /* Receive Frame Status word */ - SK_U32 TimeStamp; /* Time stamp from XMAC */ - SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ - SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ - RXD *pNextRxd; /* Pointer to next Rxd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - -typedef struct s_TxD TXD; /* the transmit descriptor */ - -struct s_TxD { - volatile SK_U32 TBControl; /* Transmit Buffer Control */ - SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ - SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ - SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ - SK_U32 FrameStat; /* Transmit Frame Status Word */ - SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ - SK_U16 TcpSumSt; /* TCP Sum Start */ - SK_U16 TcpSumWr; /* TCP Sum Write */ - SK_U32 TcpReserved; /* not used */ - TXD *pNextTxd; /* Pointer to next Txd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - - -/* definition of flags in descriptor control field */ -#define RX_CTRL_OWN_BMU UINT32_C(0x80000000) -#define RX_CTRL_STF UINT32_C(0x40000000) -#define RX_CTRL_EOF UINT32_C(0x20000000) -#define RX_CTRL_EOB_IRQ UINT32_C(0x10000000) -#define RX_CTRL_EOF_IRQ UINT32_C(0x08000000) -#define RX_CTRL_DEV_NULL UINT32_C(0x04000000) -#define RX_CTRL_STAT_VALID UINT32_C(0x02000000) -#define RX_CTRL_TIME_VALID UINT32_C(0x01000000) -#define RX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) -#define RX_CTRL_CHECK_CSUM UINT32_C(0x00560000) -#define RX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) - -#define TX_CTRL_OWN_BMU UINT32_C(0x80000000) -#define TX_CTRL_STF UINT32_C(0x40000000) -#define TX_CTRL_EOF UINT32_C(0x20000000) -#define TX_CTRL_EOB_IRQ UINT32_C(0x10000000) -#define TX_CTRL_EOF_IRQ UINT32_C(0x08000000) -#define TX_CTRL_ST_FWD UINT32_C(0x04000000) -#define TX_CTRL_DISAB_CRC UINT32_C(0x02000000) -#define TX_CTRL_SOFTWARE UINT32_C(0x01000000) -#define TX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) -#define TX_CTRL_CHECK_CSUM UINT32_C(0x00560000) -#define TX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) - - -/* The offsets of registers in the TX and RX queue control io area ***********/ - -#define RX_Q_BUF_CTRL_CNT 0x00 -#define RX_Q_NEXT_DESCR_LOW 0x04 -#define RX_Q_BUF_ADDR_LOW 0x08 -#define RX_Q_BUF_ADDR_HIGH 0x0c -#define RX_Q_FRAME_STAT 0x10 -#define RX_Q_TIME_STAMP 0x14 -#define RX_Q_CSUM_1_2 0x18 -#define RX_Q_CSUM_START_1_2 0x1c -#define RX_Q_CUR_DESCR_LOW 0x20 -#define RX_Q_DESCR_HIGH 0x24 -#define RX_Q_CUR_ADDR_LOW 0x28 -#define RX_Q_CUR_ADDR_HIGH 0x2c -#define RX_Q_CUR_BYTE_CNT 0x30 -#define RX_Q_CTRL 0x34 -#define RX_Q_FLAG 0x38 -#define RX_Q_TEST1 0x3c -#define RX_Q_TEST2 0x40 -#define RX_Q_TEST3 0x44 - -#define TX_Q_BUF_CTRL_CNT 0x00 -#define TX_Q_NEXT_DESCR_LOW 0x04 -#define TX_Q_BUF_ADDR_LOW 0x08 -#define TX_Q_BUF_ADDR_HIGH 0x0c -#define TX_Q_FRAME_STAT 0x10 -#define TX_Q_CSUM_START 0x14 -#define TX_Q_CSUM_START_POS 0x18 -#define TX_Q_RESERVED 0x1c -#define TX_Q_CUR_DESCR_LOW 0x20 -#define TX_Q_DESCR_HIGH 0x24 -#define TX_Q_CUR_ADDR_LOW 0x28 -#define TX_Q_CUR_ADDR_HIGH 0x2c -#define TX_Q_CUR_BYTE_CNT 0x30 -#define TX_Q_CTRL 0x34 -#define TX_Q_FLAG 0x38 -#define TX_Q_TEST1 0x3c -#define TX_Q_TEST2 0x40 -#define TX_Q_TEST3 0x44 - -/* definition of flags in the queue control field */ -#define RX_Q_CTRL_POLL_ON 0x00000080 -#define RX_Q_CTRL_POLL_OFF 0x00000040 -#define RX_Q_CTRL_STOP 0x00000020 -#define RX_Q_CTRL_START 0x00000010 -#define RX_Q_CTRL_CLR_I_PAR 0x00000008 -#define RX_Q_CTRL_CLR_I_EOB 0x00000004 -#define RX_Q_CTRL_CLR_I_EOF 0x00000002 -#define RX_Q_CTRL_CLR_I_ERR 0x00000001 - -#define TX_Q_CTRL_POLL_ON 0x00000080 -#define TX_Q_CTRL_POLL_OFF 0x00000040 -#define TX_Q_CTRL_STOP 0x00000020 -#define TX_Q_CTRL_START 0x00000010 -#define TX_Q_CTRL_CLR_I_EOB 0x00000004 -#define TX_Q_CTRL_CLR_I_EOF 0x00000002 -#define TX_Q_CTRL_CLR_I_ERR 0x00000001 - - -/* Interrupt bits in the interrupts source register **************************/ -#define IRQ_HW_ERROR 0x80000000 -#define IRQ_RESERVED 0x40000000 -#define IRQ_PKT_TOUT_RX1 0x20000000 -#define IRQ_PKT_TOUT_RX2 0x10000000 -#define IRQ_PKT_TOUT_TX1 0x08000000 -#define IRQ_PKT_TOUT_TX2 0x04000000 -#define IRQ_I2C_READY 0x02000000 -#define IRQ_SW 0x01000000 -#define IRQ_EXTERNAL_REG 0x00800000 -#define IRQ_TIMER 0x00400000 -#define IRQ_MAC1 0x00200000 -#define IRQ_LINK_SYNC_C_M1 0x00100000 -#define IRQ_MAC2 0x00080000 -#define IRQ_LINK_SYNC_C_M2 0x00040000 -#define IRQ_EOB_RX1 0x00020000 -#define IRQ_EOF_RX1 0x00010000 -#define IRQ_CHK_RX1 0x00008000 -#define IRQ_EOB_RX2 0x00004000 -#define IRQ_EOF_RX2 0x00002000 -#define IRQ_CHK_RX2 0x00001000 -#define IRQ_EOB_SY_TX1 0x00000800 -#define IRQ_EOF_SY_TX1 0x00000400 -#define IRQ_CHK_SY_TX1 0x00000200 -#define IRQ_EOB_AS_TX1 0x00000100 -#define IRQ_EOF_AS_TX1 0x00000080 -#define IRQ_CHK_AS_TX1 0x00000040 -#define IRQ_EOB_SY_TX2 0x00000020 -#define IRQ_EOF_SY_TX2 0x00000010 -#define IRQ_CHK_SY_TX2 0x00000008 -#define IRQ_EOB_AS_TX2 0x00000004 -#define IRQ_EOF_AS_TX2 0x00000002 -#define IRQ_CHK_AS_TX2 0x00000001 - -#define DRIVER_IRQS (IRQ_SW | IRQ_EOF_RX1 | IRQ_EOF_RX2 | \ - IRQ_EOF_SY_TX1 | IRQ_EOF_AS_TX1 | \ - IRQ_EOF_SY_TX2 | IRQ_EOF_AS_TX2) - -#define SPECIAL_IRQS (IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ - IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ - IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ - IRQ_MAC1 | IRQ_LINK_SYNC_C_M1 | \ - IRQ_MAC2 | IRQ_LINK_SYNC_C_M2 | \ - IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ - IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ - IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) - -#define IRQ_MASK (IRQ_SW | IRQ_EOB_RX1 | IRQ_EOF_RX1 | \ - IRQ_EOB_RX2 | IRQ_EOF_RX2 | \ - IRQ_EOB_SY_TX1 | IRQ_EOF_SY_TX1 | \ - IRQ_EOB_AS_TX1 | IRQ_EOF_AS_TX1 | \ - IRQ_EOB_SY_TX2 | IRQ_EOF_SY_TX2 | \ - IRQ_EOB_AS_TX2 | IRQ_EOF_AS_TX2 | \ - IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ - IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ - IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ - IRQ_MAC1 | \ - IRQ_MAC2 | \ - IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ - IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ - IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) - -#define IRQ_HWE_MASK 0x00000FFF /* enable all HW irqs */ - -typedef struct s_DevNet DEV_NET; - -struct s_DevNet { - int PortNr; - int NetNr; - int Mtu; - int Up; - SK_AC *pAC; -}; - -typedef struct s_TxPort TX_PORT; - -struct s_TxPort { - /* the transmit descriptor rings */ - caddr_t pTxDescrRing; /* descriptor area memory */ - SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ - TXD *pTxdRingHead; /* Head of Tx rings */ - TXD *pTxdRingTail; /* Tail of Tx rings */ - TXD *pTxdRingPrev; /* descriptor sent previously */ - int TxdRingFree; /* # of free entrys */ -#if 0 - spinlock_t TxDesRingLock; /* serialize descriptor accesses */ -#endif - caddr_t HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -typedef struct s_RxPort RX_PORT; - -struct s_RxPort { - /* the receive descriptor rings */ - caddr_t pRxDescrRing; /* descriptor area memory */ - SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ - RXD *pRxdRingHead; /* Head of Rx rings */ - RXD *pRxdRingTail; /* Tail of Rx rings */ - RXD *pRxdRingPrev; /* descriptor given to BMU previously */ - int RxdRingFree; /* # of free entrys */ -#if 0 - spinlock_t RxDesRingLock; /* serialize descriptor accesses */ -#endif - int RxFillLimit; /* limit for buffers in ring */ - caddr_t HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -typedef struct s_PerStrm PER_STRM; - -#define SK_ALLOC_IRQ 0x00000001 - -/**************************************************************************** - * Per board structure / Adapter Context structure: - * Allocated within attach(9e) and freed within detach(9e). - * Contains all 'per device' necessary handles, flags, locks etc.: - */ -struct s_AC { - SK_GEINIT GIni; /* GE init struct */ - SK_PNMI Pnmi; /* PNMI data struct */ - SK_VPD vpd; /* vpd data struct */ - SK_QUEUE Event; /* Event queue */ - SK_HWT Hwt; /* Hardware Timer control struct */ - SK_TIMCTRL Tim; /* Software Timer control struct */ - SK_I2C I2c; /* I2C relevant data structure */ - SK_ADDR Addr; /* for Address module */ - SK_CSUM Csum; /* for checksum module */ - SK_RLMT Rlmt; /* for rlmt module */ -#if 0 - spinlock_t SlowPathLock; /* Normal IRQ lock */ -#endif - SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */ - int RlmtMode; /* link check mode to set */ - int RlmtNets; /* Number of nets */ - - SK_IOC IoBase; /* register set of adapter */ - int BoardLevel; /* level of active hw init (0-2) */ - char DeviceStr[80]; /* adapter string from vpd */ - SK_U32 AllocFlag; /* flag allocation of resources */ -#if 0 - struct pci_dev *PciDev; /* for access to pci config space */ - SK_U32 PciDevId; /* pci device id */ -#else - int PciDev; -#endif - struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ - char Name[30]; /* driver name */ - struct SK_NET_DEVICE *Next; /* link all devices (for clearing) */ - int RxBufSize; /* length of receive buffers */ -#if 0 - struct net_device_stats stats; /* linux 'netstat -i' statistics */ -#endif - int Index; /* internal board index number */ - - /* adapter RAM sizes for queues of active port */ - int RxQueueSize; /* memory used for receive queue */ - int TxSQueueSize; /* memory used for sync. tx queue */ - int TxAQueueSize; /* memory used for async. tx queue */ - - int PromiscCount; /* promiscuous mode counter */ - int AllMultiCount; /* allmulticast mode counter */ - int MulticCount; /* number of different MC */ - /* addresses for this board */ - /* (may be more than HW can)*/ - - int HWRevision; /* Hardware revision */ - int ActivePort; /* the active XMAC port */ - int MaxPorts; /* number of activated ports */ - int TxDescrPerRing; /* # of descriptors per tx ring */ - int RxDescrPerRing; /* # of descriptors per rx ring */ - - caddr_t pDescrMem; /* Pointer to the descriptor area */ - dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ - - /* the port structures with descriptor rings */ - TX_PORT TxPort[SK_MAX_MACS][2]; - RX_PORT RxPort[SK_MAX_MACS]; - - unsigned int CsOfs1; /* for checksum calculation */ - unsigned int CsOfs2; /* for checksum calculation */ - SK_U32 CsOfs; /* for checksum calculation */ - - SK_BOOL CheckQueue; /* check event queue soon */ - - /* Only for tests */ - int PortUp; - int PortDown; - -}; - -#endif /* __INC_SKDRV2ND_H */ diff --git a/drivers/sk98lin/h/skerror.h b/drivers/sk98lin/h/skerror.h deleted file mode 100644 index a454d9daa9..0000000000 --- a/drivers/sk98lin/h/skerror.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Name: skerror.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2002/04/25 11:05:10 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skerror.h,v $ - * Revision 1.5 2002/04/25 11:05:10 rschmidt - * Editorial changes - * - * Revision 1.4 1999/11/22 13:51:59 cgoos - * Changed license header to GPL. - * - * Revision 1.3 1999/09/14 14:04:42 rwahl - * Added error base SK_ERRBASE_PECP. - * Changed error base for driver. - * - * Revision 1.2 1998/08/11 11:15:41 gklug - * chg: comments - * - * Revision 1.1 1998/08/11 11:09:38 gklug - * add: error bases - * add: error Classes - * first version - * - * - * - ******************************************************************************/ - -#ifndef _INC_SKERROR_H_ -#define _INC_SKERROR_H_ - -/* - * Define Error Classes - */ -#define SK_ERRCL_OTHER (0) /* Other error */ -#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */ -#define SK_ERRCL_INIT (1L<<1) /* Initialization error */ -#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */ -#define SK_ERRCL_SW (1L<<3) /* Internal Software error */ -#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */ -#define SK_ERRCL_COMM (1L<<5) /* Communication error */ - - -/* - * Define Error Code Bases - */ -#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */ -#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */ -#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */ -#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */ -#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */ -#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */ -#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */ -#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */ -#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */ -#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ -#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */ - -#endif /* _INC_SKERROR_H_ */ diff --git a/drivers/sk98lin/h/skgedrv.h b/drivers/sk98lin/h/skgedrv.h deleted file mode 100644 index 72ba9ce198..0000000000 --- a/drivers/sk98lin/h/skgedrv.h +++ /dev/null @@ -1,72 +0,0 @@ -/****************************************************************************** - * - * Name: skgedrv.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.6 $ - * Date: $Date: 2002/07/15 15:38:01 $ - * Purpose: Interface with the driver - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgedrv.h,v $ - * Revision 1.6 2002/07/15 15:38:01 rschmidt - * Power Management support - * Editorial changes - * - * Revision 1.5 2002/04/25 11:05:47 rschmidt - * Editorial changes - * - * Revision 1.4 1999/11/22 13:52:46 cgoos - * Changed license header to GPL. - * - * Revision 1.3 1998/12/01 13:31:39 cgoos - * SWITCH INTERN Event added. - * - * Revision 1.2 1998/11/25 08:28:38 gklug - * rmv: PORT SWITCH Event - * - * Revision 1.1 1998/09/29 06:14:07 gklug - * add: driver events (initial version) - * - * - ******************************************************************************/ - -#ifndef __INC_SKGEDRV_H_ -#define __INC_SKGEDRV_H_ - -/* defines ********************************************************************/ - -/* - * Define the driver events. - * Usually the events are defined by the destination module. - * In case of the driver we put the definition of the events here. - */ -#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */ -#define SK_DRV_NET_UP 2 /* The net is operational */ -#define SK_DRV_NET_DOWN 3 /* The net is down */ -#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */ -#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */ -#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */ -#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */ -#define SK_DRV_PORT_FAIL 8 /* One port fails */ -#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */ -#define SK_DRV_POWER_DOWN 10 /* Power down mode */ - -#endif /* __INC_SKGEDRV_H_ */ diff --git a/drivers/sk98lin/h/skgehw.h b/drivers/sk98lin/h/skgehw.h deleted file mode 100644 index 2c98427675..0000000000 --- a/drivers/sk98lin/h/skgehw.h +++ /dev/null @@ -1,2336 +0,0 @@ -/****************************************************************************** - * - * Name: skgehw.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.49 $ - * Date: $Date: 2003/01/28 09:43:49 $ - * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skgehw.h,v $ - * Revision 1.49 2003/01/28 09:43:49 rschmidt - * Added defines for PCI-Spec. 2.3 IRQ - * Added defines for CLK_RUN (YUKON-Lite) - * Editorial changes - * - * Revision 1.48 2002/12/05 10:25:11 rschmidt - * Added defines for Half Duplex Burst Mode On/Off - * Added defines for Rx GMAC FIFO Flush feature - * Editorial changes - * - * Revision 1.47 2002/11/12 17:01:31 rschmidt - * Added defines for WOL_CTL_DEFAULT - * Editorial changes - * - * Revision 1.46 2002/10/14 14:47:57 rschmidt - * Corrected bit mask for HW self test results - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.45 2002/10/11 09:25:22 mkarl - * Added bit mask for HW self test results. - * - * Revision 1.44 2002/08/16 14:44:36 rschmidt - * Added define GPC_HWCFG_GMII_FIB for YUKON Fiber - * - * Revision 1.43 2002/08/12 13:31:50 rschmidt - * Corrected macros for GMAC Address Registers: GM_INADDR(), - * GM_OUTADDR(), GM_INHASH, GM_OUTHASH. - * Editorial changes - * - * Revision 1.42 2002/08/08 15:37:56 rschmidt - * Added defines for Power Management Capabilities - * Editorial changes - * - * Revision 1.41 2002/07/23 16:02:25 rschmidt - * Added macro WOL_REG() to access WOL reg. (HW-Bug in YUKON 1st rev.) - * - * Revision 1.40 2002/07/15 15:41:37 rschmidt - * Added new defines for Power Management Cap. & Control - * Editorial changes - * - * Revision 1.39 2002/06/10 09:37:07 rschmidt - * Added macros for the ADDR-Modul - * - * Revision 1.38 2002/06/05 08:15:19 rschmidt - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.37 2002/04/25 11:39:23 rschmidt - * Added new defines for PCI Our Register 1 - * Added new registers and defines for YUKON (Rx FIFO, Tx FIFO, - * Time Stamp Timer, GMAC Control, GPHY Control,Link Control, - * GMAC IRQ Source and Mask, Wake-up Frame Pattern Match); - * Added new defines for Control/Status (VAUX available) - * Added Chip ID for YUKON - * Added define for descriptors with UDP ext. for YUKON - * Added macros to access the GMAC - * Added new Phy Type for Marvell 88E1011S (GPHY) - * Editorial changes - * - * Revision 1.36 2000/11/09 12:32:49 rassmann - * Renamed variables. - * - * Revision 1.35 2000/05/19 10:17:13 cgoos - * Added inactivity check in PHY_READ (in DEBUG mode only). - * - * Revision 1.34 1999/11/22 13:53:40 cgoos - * Changed license header to GPL. - * - * Revision 1.33 1999/08/27 11:17:10 malthoff - * It's more savely to put brackets around macro parameters. - * Brackets added for PHY_READ and PHY_WRITE. - * - * Revision 1.32 1999/05/19 07:31:01 cgoos - * Changes for 1000Base-T. - * Added HWAC_LINK_LED macro. - * - * Revision 1.31 1999/03/12 13:27:40 malthoff - * Remove __STDC__. - * - * Revision 1.30 1999/02/09 09:28:20 malthoff - * Add PCI_ERRBITS. - * - * Revision 1.29 1999/01/26 08:55:48 malthoff - * Bugfix: The 16 bit field relations inside the descriptor are - * endianess dependend if the descriptor reversal feature - * (PCI_REV_DESC bit in PCI_OUR_REG_2) is enabled. - * Drivers which use this feature has to set the define - * SK_USE_REV_DESC. - * - * Revision 1.28 1998/12/10 11:10:22 malthoff - * bug fix: IS_IRQ_STAT and IS_IRQ_MST_ERR has been twisted. - * - * Revision 1.27 1998/11/13 14:19:21 malthoff - * Bug Fix: The bit definition of B3_PA_CTRL has completely - * changed from HW Spec v1.3 to v1.5. - * - * Revision 1.26 1998/11/04 08:31:48 cgoos - * Fixed byte ordering in XM_OUTADDR/XM_OUTHASH macros. - * - * Revision 1.25 1998/11/04 07:16:25 cgoos - * Changed byte ordering in XM_INADDR/XM_INHASH again. - * - * Revision 1.24 1998/11/02 11:08:43 malthoff - * RxCtrl and TxCtrl must be volatile. - * - * Revision 1.23 1998/10/28 13:50:45 malthoff - * Fix: Endian support missing in XM_IN/OUT-ADDR/HASH macros. - * - * Revision 1.22 1998/10/26 08:01:36 malthoff - * RX_MFF_CTRL1 is split up into RX_MFF_CTRL1, - * RX_MFF_STAT_TO, and RX_MFF_TIST_TO. - * TX_MFF_CTRL1 is split up TX_MFF_CTRL1 and TX_MFF_WAF. - * - * Revision 1.21 1998/10/20 07:43:10 malthoff - * Fix: XM_IN/OUT/ADDR/HASH macros: - * The pointer must be casted. - * - * Revision 1.20 1998/10/19 15:53:59 malthoff - * Remove ML proto definitions. - * - * Revision 1.19 1998/10/16 14:40:17 gklug - * fix: typo B0_XM_IMSK regs - * - * Revision 1.18 1998/10/16 09:46:54 malthoff - * Remove temp defines for ML diag prototype. - * Fix register definition for B0_XM1_PHY_DATA, B0_XM1_PHY_DATA - * B0_XM2_PHY_DATA, B0_XM2_PHY_ADDR, B0_XA1_CSR, B0_XS1_CSR, - * B0_XS2_CSR, and B0_XA2_CSR. - * - * Revision 1.17 1998/10/14 06:03:14 cgoos - * Changed shifted constant to ULONG. - * - * Revision 1.16 1998/10/09 07:05:41 malthoff - * Rename ALL_PA_ENA_TO to PA_ENA_TO_ALL. - * - * Revision 1.15 1998/10/05 07:54:23 malthoff - * Split up RB_CTRL and it's bit definition into - * RB_CTRL, RB_TST1, and RB_TST2. - * Rename RB_RX_HTPP to RB_RX_LTPP. - * Add ALL_PA_ENA_TO. Modify F_WATER_MARK - * according to HW Spec. v1.5. - * Add MFF_TX_CTRL_DEF. - * - * Revision 1.14 1998/09/28 13:31:16 malthoff - * bug fix: B2_MAC_3 is 0x110 not 0x114 - * - * Revision 1.13 1998/09/24 14:42:56 malthoff - * Split the RX_MFF_TST into RX_MFF_CTRL2, - * RX_MFF_TST1, and RX_MFF_TST2. - * Rename RX_MFF_CTRL to RX_MFF_CTRL1. - * Add BMU bit CSR_SV_IDLE. - * Add macros PHY_READ() and PHY_WRITE(). - * Rename macro SK_ADDR() to SK_HW_ADDR() - * because of conflicts with the Address Module. - * - * Revision 1.12 1998/09/16 07:25:33 malthoff - * Change the parameter order in the XM_INxx and XM_OUTxx macros, - * to have the IoC as first parameter. - * - * Revision 1.11 1998/09/03 09:58:41 malthoff - * Rework the XM_xxx macros. Use {} instead of () to - * be compatible with SK_xxx macros which are defined - * with {}. - * - * Revision 1.10 1998/09/02 11:16:39 malthoff - * Temporary modify B2_I2C_SW to make tests with - * the GE/ML prototype. - * - * Revision 1.9 1998/08/19 09:11:49 gklug - * fix: struct are removed from c-source (see CCC) - * add: typedefs for all structs - * - * Revision 1.8 1998/08/18 08:27:27 malthoff - * Add some temporary workarounds to test GE - * sources with the ML. - * - * Revision 1.7 1998/07/03 14:42:26 malthoff - * bug fix: Correct macro XMA(). - * Add temporary workaround to access the PCI config space over I/O - * - * Revision 1.6 1998/06/23 11:30:36 malthoff - * Remove ';' with ',' in macors. - * - * Revision 1.5 1998/06/22 14:20:57 malthoff - * Add macro SK_ADDR(Base,Addr). - * - * Revision 1.4 1998/06/19 13:35:43 malthoff - * change 'pGec' with 'pAC' - * - * Revision 1.3 1998/06/17 14:58:16 cvs - * Lost keywords reinserted. - * - * Revision 1.1 1998/06/17 14:16:36 cvs - * created - * - * - ******************************************************************************/ - -#ifndef __INC_SKGEHW_H -#define __INC_SKGEHW_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -#define BIT_31 (1UL << 31) -#define BIT_30 (1L << 30) -#define BIT_29 (1L << 29) -#define BIT_28 (1L << 28) -#define BIT_27 (1L << 27) -#define BIT_26 (1L << 26) -#define BIT_25 (1L << 25) -#define BIT_24 (1L << 24) -#define BIT_23 (1L << 23) -#define BIT_22 (1L << 22) -#define BIT_21 (1L << 21) -#define BIT_20 (1L << 20) -#define BIT_19 (1L << 19) -#define BIT_18 (1L << 18) -#define BIT_17 (1L << 17) -#define BIT_16 (1L << 16) -#define BIT_15 (1L << 15) -#define BIT_14 (1L << 14) -#define BIT_13 (1L << 13) -#define BIT_12 (1L << 12) -#define BIT_11 (1L << 11) -#define BIT_10 (1L << 10) -#define BIT_9 (1L << 9) -#define BIT_8 (1L << 8) -#define BIT_7 (1L << 7) -#define BIT_6 (1L << 6) -#define BIT_5 (1L << 5) -#define BIT_4 (1L << 4) -#define BIT_3 (1L << 3) -#define BIT_2 (1L << 2) -#define BIT_1 (1L << 1) -#define BIT_0 1L - -#define BIT_15S (1U << 15) -#define BIT_14S (1 << 14) -#define BIT_13S (1 << 13) -#define BIT_12S (1 << 12) -#define BIT_11S (1 << 11) -#define BIT_10S (1 << 10) -#define BIT_9S (1 << 9) -#define BIT_8S (1 << 8) -#define BIT_7S (1 << 7) -#define BIT_6S (1 << 6) -#define BIT_5S (1 << 5) -#define BIT_4S (1 << 4) -#define BIT_3S (1 << 3) -#define BIT_2S (1 << 2) -#define BIT_1S (1 << 1) -#define BIT_0S 1 - -#define SHIFT31(x) ((x) << 31) -#define SHIFT30(x) ((x) << 30) -#define SHIFT29(x) ((x) << 29) -#define SHIFT28(x) ((x) << 28) -#define SHIFT27(x) ((x) << 27) -#define SHIFT26(x) ((x) << 26) -#define SHIFT25(x) ((x) << 25) -#define SHIFT24(x) ((x) << 24) -#define SHIFT23(x) ((x) << 23) -#define SHIFT22(x) ((x) << 22) -#define SHIFT21(x) ((x) << 21) -#define SHIFT20(x) ((x) << 20) -#define SHIFT19(x) ((x) << 19) -#define SHIFT18(x) ((x) << 18) -#define SHIFT17(x) ((x) << 17) -#define SHIFT16(x) ((x) << 16) -#define SHIFT15(x) ((x) << 15) -#define SHIFT14(x) ((x) << 14) -#define SHIFT13(x) ((x) << 13) -#define SHIFT12(x) ((x) << 12) -#define SHIFT11(x) ((x) << 11) -#define SHIFT10(x) ((x) << 10) -#define SHIFT9(x) ((x) << 9) -#define SHIFT8(x) ((x) << 8) -#define SHIFT7(x) ((x) << 7) -#define SHIFT6(x) ((x) << 6) -#define SHIFT5(x) ((x) << 5) -#define SHIFT4(x) ((x) << 4) -#define SHIFT3(x) ((x) << 3) -#define SHIFT2(x) ((x) << 2) -#define SHIFT1(x) ((x) << 1) -#define SHIFT0(x) ((x) << 0) - -/* - * Configuration Space header - * Since this module is used for different OS', those may be - * duplicate on some of them (e.g. Linux). But to keep the - * common source, we have to live with this... - */ -#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */ -#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */ -#define PCI_COMMAND 0x04 /* 16 bit Command */ -#define PCI_STATUS 0x06 /* 16 bit Status */ -#define PCI_REV_ID 0x08 /* 8 bit Revision ID */ -#if 0 -#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */ -#endif -#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */ -#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */ -#define PCI_HEADER_T 0x0e /* 8 bit Header Type */ -#define PCI_BIST 0x0f /* 8 bit Built-in selftest */ -#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */ -#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */ - /* Byte 0x18..0x2b: reserved */ -#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */ -#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */ -#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */ -#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */ - /* Byte 35..3b: reserved */ -#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */ -#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */ -#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */ -#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */ - /* Device Dependent Region */ -#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ -#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ - /* Power Management Region */ -#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ -#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */ -#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ -#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ - /* Byte 0x4e: reserved */ -#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ - /* VPD Region */ -#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ -#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */ -#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ -#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ - /* Byte 0x58..0xff: reserved */ - -/* - * I2C Address (PCI Config) - * - * Note: The temperature and voltage sensors are relocated on a different - * I2C bus. - */ -#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */ - -/* - * Define Bits and Values of the registers - */ -/* PCI_COMMAND 16 bit Command */ - /* Bit 15..11: reserved */ -#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */ -#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */ -#define PCI_SERREN BIT_8S /* SERR enable */ -#define PCI_ADSTEP BIT_7S /* Address Stepping */ -#define PCI_PERREN BIT_6S /* Parity Report Response enable */ -#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */ -#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */ -#define PCI_SCYCEN BIT_3S /* Special Cycle enable */ -#define PCI_BMEN BIT_2S /* Bus Master enable */ -#define PCI_MEMEN BIT_1S /* Memory Space Access enable */ -#define PCI_IOEN BIT_0S /* I/O Space Access enable */ - -#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\ - PCI_BMEN | PCI_MEMEN | PCI_IOEN) - -/* PCI_STATUS 16 bit Status */ -#define PCI_PERR BIT_15S /* Parity Error */ -#define PCI_SERR BIT_14S /* Signaled SERR */ -#define PCI_RMABORT BIT_13S /* Received Master Abort */ -#define PCI_RTABORT BIT_12S /* Received Target Abort */ - /* Bit 11: reserved */ -#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */ -#define PCI_DEV_FAST (0<<9) /* fast */ -#define PCI_DEV_MEDIUM (1<<9) /* medium */ -#define PCI_DEV_SLOW (2<<9) /* slow */ -#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */ -#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */ -#define PCI_UDF BIT_6S /* User Defined Features */ -#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */ -#define PCI_NEWCAP BIT_4S /* New cap. list implemented */ -#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */ - /* Bit 2.. 0: reserved */ - -#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\ - PCI_DATAPERR) - -/* PCI_CLASS_CODE 24 bit Class Code */ -/* Byte 2: Base Class (02) */ -/* Byte 1: SubClass (00) */ -/* Byte 0: Programming Interface (00) */ - -/* PCI_CACHE_LSZ 8 bit Cache Line Size */ -/* Possible values: 0,2,4,8,16,32,64,128 */ - -/* PCI_HEADER_T 8 bit Header Type */ -#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */ -#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */ - -/* PCI_BIST 8 bit Built-in selftest */ -/* Built-in Self test not supported (optional) */ - -/* PCI_BASE_1ST 32 bit 1st Base address */ -#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */ -#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */ -#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */ -#define PCI_PREFEN BIT_3 /* Prefetchable */ -#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */ -#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */ -#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */ -#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */ -#define PCI_MEMSPACE BIT_0 /* Memory Space Indic. */ - -/* PCI_BASE_2ND 32 bit 2nd Base address */ -#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */ -#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */ - /* Bit 1: reserved */ -#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */ - -/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */ -#define PCI_ROMBASE 0xfffe0000L /* Bit 31..17: ROM BASE address (1st)*/ -#define PCI_ROMBASZ (0x1cL<<14) /* Bit 16..14: Treat as BASE or SIZE */ -#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */ - /* Bit 10.. 1: reserved */ -#define PCI_ROMEN BIT_0 /* Address Decode enable */ - -/* Device Dependent Region */ -/* PCI_OUR_REG_1 32 bit Our Register 1 */ - /* Bit 31..29: reserved */ -#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode */ -#define PCI_EN_CAL BIT_27 /* Enable PCI buffer strength calibr. */ -#define PCI_DIS_CAL BIT_26 /* Disable PCI buffer strength calibr. */ -#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */ -#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */ -#define PCI_EN_IO BIT_23 /* Mapping to I/O space */ -#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */ - /* 1 = Map Flash to memory */ - /* 0 = Disable addr. dec */ -#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */ -#define PCI_PAGE_16 (0L<<20) /* 16 k pages */ -#define PCI_PAGE_32K (1L<<20) /* 32 k pages */ -#define PCI_PAGE_64K (2L<<20) /* 64 k pages */ -#define PCI_PAGE_128K (3L<<20) /* 128 k pages */ - /* Bit 19: reserved */ -#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ -#define PCI_NOTAR BIT_15 /* No turnaround cycle */ -#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */ -#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */ -#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */ -#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */ -#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */ -#define PCI_BURST_DIS BIT_9 /* Burst Disable */ -#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */ -#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */ -#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */ - - -/* PCI_OUR_REG_2 32 bit Our Register 2 */ -#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */ -#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */ -#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */ - /* Bit 13..12: reserved */ -#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */ -#define PCI_PATCH_DIR_3 BIT_11 -#define PCI_PATCH_DIR_2 BIT_10 -#define PCI_PATCH_DIR_1 BIT_9 -#define PCI_PATCH_DIR_0 BIT_8 -#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */ -#define PCI_EXT_PATCH_3 BIT_7 -#define PCI_EXT_PATCH_2 BIT_6 -#define PCI_EXT_PATCH_1 BIT_5 -#define PCI_EXT_PATCH_0 BIT_4 -#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */ -#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */ - /* Bit 1: reserved */ -#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */ - - -/* Power Management Region */ -/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */ -#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */ -#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */ -#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */ -#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */ -#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */ -#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */ -#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */ -#define PCI_PM_D1_SUP BIT_9S /* D1 Support */ - /* Bit 8.. 6: reserved */ -#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */ -#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */ -#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */ -#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */ - -/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */ -#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */ -#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */ -#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */ -#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */ - /* Bit 7.. 2: reserved */ -#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */ - -#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */ -#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */ -#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */ -#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */ - -/* VPD Region */ -/* PCI_VPD_ADR_REG 16 bit VPD Address Register */ -#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */ -#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */ - -/* Control Register File (Address Map) */ - -/* - * Bank 0 - */ -#define B0_RAP 0x0000 /* 8 bit Register Address Port */ - /* 0x0001 - 0x0003: reserved */ -#define B0_CTST 0x0004 /* 16 bit Control/Status register */ -#define B0_LED 0x0006 /* 8 Bit LED register */ -#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */ -#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */ -#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */ -#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */ -#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */ -#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */ - /* 0x001c: reserved */ - -/* B0 XMAC 1 registers (GENESIS only) */ -#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/ - /* 0x0022 - 0x0027: reserved */ -#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */ - /* 0x002a - 0x002f: reserved */ -#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */ - /* 0x0032 - 0x0033: reserved */ -#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */ - /* 0x0036 - 0x003f: reserved */ - -/* B0 XMAC 2 registers (GENESIS only) */ -#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/ - /* 0x0042 - 0x0047: reserved */ -#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */ - /* 0x004a - 0x004f: reserved */ -#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */ - /* 0x0052 - 0x0053: reserved */ -#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */ - /* 0x0056 - 0x005f: reserved */ - -/* BMU Control Status Registers */ -#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */ -#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */ -#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/ -#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/ - /* 0x0078 - 0x007f: reserved */ - -/* - * Bank 1 - * - completely empty (this is the RAP Block window) - * Note: if RAP = 1 this page is reserved - */ - -/* - * Bank 2 - */ -/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */ -#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */ - /* 0x0106 - 0x0107: reserved */ -#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */ - /* 0x010e - 0x010f: reserved */ -#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */ - /* 0x0116 - 0x0117: reserved */ -#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */ -#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */ -#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */ -#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ - /* Eprom registers are currently of no use */ -#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */ -#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */ -#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */ -#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */ -#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ -#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ - /* 0x0125 - 0x0127: reserved */ -#define B2_LD_CRTL 0x0128 /* 8 bit EPROM loader control register */ -#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ - /* 0x012a - 0x012f: reserved */ -#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ -#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ -#define B2_TI_CRTL 0x0138 /* 8 bit Timer Control */ -#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ - /* 0x013a - 0x013f: reserved */ -#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ -#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */ -#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */ -#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */ -#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */ -#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */ - /* 0x0154 - 0x0157: reserved */ -#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */ -#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */ - /* 0x015a - 0x015b: reserved */ -#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */ -#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */ -#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */ -#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */ -#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */ - -/* Blink Source Counter (GENESIS only) */ -#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */ -#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */ -#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */ -#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */ -#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */ - /* 0x017c - 0x017f: reserved */ - -/* - * Bank 3 - */ -/* RAM Random Registers */ -#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */ -#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */ -#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */ - /* 0x018c - 0x018f: reserved */ - -/* RAM Interface Registers */ -/* - * The HW-Spec. calls this registers Timeout Value 0..11. But this names are - * not usable in SW. Please notice these are NOT real timeouts, these are - * the number of qWords transferred continuously. - */ -#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */ -#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */ -#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */ -#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */ -#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */ -#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */ -#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */ -#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */ -#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */ -#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */ -#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/ -#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/ -#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */ - /* 0x019d - 0x019f: reserved */ -#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */ -#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */ - /* 0x01a3 - 0x01af: reserved */ - -/* MAC Arbiter Registers (GENESIS only) */ -/* these are the no. of qWord transferred continuously and NOT real timeouts */ -#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */ -#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */ -#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */ -#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */ -#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */ -#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */ - /* 0x01bc - 0x01bf: reserved */ -#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */ -#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */ -#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */ -#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */ -#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */ -#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */ - /* 0x01cc - 0x01cf: reserved */ - -/* Packet Arbiter Registers (GENESIS only) */ -/* these are real timeouts */ -#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */ - /* 0x01d2 - 0x01d3: reserved */ -#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */ - /* 0x01d6 - 0x01d7: reserved */ -#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */ - /* 0x01da - 0x01db: reserved */ -#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */ - /* 0x01de - 0x01df: reserved */ -#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */ - /* 0x01e2 - 0x01e3: reserved */ -#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */ - /* 0x01e6 - 0x01e7: reserved */ -#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */ - /* 0x01ea - 0x01eb: reserved */ -#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */ - /* 0x01ee - 0x01ef: reserved */ -#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ -#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ - /* 0x01f4 - 0x01ff: reserved */ - -/* - * Bank 4 - 5 - */ -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/ -#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */ -#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */ -#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */ -#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */ -#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */ -#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */ - /* 0x0213 - 0x027f: reserved */ - /* 0x0280 - 0x0292: MAC 2 */ - /* 0x0213 - 0x027f: reserved */ - -/* - * Bank 6 - */ -/* External registers (GENESIS only) */ -#define B6_EXT_REG 0x0300 - -/* - * Bank 7 - */ -/* This is a copy of the Configuration register file (lower half) */ -#define B7_CFG_SPC 0x0380 - -/* - * Bank 8 - 15 - */ -/* Receive and Transmit Queue Registers, use Q_ADDR() to access */ -#define B8_Q_REGS 0x0400 - -/* Queue Register Offsets, use Q_ADDR() to access */ -#define Q_D 0x00 /* 8*32 bit Current Descriptor */ -#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */ -#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */ -#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */ -#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */ -#define Q_BC 0x30 /* 32 bit Current Byte Counter */ -#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */ -#define Q_F 0x38 /* 32 bit Flag Register */ -#define Q_T1 0x3c /* 32 bit Test Register 1 */ -#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */ -#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */ -#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */ -#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */ -#define Q_T2 0x40 /* 32 bit Test Register 2 */ -#define Q_T3 0x44 /* 32 bit Test Register 3 */ - /* 0x48 - 0x7f: reserved */ - -/* - * Bank 16 - 23 - */ -/* RAM Buffer Registers */ -#define B16_RAM_REGS 0x0800 - -/* RAM Buffer Register Offsets, use RB_ADDR() to access */ -#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */ -#define RB_END 0x04 /* 32 bit RAM Buffer End Address */ -#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */ -#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */ -#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */ -#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */ -#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */ -#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */ - /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ -#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */ -#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */ -#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */ -#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */ -#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */ - /* 0x2c - 0x7f: reserved */ - -/* - * Bank 24 - */ -/* - * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) - * use MR_ADDR() to access - */ -#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */ -#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ - /* 0x0c08 - 0x0c0b: reserved */ -#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */ -#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */ -#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */ -#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/ -#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */ -#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */ -#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/ -#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */ -#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */ - /* 0x0c1f: reserved */ -#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */ -#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */ -#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */ -#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */ - /* 0x0c2a - 0x0c2f: reserved */ -#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */ -#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */ -#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */ -#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */ - /* 0x0c3a - 0x0c3b: reserved */ -#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */ - /* 0x0c3d - 0x0c3f: reserved */ - -/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */ -#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */ -#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */ -#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ -#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ - /* 0x0c54 - 0x0c5f: reserved */ -#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ - /* 0x0c64 - 0x0c67: reserved */ -#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ - /* 0x0c6c - 0x0c6f: reserved */ -#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ - /* 0x0c74 - 0x0c77: reserved */ -#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ - /* 0x0c7c - 0x0c7f: reserved */ - -/* - * Bank 25 - */ - /* 0x0c80 - 0x0cbf: MAC 2 */ - /* 0x0cc0 - 0x0cff: reserved */ - -/* - * Bank 26 - */ -/* - * Transmit MAC FIFO and Transmit LED Registers (GENESIS only), - * use MR_ADDR() to access - */ -#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */ -#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ -#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */ -#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */ -#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */ -#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */ -#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ -#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */ - /* 0x0c1b: reserved */ -#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ -#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */ -#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */ - /* 0x0d1f: reserved */ -#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */ -#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */ -#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */ -#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */ - /* 0x0d2a - 0x0d3f: reserved */ - -/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */ -#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */ - /* 0x0d4c - 0x0d5f: reserved */ -#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ -#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ - /* 0x0d6c - 0x0d6f: reserved */ -#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ -#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ -#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ - /* 0x0d7c - 0x0d7f: reserved */ - -/* - * Bank 27 - */ - /* 0x0d80 - 0x0dbf: MAC 2 */ - /* 0x0daa - 0x0dff: reserved */ - -/* - * Bank 28 - */ -/* Descriptor Poll Timer Registers */ -#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */ -#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */ -#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */ - /* 0x0e09: reserved */ -#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */ - /* 0x0e0b: reserved */ - -/* Time Stamp Timer Registers (YUKON only) */ - /* 0x0e10: reserved */ -#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */ -#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */ - /* 0x0e19: reserved */ -#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */ - /* 0x0e1b - 0x0e7f: reserved */ - -/* - * Bank 29 - */ - /* 0x0e80 - 0x0efc: reserved */ - -/* - * Bank 30 - */ -/* GMAC and GPHY Control Registers (YUKON only) */ -#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */ -#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */ -#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */ - /* 0x0f09 - 0x0f0b: reserved */ -#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */ - /* 0x0f0d - 0x0f0f: reserved */ -#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */ - /* 0x0f14 - 0x0f1f: reserved */ - -/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ - -#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */ - -#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */ -#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */ -#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */ -#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */ -#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */ -#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */ - -/* use this macro to access above registers */ -#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs)) - - -/* WOL Pattern Length Registers (YUKON only) */ - -#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */ -#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */ - -/* WOL Pattern Counter Registers (YUKON only) */ - -#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */ -#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */ - /* 0x0f40 - 0x0f7f: reserved */ - -/* - * Bank 31 - */ -/* 0x0f80 - 0x0fff: reserved */ - -/* - * Bank 32 - 33 - */ -#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */ - -/* - * Bank 0x22 - 0x3f - */ -/* 0x1100 - 0x1fff: reserved */ - -/* - * Bank 0x40 - 0x4f - */ -#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */ - -/* - * Bank 0x50 - 0x5f - */ - -#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */ - -/* - * Bank 0x60 - 0x6f - */ -#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */ - -/* - * Bank 0x70 - 0x7f - */ -#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */ - -/* - * Control Register Bit Definitions: - */ -/* B0_RAP 8 bit Register Address Port */ - /* Bit 7: reserved */ -#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ - -/* B0_CTST 16 bit Control/Status register */ - /* Bit 15..14: reserved */ -#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ -#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ -#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */ -#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */ -#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */ -#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */ -#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */ -#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */ -#define CS_STOP_DONE BIT_5S /* Stop Master is finished */ -#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */ -#define CS_MRST_CLR BIT_3S /* Clear Master reset */ -#define CS_MRST_SET BIT_2S /* Set Master reset */ -#define CS_RST_CLR BIT_1S /* Clear Software reset */ -#define CS_RST_SET BIT_0S /* Set Software reset */ - -/* B0_LED 8 Bit LED register */ - /* Bit 7.. 2: reserved */ -#define LED_STAT_ON BIT_1S /* Status LED on */ -#define LED_STAT_OFF BIT_0S /* Status LED off */ - -/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ -#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */ -#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ -#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ -#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ -#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ -#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ -#define PC_VCC_ON BIT_1 /* Switch VCC On */ -#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ - -/* B0_ISRC 32 bit Interrupt Source Register */ -/* B0_IMSK 32 bit Interrupt Mask Register */ -/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ -/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -#define IS_ALL_MSK 0xbfffffffL /* All Interrupt bits */ -#define IS_HW_ERR BIT_31 /* Interrupt HW Error */ - /* Bit 30: reserved */ -#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */ -#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */ -#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */ -#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */ -#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */ -#define IS_IRQ_SW BIT_24 /* SW forced IRQ */ -#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */ - /* IRQ from PHY (YUKON only) */ -#define IS_TIMINT BIT_22 /* IRQ from Timer */ -#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */ -#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */ -#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */ -#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */ -/* Receive Queue 1 */ -#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */ -#define IS_R1_F BIT_16 /* Q_R1 End of Frame */ -#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */ -/* Receive Queue 2 */ -#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */ -#define IS_R2_F BIT_13 /* Q_R2 End of Frame */ -#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */ -/* Synchronous Transmit Queue 1 */ -#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */ -#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */ -#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */ -/* Asynchronous Transmit Queue 1 */ -#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */ -#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */ -#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */ -/* Synchronous Transmit Queue 2 */ -#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */ -#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */ -#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */ -/* Asynchronous Transmit Queue 2 */ -#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */ -#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */ -#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ - - -/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ -/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -#define IS_ERR_MSK 0x00000fffL /* All Error bits */ - /* Bit 31..14: reserved */ -#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ -#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */ -#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */ -#define IS_IRQ_STAT BIT_10 /* IRQ status exception */ -#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */ -#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */ -#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */ -#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */ -#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */ -#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */ -#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */ -#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */ -#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ -#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ - -/* B2_CONN_TYP 8 bit Connector type */ -/* B2_PMD_TYP 8 bit PMD type */ -/* Values of connector and PMD type comply to SysKonnect internal std */ - -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ -#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ - /* Bit 3.. 2: reserved */ -#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ -#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ - -/* B2_CHIP_ID 8 bit Chip Identification Number */ -#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ -#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ - -/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ -#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ - -/* B2_LD_CRTL 8 bit EPROM loader control register */ -/* Bits are currently reserved */ - -/* B2_LD_TEST 8 bit EPROM loader test register */ - /* Bit 7.. 4: reserved */ -#define LD_T_ON BIT_3S /* Loader Test mode on */ -#define LD_T_OFF BIT_2S /* Loader Test mode off */ -#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */ -#define LD_START BIT_0S /* Start loading FPROM */ - -/* - * Timer Section - */ -/* B2_TI_CRTL 8 bit Timer control */ -/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ - /* Bit 7.. 3: reserved */ -#define TIM_START BIT_2S /* Start Timer */ -#define TIM_STOP BIT_1S /* Stop Timer */ -#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ - -/* B2_TI_TEST 8 Bit Timer Test */ -/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ - /* Bit 7.. 3: reserved */ -#define TIM_T_ON BIT_2S /* Test mode on */ -#define TIM_T_OFF BIT_1S /* Test mode off */ -#define TIM_T_STEP BIT_0S /* Test step */ - -/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */ -/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */ - /* Bit 31..24: reserved */ -#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */ - -/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ - /* Bit 7.. 2: reserved */ -#define DPT_START BIT_1S /* Start Descriptor Poll Timer */ -#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */ - -/* B2_E_3 8 bit lower 4 bits used for HW self test result */ -#define B2_E3_RES_MASK 0x0f - -/* B2_TST_CTRL1 8 bit Test Control Register 1 */ -#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */ -#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */ -#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */ -#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */ -#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */ -#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */ -#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */ -#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */ - -/* B2_TST_CTRL2 8 bit Test Control Register 2 */ - /* Bit 7.. 4: reserved */ - /* force the following error on the next master read/write */ -#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */ -#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */ -#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ -#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ - -/* B2_GP_IO 32 bit General Purpose I/O Register */ - /* Bit 31..26: reserved */ -#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=I/1=O */ -#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=I/1=O */ -#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=I/1=O */ -#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=I/1=O */ -#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=I/1=O */ -#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=I/1=O */ -#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=I/1=O */ -#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=I/1=O */ -#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=I/1=O */ -#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=I/1=O */ - /* Bit 15..10: reserved */ -#define GP_IO_9 BIT_9 /* IO_9 pin */ -#define GP_IO_8 BIT_8 /* IO_8 pin */ -#define GP_IO_7 BIT_7 /* IO_7 pin */ -#define GP_IO_6 BIT_6 /* IO_6 pin */ -#define GP_IO_5 BIT_5 /* IO_5 pin */ -#define GP_IO_4 BIT_4 /* IO_4 pin */ -#define GP_IO_3 BIT_3 /* IO_3 pin */ -#define GP_IO_2 BIT_2 /* IO_2 pin */ -#define GP_IO_1 BIT_1 /* IO_1 pin */ -#define GP_IO_0 BIT_0 /* IO_0 pin */ - -/* B2_I2C_CTRL 32 bit I2C HW Control Register */ -#define I2C_FLAG BIT_31 /* Start read/write if WR */ -#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ -#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ - /* Bit 8.. 5: reserved */ -#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ -#define I2C_DEV_SIZE (7L<<1) /* Bit 3.. 1: I2C Device Size */ -#define I2C_025K_DEV (0L<<1) /* 0: 256 Bytes or smal. */ -#define I2C_05K_DEV (1L<<1) /* 1: 512 Bytes */ -#define I2C_1K_DEV (2L<<1) /* 2: 1024 Bytes */ -#define I2C_2K_DEV (3L<<1) /* 3: 2048 Bytes */ -#define I2C_4K_DEV (4L<<1) /* 4: 4096 Bytes */ -#define I2C_8K_DEV (5L<<1) /* 5: 8192 Bytes */ -#define I2C_16K_DEV (6L<<1) /* 6: 16384 Bytes */ -#define I2C_32K_DEV (7L<<1) /* 7: 32768 Bytes */ -#define I2C_STOP BIT_0 /* Interrupt I2C transfer */ - -/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ - /* Bit 31.. 1 reserved */ -#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ - -/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ - /* Bit 7.. 3: reserved */ -#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ -#define I2C_DATA BIT_1S /* I2C Data Port */ -#define I2C_CLK BIT_0S /* I2C Clock Port */ - -/* - * I2C Address - */ -#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ - - -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ - /* Bit 7.. 2: reserved */ -#define BSC_START BIT_1S /* Start Blink Source Counter */ -#define BSC_STOP BIT_0S /* Stop Blink Source Counter */ - -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ - /* Bit 7.. 1: reserved */ -#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ - -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ -#define BSC_T_ON BIT_2S /* Test mode on */ -#define BSC_T_OFF BIT_1S /* Test mode off */ -#define BSC_T_STEP BIT_0S /* Test step */ - - -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ - /* Bit 31..19: reserved */ -#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ - -/* RAM Interface Registers */ -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ - /* Bit 15..10: reserved */ -#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ -#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ - /* Bit 7.. 2: reserved */ -#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ -#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ - -/* B3_RI_TEST 8 bit RAM Iface Test Register */ - /* Bit 15.. 4: reserved */ -#define RI_T_EV BIT_3S /* Timeout Event occured */ -#define RI_T_ON BIT_2S /* Timeout Timer Test On */ -#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */ -#define RI_T_STEP BIT_0S /* Timeout Timer Step */ - -/* MAC Arbiter Registers */ -/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ - /* Bit 15.. 4: reserved */ -#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */ -#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */ -#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */ - /* Bit 15.. 8: reserved */ -#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */ -#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */ -#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */ -#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */ -#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */ -#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */ -#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */ -#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ - -/* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ - /* Bit 15..14: reserved */ -#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ -#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ -#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */ -#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */ -#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */ -#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */ -#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */ -#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */ -#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */ -#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */ -#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */ -#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */ -#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ - PA_ENA_TO_TX1 | PA_ENA_TO_TX2) - -/* Rx/Tx Path related Arbiter Test Registers */ -/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ -/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ -/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ -/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ -#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ -#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ -#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */ -#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */ -#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */ -#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */ -#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */ -#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */ -#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */ -#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */ -#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */ -#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */ -#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */ -#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */ -#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */ -#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */ - - -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ - /* Bit 31..24: reserved */ -#define TXA_MAX_VAL 0x00ffffffL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ - -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ -#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ -#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ -#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ -#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */ -#define TXA_START_RC BIT_3S /* Start sync Rate Control */ -#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */ -#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ -#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ - -/* TXA_TEST 8 bit Tx Arbiter Test Register */ - /* Bit 7.. 6: reserved */ -#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ -#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ -#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */ -#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */ -#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ -#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ - -/* TXA_STAT 8 bit Tx Arbiter Status Register */ - /* Bit 7.. 1: reserved */ -#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ - -/* Q_BC 32 bit Current Byte Counter */ - /* Bit 31..16: reserved */ -#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ - -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ - /* Bit 31..25: reserved */ -#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ - /* Bit 23..22: reserved */ -#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */ -#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */ -#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */ -#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */ -#define CSR_HPI_RUN BIT_17 /* Release HPI SM */ -#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */ -#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */ -#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */ -#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */ -#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */ -#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */ -#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */ -#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */ -#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */ -#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */ -#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */ -#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */ -#define CSR_START BIT_4 /* Start Rx/Tx Queue */ -#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */ -#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */ -#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */ -#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */ - -#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ - CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ - CSR_TRANS_RST) -#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ - CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ - CSR_TRANS_RUN) - -/* Q_F 32 bit Flag Register */ - /* Bit 31..28: reserved */ -#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ -#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ -#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ -#define F_WM_REACHED BIT_25 /* Watermark reached */ - /* reserved */ -#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */ - /* Bit 15..11: reserved */ -#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ - -/* Q_T1 32 bit Test Register 1 */ -/* Holds four State Machine control Bytes */ -#define SM_CRTL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ -#define SM_CRTL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ -#define SM_CRTL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ -#define SM_CRTL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ - -/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ -/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ -/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ -/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ - -/* The control status byte of each machine looks like ... */ -#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ -#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */ -#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */ -#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */ -#define SM_STEP BIT_0S /* Step the State Machine */ -/* The encoding of the states is not supported by the Diagnostics Tool */ - -/* Q_T2 32 bit Test Register 2 */ - /* Bit 31.. 8: reserved */ -#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ -#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ -#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */ -#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */ -#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */ -#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */ -#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ -#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ - -/* Q_T3 32 bit Test Register 3 */ - /* Bit 31.. 7: reserved */ -#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ - /* Bit 3: reserved */ -#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ - -/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ - /* Bit 31..19: reserved */ -#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ - -/* RB_TST2 8 bit RAM Buffer Test Register 2 */ - /* Bit 7.. 4: reserved */ -#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */ -#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */ -#define RB_PC_INC BIT_0S /* Packet Counter Increm */ - -/* RB_TST1 8 bit RAM Buffer Test Register 1 */ - /* Bit 7: reserved */ -#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define RB_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RB_CTRL 8 bit RAM Buffer Control Register */ - /* Bit 7.. 6: reserved */ -#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */ -#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */ -#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */ -#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */ - - -/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ - -/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ -/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ -/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ -/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ -/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ -/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ -/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ -/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ -/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ -/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ -/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ - /* Bit 31.. 6: reserved */ -#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ - -/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ - /* Bit 15..14: reserved */ -#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */ -#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */ -#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */ -#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */ -#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */ -#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */ -#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */ -#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */ -#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */ -#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */ -#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */ -#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */ -#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */ -#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */ - -#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT - -/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ -#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */ - /* Bit 14: reserved */ -#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */ -#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */ -/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */ -/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */ -/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */ -/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */ -#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */ -#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */ -/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */ -/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */ -#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */ -#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */ -#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */ -#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */ - -#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) - -/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ -/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ - /* Bit 7: reserved */ -#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */ -#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */ -#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */ -#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */ -#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */ -#define MFF_PC_INC BIT_0S /* Packet Counter Increment */ - -/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ -/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ - /* Bit 7: reserved */ -#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define MFF_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ -/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ - /* Bit 7..4: reserved */ -#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */ -#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */ - - -/* Link LED Counter Registers (GENESIS only) */ - -/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ -/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ -/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ - /* Bit 7.. 3: reserved */ -#define LED_START BIT_2S /* Start Timer */ -#define LED_STOP BIT_1S /* Stop Timer */ -#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */ -#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */ - -/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ -/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ -/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ - /* Bit 7.. 3: reserved */ -#define LED_T_ON BIT_2S /* LED Counter Test mode On */ -#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */ -#define LED_T_STEP BIT_0S /* LED Counter Step */ - -/* LNK_LED_REG 8 bit Link LED Register */ - /* Bit 7.. 6: reserved */ -#define LED_BLK_ON BIT_5S /* Link LED Blinking On */ -#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */ -#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */ -#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */ -#define LED_ON BIT_1S /* switch LED on */ -#define LED_OFF BIT_0S /* switch LED off */ - -/* Receive and Transmit GMAC FIFO Registers (YUKON only) */ - -/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */ -/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */ -/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ -/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ -/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ -/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ -/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ -/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ -/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ -/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ -/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ -/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ - -/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ - /* Bits 31..15: reserved */ -#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ -#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ -#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ - /* Bit 11: reserved */ -#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ -#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ -#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ -#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ -#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ -#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ -#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ -#define GMF_OPER_ON BIT_3 /* Operational Mode On */ -#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ -#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ -#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ - -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ - /* Bits 31..19: reserved */ -#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ -#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ -#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ - /* Bits 15..7: same as for RX_GMF_CTRL_T */ -#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ -#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ -#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ - /* Bits 3..0: same as for RX_GMF_CTRL_T */ - -#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON) -#define GMF_TX_CTRL_DEF GMF_OPER_ON - -#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ - -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ - /* Bit 7.. 3: reserved */ -#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ -#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ -#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ - -/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ - /* Bits 31.. 8: reserved */ -#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ -#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ -#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ -#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ -#define GMC_PAUSE_ON BIT_3 /* Pause On */ -#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ -#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ -#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ - -/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ - /* Bits 31..29: reserved */ -#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */ -#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */ -#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */ -#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */ -#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */ -#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */ -#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */ -#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */ -#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */ -#define GPC_ANEG_0 BIT_19 /* ANEG[0] */ -#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */ -#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */ -#define GPC_ANEG_3 BIT_16 /* ANEG[3] */ -#define GPC_ANEG_2 BIT_15 /* ANEG[2] */ -#define GPC_ANEG_1 BIT_14 /* ANEG[1] */ -#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */ -#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */ -#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */ -#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */ -#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */ -#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */ - /* Bits 7..2: reserved */ -#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */ -#define GPC_RST_SET BIT_0 /* Set GPHY Reset */ - -#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \ - GPC_ANEG_1 | GPC_ANEG_0) - -/* forced speed and duplex mode (don't mix with other ANEG bits) */ -#define GPC_FRC10MBIT_HALF 0 -#define GPC_FRC10MBIT_FULL GPC_ANEG_0 -#define GPC_FRC100MBIT_HALF GPC_ANEG_1 -#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) - -/* auto-negotiation with limited advertised speeds */ -/* mix only with master/slave settings (for copper) */ -#define GPC_ADV_1000_HALF GPC_ANEG_2 -#define GPC_ADV_1000_FULL GPC_ANEG_3 -#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) - -/* master/slave settings */ -/* only for copper with 1000 Mbps */ -#define GPC_FORCE_MASTER 0 -#define GPC_FORCE_SLAVE GPC_ANEG_0 -#define GPC_PREF_MASTER GPC_ANEG_1 -#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) - -/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ -/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */ -#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */ -#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */ -#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */ -#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */ -#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */ - -#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ - GM_IS_TX_FF_UR) - -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ - /* Bits 15.. 2: reserved */ -#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ -#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ - - -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ -#define WOL_CTL_LINK_CHG_OCC BIT_15S -#define WOL_CTL_MAGIC_PKT_OCC BIT_14S -#define WOL_CTL_PATTERN_OCC BIT_13S - -#define WOL_CTL_CLEAR_RESULT BIT_12S - -#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S -#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S -#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S -#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S -#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S -#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S - -#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S -#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S -#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S -#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S -#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S -#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S - -#define WOL_CTL_DEFAULT \ - (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) - -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ -#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) - -#define SK_NUM_WOL_PATTERN 7 -#define SK_PATTERN_PER_WORD 4 -#define SK_BITMASK_PATTERN 7 -#define SK_POW_PATTERN_LENGTH 128 - -#define WOL_LENGTH_MSK 0x7f -#define WOL_LENGTH_SHIFT 8 - - -/* Receive and Transmit Descriptors ******************************************/ - -/* Transmit Descriptor struct */ -typedef struct s_HwTxd { - SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */ - SK_U32 TxNext; /* Physical Address Pointer to the next TxD */ - SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */ - SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */ - SK_U32 TxStat; /* Transmit Frame Status Word */ -#ifndef SK_USE_REV_DESC - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ -#else /* SK_USE_REV_DESC */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ -#endif /* SK_USE_REV_DESC */ - SK_U32 TxRes2; /* 32 bit reserved field */ -} SK_HWTXD; - -/* Receive Descriptor struct */ -typedef struct s_HwRxd { - SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */ - SK_U32 RxNext; /* Physical Address Pointer to the next RxD */ - SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */ - SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */ - SK_U32 RxStat; /* Receive Frame Status Word */ - SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */ -#ifndef SK_USE_REV_DESC - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ -#else /* SK_USE_REV_DESC */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ -#endif /* SK_USE_REV_DESC */ -} SK_HWRXD; - -/* - * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2) - * should set the define SK_USE_REV_DESC. - * Structures are 'normaly' not endianess dependent. But in - * this case the SK_U16 fields are bound to bit positions inside the - * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord. - * The bit positions inside a DWord are of course endianess dependent and - * swaps if the DWord is swapped by the hardware. - */ - - -/* Descriptor Bit Definition */ -/* TxCtrl Transmit Buffer Control Field */ -/* RxCtrl Receive Buffer Control Field */ -#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */ -#define BMU_STF BIT_30 /* Start of Frame */ -#define BMU_EOF BIT_29 /* End of Frame */ -#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */ -#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */ -/* TxCtrl specific bits */ -#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */ -#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */ -#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */ -/* RxCtrl specific bits */ -#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */ -#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */ -#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */ - /* Bit 23..16: BMU Check Opcodes */ -#define BMU_CHECK (0x55L<<16) /* Default BMU check */ -#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */ -#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */ -#define BMU_BBC 0xFFFFL /* Bit 15.. 0: Buffer Byte Counter */ - -/* TxStat Transmit Frame Status Word */ -/* RxStat Receive Frame Status Word */ -/* - *Note: TxStat is reserved for ASIC loopback mode only - * - * The Bits of the Status words are defined in xmac_ii.h - * (see XMR_FS bits) - */ - -/* other defines *************************************************************/ - -/* - * FlashProm specification - */ -#define MAX_PAGES 0x20000L /* Every byte has a single page */ -#define MAX_FADDR 1 /* 1 byte per page */ -#define SKFDDI_PSZ 8 /* address PROM size */ - -/* macros ********************************************************************/ - -/* - * Receive and Transmit Queues - */ -#define Q_R1 0x0000 /* Receive Queue 1 */ -#define Q_R2 0x0080 /* Receive Queue 2 */ -#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */ -#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */ -#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */ -#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */ - -/* - * Macro Q_ADDR() - * - * Use this macro to access the Receive and Transmit Queue Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: Q_D, Q_DA_L ... Q_T2, Q_T3 - * - * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal) - */ -#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs)) - -/* - * Macro RB_ADDR() - * - * Use this macro to access the RAM Buffer Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: RB_START, RB_END ... RB_LEV, RB_CTRL - * - * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal) - */ -#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs)) - - -/* - * MAC Related Registers - */ -#define MAC_1 0 /* belongs to the port near the slot */ -#define MAC_2 1 /* belongs to the port far away from the slot */ - -/* - * Macro MR_ADDR() - * - * Use this macro to access a MAC Related Registers inside the ASIC. - * - * para: - * Mac MAC to access. - * Values: MAC_1, MAC_2 - * Offs MAC register offset. - * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG, - * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST - * - * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) - */ -#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs)) - -#ifdef SK_LITTLE_ENDIAN -#define XM_WORD_LO 0 -#define XM_WORD_HI 1 -#else /* !SK_LITTLE_ENDIAN */ -#define XM_WORD_LO 1 -#define XM_WORD_HI 0 -#endif /* !SK_LITTLE_ENDIAN */ - - -/* - * macros to access the XMAC (GENESIS only) - * - * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD) - * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD) - * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK) - * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK) - * XM_INHASH(), to read the XM_HSM_CHK register - * XM_OUTHASH() to write the XM_HSM_CHK register - * - * para: - * Mac XMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg XMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value); - */ - -#define XMA(Mac, Reg) \ - ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1)) - -#define XM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), XMA((Mac), (Reg)), (pVal)) - -#define XM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (Val)) - -#define XM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), XMA((Mac), (Reg)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ -} - -#define XM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */ - -#define XM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define XM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * macros to access the GMAC (YUKON only) - * - * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT) - * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL) - * GM_IN32(), to read a 32 bit register (e.g. GM_) - * GM_OUT32(), to write a 32 bit register (e.g. GM_) - * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L) - * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L) - * GM_INHASH(), to read the GM_MC_ADDR_H1 register - * GM_OUTHASH() to write the GM_MC_ADDR_H1 register - * - * para: - * Mac GMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg GMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value); - */ - -#define GMA(Mac, Reg) \ - ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg)) - -#define GM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), GMA((Mac), (Reg)), (pVal)) - -#define GM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (Val)) - -#define GM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), GMA((Mac), (Reg)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ -} - -#define GM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -#define GM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define GM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * Different MAC Types - */ -#define SK_MAC_XMAC 0 /* Xaqti XMAC II */ -#define SK_MAC_GMAC 1 /* Marvell GMAC */ - -/* - * Different PHY Types - */ -#define SK_PHY_XMAC 0 /* integrated in XMAC II */ -#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */ -#define SK_PHY_LONE 2 /* Level One LXT1000 */ -#define SK_PHY_NAT 3 /* National DP83891 */ -#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */ -#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */ - -/* - * PHY addresses (bits 12..8 of PHY address reg) - */ -#define PHY_ADDR_XMAC (0<<8) -#define PHY_ADDR_BCOM (1<<8) -#define PHY_ADDR_LONE (3<<8) -#define PHY_ADDR_NAT (0<<8) - -/* GPHY address (bits 15..11 of SMI control reg) */ -#define PHY_ADDR_MARV 0 - -/* - * macros to access the PHY - * - * PHY_READ() read a 16 bit value from the PHY - * PHY_WRITE() write a 16 bit value to the PHY - * - * para: - * IoC I/O context needed for SK I/O macros - * pPort Pointer to port struct for PhyAddr - * Mac XMAC to access values: MAC_1 or MAC_2 - * PhyReg PHY Register to read or write - * (p)Val Value or pointer to the value which should be read or - * written. - * - * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value); - * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never - * comes back. This is checked in DEBUG mode. - */ -#ifndef DEBUG -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#else -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - int __i = 0; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - __i++; \ - if (__i > 100000) { \ - SK_DBG_PRINTF("*****************************\n"); \ - SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \ - SK_DBG_PRINTF("*****************************\n"); \ - break; \ - } \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#endif /* DEBUG */ - -#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \ - SK_U16 Mmu; \ - \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ -} - -/* - * Macro PCI_C() - * - * Use this macro to access PCI config register from the I/O space. - * - * para: - * Addr PCI configuration register to access. - * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG, - * - * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal); - */ -#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */ - -/* - * Macro SK_HW_ADDR(Base, Addr) - * - * Calculates the effective HW address - * - * para: - * Base I/O or memory base address - * Addr Address offset - * - * usage: May be used in SK_INxx and SK_OUTxx macros - * #define SK_IN8(pAC, Addr, pVal) ...\ - * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr))) - */ -#ifdef SK_MEM_MAPPED_IO -#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr)) -#else /* SK_MEM_MAPPED_IO */ -#define SK_HW_ADDR(Base, Addr) \ - ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0))) -#endif /* SK_MEM_MAPPED_IO */ - -#define SZ_LONG (sizeof(SK_U32)) - -/* - * Macro SK_HWAC_LINK_LED() - * - * Use this macro to set the link LED mode. - * para: - * pAC Pointer to adapter context struct - * IoC I/O context needed for SK I/O macros - * Port Port number - * Mode Mode to set for this LED - */ -#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \ - SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode); - - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEHW_H */ diff --git a/drivers/sk98lin/h/skgehwt.h b/drivers/sk98lin/h/skgehwt.h deleted file mode 100644 index 8aa9edd71c..0000000000 --- a/drivers/sk98lin/h/skgehwt.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Name: skhwt.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 1999/11/22 13:54:24 $ - * Purpose: Defines for the hardware timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgehwt.h,v $ - * Revision 1.5 1999/11/22 13:54:24 cgoos - * Changed license header to GPL. - * - * Revision 1.4 1998/08/19 09:50:58 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.3 1998/08/14 07:09:29 gklug - * fix: chg pAc -> pAC - * - * Revision 1.2 1998/08/07 12:54:21 gklug - * fix: first compiled version - * - * Revision 1.1 1998/08/07 09:32:58 gklug - * first version - * - * - * - * - * - ******************************************************************************/ - -/* - * SKGEHWT.H contains all defines and types for the timer functions - */ - -#ifndef _SKGEHWT_H_ -#define _SKGEHWT_H_ - -/* - * SK Hardware Timer - * - needed wherever the HWT module is used - * - use in Adapters context name pAC->Hwt - */ -typedef struct s_Hwt { - SK_U32 TStart ; /* HWT start */ - SK_U32 TStop ; /* HWT stop */ - int TActive ; /* HWT: flag : active/inactive */ -} SK_HWT; - -extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); -extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); -extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); -extern SK_U32 SkHwtRead(SK_AC *pAC,SK_IOC Ioc); -extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); -#endif /* _SKGEHWT_H_ */ diff --git a/drivers/sk98lin/h/skgei2c.h b/drivers/sk98lin/h/skgei2c.h deleted file mode 100644 index e639f733c6..0000000000 --- a/drivers/sk98lin/h/skgei2c.h +++ /dev/null @@ -1,299 +0,0 @@ -/****************************************************************************** - * - * Name: skgei2c.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.23 $ - * Date: $Date: 2002/12/19 14:34:27 $ - * Purpose: Special GEnesis defines for TWSI - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgei2c.h,v $ - * Revision 1.23 2002/12/19 14:34:27 rschmidt - * Added cast in macros SK_I2C_SET_BIT() and SK_I2C_CLR_BIT() - * Editorial changes (TWSI) - * - * Revision 1.22 2002/10/14 16:45:56 rschmidt - * Editorial changes (TWSI) - * - * Revision 1.21 2002/08/13 08:42:24 rschmidt - * Changed define for SK_MIN_SENSORS back to 5 - * Merged defines for PHY PLL 3V3 voltage (A and B) - * Editorial changes - * - * Revision 1.20 2002/08/06 09:43:56 jschmalz - * Extensions and changes for Yukon - * - * Revision 1.19 2002/08/02 12:00:08 rschmidt - * Added defines for YUKON sensors - * Editorial changes - * - * Revision 1.18 2001/08/16 12:44:33 afischer - * LM80 sensor init values corrected - * - * Revision 1.17 1999/11/22 13:55:25 cgoos - * Changed license header to GPL. - * - * Revision 1.16 1999/11/12 08:24:10 malthoff - * Change voltage warning and error limits - * (warning +-5%, error +-10%). - * - * Revision 1.15 1999/09/14 14:14:43 malthoff - * The 1000BT Dual Link adapter has got only one Fan. - * The second Fan has been removed. - * - * Revision 1.14 1999/05/27 13:40:50 malthoff - * Fan Divisor = 1. Assuming fan with 6500 rpm. - * - * Revision 1.13 1999/05/20 14:56:55 malthoff - * Bug Fix: Missing brace in SK_LM80_FAN_FAKTOR. - * - * Revision 1.12 1999/05/20 09:22:00 cgoos - * Changes for 1000Base-T (Fan sensors). - * - * Revision 1.11 1998/10/14 05:57:22 cgoos - * Fixed compilation warnings. - * - * Revision 1.10 1998/09/04 08:37:00 malthoff - * bugfix: correct the SK_I2C_GET_CTL() macro. - * - * Revision 1.9 1998/08/25 06:10:03 gklug - * add: thresholds for all sensors - * - * Revision 1.8 1998/08/20 11:37:42 gklug - * chg: change Ioc to IoC - * - * Revision 1.7 1998/08/20 08:53:11 gklug - * fix: compiler errors - * add: Threshold values - * - * Revision 1.6 1998/08/17 11:37:09 malthoff - * Bugfix in SK_I2C_CTL macro. The parameter 'dev' - * has to be shifted 9 bits. - * - * Revision 1.5 1998/08/17 06:52:21 malthoff - * Remove unrequired macros. - * Add macros for accessing TWSI SW register. - * - * Revision 1.4 1998/08/13 08:30:18 gklug - * add: conversion factors for read values - * add: new state SEN_VALEXT to read extension value of temperature sensor - * - * Revision 1.3 1998/08/12 13:37:56 gklug - * rmv: error numbers and messages - * - * Revision 1.2 1998/08/11 07:54:38 gklug - * add: sensor states for GE sensors - * add: Macro to access TWSI hardware register - * chg: Error messages for TWSI errors - * - * Revision 1.1 1998/07/17 11:27:56 gklug - * Created. - * - * - * - ******************************************************************************/ - -/* - * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling - */ - -#ifndef _INC_SKGEI2C_H_ -#define _INC_SKGEI2C_H_ - -/* - * Macros to access the B2_I2C_CTRL - */ -#define SK_I2C_CTL(IoC, flag, dev, reg, burst) \ - SK_OUT32(IoC, B2_I2C_CTRL,\ - (flag ? 0x80000000UL : 0x0L) | \ - (((SK_U32) reg << 16) & I2C_ADDR) | \ - (((SK_U32) dev << 9) & I2C_DEV_SEL) | \ - (( burst << 4) & I2C_BURST_LEN)) - -#define SK_I2C_STOP(IoC) { \ - SK_U32 I2cCtrl; \ - SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \ - SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \ -} - -#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl) - -/* - * Macros to access the TWSI SW Registers - */ -#define SK_I2C_SET_BIT(IoC, SetBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \ -} - -#define SK_I2C_CLR_BIT(IoC, ClrBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \ -} - -#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw) - -/* - * define the possible sensor states - */ -#define SK_SEN_IDLE 0 /* Idle: sensor not read */ -#define SK_SEN_VALUE 1 /* Value Read cycle */ -#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */ - -/* - * Conversion factor to convert read Voltage sensor to milli Volt - * Conversion factor to convert read Temperature sensor to 10th degree Celsius - */ -#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ -#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ -#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for the - * extension value - */ -#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) -/* formula: counter = (22500*60)/(rpm * divisor * pulses/2) - * assuming: 6500rpm, 4 pulses, divisor 1 - */ - -/* - * Define sensor management data - * Maximum is reached on copperfield with dual Broadcom. - * Board specific maximum is in pAC->I2c.MaxSens - */ -#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ -#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ - -/* - * To watch the statemachine (JS) use the timer in two ways instead of one as hitherto - */ -#define SK_TIMER_WATCH_STATEMACHINE 0 /* Watch the statemachine to finish in a specific time */ -#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ - - -/* - * Defines for the individual Thresholds - */ - -/* Temperature sensor */ -#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ -#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ -#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ -#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ - -/* VCC which should be 5 V */ -#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ -#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ - -/* - * VIO may be 5 V or 3.3 V. Initialization takes two parts: - * 1. Initialize lowest lower limit and highest higher limit. - * 2. After the first value is read correct the upper or the lower limit to - * the appropriate C constant. - * - * Warning limits are +-5% of the exepected voltage. - * Error limits are +-10% of the expected voltage. - */ - -/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ - -#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */ - /* 5000 mVolt */ -#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */ - -#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */ - -/* correction values for the second pass */ -#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ - /* 3300 mVolt */ -#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ - - -/* - * VDD voltage - */ -#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ -#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ -#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ -#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ - -/* - * PHY PLL 3V3 voltage - */ -#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */ -#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */ - -/* - * VAUX (YUKON only) - */ -#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */ -#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ -#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ -#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ - -/* - * PHY 2V5 voltage - */ -#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */ -#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */ - -/* - * ASIC Core 1V5 voltage (YUKON only) - */ -#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ -#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */ - -/* - * FAN 1 speed - */ -/* assuming: 6500rpm +-15%, 4 pulses, - * warning at: 80 % - * error at: 70 % - * no upper limit - */ -#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ -#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ -#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ -#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ - -/* - * Some Voltages need dynamic thresholds - */ -#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */ -#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */ -#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */ - -extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); -#endif /* n_INC_SKGEI2C_H */ diff --git a/drivers/sk98lin/h/skgeinit.h b/drivers/sk98lin/h/skgeinit.h deleted file mode 100644 index cdddef92b3..0000000000 --- a/drivers/sk98lin/h/skgeinit.h +++ /dev/null @@ -1,1113 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.75 $ - * Date: $Date: 2003/02/05 13:36:39 $ - * Purpose: Structures and prototypes for the GE Init Module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgeinit.h,v $ - * Revision 1.75 2003/02/05 13:36:39 rschmidt - * Added define SK_FACT_78 for YUKON's Host Clock of 78.12 MHz - * Editorial changes - * - * Revision 1.74 2003/01/28 09:39:16 rschmidt - * Added entry GIYukonLite in s_GeInit structure - * Editorial changes - * - * Revision 1.73 2002/11/15 12:47:25 rschmidt - * Replaced error message SKERR_HWI_E024 for Cable Diagnostic with - * Rx queue error in SkGeStopPort(). - * - * Revision 1.72 2002/11/12 17:08:35 rschmidt - * Added entries for Cable Diagnostic to Port structure - * Added entries GIPciSlot64 and GIPciClock66 in s_GeInit structure - * Added error message for Cable Diagnostic - * Added prototypes for SkGmCableDiagStatus() - * Editorial changes - * - * Revision 1.71 2002/10/21 11:26:10 mkarl - * Changed interface of SkGeInitAssignRamToQueues(). - * - * Revision 1.70 2002/10/14 08:21:32 rschmidt - * Changed type of GICopperType, GIVauxAvail to SK_BOOL - * Added entry PRxOverCnt to Port structure - * Added entry GIYukon32Bit in s_GeInit structure - * Editorial changes - * - * Revision 1.69 2002/10/09 16:57:15 mkarl - * Added some constants and macros for SkGeInitAssignRamToQueues(). - * - * Revision 1.68 2002/09/12 08:58:51 rwahl - * Retrieve counters needed for XMAC errata workarounds directly because - * PNMI returns corrected counter values (e.g. #10620). - * - * Revision 1.67 2002/08/16 14:40:30 rschmidt - * Added entries GIGenesis and GICopperType in s_GeInit structure - * Added prototypes for SkMacHashing() - * Editorial changes - * - * Revision 1.66 2002/08/12 13:27:21 rschmidt - * Added defines for Link speed capabilities - * Added entry PLinkSpeedCap to Port structure - * Added entry GIVauxAvail in s_GeInit structure - * Added prototypes for SkMacPromiscMode() - * Editorial changes - * - * Revision 1.65 2002/08/08 15:46:18 rschmidt - * Added define SK_PHY_ACC_TO for PHY access timeout - * Added define SK_XM_RX_HI_WM for XMAC Rx High Watermark - * Added define SK_MIN_TXQ_SIZE for Min RAM Buffer Tx Queue Size - * Added entry PhyId1 to Port structure - * - * Revision 1.64 2002/07/23 16:02:56 rschmidt - * Added entry GIWolOffs in s_GeInit struct (HW-Bug in YUKON 1st rev.) - * Added prototypes for: SkGePhyRead(), SkGePhyWrite() - * - * Revision 1.63 2002/07/18 08:17:38 rwahl - * Corrected definitions for SK_LSPEED_xxx & SK_LSPEED_STAT_xxx. - * - * Revision 1.62 2002/07/17 18:21:55 rwahl - * Added SK_LSPEED_INDETERMINATED define. - * - * Revision 1.61 2002/07/17 17:16:03 rwahl - * - MacType now member of GIni struct. - * - Struct alignment to 32bit. - * - Editorial change. - * - * Revision 1.60 2002/07/15 18:23:39 rwahl - * Added GeMacFunc to GE Init structure. - * Added prototypes for SkXmUpdateStats(), SkGmUpdateStats(), - * SkXmMacStatistic(), SkGmMacStatistic(), SkXmResetCounter(), - * SkGmResetCounter(), SkXmOverflowStatus(), SkGmOverflowStatus(). - * Added defines for current link speed state. - * Added ERRMSG defintions for MacUpdateStat() & MacStatistics(). - * - * Revision 1.59 2002/07/15 15:40:22 rschmidt - * Added entry PLinkSpeedUsed to Port structure - * Editorial changes - * - * Revision 1.58 2002/06/10 09:36:30 rschmidt - * Editorial changes. - * - * Revision 1.57 2002/06/05 08:18:00 rschmidt - * Corrected alignment in Port Structure - * Added new prototypes for GMAC - * Editorial changes - * - * Revision 1.56 2002/04/25 11:38:12 rschmidt - * Added defines for Link speed values - * Added defines for Loopback parameters for MAC and PHY - * Removed entry PRxCmd from Port structure - * Added entry PLinkSpeed to Port structure - * Added entries GIChipId and GIChipRev to GE Init structure - * Removed entry GIAnyPortAct from GE Init structure - * Added prototypes for: SkMacInit(), SkMacInitPhy(), - * SkMacRxTxDisable(), SkMacSoftRst(), SkMacHardRst(), SkMacIrq(), - * SkMacIrqDisable(), SkMacFlushTxFifo(), SkMacFlushRxFifo(), - * SkMacAutoNegDone(), SkMacAutoNegLipaPhy(), SkMacSetRxTxEn(), - * SkXmPhyRead(), SkXmPhyRead(), SkGmPhyWrite(), SkGmPhyWrite(); - * Removed prototypes for static functions in SkXmac2.c - * Editorial changes - * - * Revision 1.55 2002/02/26 15:24:53 rwahl - * Fix: no link with manual configuration (#10673). The previous fix for - * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to - * misconfigured port. It should not occur for the other RLMT modes. - * - * Revision 1.54 2002/01/18 16:52:52 rwahl - * Editorial corrections. - * - * Revision 1.53 2001/11/20 09:19:58 rwahl - * Reworked bugfix #10639 (no dependency to RLMT mode). - * - * Revision 1.52 2001/10/26 07:52:23 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.51 2001/02/09 12:26:38 cgoos - * Inserted #ifdef DIAG for half duplex workaround timer. - * - * Revision 1.50 2001/02/07 07:56:40 rassmann - * Corrected copyright. - * - * Revision 1.49 2001/01/31 15:32:18 gklug - * fix: problem with autosensing an SR8800 switch - * add: counter for autoneg timeouts - * - * Revision 1.48 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.47 2000/10/18 12:22:40 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.46 2000/08/10 11:28:00 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * - * Revision 1.45 1999/11/22 13:56:19 cgoos - * Changed license header to GPL. - * - * Revision 1.44 1999/10/26 07:34:15 malthoff - * The define SK_LNK_ON has been lost in v1.41. - * - * Revision 1.43 1999/10/06 09:30:16 cgoos - * Changed SK_XM_THR_JUMBO. - * - * Revision 1.42 1999/09/16 12:58:26 cgoos - * Changed SK_LED_STANDY macro to be independent of HW link sync. - * - * Revision 1.41 1999/07/30 06:56:14 malthoff - * Correct comment for SK_MS_STAT_UNSET. - * - * Revision 1.40 1999/05/27 13:38:46 cgoos - * Added SK_BMU_TX_WM. - * Made SK_BMU_TX_WM and SK_BMU_RX_WM user-definable. - * Changed XMAC Tx treshold to max. values. - * - * Revision 1.39 1999/05/20 14:35:26 malthoff - * Remove prototypes for SkGeLinkLED(). - * - * Revision 1.38 1999/05/19 11:59:12 cgoos - * Added SK_MS_CAP_INDETERMINATED define. - * - * Revision 1.37 1999/05/19 07:32:33 cgoos - * Changes for 1000Base-T. - * LED-defines for HWAC_LINK_LED macro. - * - * Revision 1.36 1999/04/08 14:00:24 gklug - * add:Port struct field PLinkResCt - * - * Revision 1.35 1999/03/25 07:43:07 malthoff - * Add error string for SKERR_HWI_E018MSG. - * - * Revision 1.34 1999/03/12 16:25:57 malthoff - * Remove PPollRxD and PPollTxD. - * Add SKERR_HWI_E017MSG. and SK_DPOLL_MAX. - * - * Revision 1.33 1999/03/12 13:34:41 malthoff - * Add Autonegotiation error codes. - * Change defines for parameter Mode in SkXmSetRxCmd(). - * Replace __STDC__ by SK_KR_PROTO. - * - * Revision 1.32 1999/01/25 14:40:20 mhaveman - * Added new return states for the virtual management port if multiple - * ports are active but differently configured. - * - * Revision 1.31 1998/12/11 15:17:02 gklug - * add: Link partnet autoneg states : Unknown Manual and Auto-negotiation - * - * Revision 1.30 1998/12/07 12:17:04 gklug - * add: Link Partner auto-negotiation flag - * - * Revision 1.29 1998/12/01 10:54:42 gklug - * add: variables for XMAC Errata - * - * Revision 1.28 1998/12/01 10:14:15 gklug - * add: PIsave saves the Interrupt status word - * - * Revision 1.27 1998/11/26 15:24:52 mhaveman - * Added link status states SK_LMODE_STAT_AUTOHALF and - * SK_LMODE_STAT_AUTOFULL which are used by PNMI. - * - * Revision 1.26 1998/11/26 14:53:01 gklug - * add:autoNeg Timeout variable - * - * Revision 1.25 1998/11/26 08:58:50 gklug - * add: Link Mode configuration (AUTO Sense mode) - * - * Revision 1.24 1998/11/24 13:30:27 gklug - * add: PCheckPar to port struct - * - * Revision 1.23 1998/11/18 13:23:26 malthoff - * Add SK_PKT_TO_MAX. - * - * Revision 1.22 1998/11/18 13:19:54 gklug - * add: PPrevShorts and PLinkBroken to port struct for WA XMAC Errata #C1 - * - * Revision 1.21 1998/10/26 08:02:57 malthoff - * Add GIRamOffs. - * - * Revision 1.20 1998/10/19 07:28:37 malthoff - * Add prototype for SkGeInitRamIface(). - * - * Revision 1.19 1998/10/14 14:47:48 malthoff - * SK_TIMER should not be defined for Diagnostics. - * Add SKERR_HWI_E015MSG and SKERR_HWI_E016MSG. - * - * Revision 1.18 1998/10/14 14:00:03 gklug - * add: timer to port struct for workaround of Errata #2 - * - * Revision 1.17 1998/10/14 11:23:09 malthoff - * Add prototype for SkXmAutoNegDone(). - * Fix SkXmSetRxCmd() prototype statement. - * - * Revision 1.16 1998/10/14 05:42:29 gklug - * add: HWLinkUp flag to Port struct - * - * Revision 1.15 1998/10/09 08:26:33 malthoff - * Rename SK_RB_ULPP_B to SK_RB_LLPP_B. - * - * Revision 1.14 1998/10/09 07:11:13 malthoff - * bug fix: SK_FACT_53 is 85 not 117. - * Rework time out init values. - * Add GIPortUsage and corresponding defines. - * Add some error log messages. - * - * Revision 1.13 1998/10/06 14:13:14 malthoff - * Add prototype for SkGeLoadLnkSyncCnt(). - * - * Revision 1.12 1998/10/05 11:29:53 malthoff - * bug fix: A comment was not closed. - * - * Revision 1.11 1998/10/05 08:01:59 malthoff - * Add default Timeout- Threshold- and - * Watermark constants. Add QRam start and end - * variables. Also add vars to store the polling - * mode and receive command. Add new Error Log - * Messages and function prototypes. - * - * Revision 1.10 1998/09/28 13:34:48 malthoff - * Add mode bits for LED functions. - * Move Autoneg and Flow Ctrl bits from shgesirq.h - * Add the required Error Log Entries - * and Function Prototypes. - * - * Revision 1.9 1998/09/16 14:38:41 malthoff - * Rework the SK_LNK_xxx defines. - * Add error log message defines. - * Add prototypes for skxmac2.c - * - * Revision 1.8 1998/09/11 05:29:18 gklug - * add: init state of a port - * - * Revision 1.7 1998/09/08 08:35:52 gklug - * add: defines of the Init Levels - * - * Revision 1.6 1998/09/03 13:48:42 gklug - * add: Link strati, capabilities to Port struct - * - * Revision 1.5 1998/09/03 13:30:59 malthoff - * Add SK_LNK_BLINK and SK_LNK_PERM. - * - * Revision 1.4 1998/09/03 09:55:31 malthoff - * Add constants for parameters Dir and RstMode - * when calling SkGeStopPort(). - * Rework the prototype section. - * Add Queue Address offsets PRxQOff, PXsQOff, and PXaQOff. - * Remove Ioc with IoC. - * - * Revision 1.3 1998/08/19 09:11:54 gklug - * fix: struct are removed from c-source (see CCC) - * add: typedefs for all structs - * - * Revision 1.2 1998/07/28 12:38:26 malthoff - * The prototypes got the parameter 'IoC'. - * - * Revision 1.1 1998/07/23 09:50:24 malthoff - * Created. - * - ******************************************************************************/ - -#ifndef __INC_SKGEINIT_H_ -#define __INC_SKGEINIT_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* modifying Link LED behaviour (used with SkGeLinkLED()) */ -#define SK_LNK_OFF LED_OFF -#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON) -#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON) -#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */ -#define SK_LED_OFF LED_OFF -#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* addressing LED Registers in SkGeXmitLED() */ -#define XMIT_LED_INI 0 -#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI) -#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI) -#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI) - -/* parameter 'Mode' when calling SkGeXmitLED() */ -#define SK_LED_DIS 0 -#define SK_LED_ENA 1 -#define SK_LED_TST 2 - -/* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08L /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650L /* 500 ms */ - -#define SK_DPOLL_DEF 0x00ee6b28L /* 250 ms at 62.5 MHz */ - -#define SK_DPOLL_MAX 0x00ffffffL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ - -#define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ -#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ - -/* Timeout values */ -#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ -#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ -#define SK_PKT_TO_MAX 0xffff /* Maximum value */ -#define SK_RI_TO_53 36 /* RAM interface timeout */ - -#define SK_PHY_ACC_TO 600000 /* PHY access timeout */ - -/* RAM Buffer High Pause Threshold values */ -#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */ -#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */ -#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */ - -#ifndef SK_BMU_RX_WM -#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ -#endif -#ifndef SK_BMU_TX_WM -#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ -#endif - -/* XMAC II Rx High Watermark */ -#define SK_XM_RX_HI_WM 0x05aa /* 1450 */ - -/* XMAC II Tx Threshold */ -#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */ -#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */ -#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */ -#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */ - -/* values for GIPortUsage */ -#define SK_RED_LINK 1 /* redundant link usage */ -#define SK_MUL_LINK 2 /* multiple link usage */ -#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */ - -/* Minimum RAM Buffer Rx Queue Size */ -#define SK_MIN_RXQ_SIZE 16 /* 16 kB */ - -/* Minimum RAM Buffer Tx Queue Size */ -#define SK_MIN_TXQ_SIZE 16 /* 16 kB */ - -/* Queue Size units */ -#define QZ_UNITS 0x7 -#define QZ_STEP 8 - -/* Percentage of queue size from whole memory */ -/* 80 % for receive */ -#define RAM_QUOTA_RX 80L -/* 0% for sync transfer */ -#define RAM_QUOTA_SYNC 0L -/* the rest (20%) is taken for async transfer */ - -/* Get the rounded queue size in Bytes in 8k steps */ -#define ROUND_QUEUE_SIZE(SizeInBytes) \ - ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \ - ~(QZ_STEP-1)) - -/* Get the rounded queue size in KBytes in 8k steps */ -#define ROUND_QUEUE_SIZE_KB(Kilobytes) \ - ROUND_QUEUE_SIZE((Kilobytes) * 1024L) - -/* Types of RAM Buffer Queues */ -#define SK_RX_SRAM_Q 1 /* small receive queue */ -#define SK_RX_BRAM_Q 2 /* big receive queue */ -#define SK_TX_RAM_Q 3 /* small or big transmit queue */ - -/* parameter 'Dir' when calling SkGeStopPort() */ -#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */ -#define SK_STOP_RX 2 /* Stops the receive path */ -#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */ - -/* parameter 'RstMode' when calling SkGeStopPort() */ -#define SK_SOFT_RST 1 /* perform a software reset */ -#define SK_HARD_RST 2 /* perform a hardware reset */ - -/* Init Levels */ -#define SK_INIT_DATA 0 /* Init level 0: init data structures */ -#define SK_INIT_IO 1 /* Init level 1: init with IOs */ -#define SK_INIT_RUN 2 /* Init level 2: init for run time */ - -/* Link Mode Parameter */ -#define SK_LMODE_HALF 1 /* Half Duplex Mode */ -#define SK_LMODE_FULL 2 /* Full Duplex Mode */ -#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */ -#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */ -#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */ -#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */ -#define SK_LMODE_INDETERMINATED 7 /* indeterminated */ - -/* Auto-negotiation timeout in 100ms granularity */ -#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */ - -/* Auto-negotiation error codes */ -#define SK_AND_OK 0 /* no error */ -#define SK_AND_OTHER 1 /* other error than below */ -#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */ - - -/* Link Speed Capabilities */ -#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */ -#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */ -#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */ -#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Speed Parameter */ -#define SK_LSPEED_AUTO 1 /* Automatic resolution */ -#define SK_LSPEED_10MBPS 2 /* 10 Mbps */ -#define SK_LSPEED_100MBPS 3 /* 100 Mbps */ -#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */ -#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */ - -/* Link Speed Current State */ -#define SK_LSPEED_STAT_UNKNOWN 1 -#define SK_LSPEED_STAT_10MBPS 2 -#define SK_LSPEED_STAT_100MBPS 3 -#define SK_LSPEED_STAT_1000MBPS 4 -#define SK_LSPEED_STAT_INDETERMINATED 5 - - -/* Link Capability Parameter */ -#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */ -#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */ -#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */ -#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */ -#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Mode Current State */ -#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */ -#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */ -#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */ -#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */ - -/* Flow Control Mode Parameter (and capabilities) */ -#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */ -#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */ -#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */ -#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or - * just the remote station may send PAUSE - */ -#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */ - -/* Flow Control Status Parameter */ -#define SK_FLOW_STAT_NONE 1 /* No Flow Control */ -#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */ -#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */ -#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */ -#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */ - -/* Master/Slave Mode Capabilities */ -#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_MS_CAP_MASTER (1<<1) /* This station is master */ -#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */ -#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */ - -/* Set Master/Slave Mode Parameter (and capabilities) */ -#define SK_MS_MODE_AUTO 1 /* Automatic resolution */ -#define SK_MS_MODE_MASTER 2 /* This station is master */ -#define SK_MS_MODE_SLAVE 3 /* This station is slave */ -#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */ - -/* Master/Slave Status Parameter */ -#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */ -#define SK_MS_STAT_MASTER 2 /* This station is Master */ -#define SK_MS_STAT_SLAVE 3 /* This station is Dlave */ -#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */ -#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */ - -/* parameter 'Mode' when calling SkXmSetRxCmd() */ -#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */ -#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */ -#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */ -#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */ -#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */ -#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */ -#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */ -#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */ -#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */ -#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */ - -/* parameter 'Para' when calling SkMacSetRxTxEn() */ -#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */ -#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */ -#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */ -#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */ -#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */ -#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */ - -/* States of PState */ -#define SK_PRT_RESET 0 /* the port is reset */ -#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */ -#define SK_PRT_INIT 2 /* the port is initialized */ -#define SK_PRT_RUN 3 /* the port has an active link */ - -/* Default receive frame limit for Workaround of XMAC Errata */ -#define SK_DEF_RX_WA_LIM SK_CONSTU64(100) - -/* Link Partner Status */ -#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */ -#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */ -#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */ - -/* Maximum Restarts before restart is ignored (3Com WA) */ -#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */ - -/* Max. Auto-neg. timeouts before link detection in sense mode is reset */ -#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */ - -/* structures *****************************************************************/ - -/* - * MAC specific functions - */ -typedef struct s_GeMacFunc { - int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 StatAddr, SK_U32 *pVal); - int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 IStatus, SK_U64 *pVal); -} SK_GEMACFUNC; - -/* - * Port Structure - */ -typedef struct s_GePort { -#ifndef SK_DIAG - SK_TIMER PWaTimer; /* Workaround Timer */ - SK_TIMER HalfDupChkTimer; -#endif /* SK_DIAG */ - SK_U32 PPrevShorts; /* Previous short Counter checking */ - SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */ - SK_U64 PPrevRx; /* Previous RxOk Counter checking */ - SK_U64 PRxLim; /* Previous RxOk Counter checking */ - SK_U64 LastOctets; /* For half duplex hang check */ - int PLinkResCt; /* Link Restart Counter */ - int PAutoNegTimeOut;/* Auto-negotiation timeout current value */ - int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */ - int PRxQSize; /* Port Rx Queue Size in kB */ - int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */ - int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */ - SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */ - SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */ - SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */ - SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */ - SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */ - SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */ - SK_U32 PRxOverCnt; /* Receive Overflow Counter */ - int PRxQOff; /* Rx Queue Address Offset */ - int PXsQOff; /* Synchronous Tx Queue Address Offset */ - int PXaQOff; /* Asynchronous Tx Queue Address Offset */ - int PhyType; /* PHY used on this port */ - SK_U16 PhyId1; /* PHY Id1 on this port */ - SK_U16 PhyAddr; /* MDIO/MDC PHY address */ - SK_U16 PIsave; /* Saved Interrupt status word */ - SK_U16 PSsave; /* Saved PHY status word */ - SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */ - SK_BOOL PState; /* Is port initialized ? */ - SK_BOOL PLinkBroken; /* Is Link broken ? */ - SK_BOOL PCheckPar; /* Do we check for parity errors ? */ - SK_BOOL HalfDupTimerActive; - SK_U8 PLinkCap; /* Link Capabilities */ - SK_U8 PLinkModeConf; /* Link Mode configured */ - SK_U8 PLinkMode; /* Link Mode currently used */ - SK_U8 PLinkModeStatus;/* Link Mode Status */ - SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */ - SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */ - SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */ - SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */ - SK_U8 PFlowCtrlMode; /* Flow Control Mode */ - SK_U8 PFlowCtrlStatus;/* Flow Control Status */ - SK_U8 PMSCap; /* Master/Slave Capabilities */ - SK_U8 PMSMode; /* Master/Slave Mode */ - SK_U8 PMSStatus; /* Master/Slave Status */ - SK_U8 PAutoNegFail; /* Auto-negotiation fail flag */ - SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */ - SK_U8 PCableLen; /* Cable Length */ - SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ - SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ -} SK_GEPORT; - -/* - * Gigabit Ethernet Initialization Struct - * (has to be included in the adapter context) - */ -typedef struct s_GeInit { - SK_U8 GIPciHwRev; /* PCI HW Revision Number */ - SK_U8 GIChipId; /* Chip Identification Number */ - SK_U8 GIChipRev; /* Chip Revision Number */ - SK_BOOL GIGenesis; /* Genesis adapter ? */ - SK_BOOL GICopperType; /* Copper Type adapter ? */ - SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */ - SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */ - SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */ - SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */ - SK_BOOL GIYukonLite; /* YUKON-Lite chip */ - int GIMacsFound; /* Number of MACs found on this adapter */ - int GIMacType; /* MAC Type used on this adapter */ - int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */ - int GIPortUsage; /* Driver Port Usage */ - int GILevel; /* Initialization Level completed */ - int GIRamSize; /* The RAM size of the adapter in kB */ - int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */ - SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */ - SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */ - SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */ - SK_GEMACFUNC GIFunc; /* MAC depedent functions */ -} SK_GEINIT; - -/* - * Error numbers and messages for skxmac2.c and skgeinit.c - */ -#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT) -#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters" -#define SKERR_HWI_E002 (SKERR_HWI_E001+1) -#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing" -#define SKERR_HWI_E003 (SKERR_HWI_E002+1) -#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level" -#define SKERR_HWI_E004 (SKERR_HWI_E003+1) -#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured" -#define SKERR_HWI_E005 (SKERR_HWI_E004+1) -#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports" -#define SKERR_HWI_E006 (SKERR_HWI_E005+1) -#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state" -#define SKERR_HWI_E007 (SKERR_HWI_E006+1) -#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode" -#define SKERR_HWI_E008 (SKERR_HWI_E007+1) -#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode" -#define SKERR_HWI_E009 (SKERR_HWI_E008+1) -#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero" -#define SKERR_HWI_E010 (SKERR_HWI_E009+1) -#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters" -#define SKERR_HWI_E011 (SKERR_HWI_E010+1) -#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small" -#define SKERR_HWI_E012 (SKERR_HWI_E011+1) -#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified" -#define SKERR_HWI_E013 (SKERR_HWI_E012+1) -#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue" -#define SKERR_HWI_E014 (SKERR_HWI_E013+1) -#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified" -#define SKERR_HWI_E015 (SKERR_HWI_E014+1) -#define SKERR_HWI_E015MSG "Illegal Link mode parameter" -#define SKERR_HWI_E016 (SKERR_HWI_E015+1) -#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter" -#define SKERR_HWI_E017 (SKERR_HWI_E016+1) -#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal" -#define SKERR_HWI_E018 (SKERR_HWI_E017+1) -#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)" -#define SKERR_HWI_E019 (SKERR_HWI_E018+1) -#define SKERR_HWI_E019MSG "Illegal Speed parameter" -#define SKERR_HWI_E020 (SKERR_HWI_E019+1) -#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter" -#define SKERR_HWI_E021 (SKERR_HWI_E020+1) -#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" -#define SKERR_HWI_E022 (SKERR_HWI_E021+1) -#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" -#define SKERR_HWI_E023 (SKERR_HWI_E022+1) -#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small" -#define SKERR_HWI_E024 (SKERR_HWI_E023+1) -#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)" -#define SKERR_HWI_E025 (SKERR_HWI_E024+1) -#define SKERR_HWI_E025MSG "" - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* - * public functions in skgeinit.c - */ -extern void SkGePollRxD( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL PollRxD); - -extern void SkGePollTxD( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL PollTxD); - -extern void SkGeYellowLED( - SK_AC *pAC, - SK_IOC IoC, - int State); - -extern int SkGeCfgSync( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 IntTime, - SK_U32 LimCount, - int SyncMode); - -extern void SkGeLoadLnkSyncCnt( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 CntVal); - -extern void SkGeStopPort( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Dir, - int RstMode); - -extern int SkGeInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern void SkGeDeInit( - SK_AC *pAC, - SK_IOC IoC); - -extern int SkGeInitPort( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGeXmitLED( - SK_AC *pAC, - SK_IOC IoC, - int Led, - int Mode); - -extern void SkGeInitRamIface( - SK_AC *pAC, - SK_IOC IoC); - -extern int SkGeInitAssignRamToQueues( - SK_AC *pAC, - int ActivePort, - SK_BOOL DualNet); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacSoftRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacHardRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacInitPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL DoLoop); - -extern void SkMacIrqDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacFlushTxFifo( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacFlushRxFifo( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacIrq( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern int SkMacAutoNegDone( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacAutoNegLipaPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern void SkMacSetRxTxEn( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Para); - -extern int SkMacRxTxEnable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacPromiscMode( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkMacHashing( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkXmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkXmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkGmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkGmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkGePhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkGePhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkXmClrExactAddr( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int StartNum, - int StopNum); - -extern void SkXmInitDupMd( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmInitPauseMd( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmAutoNegLipaXmac( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern int SkXmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 *pVal); - -extern int SkGmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 *pVal); - -extern int SkXmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 IStatus, - SK_U64 *pStatus); - -extern int SkGmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 MacStatus, - SK_U64 *pStatus); - -extern int SkGmCableDiagStatus( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL StartTest); - -#ifdef SK_DIAG -extern void SkMacSetRxCmd( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Mode); -extern void SkMacCrcGener( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkMacTimeStamp( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkXmSendCont( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -#endif /* SK_DIAG */ - -#else /* SK_KR_PROTO */ - -/* - * public functions in skgeinit.c - */ -extern void SkGePollRxD(); -extern void SkGePollTxD(); -extern void SkGeYellowLED(); -extern int SkGeCfgSync(); -extern void SkGeLoadLnkSyncCnt(); -extern void SkGeStopPort(); -extern int SkGeInit(); -extern void SkGeDeInit(); -extern int SkGeInitPort(); -extern void SkGeXmitLED(); -extern void SkGeInitRamIface(); -extern int SkGeInitAssignRamToQueues(); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable(); -extern void SkMacSoftRst(); -extern void SkMacHardRst(); -extern void SkMacInitPhy(); -extern int SkMacRxTxEnable(); -extern void SkMacPromiscMode(); -extern void SkMacHashing(); -extern void SkMacIrqDisable(); -extern void SkMacFlushTxFifo(); -extern void SkMacFlushRxFifo(); -extern void SkMacIrq(); -extern int SkMacAutoNegDone(); -extern void SkMacAutoNegLipaPhy(); -extern void SkMacSetRxTxEn(); -extern void SkGePhyRead(); -extern void SkGePhyWrite(); -extern void SkXmInitMac(); -extern void SkXmPhyRead(); -extern void SkXmPhyWrite(); -extern void SkGmInitMac(); -extern void SkGmPhyRead(); -extern void SkGmPhyWrite(); -extern void SkXmClrExactAddr(); -extern void SkXmInitDupMd(); -extern void SkXmInitPauseMd(); -extern void SkXmAutoNegLipaXmac(); -extern int SkXmUpdateStats(); -extern int SkGmUpdateStats(); -extern int SkXmMacStatistic(); -extern int SkGmMacStatistic(); -extern int SkXmResetCounter(); -extern int SkGmResetCounter(); -extern int SkXmOverflowStatus(); -extern int SkGmOverflowStatus(); -extern int SkGmCableDiagStatus(); - -#ifdef SK_DIAG -extern void SkMacSetRxCmd(); -extern void SkMacCrcGener(); -extern void SkMacTimeStamp(); -extern void SkXmSendCont(); -#endif /* SK_DIAG */ - -#endif /* SK_KR_PROTO */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEINIT_H_ */ diff --git a/drivers/sk98lin/h/skgepnm2.h b/drivers/sk98lin/h/skgepnm2.h deleted file mode 100644 index 5c44f47719..0000000000 --- a/drivers/sk98lin/h/skgepnm2.h +++ /dev/null @@ -1,462 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnm2.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.34 $ - * Date: $Date: 2002/12/16 09:05:18 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgepnm2.h,v $ - * Revision 1.34 2002/12/16 09:05:18 tschilli - * Code for VCT handling added. - * - * Revision 1.33 2002/09/10 09:00:03 rwahl - * Adapted boolean definitions according sktypes. - * - * Revision 1.32 2002/08/09 09:47:01 rwahl - * Added write-only flag to oid access defines. - * Editorial changes. - * - * Revision 1.31 2002/07/17 19:23:18 rwahl - * - Replaced MAC counter definitions by enumeration. - * - Added definition SK_PNMI_MAC_TYPES. - * - Added chipset defnition for Yukon. - * - * Revision 1.30 2001/02/06 10:03:41 mkunz - * - Pnmi V4 dual net support added. Interface functions and macros extended - * - Vpd bug fixed - * - OID_SKGE_MTU added - * - * Revision 1.29 2001/01/22 13:41:37 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.28 2000/08/03 15:12:48 rwahl - * - Additional comment for MAC statistic data structure. - * - * Revision 1.27 2000/08/01 16:10:18 rwahl - * - Added mac statistic data structure for StatRxLongFrame counter. - * - * Revision 1.26 2000/03/31 13:51:34 rwahl - * Added SK_UPTR cast to offset calculation for PNMI struct fields; - * missing cast caused compiler warnings by Win64 compiler. - * - * Revision 1.25 1999/11/22 13:57:41 cgoos - * Changed license header to GPL. - * Allowing overwrite for SK_PNMI_STORE/_READ defines. - * - * Revision 1.24 1999/04/13 15:11:11 mhaveman - * Changed copyright. - * - * Revision 1.23 1999/01/28 15:07:12 mhaveman - * Changed default threshold for port switches per hour from 10 - * to 240 which means 4 switches per minute. This fits better - * the granularity of 32 for the port switch estimate - * counter. - * - * Revision 1.22 1999/01/05 12:52:30 mhaveman - * Removed macro SK_PNMI_MICRO_SEC. - * - * Revision 1.21 1999/01/05 12:50:34 mhaveman - * Enlarged macro definition SK_PNMI_HUNDREDS_SEC() so that no 64-bit - * arithmetic is necessary if SK_TICKS_PER_SEC is 100. - * - * Revision 1.20 1998/12/09 14:02:53 mhaveman - * Defined macro SK_PNMI_DEF_RLMT_CHG_THRES for default port switch - * threshold. - * - * Revision 1.19 1998/12/03 11:28:41 mhaveman - * Removed SK_PNMI_CHECKPTR macro. - * - * Revision 1.18 1998/12/03 11:21:00 mhaveman - * -Added pointer check macro SK_PNMI_CHECKPTR - * -Added macros SK_PNMI_VPD_ARR_SIZE and SK_PNMI_VPD_STR_SIZE for - * VPD key evaluation. - * - * Revision 1.17 1998/11/20 13:20:33 mhaveman - * Fixed bug in SK_PNMI_SET_STAT macro. ErrorStatus was not correctly set. - * - * Revision 1.16 1998/11/20 08:08:49 mhaveman - * Macro SK_PNMI_CHECKFLAGS has got a if clause. - * - * Revision 1.15 1998/11/03 13:53:40 mhaveman - * Fixed alignment problem in macor SK_PNMI_SET_STAT macro. - * - * Revision 1.14 1998/10/30 15:50:13 mhaveman - * Added macro SK_PNMI_MICRO_SEC() - * - * Revision 1.13 1998/10/30 12:32:20 mhaveman - * Added forgotten cast in SK_PNMI_READ_U32 macro. - * - * Revision 1.12 1998/10/29 15:40:26 mhaveman - * -Changed SK_PNMI_TRAP_SENSOR_LEN because SensorDescr has now - * variable string length. - * -Defined SK_PNMI_CHECKFLAGS macro - * - * Revision 1.11 1998/10/29 08:53:34 mhaveman - * Removed SK_PNMI_RLM_XXX table indexed because these counters need - * not been saved over XMAC resets. - * - * Revision 1.10 1998/10/28 08:48:20 mhaveman - * -Added macros for storage according to alignment - * -Changed type of Instance to SK_U32 because of VPD - * -Removed trap structures. Not needed because of alignment problem - * -Changed type of Action form SK_U8 to int - * - * Revision 1.9 1998/10/21 13:34:45 mhaveman - * Shit, mismatched calculation of SK_PNMI_HUNDREDS_SEC. Corrected. - * - * Revision 1.8 1998/10/21 13:24:58 mhaveman - * Changed calculation of hundreds of seconds. - * - * Revision 1.7 1998/10/20 07:31:41 mhaveman - * Made type changes to unsigned int where possible. - * - * Revision 1.6 1998/09/04 17:04:05 mhaveman - * Added Sync counters to offset storage to provided settled values on - * port switch. - * - * Revision 1.5 1998/09/04 12:45:35 mhaveman - * Removed dummies for SK_DRIVER_ macros. They should be added by driver - * writer in skdrv2nd.h. - * - * Revision 1.4 1998/09/04 11:59:50 mhaveman - * Everything compiles now. Driver Macros for counting still missing. - * - * Revision 1.3 1998/08/24 12:01:35 mhaveman - * Intermediate state. - * - * Revision 1.2 1998/08/17 07:51:40 mhaveman - * Intermediate state. - * - * Revision 1.1 1998/08/11 09:08:40 mhaveman - * Intermediate state. - * - ****************************************************************************/ - -#ifndef _SKGEPNM2_H_ -#define _SKGEPNM2_H_ - -/* - * General definitions - */ -#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ -#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ - -#define SK_PNMI_BUS_PCI 1 /* PCI bus*/ - -/* - * Actions - */ -#define SK_PNMI_ACT_IDLE 1 -#define SK_PNMI_ACT_RESET 2 -#define SK_PNMI_ACT_SELFTEST 3 -#define SK_PNMI_ACT_RESETCNT 4 - -/* - * VPD releated defines - */ - -#define SK_PNMI_VPD_RW 1 -#define SK_PNMI_VPD_RO 2 - -#define SK_PNMI_VPD_OK 0 -#define SK_PNMI_VPD_NOTFOUND 1 -#define SK_PNMI_VPD_CUT 2 -#define SK_PNMI_VPD_TIMEOUT 3 -#define SK_PNMI_VPD_FULL 4 -#define SK_PNMI_VPD_NOWRITE 5 -#define SK_PNMI_VPD_FATAL 6 - -#define SK_PNMI_VPD_IGNORE 0 -#define SK_PNMI_VPD_CREATE 1 -#define SK_PNMI_VPD_DELETE 2 - - -/* - * RLMT related defines - */ -#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */ - - -/* - * VCT internal status values - */ -#define SK_PNMI_VCT_PENDING 32 -#define SK_PNMI_VCT_TEST_DONE 64 -#define SK_PNMI_VCT_LINK 128 - -/* - * Internal table definitions - */ -#define SK_PNMI_GET 0 -#define SK_PNMI_PRESET 1 -#define SK_PNMI_SET 2 - -#define SK_PNMI_RO 0 -#define SK_PNMI_RW 1 -#define SK_PNMI_WO 2 - -typedef struct s_OidTabEntry { - SK_U32 Id; - SK_U32 InstanceNo; - unsigned int StructSize; - unsigned int Offset; - int Access; - int (* Func)(SK_AC *pAc, SK_IOC pIo, int action, - SK_U32 Id, char* pBuf, unsigned int* pLen, - SK_U32 Instance, unsigned int TableIndex, - SK_U32 NetNumber); - SK_U16 Param; -} SK_PNMI_TAB_ENTRY; - - -/* - * Trap lengths - */ -#define SK_PNMI_TRAP_SIMPLE_LEN 17 -#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46 -#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23 -#define SK_PNMI_TRAP_RLMT_PORT_LEN 23 - -/* - * Number of MAC types supported - */ -#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1) - -/* - * MAC statistic data list (overall set for MAC types used) - */ -enum SK_MACSTATS { - SK_PNMI_HTX = 0, - SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETLOW, - SK_PNMI_HTX_BROADCAST, - SK_PNMI_HTX_MULTICAST, - SK_PNMI_HTX_UNICAST, - SK_PNMI_HTX_BURST, - SK_PNMI_HTX_PMACC, - SK_PNMI_HTX_MACC, - SK_PNMI_HTX_COL, - SK_PNMI_HTX_SINGLE_COL, - SK_PNMI_HTX_MULTI_COL, - SK_PNMI_HTX_EXCESS_COL, - SK_PNMI_HTX_LATE_COL, - SK_PNMI_HTX_DEFFERAL, - SK_PNMI_HTX_EXCESS_DEF, - SK_PNMI_HTX_UNDERRUN, - SK_PNMI_HTX_CARRIER, - SK_PNMI_HTX_UTILUNDER, - SK_PNMI_HTX_UTILOVER, - SK_PNMI_HTX_64, - SK_PNMI_HTX_127, - SK_PNMI_HTX_255, - SK_PNMI_HTX_511, - SK_PNMI_HTX_1023, - SK_PNMI_HTX_MAX, - SK_PNMI_HTX_LONGFRAMES, - SK_PNMI_HTX_SYNC, - SK_PNMI_HTX_SYNC_OCTET, - SK_PNMI_HTX_RESERVED, - - SK_PNMI_HRX, - SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETLOW, - SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETLOW, - SK_PNMI_HRX_BROADCAST, - SK_PNMI_HRX_MULTICAST, - SK_PNMI_HRX_UNICAST, - SK_PNMI_HRX_PMACC, - SK_PNMI_HRX_MACC, - SK_PNMI_HRX_PMACC_ERR, - SK_PNMI_HRX_MACC_UNKWN, - SK_PNMI_HRX_BURST, - SK_PNMI_HRX_MISSED, - SK_PNMI_HRX_FRAMING, - SK_PNMI_HRX_UNDERSIZE, - SK_PNMI_HRX_OVERFLOW, - SK_PNMI_HRX_JABBER, - SK_PNMI_HRX_CARRIER, - SK_PNMI_HRX_IRLENGTH, - SK_PNMI_HRX_SYMBOL, - SK_PNMI_HRX_SHORTS, - SK_PNMI_HRX_RUNT, - SK_PNMI_HRX_TOO_LONG, - SK_PNMI_HRX_FCS, - SK_PNMI_HRX_CEXT, - SK_PNMI_HRX_UTILUNDER, - SK_PNMI_HRX_UTILOVER, - SK_PNMI_HRX_64, - SK_PNMI_HRX_127, - SK_PNMI_HRX_255, - SK_PNMI_HRX_511, - SK_PNMI_HRX_1023, - SK_PNMI_HRX_MAX, - SK_PNMI_HRX_LONGFRAMES, - - SK_PNMI_HRX_RESERVED, - - SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */ -}; - -/* - * MAC specific data - */ -typedef struct s_PnmiStatAddr { - SK_U16 Reg; /* MAC register containing the value */ - SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/ -} SK_PNMI_STATADDR; - - -/* - * SK_PNMI_STRUCT_DATA copy offset evaluation macros - */ -#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e)) -#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e)) -#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e)) -#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e)) -#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e)) -#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e)) -#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e)) -#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e)) - -#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \ - Val32 = (s); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorStatus)); \ - SK_PNMI_STORE_U32(pVal, Val32); \ - Val32 = (o); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorOffset)); \ - SK_PNMI_STORE_U32(pVal, Val32);} - -/* - * Time macros - */ -#if SK_TICKS_PER_SEC == 100 -#define SK_PNMI_HUNDREDS_SEC(t) (t) -#else -#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) -#endif - -/* - * Macros to work around alignment problems - */ -#ifndef SK_PNMI_STORE_U16 -#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1);} -#endif - -#ifndef SK_PNMI_STORE_U32 -#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3);} -#endif - -#ifndef SK_PNMI_STORE_U64 -#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3); \ - *((char *)(p) + 4) = \ - *(((char *)&(v)) + 4); \ - *((char *)(p) + 5) = \ - *(((char *)&(v)) + 5); \ - *((char *)(p) + 6) = \ - *(((char *)&(v)) + 6); \ - *((char *)(p) + 7) = \ - *(((char *)&(v)) + 7);} -#endif - -#ifndef SK_PNMI_READ_U16 -#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1);} -#endif - -#ifndef SK_PNMI_READ_U32 -#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3);} -#endif - -#ifndef SK_PNMI_READ_U64 -#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3); \ - *(((char *)&(v)) + 4) = \ - *((char *)(p) + 4); \ - *(((char *)&(v)) + 5) = \ - *((char *)(p) + 5); \ - *(((char *)&(v)) + 6) = \ - *((char *)(p) + 6); \ - *(((char *)&(v)) + 7) = \ - *((char *)(p) + 7);} -#endif - -/* - * Macros for Debug - */ -#ifdef DEBUG - -#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \ - pAC->Pnmi.RlmtUpdatedFlag > 0 || \ - pAC->Pnmi.SirqUpdatedFlag > 0) { \ - SK_DBG_MSG(pAC, \ - SK_DBGMOD_PNMI, \ - SK_DBGCAT_CTRL, \ - ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \ - vSt, \ - pAC->Pnmi.MacUpdatedFlag, \ - pAC->Pnmi.RlmtUpdatedFlag, \ - pAC->Pnmi.SirqUpdatedFlag))}} - -#else /* !DEBUG */ - -#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */ - -#endif /* !DEBUG */ - -#endif /* _SKGEPNM2_H_ */ diff --git a/drivers/sk98lin/h/skgepnmi.h b/drivers/sk98lin/h/skgepnmi.h deleted file mode 100644 index 7532313ba8..0000000000 --- a/drivers/sk98lin/h/skgepnmi.h +++ /dev/null @@ -1,1114 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.59 $ - * Date: $Date: 2002/12/16 14:03:50 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgepnmi.h,v $ - * Revision 1.59 2002/12/16 14:03:50 tschilli - * New defines for VCT added. - * - * Revision 1.58 2002/12/16 09:04:59 tschilli - * Code for VCT handling added. - * - * Revision 1.57 2002/09/26 12:41:05 tschilli - * SK_PNMI_PORT BufPort entry in struct SK_PNMI added. - * - * Revision 1.56 2002/08/16 11:10:41 rwahl - * - Replaced c++ comment. - * - * Revision 1.55 2002/08/09 15:40:21 rwahl - * Editorial change (renamed ConfSpeedCap). - * - * Revision 1.54 2002/08/09 11:06:07 rwahl - * Added OID_SKGE_SPEED_CAP. - * - * Revision 1.53 2002/08/09 09:45:28 rwahl - * Added support for NDIS OID_PNP_xxx. - * Editorial changes. - * - * Revision 1.52 2002/08/06 17:54:07 rwahl - * - Added speed cap to PNMI config struct. - * - * Revision 1.51 2002/07/17 19:19:26 rwahl - * - Added OID_SKGE_SPEED_MODE and OID_SKGE_SPEED_STATUS. - * - Added SK_PNMI_CNT_RX_PMACC_ERR() & SK_PNMI_CNT_RX_LONGFRAMES(). - * - Added speed mode & status to PNMI config struct. - * - Editorial changes. - * - * Revision 1.50 2002/05/22 08:59:37 rwahl - * Added string definitions for error msgs. - * - * Revision 1.49 2001/11/20 09:23:50 rwahl - * - pnmi struct: reordered and aligned to 32bit. - * - * Revision 1.48 2001/02/23 14:34:24 mkunz - * Changed macro PHYS2INST. Added pAC to Interface - * - * Revision 1.47 2001/02/07 08:28:23 mkunz - * - Added Oids: OID_SKGE_DIAG_ACTION - * OID_SKGE_DIAG_RESULT - * OID_SKGE_MULTICAST_LIST - * OID_SKGE_CURRENT_PACKET_FILTER - * OID_SKGE_INTERMEDIATE_SUPPORT - * - Changed value of OID_SKGE_MTU - * - * Revision 1.46 2001/02/06 10:01:41 mkunz - * - Pnmi V4 dual net support added. Interface functions and macros extended - * - Vpd bug fixed - * - OID_SKGE_MTU added - * - * Revision 1.45 2001/01/22 13:41:37 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.44 2000/09/07 07:35:27 rwahl - * - removed NDIS counter specific data type. - * - fixed spelling for OID_SKGE_RLMT_PORT_PREFERRED. - * - * Revision 1.43 2000/08/04 11:41:08 rwahl - * - Fixed compiler warning (port is always >= 0) for macros - * SK_PNMI_CNT_RX_LONGFRAMES & SK_PNMI_CNT_SYNC_OCTETS - * - * Revision 1.42 2000/08/03 15:14:07 rwahl - * - Corrected error in driver macros addressing a physical port. - * - * Revision 1.41 2000/08/01 16:22:29 rwahl - * - Changed MDB version to 3.1. - * - Added definitions for StatRxLongFrames counter. - * - Added macro to be used by driver to count long frames received. - * - Added directive to control width (default = 32bit) of NDIS statistic - * counters (SK_NDIS_64BIT_CTR). - * - * Revision 1.40 2000/03/31 13:51:34 rwahl - * Added SK_UPTR cast to offset calculation for PNMI struct fields; - * missing cast caused compiler warnings by Win64 compiler. - * - * Revision 1.39 1999/12/06 10:09:47 rwahl - * Added new error log message. - * - * Revision 1.38 1999/11/22 13:57:55 cgoos - * Changed license header to GPL. - * - * Revision 1.37 1999/09/14 14:25:32 rwahl - * Set MDB version for 1000Base-T (sensors, Master/Slave) changes. - * - * Revision 1.36 1999/05/20 09:24:56 cgoos - * Changes for 1000Base-T (sensors, Master/Slave). - * - * Revision 1.35 1999/04/13 15:10:51 mhaveman - * Replaced RLMT macros SK_RLMT_CHECK_xxx again by those of PNMI to - * grant unified interface. But PNMI macros will store the same - * value as RLMT macros. - * - * Revision 1.34 1999/04/13 15:03:49 mhaveman - * -Changed copyright - * -Removed SK_PNMI_RLMT_MODE_CHK_xxx macros. Those of RLMT should be - * used. - * - * Revision 1.33 1999/03/23 10:41:02 mhaveman - * Changed comments. - * - * Revision 1.32 1999/01/25 15:01:33 mhaveman - * Added support for multiple simultaniously active ports. - * - * Revision 1.31 1999/01/19 10:06:26 mhaveman - * Added new error log message. - * - * Revision 1.30 1999/01/05 10:34:49 mhaveman - * Fixed little error in RlmtChangeEstimate calculation. - * - * Revision 1.29 1999/01/05 09:59:41 mhaveman - * Redesigned port switch average calculation to avoid 64bit - * arithmetic. - * - * Revision 1.28 1998/12/08 10:05:48 mhaveman - * Defined macro SK_PNMI_MIN_STRUCT_SIZE. - * - * Revision 1.27 1998/12/03 14:39:35 mhaveman - * Fixed problem that LSTAT was enumerated wrong. - * - * Revision 1.26 1998/12/03 11:19:51 mhaveman - * Changed contents of errlog message SK_PNMI_ERR016MSG - * - * Revision 1.25 1998/12/01 10:40:04 mhaveman - * Changed size of SensorNumber, ChecksumNumber and RlmtPortNumber in - * SK_PNMI_STRUCT_DATA to be conform with OID definition. - * - * Revision 1.24 1998/11/20 08:09:27 mhaveman - * Added macros to convert between logical, physical port indexes and - * instances. - * - * Revision 1.23 1998/11/10 13:41:13 mhaveman - * Needed to change interface, because NT driver needs a return value - * of needed buffer space on TOO_SHORT errors. Therefore all - * SkPnmiGet/Preset/Set functions now have a pointer to the length - * parameter, where the needed space on error is returned. - * - * Revision 1.22 1998/11/03 12:05:51 mhaveman - * Added pAC parameter to counter macors. - * - * Revision 1.21 1998/11/02 10:47:36 mhaveman - * Added syslog messages for internal errors. - * - * Revision 1.20 1998/10/30 15:49:36 mhaveman - * -Removed unused SK_PNMI_UTILIZATION_BASE and EstOldCnt. - * -Redefined SK_PNMI_CHG_EST_BASE to hundreds of seconds. - * - * Revision 1.19 1998/10/29 15:38:44 mhaveman - * Changed string lengths of PNMI_STRUCT_DATA structure because - * string OIDs are now encoded with leading length ocetet. - * - * Revision 1.18 1998/10/29 08:52:27 mhaveman - * -Added byte to strings in PNMI_STRUCT_DATA structure. - * -Shortened SK_PNMI_RLMT structure to SK_MAX_MACS elements. - * - * Revision 1.17 1998/10/28 08:49:50 mhaveman - * -Changed type of Instance back to SK_U32 because of VPD - * -Changed type from SK_U8 to char of PciBusSpeed, PciBusWidth, PMD, - * and Connector. - * - * Revision 1.16 1998/10/22 10:42:31 mhaveman - * -Removed (SK_U32) casts for OIDs - * -excluded NDIS OIDs when they are already defined with ifndef _NDIS_ - * - * Revision 1.15 1998/10/20 13:56:28 mhaveman - * Headerfile includes now directly other header files to comile correctly. - * - * Revision 1.14 1998/10/20 07:31:09 mhaveman - * Made type changes to unsigned int where possible. - * - * Revision 1.13 1998/10/19 10:53:13 mhaveman - * -Casted OID definitions to SK_U32 - * -Renamed RlmtMAC... to RlmtPort... - * -Changed wrong type of VpdEntriesList from SK_U32 to char * - * - * Revision 1.12 1998/10/13 07:42:27 mhaveman - * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA - * -Removed old cvs history entries - * -Renamed MacNumber to PortNumber - * - * Revision 1.11 1998/10/07 10:55:24 mhaveman - * -Added OID_MDB_VERSION. Therefore was a renumbering of the VPD OIDs - * necessary. - * -Added OID_GEN_ Ids to support the windows driver. - * - * Revision 1.10 1998/09/30 13:41:10 mhaveman - * Renamed some OIDs to reduce usage of 'MAC' which is replaced by 'PORT'. - * - * Revision 1.9 1998/09/04 17:06:17 mhaveman - * -Added SyncCounter as macro. - * -Renamed OID_SKGE_.._NO_DESCR_CTS to OID_SKGE_.._NO_BUF_CTS. - * -Added macros for driver description and version strings. - * - * Revision 1.8 1998/09/04 14:36:52 mhaveman - * Added OIDs and Structure to access value of macro counters which are - * counted by the driver. - * - * Revision 1.7 1998/09/04 11:59:36 mhaveman - * Everything compiles now. Driver Macros for counting still missing. - * - ****************************************************************************/ - -#ifndef _SKGEPNMI_H_ -#define _SKGEPNMI_H_ - -/* - * Include dependencies - */ -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skaddr.h" -#include "h/skrlmt.h" -#include "h/skvpd.h" - -/* - * Management Database Version - */ -#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */ - - -/* - * Event definitions - */ -#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */ -#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */ -#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */ -#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */ -#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */ -#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */ -#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */ - -#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */ -#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets - 1 = single net; 2 = dual net */ -#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ - - -/* - * Return values - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_GENERAL 1 -#define SK_PNMI_ERR_TOO_SHORT 2 -#define SK_PNMI_ERR_BAD_VALUE 3 -#define SK_PNMI_ERR_READ_ONLY 4 -#define SK_PNMI_ERR_UNKNOWN_OID 5 -#define SK_PNMI_ERR_UNKNOWN_INST 6 -#define SK_PNMI_ERR_UNKNOWN_NET 7 - - -/* - * Return values of driver reset function SK_DRIVER_RESET() and - * driver event function SK_DRIVER_EVENT() - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_FAIL 1 - - -/* - * Return values of driver test function SK_DRIVER_SELFTEST() - */ -#define SK_PNMI_TST_UNKNOWN (1 << 0) -#define SK_PNMI_TST_TRANCEIVER (1 << 1) -#define SK_PNMI_TST_ASIC (1 << 2) -#define SK_PNMI_TST_SENSOR (1 << 3) -#define SK_PNMI_TST_POWERMGMT (1 << 4) -#define SK_PNMI_TST_PCI (1 << 5) -#define SK_PNMI_TST_MAC (1 << 6) - - -/* - * RLMT specific definitions - */ -#define SK_PNMI_RLMT_STATUS_STANDBY 1 -#define SK_PNMI_RLMT_STATUS_ACTIVE 2 -#define SK_PNMI_RLMT_STATUS_ERROR 3 - -#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1 -#define SK_PNMI_RLMT_LSTAT_AUTONEG 2 -#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3 -#define SK_PNMI_RLMT_LSTAT_LOG_UP 4 -#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5 - -#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK) -#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK) -#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG) -/* #define SK_PNMI_RLMT_MODE_CHK_EX */ - -/* - * OID definition - */ -#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */ - -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */ -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */ -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */ -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */ -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */ -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */ -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -/* #define OID_802_3_MULTICAST_LIST 0x01010103 */ -/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */ -/* #define OID_802_3_MAC_OPTIONS 0x01010105 */ - -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* - * PnP and PM OIDs - */ -#ifdef SK_POWER_MGMT -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 -#endif /* SK_POWER_MGMT */ - -#endif /* _NDIS_ */ - -#define OID_SKGE_MDB_VERSION 0xFF010100 -#define OID_SKGE_SUPPORTED_LIST 0xFF010101 -#define OID_SKGE_VPD_FREE_BYTES 0xFF010102 -#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103 -#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104 -#define OID_SKGE_VPD_KEY 0xFF010105 -#define OID_SKGE_VPD_VALUE 0xFF010106 -#define OID_SKGE_VPD_ACCESS 0xFF010107 -#define OID_SKGE_VPD_ACTION 0xFF010108 - -#define OID_SKGE_PORT_NUMBER 0xFF010110 -#define OID_SKGE_DEVICE_TYPE 0xFF010111 -#define OID_SKGE_DRIVER_DESCR 0xFF010112 -#define OID_SKGE_DRIVER_VERSION 0xFF010113 -#define OID_SKGE_HW_DESCR 0xFF010114 -#define OID_SKGE_HW_VERSION 0xFF010115 -#define OID_SKGE_CHIPSET 0xFF010116 -#define OID_SKGE_ACTION 0xFF010117 -#define OID_SKGE_RESULT 0xFF010118 -#define OID_SKGE_BUS_TYPE 0xFF010119 -#define OID_SKGE_BUS_SPEED 0xFF01011A -#define OID_SKGE_BUS_WIDTH 0xFF01011B -/* 0xFF01011C unused */ -#define OID_SKGE_DIAG_ACTION 0xFF01011D -#define OID_SKGE_DIAG_RESULT 0xFF01011E -#define OID_SKGE_MTU 0xFF01011F -#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120 -#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121 -#define OID_SKGE_PMD 0xFF010122 -#define OID_SKGE_CONNECTOR 0xFF010123 -#define OID_SKGE_LINK_CAP 0xFF010124 -#define OID_SKGE_LINK_MODE 0xFF010125 -#define OID_SKGE_LINK_MODE_STATUS 0xFF010126 -#define OID_SKGE_LINK_STATUS 0xFF010127 -#define OID_SKGE_FLOWCTRL_CAP 0xFF010128 -#define OID_SKGE_FLOWCTRL_MODE 0xFF010129 -#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A -#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B -#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C -#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D -#define OID_SKGE_MULTICAST_LIST 0xFF01012E -#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F - -#define OID_SKGE_TRAP 0xFF010130 -#define OID_SKGE_TRAP_NUMBER 0xFF010131 - -#define OID_SKGE_RLMT_MODE 0xFF010140 -#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141 -#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142 -#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143 -#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 - -#define OID_SKGE_SPEED_CAP 0xFF010170 -#define OID_SKGE_SPEED_MODE 0xFF010171 -#define OID_SKGE_SPEED_STATUS 0xFF010172 - -#define OID_SKGE_SENSOR_NUMBER 0xFF020100 -#define OID_SKGE_SENSOR_INDEX 0xFF020101 -#define OID_SKGE_SENSOR_DESCR 0xFF020102 -#define OID_SKGE_SENSOR_TYPE 0xFF020103 -#define OID_SKGE_SENSOR_VALUE 0xFF020104 -#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105 -#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106 -#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107 -#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108 -#define OID_SKGE_SENSOR_STATUS 0xFF020109 -#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A -#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B -#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C -#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D - -#define OID_SKGE_CHKSM_NUMBER 0xFF020110 -#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111 -#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112 -#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113 -#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114 -#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115 - -#define OID_SKGE_STAT_TX 0xFF020120 -#define OID_SKGE_STAT_TX_OCTETS 0xFF020121 -#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122 -#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123 -#define OID_SKGE_STAT_TX_UNICAST 0xFF020124 -#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125 -#define OID_SKGE_STAT_TX_BURST 0xFF020126 -#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127 -#define OID_SKGE_STAT_TX_FLOWC 0xFF020128 -#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129 -#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A -#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B -#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C -#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D -#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E -#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F -#define OID_SKGE_STAT_TX_CARRIER 0xFF020130 -/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */ -#define OID_SKGE_STAT_TX_64 0xFF020132 -#define OID_SKGE_STAT_TX_127 0xFF020133 -#define OID_SKGE_STAT_TX_255 0xFF020134 -#define OID_SKGE_STAT_TX_511 0xFF020135 -#define OID_SKGE_STAT_TX_1023 0xFF020136 -#define OID_SKGE_STAT_TX_MAX 0xFF020137 -#define OID_SKGE_STAT_TX_SYNC 0xFF020138 -#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139 -#define OID_SKGE_STAT_RX 0xFF02013A -#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B -#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C -#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D -#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E -#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F -#define OID_SKGE_STAT_RX_FLOWC 0xFF020140 -#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141 -#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142 -#define OID_SKGE_STAT_RX_BURST 0xFF020143 -#define OID_SKGE_STAT_RX_MISSED 0xFF020144 -#define OID_SKGE_STAT_RX_FRAMING 0xFF020145 -#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146 -#define OID_SKGE_STAT_RX_JABBER 0xFF020147 -#define OID_SKGE_STAT_RX_CARRIER 0xFF020148 -#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149 -#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A -#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B -#define OID_SKGE_STAT_RX_RUNT 0xFF02014C -#define OID_SKGE_STAT_RX_CEXT 0xFF02014D -#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E -#define OID_SKGE_STAT_RX_FCS 0xFF02014F -/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */ -#define OID_SKGE_STAT_RX_64 0xFF020151 -#define OID_SKGE_STAT_RX_127 0xFF020152 -#define OID_SKGE_STAT_RX_255 0xFF020153 -#define OID_SKGE_STAT_RX_511 0xFF020154 -#define OID_SKGE_STAT_RX_1023 0xFF020155 -#define OID_SKGE_STAT_RX_MAX 0xFF020156 -#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157 - -#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160 -#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161 -#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162 -#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163 - -#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164 -#define OID_SKGE_RLMT_STATUS 0xFF020165 -#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166 -#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167 -#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168 -#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169 - -#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 -#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 -#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 -#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 -#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 -#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 - -#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170 -#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171 -#define OID_SKGE_TX_RETRY 0xFF020172 -#define OID_SKGE_RX_INTR_CTS 0xFF020173 -#define OID_SKGE_TX_INTR_CTS 0xFF020174 -#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175 -#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176 -#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177 -#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178 -#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179 -#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A -#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B -#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C -#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D -#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E -#define OID_SKGE_SYSUPTIME 0xFF02017F - -#define OID_SKGE_ALL_DATA 0xFF020190 - -/* Defines for VCT. */ -#define OID_SKGE_VCT_GET 0xFF020200 -#define OID_SKGE_VCT_SET 0xFF020201 -#define OID_SKGE_VCT_STATUS 0xFF020202 - - -/* VCT struct to store a backup copy of VCT data after a port reset. */ -typedef struct s_PnmiVct { - SK_U8 VctStatus; - SK_U8 PCableLen; - SK_U32 PMdiPairLen[4]; - SK_U8 PMdiPairSts[4]; -} SK_PNMI_VCT; - - -/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */ -#define SK_PNMI_VCT_NONE 0 -#define SK_PNMI_VCT_OLD_VCT_DATA 1 -#define SK_PNMI_VCT_NEW_VCT_DATA 2 -#define SK_PNMI_VCT_OLD_DSP_DATA 4 -#define SK_PNMI_VCT_NEW_DSP_DATA 8 -#define SK_PNMI_VCT_RUNNING 16 - - -/* VCT cable test status. */ -#define SK_PNMI_VCT_NORMAL_CABLE 0 -#define SK_PNMI_VCT_SHORT_CABLE 1 -#define SK_PNMI_VCT_OPEN_CABLE 2 -#define SK_PNMI_VCT_TEST_FAIL 3 -#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 - -#define OID_SKGE_TRAP_SEN_WAR_LOW 500 -#define OID_SKGE_TRAP_SEN_WAR_UPP 501 -#define OID_SKGE_TRAP_SEN_ERR_LOW 502 -#define OID_SKGE_TRAP_SEN_ERR_UPP 503 -#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520 -#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521 -#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522 -#define OID_SKGE_TRAP_RLMT_PORT_UP 523 -#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 - - -/* - * Define error numbers and messages for syslog - */ -#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1) -#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID" -#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2) -#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys" -#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3) -#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID" -#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4) -#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action" -#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5) -#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver" -#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6) -#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command" -#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7) -#define SK_PNMI_ERR007MSG "General: Driver description not initialized" -#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8) -#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID" -#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9) -#define SK_PNMI_ERR009MSG "Addr: Unknown OID" -#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10) -#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID" -#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11) -#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long" -#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12) -#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID" -#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13) -#define SK_PNMI_ERR013MSG "" -#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14) -#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys" -#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15) -#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small" -#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16) -#define SK_PNMI_ERR016MSG "Vpd: Key string too long" -#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17) -#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer" -#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18) -#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid" -#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19) -#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long" -#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21) -#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long" -#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22) -#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before" -#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23) -#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action" -#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24) -#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action" -#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25) -#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry" -#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26) -#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD" -#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27) -#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry" -#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28) -#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry" -#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29) -#define SK_PNMI_ERR029MSG "General: Driver description string too long" -#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30) -#define SK_PNMI_ERR030MSG "General: Driver version not initialized" -#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31) -#define SK_PNMI_ERR031MSG "General: Driver version string too long" -#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32) -#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr" -#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33) -#define SK_PNMI_ERR033MSG "General: HW description string too long" -#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34) -#define SK_PNMI_ERR034MSG "General: Unknown OID" -#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35) -#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID" -#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36) -#define SK_PNMI_ERR036MSG "" -#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37) -#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0" -#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38) -#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0" -#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39) -#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID" -#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40) -#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID" -#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41) -#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID" -#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42) -#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0" -#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43) -#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0" -#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44) -#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0" -#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45) -#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0" -#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46) -#define SK_PNMI_ERR046MSG "Monitor: Unknown OID" -#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47) -#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0" -#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48) -#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0" -#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49) -#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!" -#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50) -#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!" -#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51) -#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" -#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) -#define SK_PNMI_ERR052MSG "" - -/* - * Management counter macros called by the driver - */ -#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ - (char *)(v)) - - -#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ - { \ - (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \ - if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \ - (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \ - } \ - } -#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++) -#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++) -#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++) -#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++) -#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++) -#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \ - ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v)); -#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \ - { \ - ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \ - (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \ - } -#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++); - -#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatSyncCts)++; \ - (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \ - } \ - } - -#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \ - } \ - } - -/* - * Conversion Macros - */ -#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1) -#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1) -#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1) -#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1) -#define SK_PNMI_PORT_PHYS2INST(pAC,p) \ - (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2)) -#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2) - -/* - * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct - */ -#define SK_PNMI_VPD_KEY_SIZE 5 -#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE) -#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4) -#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */ - -#define SK_PNMI_MULTICAST_LISTLEN 64 -#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS) -#define SK_PNMI_CHECKSUM_ENTRIES 3 -#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1) -#define SK_PNMI_MONITOR_ENTRIES 20 -#define SK_PNMI_TRAP_ENTRIES 10 -#define SK_PNMI_TRAPLEN 128 -#define SK_PNMI_STRINGLEN1 80 -#define SK_PNMI_STRINGLEN2 25 -#define SK_PNMI_TRAP_QUEUE_LEN 512 - -typedef struct s_PnmiVpd { - char VpdKey[SK_PNMI_VPD_KEY_SIZE]; - char VpdValue[SK_PNMI_VPD_DATALEN]; - SK_U8 VpdAccess; - SK_U8 VpdAction; -} SK_PNMI_VPD; - -typedef struct s_PnmiSensor { - SK_U8 SensorIndex; - char SensorDescr[SK_PNMI_STRINGLEN2]; - SK_U8 SensorType; - SK_U32 SensorValue; - SK_U32 SensorWarningThresholdLow; - SK_U32 SensorWarningThresholdHigh; - SK_U32 SensorErrorThresholdLow; - SK_U32 SensorErrorThresholdHigh; - SK_U8 SensorStatus; - SK_U64 SensorWarningCts; - SK_U64 SensorErrorCts; - SK_U64 SensorWarningTimestamp; - SK_U64 SensorErrorTimestamp; -} SK_PNMI_SENSOR; - -typedef struct s_PnmiChecksum { - SK_U64 ChecksumRxOkCts; - SK_U64 ChecksumRxUnableCts; - SK_U64 ChecksumRxErrCts; - SK_U64 ChecksumTxOkCts; - SK_U64 ChecksumTxUnableCts; -} SK_PNMI_CHECKSUM; - -typedef struct s_PnmiStat { - SK_U64 StatTxOkCts; - SK_U64 StatTxOctetsOkCts; - SK_U64 StatTxBroadcastOkCts; - SK_U64 StatTxMulticastOkCts; - SK_U64 StatTxUnicastOkCts; - SK_U64 StatTxLongFramesCts; - SK_U64 StatTxBurstCts; - SK_U64 StatTxPauseMacCtrlCts; - SK_U64 StatTxMacCtrlCts; - SK_U64 StatTxSingleCollisionCts; - SK_U64 StatTxMultipleCollisionCts; - SK_U64 StatTxExcessiveCollisionCts; - SK_U64 StatTxLateCollisionCts; - SK_U64 StatTxDeferralCts; - SK_U64 StatTxExcessiveDeferralCts; - SK_U64 StatTxFifoUnderrunCts; - SK_U64 StatTxCarrierCts; - SK_U64 Dummy1; /* StatTxUtilization */ - SK_U64 StatTx64Cts; - SK_U64 StatTx127Cts; - SK_U64 StatTx255Cts; - SK_U64 StatTx511Cts; - SK_U64 StatTx1023Cts; - SK_U64 StatTxMaxCts; - SK_U64 StatTxSyncCts; - SK_U64 StatTxSyncOctetsCts; - SK_U64 StatRxOkCts; - SK_U64 StatRxOctetsOkCts; - SK_U64 StatRxBroadcastOkCts; - SK_U64 StatRxMulticastOkCts; - SK_U64 StatRxUnicastOkCts; - SK_U64 StatRxLongFramesCts; - SK_U64 StatRxPauseMacCtrlCts; - SK_U64 StatRxMacCtrlCts; - SK_U64 StatRxPauseMacCtrlErrorCts; - SK_U64 StatRxMacCtrlUnknownCts; - SK_U64 StatRxBurstCts; - SK_U64 StatRxMissedCts; - SK_U64 StatRxFramingCts; - SK_U64 StatRxFifoOverflowCts; - SK_U64 StatRxJabberCts; - SK_U64 StatRxCarrierCts; - SK_U64 StatRxIRLengthCts; - SK_U64 StatRxSymbolCts; - SK_U64 StatRxShortsCts; - SK_U64 StatRxRuntCts; - SK_U64 StatRxCextCts; - SK_U64 StatRxTooLongCts; - SK_U64 StatRxFcsCts; - SK_U64 Dummy2; /* StatRxUtilization */ - SK_U64 StatRx64Cts; - SK_U64 StatRx127Cts; - SK_U64 StatRx255Cts; - SK_U64 StatRx511Cts; - SK_U64 StatRx1023Cts; - SK_U64 StatRxMaxCts; -} SK_PNMI_STAT; - -typedef struct s_PnmiConf { - char ConfMacCurrentAddr[6]; - char ConfMacFactoryAddr[6]; - SK_U8 ConfPMD; - SK_U8 ConfConnector; - SK_U8 ConfLinkCapability; - SK_U8 ConfLinkMode; - SK_U8 ConfLinkModeStatus; - SK_U8 ConfLinkStatus; - SK_U8 ConfFlowCtrlCapability; - SK_U8 ConfFlowCtrlMode; - SK_U8 ConfFlowCtrlStatus; - SK_U8 ConfPhyOperationCapability; - SK_U8 ConfPhyOperationMode; - SK_U8 ConfPhyOperationStatus; - SK_U8 ConfSpeedCapability; - SK_U8 ConfSpeedMode; - SK_U8 ConfSpeedStatus; -} SK_PNMI_CONF; - -typedef struct s_PnmiRlmt { - SK_U32 RlmtIndex; - SK_U32 RlmtStatus; - SK_U64 RlmtTxHelloCts; - SK_U64 RlmtRxHelloCts; - SK_U64 RlmtTxSpHelloReqCts; - SK_U64 RlmtRxSpHelloCts; -} SK_PNMI_RLMT; - -typedef struct s_PnmiRlmtMonitor { - SK_U32 RlmtMonitorIndex; - char RlmtMonitorAddr[6]; - SK_U64 RlmtMonitorErrorCts; - SK_U64 RlmtMonitorTimestamp; - SK_U8 RlmtMonitorAdmin; -} SK_PNMI_RLMT_MONITOR; - -typedef struct s_PnmiRequestStatus { - SK_U32 ErrorStatus; - SK_U32 ErrorOffset; -} SK_PNMI_REQUEST_STATUS; - -typedef struct s_PnmiStrucData { - SK_U32 MgmtDBVersion; - SK_PNMI_REQUEST_STATUS ReturnStatus; - SK_U32 VpdFreeBytes; - char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE]; - SK_U32 VpdEntriesNumber; - SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES]; - SK_U32 PortNumber; - SK_U32 DeviceType; - char DriverDescr[SK_PNMI_STRINGLEN1]; - char DriverVersion[SK_PNMI_STRINGLEN2]; - char HwDescr[SK_PNMI_STRINGLEN1]; - char HwVersion[SK_PNMI_STRINGLEN2]; - SK_U16 Chipset; - SK_U32 MtuSize; - SK_U32 Action; - SK_U32 TestResult; - SK_U8 BusType; - SK_U8 BusSpeed; - SK_U8 BusWidth; - SK_U8 SensorNumber; - SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES]; - SK_U8 ChecksumNumber; - SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES]; - SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES]; - SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES]; - SK_U8 RlmtMode; - SK_U32 RlmtPortNumber; - SK_U8 RlmtPortActive; - SK_U8 RlmtPortPreferred; - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_U64 RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - SK_PNMI_RLMT Rlmt[SK_MAX_MACS]; - SK_U32 RlmtMonitorNumber; - SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES]; - SK_U32 TrapNumber; - SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN]; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 SysUpTime; -} SK_PNMI_STRUCT_DATA; - -#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA)) -#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\ - &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes)) - /* - * ReturnStatus field - * must be located - * before VpdFreeBytes - */ - -/* - * Various definitions - */ -#define SK_PNMI_MAX_PROTOS 3 - -#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum - * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK - * for check while init phase 1 - */ - -/* - * Estimate data structure - */ -typedef struct s_PnmiEstimate { - unsigned int EstValueIndex; - SK_U64 EstValue[7]; - SK_U64 Estimate; - SK_TIMER EstTimer; -} SK_PNMI_ESTIMATE; - - -/* - * VCT timer data structure - */ -typedef struct s_VctTimer { - SK_TIMER VctTimer; -} SK_PNMI_VCT_TIMER; - - -/* - * PNMI specific adapter context structure - */ -typedef struct s_PnmiPort { - SK_U64 StatSyncCts; - SK_U64 StatSyncOctetsCts; - SK_U64 StatRxLongFrameCts; - SK_U64 StatRxFrameTooLongCts; - SK_U64 StatRxPMaccErr; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 RxShortZeroMark; - SK_U64 CounterOffset[SK_PNMI_CNT_NO]; - SK_U32 CounterHigh[SK_PNMI_CNT_NO]; - SK_BOOL ActiveFlag; - SK_U8 Align[3]; -} SK_PNMI_PORT; - - -typedef struct s_PnmiData { - SK_PNMI_PORT Port [SK_MAX_MACS]; - SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */ - SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO]; - SK_U32 TestResult; - char HwVersion[10]; - SK_U16 Align01; - - char *pDriverDescription; - char *pDriverVersion; - - int MacUpdatedFlag; - int RlmtUpdatedFlag; - int SirqUpdatedFlag; - - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_PNMI_ESTIMATE RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - - SK_U64 StartUpTime; - SK_U32 DeviceType; - char PciBusSpeed; - char PciBusWidth; - char Chipset; - char PMD; - char Connector; - SK_BOOL DualNetActiveFlag; - SK_U16 Align02; - - char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN]; - unsigned int TrapBufFree; - unsigned int TrapQueueBeg; - unsigned int TrapQueueEnd; - unsigned int TrapBufPad; - unsigned int TrapUnique; - SK_U8 VctStatus[SK_MAX_MACS]; - SK_PNMI_VCT VctBackup[SK_MAX_MACS]; - SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; -} SK_PNMI; - - -/* - * Function prototypes - */ -extern int SkPnmiInit(SK_AC *pAc, SK_IOC IoC, int level); -extern int SkPnmiGetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, - unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiPreSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, - void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiGetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiPreSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiEvent(SK_AC *pAc, SK_IOC IoC, SK_U32 Event, - SK_EVPARA Param); - -#endif diff --git a/drivers/sk98lin/h/skgesirq.h b/drivers/sk98lin/h/skgesirq.h deleted file mode 100644 index fc001b2376..0000000000 --- a/drivers/sk98lin/h/skgesirq.h +++ /dev/null @@ -1,194 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.26 $ - * Date: $Date: 2002/10/14 09:52:36 $ - * Purpose: SK specific Gigabit Ethernet special IRQ functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skgesirq.h,v $ - * Revision 1.26 2002/10/14 09:52:36 rschmidt - * Added SKERR_SIRQ_E023 and SKERR_SIRQ_E023 for GPHY (Yukon) - * Editorial changes - * - * Revision 1.25 2002/07/15 18:15:52 rwahl - * Editorial changes. - * - * Revision 1.24 2002/07/15 15:39:21 rschmidt - * Corrected define for SKERR_SIRQ_E022 - * Editorial changes - * - * Revision 1.23 2002/04/25 11:09:45 rschmidt - * Removed declarations for SkXmInitPhy(), SkXmRxTxEnable() - * Editorial changes - * - * Revision 1.22 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.21 2000/10/18 12:22:40 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.20 1999/12/06 10:00:44 cgoos - * Added SET event for role. - * - * Revision 1.19 1999/11/22 13:58:26 cgoos - * Changed license header to GPL. - * - * Revision 1.18 1999/05/19 07:32:59 cgoos - * Changes for 1000Base-T. - * - * Revision 1.17 1999/03/12 13:29:31 malthoff - * Move Autonegotiation Error Codes to skgeinit.h. - * - * Revision 1.16 1999/03/08 10:11:28 gklug - * add: AutoNegDone return codes - * - * Revision 1.15 1998/11/18 13:20:53 gklug - * add: different timeouts for active and non-active links - * - * Revision 1.14 1998/11/04 07:18:14 cgoos - * Added prototype for SkXmRxTxEnable. - * - * Revision 1.13 1998/10/21 05:52:23 gklug - * add: parameter DoLoop to InitPhy function - * - * Revision 1.12 1998/10/19 06:45:03 cgoos - * Added prototype for SkXmInitPhy. - * - * Revision 1.11 1998/10/15 14:34:10 gklug - * add: WA_TIME is 500 msec - * - * Revision 1.10 1998/10/14 14:49:41 malthoff - * Remove err log defines E021 and E022. They are - * defined in skgeinit.h now. - * - * Revision 1.9 1998/10/14 14:00:39 gklug - * add: error logs for init phys - * - * Revision 1.8 1998/10/14 05:44:05 gklug - * add: E020 - * - * Revision 1.7 1998/10/02 06:24:58 gklug - * add: error messages - * - * Revision 1.6 1998/10/01 07:54:45 gklug - * add: PNMI debug module - * - * Revision 1.5 1998/09/28 13:36:31 malthoff - * Move the bit definitions for Autonegotiation - * and Flow Control to skgeinit.h. - * - * Revision 1.4 1998/09/15 12:29:34 gklug - * add: error logs - * - * Revision 1.3 1998/09/03 13:54:02 gklug - * add: function prototypes - * - * Revision 1.2 1998/09/03 10:24:36 gklug - * add: Events send by PNMI - * add: parameter definition for Flow Control etc. - * - * Revision 1.1 1998/08/27 11:50:27 gklug - * initial revision - * - * - ******************************************************************************/ - -#ifndef _INC_SKGESIRQ_H_ -#define _INC_SKGESIRQ_H_ - -/* - * Define the Event the special IRQ/INI module can handle - */ -#define SK_HWEV_WATIM 1 /* Timeout for WA errata #2 XMAC */ -#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */ -#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */ -#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */ -#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */ -#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */ -#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */ -#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */ -#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */ -#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */ - -#define SK_WA_ACT_TIME (5000000L) /* 5 sec */ -#define SK_WA_INA_TIME (100000L) /* 100 msec */ - -#define SK_HALFDUP_CHK_TIME (10000L) /* 10 msec */ - -/* - * Define the error numbers and messages - */ -#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0) -#define SKERR_SIRQ_E001MSG "Unknown event" -#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1) -#define SKERR_SIRQ_E002MSG "Packet timeout RX1" -#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1) -#define SKERR_SIRQ_E003MSG "Packet timeout RX2" -#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1) -#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized" -#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1) -#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized" -#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1) -#define SKERR_SIRQ_E006MSG "CHECK failure R1" -#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1) -#define SKERR_SIRQ_E007MSG "CHECK failure R2" -#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1) -#define SKERR_SIRQ_E008MSG "CHECK failure XS1" -#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1) -#define SKERR_SIRQ_E009MSG "CHECK failure XA1" -#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1) -#define SKERR_SIRQ_E010MSG "CHECK failure XS2" -#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1) -#define SKERR_SIRQ_E011MSG "CHECK failure XA2" -#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1) -#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error" -#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1) -#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error" -#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1) -#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)" -#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1) -#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)" -#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1) -#define SKERR_SIRQ_E016MSG "Parity error MAC 1" -#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1) -#define SKERR_SIRQ_E017MSG "Parity error MAC 2" -#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1) -#define SKERR_SIRQ_E018MSG "Parity error RX 1" -#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1) -#define SKERR_SIRQ_E019MSG "Parity error RX 2" -#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1) -#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun" -#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1) -#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt" -#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1) -#define SKERR_SIRQ_E022MSG "Cable pair swap error" -#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1) -#define SKERR_SIRQ_E023MSG "Auto-negotiation error" -#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1) -#define SKERR_SIRQ_E024MSG "FIFO overflow error" - -extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); -extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port); -extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); - -#endif /* _INC_SKGESIRQ_H_ */ diff --git a/drivers/sk98lin/h/ski2c.h b/drivers/sk98lin/h/ski2c.h deleted file mode 100644 index 5ffaf6ede1..0000000000 --- a/drivers/sk98lin/h/ski2c.h +++ /dev/null @@ -1,292 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.34 $ - * Date: $Date: 2003/01/28 09:11:21 $ - * Purpose: Defines to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: ski2c.h,v $ - * Revision 1.34 2003/01/28 09:11:21 rschmidt - * Editorial changes - * - * Revision 1.33 2002/10/14 16:40:50 rschmidt - * Editorial changes (TWSI) - * - * Revision 1.32 2002/08/13 08:55:07 rschmidt - * Editorial changes - * - * Revision 1.31 2002/08/06 09:44:22 jschmalz - * Extensions and changes for Yukon - * - * Revision 1.30 2001/04/05 11:38:09 rassmann - * Set SenState to idle in SkI2cWaitIrq(). - * Changed error message in SkI2cWaitIrq(). - * - * Revision 1.29 2000/08/03 14:28:17 rassmann - * - Added function to wait for I2C being ready before resetting the board. - * - Replaced one duplicate "out of range" message with correct one. - * - * Revision 1.28 1999/11/22 13:55:46 cgoos - * Changed license header to GPL. - * - * Revision 1.27 1999/05/20 09:23:10 cgoos - * Changes for 1000Base-T (Fan sensors). - * - * Revision 1.26 1998/12/01 13:45:47 gklug - * add: InitLevel to I2c struct - * - * Revision 1.25 1998/11/03 06:55:16 gklug - * add: Dummy Reads to I2c struct - * - * Revision 1.24 1998/10/02 14:28:59 cgoos - * Added prototype for SkI2cIsr. - * - * Revision 1.23 1998/09/08 12:20:11 gklug - * add: prototypes for init and read functions - * - * Revision 1.22 1998/09/08 07:37:56 gklug - * add: log error if PCI_IO voltage sensor could not be initialized - * - * Revision 1.21 1998/09/04 08:38:05 malthoff - * Change the values for I2C_READ and I2C_WRITE - * - * Revision 1.20 1998/08/25 07:52:22 gklug - * chg: Timestamps (last) added for logging - * - * Revision 1.19 1998/08/25 06:09:00 gklug - * rmv: warning and error levels of the individual sensors. - * add: timing definitions for sending traps and logging errors - * - * Revision 1.18 1998/08/20 11:41:15 gklug - * chg: omit STRCPY macro by using char * as Sensor Description - * - * Revision 1.17 1998/08/20 11:37:43 gklug - * chg: change Ioc to IoC - * - * Revision 1.16 1998/08/20 11:30:38 gklug - * fix: SenRead declaration - * - * Revision 1.15 1998/08/20 11:27:53 gklug - * fix: Compile bugs with new awrning constants - * - * Revision 1.14 1998/08/20 08:53:12 gklug - * fix: compiler errors - * add: Threshold values - * - * Revision 1.13 1998/08/19 12:21:16 gklug - * fix: remove struct from C files (see CCC) - * add: typedefs for all structs - * - * Revision 1.12 1998/08/19 10:57:41 gklug - * add: Warning levels - * - * Revision 1.11 1998/08/18 08:37:02 malthoff - * Prototypes not required for SK_DIAG. - * - * Revision 1.10 1998/08/17 13:54:00 gklug - * fix: declaration of event function - * - * Revision 1.9 1998/08/17 06:48:39 malthoff - * Remove some unrequired macros. - * Fix the compiler errors. - * - * Revision 1.8 1998/08/14 06:47:19 gklug - * fix: Values are intergers - * - * Revision 1.7 1998/08/14 06:26:05 gklug - * add: Init error message - * - * Revision 1.6 1998/08/13 08:31:08 gklug - * add: Error message - * - * Revision 1.5 1998/08/12 14:32:04 gklug - * add: new error code/message - * - * Revision 1.4 1998/08/12 13:39:08 gklug - * chg: names of error messages - * add: defines for Sensor type and thresholds - * - * Revision 1.3 1998/08/11 07:57:16 gklug - * add: sensor struct - * add: Timeout defines - * add: I2C control struct for pAC - * - * Revision 1.2 1998/07/17 11:29:02 gklug - * rmv: Microwire and SMTPANIC - * - * Revision 1.1 1998/06/19 14:30:10 malthoff - * Created. Sources taken from ML Project. - * - * - ******************************************************************************/ - -/* - * SKI2C.H contains all I2C specific defines - */ - -#ifndef _SKI2C_H_ -#define _SKI2C_H_ - -typedef struct s_Sensor SK_SENSOR; - -#include "h/skgei2c.h" - -/* - * Define the I2C events. - */ -#define SK_I2CEV_IRQ 1 /* IRQ happened Event */ -#define SK_I2CEV_TIM 2 /* Timeout event */ -#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */ - -/* - * Define READ and WRITE Constants. - */ -#undef I2C_READ /* just in case */ -#undef I2C_WRITE /* just in case */ -#define I2C_READ 0 -#define I2C_WRITE 1 -#define I2C_BURST 1 -#define I2C_SINGLE 0 - -#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0) -#define SKERR_I2C_E001MSG "Sensor index unknown" -#define SKERR_I2C_E002 (SKERR_I2C_E001+1) -#define SKERR_I2C_E002MSG "TWSI: transfer does not complete" -#define SKERR_I2C_E003 (SKERR_I2C_E002+1) -#define SKERR_I2C_E003MSG "LM80: NAK on device send" -#define SKERR_I2C_E004 (SKERR_I2C_E003+1) -#define SKERR_I2C_E004MSG "LM80: NAK on register send" -#define SKERR_I2C_E005 (SKERR_I2C_E004+1) -#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send" -#define SKERR_I2C_E006 (SKERR_I2C_E005+1) -#define SKERR_I2C_E006MSG "Unknown event" -#define SKERR_I2C_E007 (SKERR_I2C_E006+1) -#define SKERR_I2C_E007MSG "LM80 read out of state" -#define SKERR_I2C_E008 (SKERR_I2C_E007+1) -#define SKERR_I2C_E008MSG "Unexpected sensor read completed" -#define SKERR_I2C_E009 (SKERR_I2C_E008+1) -#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range" -#define SKERR_I2C_E010 (SKERR_I2C_E009+1) -#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range" -#define SKERR_I2C_E011 (SKERR_I2C_E010+1) -#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range" -#define SKERR_I2C_E012 (SKERR_I2C_E011+1) -#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range" -#define SKERR_I2C_E013 (SKERR_I2C_E012+1) -#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor" -#define SKERR_I2C_E014 (SKERR_I2C_E013+1) -#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range" -#define SKERR_I2C_E015 (SKERR_I2C_E014+1) -#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range" -#define SKERR_I2C_E016 (SKERR_I2C_E015+1) -#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete" - -/* - * Define Timeout values - */ -#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */ -#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */ -#define SK_I2C_TIM_WATCH 1000000L /* 1 second */ - -/* - * Define trap and error log hold times - */ -#ifndef SK_SEN_ERR_TR_HOLD -#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_ERR_LOG_HOLD -#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_TR_HOLD -#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_LOG_HOLD -#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC) -#endif - -/* - * Defines for SenType - */ -#define SK_SEN_UNKNOWN 0 -#define SK_SEN_TEMP 1 -#define SK_SEN_VOLT 2 -#define SK_SEN_FAN 3 - -/* - * Define for the SenErrorFlag - */ -#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */ -#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */ -#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */ -#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */ -#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */ - -/* - * Define the Sensor struct - */ -struct s_Sensor { - char *SenDesc; /* Description */ - int SenType; /* Voltage or Temperature */ - SK_I32 SenValue; /* Current value of the sensor */ - SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */ - SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */ - SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */ - SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ - int SenErrFlag; /* Sensor indicated an error */ - SK_BOOL SenInit; /* Is sensor initialized ? */ - SK_U64 SenErrCts; /* Error trap counter */ - SK_U64 SenWarnCts; /* Warning trap counter */ - SK_U64 SenBegErrTS; /* Begin error timestamp */ - SK_U64 SenBegWarnTS; /* Begin warning timestamp */ - SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */ - SK_U64 SenLastErrLogTS; /* Last error log timestamp */ - SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */ - SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */ - int SenState; /* Sensor State (see HW specific include) */ - int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen); - /* Sensors read function */ - SK_U16 SenReg; /* Register Address for this sensor */ - SK_U8 SenDev; /* Device Selection for this sensor */ -}; - -typedef struct s_I2c { - SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */ - int CurrSens; /* Which sensor is currently queried */ - int MaxSens; /* Max. number of sensors */ - int TimerMode; /* Use the timer also to watch the state machine */ - int InitLevel; /* Initialized Level */ -#ifndef SK_DIAG - int DummyReads; /* Number of non-checked dummy reads */ - SK_TIMER SenTimer; /* Sensors timer */ -#endif /* !SK_DIAG */ -} SK_I2C; - -extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); -#ifndef SK_DIAG -extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); -extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); -extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); - -#endif -#endif /* n_SKI2C_H */ diff --git a/drivers/sk98lin/h/skqueue.h b/drivers/sk98lin/h/skqueue.h deleted file mode 100644 index bce20a75b6..0000000000 --- a/drivers/sk98lin/h/skqueue.h +++ /dev/null @@ -1,147 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.14 $ - * Date: $Date: 2002/03/15 10:52:13 $ - * Purpose: Defines for the Event queue - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skqueue.h,v $ - * Revision 1.14 2002/03/15 10:52:13 mkunz - * Added event classes for link aggregation - * - * Revision 1.13 1999/11/22 13:59:05 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/09/08 08:48:01 gklug - * add: init level handling - * - * Revision 1.11 1998/09/03 14:15:11 gklug - * add: CSUM and HWAC Eventclass and function. - * fix: pParaPtr according to CCC - * - * Revision 1.10 1998/08/20 12:43:03 gklug - * add: typedef SK_QUEUE - * - * Revision 1.9 1998/08/19 09:50:59 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.8 1998/08/18 07:00:01 gklug - * fix: SK_PTR not defined use void * instead. - * - * Revision 1.7 1998/08/17 13:43:19 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.6 1998/08/14 07:09:30 gklug - * fix: chg pAc -> pAC - * - * Revision 1.5 1998/08/11 14:26:44 gklug - * chg: Event Dispatcher returns now int. - * - * Revision 1.4 1998/08/11 12:15:21 gklug - * add: Error numbers of skqueue module - * - * Revision 1.3 1998/08/07 12:54:23 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:34:00 gklug - * adapt structure defs to CCC - * add: prototypes for functions - * - * Revision 1.1 1998/07/30 14:52:12 gklug - * Initial version. - * Defines Event Classes, Event structs and queue management variables. - * - * - * - ******************************************************************************/ - -/* - * SKQUEUE.H contains all defines and types for the event queue - */ - -#ifndef _SKQUEUE_H_ -#define _SKQUEUE_H_ - - -/* - * define the event classes to be served - */ -#define SKGE_DRV 1 /* Driver Event Class */ -#define SKGE_RLMT 2 /* RLMT Event Class */ -#define SKGE_I2C 3 /* i2C Event Class */ -#define SKGE_PNMI 4 /* PNMI Event Class */ -#define SKGE_CSUM 5 /* Checksum Event Class */ -#define SKGE_HWAC 6 /* Hardware Access Event Class */ - -#define SKGE_SWT 9 /* Software Timer Event Class */ -#define SKGE_LACP 10 /* LACP Aggregation Event Class */ -#define SKGE_RSF 11 /* RSF Aggregation Event Class */ -#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */ -#define SKGE_FD 13 /* FD Distributor Event Class */ - -/* - * define event queue as circular buffer - */ -#define SK_MAX_EVENT 64 - -/* - * Parameter union for the Para stuff - */ -typedef union u_EvPara { - void *pParaPtr; /* Parameter Pointer */ - SK_U64 Para64; /* Parameter 64bit version */ - SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */ -} SK_EVPARA; - -/* - * Event Queue - * skqueue.c - * events are class/value pairs - * class is addressee, e.g. RMT, PCM etc. - * value is command, e.g. line state change, ring op change etc. - */ -typedef struct s_EventElem { - SK_U32 Class ; /* Event class */ - SK_U32 Event ; /* Event value */ - SK_EVPARA Para ; /* Event parameter */ -} SK_EVENTELEM; - -typedef struct s_Queue { - SK_EVENTELEM EvQueue[SK_MAX_EVENT]; - SK_EVENTELEM *EvPut ; - SK_EVENTELEM *EvGet ; -} SK_QUEUE; - -extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); -extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, - SK_EVPARA Para); -extern int SkEventDispatcher(SK_AC *pAC,SK_IOC Ioc); - - -/* Define Error Numbers and messages */ -#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0) -#define SKERR_Q_E001MSG "Event queue overflow" -#define SKERR_Q_E002 (SKERR_Q_E001+1) -#define SKERR_Q_E002MSG "Undefined event class" -#endif /* _SKQUEUE_H_ */ diff --git a/drivers/sk98lin/h/skrlmt.h b/drivers/sk98lin/h/skrlmt.h deleted file mode 100644 index 04d025b009..0000000000 --- a/drivers/sk98lin/h/skrlmt.h +++ /dev/null @@ -1,563 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.35 $ - * Date: $Date: 2003/01/31 14:12:41 $ - * Purpose: Header file for Redundant Link ManagemenT. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skrlmt.h,v $ - * Revision 1.35 2003/01/31 14:12:41 mkunz - * single port adapter runs now with two identical MAC addresses - * - * Revision 1.34 2002/09/23 15:13:41 rwahl - * Editorial changes. - * - * Revision 1.33 2001/07/03 12:16:48 mkunz - * New Flag ChgBcPrio (Change priority of last broadcast received) - * - * Revision 1.32 2001/02/14 14:06:31 rassmann - * Editorial changes. - * - * Revision 1.31 2001/02/05 14:25:26 rassmann - * Prepared RLMT for transparent operation. - * - * Revision 1.30 2001/01/22 13:41:39 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.29 2000/11/17 08:58:00 rassmann - * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. - * - * Revision 1.28 2000/11/09 12:24:34 rassmann - * Editorial changes. - * - * Revision 1.27 1999/11/22 13:59:56 cgoos - * Changed license header to GPL. - * - * Revision 1.26 1999/10/04 14:01:19 rassmann - * Corrected reaction to reception of BPDU frames (#10441). - * - * Revision 1.25 1999/07/20 12:53:39 rassmann - * Fixed documentation errors for lookahead macros. - * - * Revision 1.24 1999/05/28 11:15:56 rassmann - * Changed behaviour to reflect Design Spec v1.2. - * Controlling Link LED(s). - * Introduced RLMT Packet Version field in RLMT Packet. - * Newstyle lookahead macros (checking meta-information before looking at - * the packet). - * - * Revision 1.23 1999/01/28 12:50:42 rassmann - * Not using broadcast time stamps in CheckLinkState mode. - * - * Revision 1.22 1999/01/27 14:13:04 rassmann - * Monitoring broadcast traffic. - * Switching more reliably and not too early if switch is - * configured for spanning tree. - * - * Revision 1.21 1998/12/08 13:11:25 rassmann - * Stopping SegTimer at RlmtStop. - * - * Revision 1.20 1998/11/24 12:37:33 rassmann - * Implemented segmentation check. - * - * Revision 1.19 1998/11/17 13:43:06 rassmann - * Handling (logical) tx failure. - * Sending packet on logical address after PORT_SWITCH. - * - * Revision 1.18 1998/11/13 16:56:56 rassmann - * Added macro version of SkRlmtLookaheadPacket. - * - * Revision 1.17 1998/11/06 18:06:05 rassmann - * Corrected timing when RLMT checks fail. - * Clearing tx counter earlier in periodical checks. - * - * Revision 1.16 1998/11/03 13:53:50 rassmann - * RLMT should switch now (at least in mode 3). - * - * Revision 1.15 1998/10/22 11:39:52 rassmann - * Corrected signed/unsigned mismatches. - * Corrected receive list handling and address recognition. - * - * Revision 1.14 1998/10/15 15:16:36 rassmann - * Finished Spanning Tree checking. - * Checked with lint. - * - * Revision 1.13 1998/09/24 19:16:08 rassmann - * Code cleanup. - * Introduced Timer for PORT_DOWN due to no RX. - * - * Revision 1.12 1998/09/16 11:09:52 rassmann - * Syntax corrections. - * - * Revision 1.11 1998/09/15 11:28:50 rassmann - * Syntax corrections. - * - * Revision 1.10 1998/09/14 17:07:38 rassmann - * Added code for port checking via LAN. - * Changed Mbuf definition. - * - * Revision 1.9 1998/09/07 11:14:15 rassmann - * Syntax corrections. - * - * Revision 1.8 1998/09/07 09:06:08 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/04 19:41:34 rassmann - * Syntax corrections. - * Started entering code for checking local links. - * - * Revision 1.6 1998/09/04 12:14:28 rassmann - * Interface cleanup. - * - * Revision 1.5 1998/09/02 16:55:29 rassmann - * Updated to reflect new DRV/HWAC/RLMT interface. - * - * Revision 1.4 1998/09/02 07:26:02 afischer - * typedef for SK_RLMT_PORT - * - * Revision 1.3 1998/08/27 14:29:03 rassmann - * Code cleanup. - * - * Revision 1.2 1998/08/27 14:26:25 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:29:10 rassmann - * First public version. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the header file for Redundant Link ManagemenT. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * "skrlmt.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKRLMT_H -#define __INC_SKRLMT_H - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */ -#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */ - -/* ----- Default queue sizes - must be multiples of 8 KB ----- */ - -/* Less than 8 KB free in RX queue => pause frames. */ -#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */ -#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */ -#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */ - -#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */ - -/* ----- PORT states ----- */ - -#define SK_RLMT_PS_INIT 0 /* Port state: Init. */ -#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */ -#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */ -#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */ -#define SK_RLMT_PS_UP 4 /* Port state: Up. */ - -/* ----- RLMT states ----- */ - -#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */ -#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */ -#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */ - -/* ----- PORT events ----- */ - -#define SK_RLMT_LINK_UP 1001 /* Link came up. */ -#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */ -#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */ - -/* ----- RLMT events ----- */ - -#define SK_RLMT_START 2001 /* Start RLMT. */ -#define SK_RLMT_STOP 2002 /* Stop RLMT. */ -#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */ -#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */ -#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */ -#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */ -#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */ -#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */ - -/* ----- RLMT mode bits ----- */ - -/* - * CAUTION: These defines are private to RLMT. - * Please use the RLMT mode defines below. - */ - -#define SK_RLMT_CHECK_LINK 1 /* Check Link. */ -#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */ -#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */ - -#ifndef RLMT_CHECK_REMOTE -#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK -#else /* RLMT_CHECK_REMOTE */ -#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */ -#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3 -#define SK_RLMT_CHECK_OTHERS \ - (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) -#endif /* RLMT_CHECK_REMOTE */ - -#ifndef SK_RLMT_ENABLE_TRANSPARENT -#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */ -#else /* SK_RLMT_ENABLE_TRANSPARENT */ -#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */ -#endif /* SK_RLMT_ENABLE_TRANSPARENT */ - -/* ----- RLMT modes ----- */ - -/* Check Link State. */ -#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK) - -/* Check Local Ports: check other links on the same adapter. */ -#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK) - -/* Check Local Ports and Segmentation Status. */ -#define SK_RLMT_MODE_CLPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG) - -#ifdef RLMT_CHECK_REMOTE -/* Check Local and Remote Ports: check links (local or remote). */ - Name of define TBD! -#define SK_RLMT_MODE_CRP \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) - -/* Check Local and Remote Ports and Segmentation Status. */ - Name of define TBD! -#define SK_RLMT_MODE_CRPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \ - SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG) -#endif /* RLMT_CHECK_REMOTE */ - -/* ----- RLMT lookahead result bits ----- */ - -#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */ -#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */ - -/* Macros */ - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -unsigned PktLen /* received packet's length */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */ -unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */ -#endif /* 0 */ - -#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \ - _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \ - if (_pAC->Rlmt.RlmtOff) { \ - *(pNumBytes) = 0; \ - } \ - else {\ - if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ - *(pNumBytes) = 0; \ - } \ - else if (IsBc) { \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ - *(pNumBytes) = 6; \ - *(pOffset) = 6; \ - } \ - else { \ - *(pNumBytes) = 0; \ - } \ - } \ - else { \ - if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pNumBytes) = 0; \ - } \ - else { \ - *(pNumBytes) = 6; \ - *(pOffset) = 0; \ - } \ - } \ - } \ -} - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -SK_BOOL IsMc /* Flag: packet is multicast */ -unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */ -SK_RLMT_LOOKAHEAD() expects *pNumBytes from -packet offset *pOffset (s.a.) at *pLaPacket. - -If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is -BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler -can trash unneeded parts of the if construction. -#endif /* 0 */ - -#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - SK_U8 *_pLaPacket; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - _pLaPacket = (SK_U8 *)(pLaPacket); \ - if (IsBc) {\ - if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \ - _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \ - _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \ - _pAC->Rlmt.CheckSwitch = SK_TRUE; \ - } \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - else if (IsMc) { \ - if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \ - _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \ - } \ - else { \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else { \ - if (SK_ADDR_EQUAL( \ - _pLaPacket, \ - _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ -} - -#ifdef SK_RLMT_FAST_LOOKAHEAD -Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_FAST_LOOKAHEAD */ -#ifdef SK_RLMT_SLOW_LOOKAHEAD -Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_SLOW_LOOKAHEAD */ - -/* typedefs *******************************************************************/ - -#ifdef SK_RLMT_MBUF_PRIVATE -typedef struct s_RlmtMbuf { - some content -} SK_RLMT_MBUF; -#endif /* SK_RLMT_MBUF_PRIVATE */ - - -#ifdef SK_LA_INFO -typedef struct s_Rlmt_PacketInfo { - unsigned PacketLength; /* Length of packet. */ - unsigned PacketType; /* Directed/Multicast/Broadcast. */ -} SK_RLMT_PINFO; -#endif /* SK_LA_INFO */ - - -typedef struct s_RootId { - SK_U8 Id[8]; /* Root Bridge Id. */ -} SK_RLMT_ROOT_ID; - - -typedef struct s_port { - SK_MAC_ADDR CheckAddr; - SK_BOOL SuspectTx; -} SK_PORT_CHECK; - - -typedef struct s_RlmtNet SK_RLMT_NET; - - -typedef struct s_RlmtPort { - -/* ----- Public part (read-only) ----- */ - - SK_U8 PortState; /* Current state of this port. */ - - /* For PNMI */ - SK_BOOL LinkDown; - SK_BOOL PortDown; - SK_U8 Align01; - - SK_U32 PortNumber; /* Number of port on adapter. */ - SK_RLMT_NET * Net; /* Net port belongs to. */ - - SK_U64 TxHelloCts; - SK_U64 RxHelloCts; - SK_U64 TxSpHelloReqCts; - SK_U64 RxSpHelloCts; - -/* ----- Private part ----- */ - -/* SK_U64 PacketsRx; */ /* Total packets received. */ - SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */ -/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */ - SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */ - SK_U64 BcTimeStamp; /* Time of last BC receive. */ - SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */ - - SK_TIMER UpTimer; /* Timer struct Link/Port up. */ - SK_TIMER DownRxTimer; /* Timer struct down rx. */ - SK_TIMER DownTxTimer; /* Timer struct down tx. */ - - SK_U32 CheckingState; /* Checking State. */ - - SK_ADDR_PORT * AddrPort; - - SK_U8 Random[4]; /* Random value. */ - unsigned PortsChecked; /* #ports checked. */ - unsigned PortsSuspect; /* #ports checked that are s. */ - SK_PORT_CHECK PortCheck[1]; -/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */ - - SK_BOOL PortStarted; /* Port is started. */ - SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */ - SK_BOOL RootIdSet; - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ -} SK_RLMT_PORT; - - -struct s_RlmtNet { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NetNumber; /* Number of net. */ - - SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */ - SK_U32 NumPorts; /* Number of ports. */ - SK_U32 PrefPort; /* Preferred port. */ - - /* For PNMI */ - - SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */ - SK_U32 RlmtMode; /* Check ... */ - SK_U32 ActivePort; /* Active port. */ - SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */ - - SK_U8 RlmtState; /* Current RLMT state. */ - -/* ----- Private part ----- */ - SK_BOOL RootIdSet; - SK_U16 Align01; - - int LinksUp; /* #Links up. */ - int PortsUp; /* #Ports up. */ - SK_U32 TimeoutValue; /* RLMT timeout value. */ - - SK_U32 CheckingState; /* Checking State. */ - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ - - SK_TIMER LocTimer; /* Timer struct. */ - SK_TIMER SegTimer; /* Timer struct. */ -}; - - -typedef struct s_Rlmt { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NumNets; /* Number of nets. */ - SK_U32 NetsStarted; /* Number of nets started. */ - SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */ - SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */ - -/* ----- Private part ----- */ - SK_BOOL CheckSwitch; - SK_BOOL RlmtOff; /* set to zero if the Mac addresses - are equal or the second one - is zero */ - SK_U16 Align01; - -} SK_RLMT; - - -extern SK_MAC_ADDR BridgeMcAddr; -extern SK_MAC_ADDR SkRlmtMcAddr; - -/* function prototypes ********************************************************/ - - -#ifndef SK_KR_PROTO - -/* Functions provided by SkRlmt */ - -/* ANSI/C++ compliant function prototypes */ - -extern void SkRlmtInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkRlmtEvent( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 Event, - SK_EVPARA Para); - -#else /* defined(SK_KR_PROTO) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style function prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKRLMT_H */ diff --git a/drivers/sk98lin/h/sktimer.h b/drivers/sk98lin/h/sktimer.h deleted file mode 100644 index 36f8ccb6af..0000000000 --- a/drivers/sk98lin/h/sktimer.h +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.9 $ - * Date: $Date: 1999/11/22 14:00:29 $ - * Purpose: Defines for the timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: sktimer.h,v $ - * Revision 1.9 1999/11/22 14:00:29 cgoos - * Changed license header to GPL. - * - * Revision 1.8 1998/09/08 08:48:02 gklug - * add: init level handling - * - * Revision 1.7 1998/08/20 12:31:29 gklug - * fix: SK_TIMCTRL needs to be defined - * - * Revision 1.6 1998/08/19 09:51:00 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.5 1998/08/17 13:43:21 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.4 1998/08/14 07:09:31 gklug - * fix: chg pAc -> pAC - * - * Revision 1.3 1998/08/07 12:54:24 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:35:29 gklug - * add: Timer control struct for Adapters context - * add: function prototypes - * - * Revision 1.1 1998/08/05 11:27:01 gklug - * First version: adapted from SMT - * - * - ******************************************************************************/ - -/* - * SKTIMER.H contains all defines and types for the timer functions - */ - -#ifndef _SKTIMER_H_ -#define _SKTIMER_H_ - -#include "h/skqueue.h" - -/* - * SK timer - * - needed wherever a timer is used. Put this in your data structure - * wherever you want. - */ -typedef struct s_Timer SK_TIMER; - -struct s_Timer { - SK_TIMER *TmNext ; /* linked list */ - SK_U32 TmClass ; /* Timer Event class */ - SK_U32 TmEvent ; /* Timer Event value */ - SK_EVPARA TmPara ; /* Timer Event parameter */ - SK_U32 TmDelta ; /* delta time */ - int TmActive ; /* flag : active/inactive */ -} ; - -/* - * Timer control struct. - * - use in Adapters context name pAC->Tim - */ -typedef struct s_TimCtrl { - SK_TIMER *StQueue ; /* Head of Timer queue */ -} SK_TIMCTRL ; - -extern void SkTimerInit(SK_AC *pAC,SK_IOC Ioc, int Level); -extern void SkTimerStop(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer); -extern void SkTimerStart(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer, - SK_U32 Time,SK_U32 Class,SK_U32 Event,SK_EVPARA Para); -extern void SkTimerDone(SK_AC *pAC,SK_IOC Ioc); -#endif /* _SKTIMER_H_ */ diff --git a/drivers/sk98lin/h/sktypes.h b/drivers/sk98lin/h/sktypes.h deleted file mode 100644 index e657016e5b..0000000000 --- a/drivers/sk98lin/h/sktypes.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * - * Name: sktypes.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.3 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: Define data types for Linux - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - /***************************************************************************** - * - * History: - * - * $Log: sktypes.h,v $ - * Revision 1.3 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.2 1999/11/22 14:01:58 cgoos - * Changed license header to GPL. - * Now using Linux' fixed size types instead of standard types. - * - * Revision 1.1 1999/02/16 07:41:40 cgoos - * First version. - * - * - * - *****************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * In this file, all data types that are needed by the common modules - * are mapped to Linux data types. - * - * - * Include File Hierarchy: - * - * - ******************************************************************************/ - -#ifndef __INC_SKTYPES_H -#define __INC_SKTYPES_H - - -/* defines *******************************************************************/ - -/* - * Data types with a specific size. 'I' = signed, 'U' = unsigned. - */ -#define SK_I8 s8 -#define SK_U8 u8 -#define SK_I16 s16 -#define SK_U16 u16 -#define SK_I32 s32 -#define SK_U32 u32 -#define SK_I64 s64 -#define SK_U64 u64 - -#define SK_UPTR ulong /* casting pointer <-> integral */ - -/* -* Boolean type. -*/ -#define SK_BOOL SK_U8 -#define SK_FALSE 0 -#define SK_TRUE (!SK_FALSE) - -/* typedefs *******************************************************************/ - -/* function prototypes ********************************************************/ - -#endif /* __INC_SKTYPES_H */ diff --git a/drivers/sk98lin/h/skversion.h b/drivers/sk98lin/h/skversion.h deleted file mode 100644 index ef466857d1..0000000000 --- a/drivers/sk98lin/h/skversion.h +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * - * Name: version.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skversion.h,v $ - * Revision 1.4 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.3 2003/02/25 13:30:18 mlindner - * Add: Support for various vendors - * - * Revision 1.1.2.1 2001/09/05 13:38:30 mlindner - * Removed FILE description - * - * Revision 1.1 2001/03/06 09:25:00 mlindner - * first version - * - * - * - ******************************************************************************/ - - -static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; -static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.05 PL: 01"; - -#define BOOT_STRING "sk98lin: Network Device Driver v6.05\n" \ - "(C)Copyright 1999-2003 Marvell(R)." - -#define VER_STRING "6.05" diff --git a/drivers/sk98lin/h/skvpd.h b/drivers/sk98lin/h/skvpd.h deleted file mode 100644 index 1be34c5a97..0000000000 --- a/drivers/sk98lin/h/skvpd.h +++ /dev/null @@ -1,335 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/01/13 10:39:38 $ - * Purpose: Defines and Macros for VPD handling - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skvpd.h,v $ - * Revision 1.15 2003/01/13 10:39:38 rschmidt - * Replaced define for PCI device Id for YUKON with GENESIS - * Editorial changes - * - * Revision 1.14 2002/11/14 15:18:10 gheinig - * Added const specifier to key and buf parameters for VpdPara,VpdRead - * and VpdWrite. This is necessary for the Diag 7 GUI API - * - * Revision 1.13 2002/10/14 15:58:18 rschmidt - * Added entry in rom_size struct s_vpd - * Editorial changes - * - * Revision 1.12 2002/09/09 14:43:51 mkarl - * added PCI Id of Yukon for reading VPD in diag before the adapter has - * been initialized - * editorial changes - * - * Revision 1.11 2002/07/26 13:19:16 mkarl - * added support for Yukon - * added vpd_size to VPD struct - * - * Revision 1.10 2000/08/10 11:29:07 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * Removed unused function VpdWriteDword() (#if 0). - * Made VpdReadKeyword() available for SKDIAG only. - * - * Revision 1.9 1999/11/22 14:02:27 cgoos - * Changed license header to GPL. - * - * Revision 1.8 1999/03/11 14:26:40 malthoff - * Replace __STDC__ with SK_KR_PROTO. - * - * Revision 1.7 1998/10/28 07:27:17 gklug - * rmv: SWAP macros - * add: VPD_IN/OUT8 macros - * chg: interface definition - * - * Revision 1.6 1998/10/22 10:03:44 gklug - * fix: use SK_OUT16 instead of SK_OUTW - * - * Revision 1.5 1998/10/14 07:05:31 cgoos - * Changed constants in SK_SWAP_32 to UL. - * - * Revision 1.4 1998/08/19 08:14:09 gklug - * fix: remove struct keyword as much as possible from the C-code (see CCC) - * - * Revision 1.3 1998/08/18 08:18:56 malthoff - * Modify VPD in and out macros for SK_DIAG - * - * Revision 1.2 1998/07/03 14:49:08 malthoff - * Add VPD_INxx() and VPD_OUTxx() macros for the Diagnostics tool. - * - * Revision 1.1 1998/06/19 14:08:03 malthoff - * Created. - * - * - ******************************************************************************/ - -/* - * skvpd.h contains Diagnostic specific defines for VPD handling - */ - -#ifndef __INC_SKVPD_H_ -#define __INC_SKVPD_H_ - -/* - * Define Resource Type Identifiers and VPD keywords - */ -#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ -#define RES_VPD_R 0x90 /* start of VPD read only area */ -#define RES_VPD_W 0x91 /* start of VPD read/write area */ -#define RES_END 0x78 /* Resource Type End Tag */ - -#ifndef VPD_NAME -#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */ -#endif /* VPD_NAME */ -#define VPD_PN "PN" /* Adapter Part Number */ -#define VPD_EC "EC" /* Adapter Engineering Level */ -#define VPD_MN "MN" /* Manufacture ID */ -#define VPD_SN "SN" /* Serial Number */ -#define VPD_CP "CP" /* Extended Capability */ -#define VPD_RV "RV" /* Checksum and Reserved */ -#define VPD_YA "YA" /* Asset Tag Identifier */ -#define VPD_VL "VL" /* First Error Log Message (SK specific) */ -#define VPD_VF "VF" /* Second Error Log Message (SK specific) */ -#define VPD_RW "RW" /* Remaining Read / Write Area */ - -/* 'type' values for vpd_setup_para() */ -#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */ -#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */ - -/* 'op' values for vpd_setup_para() */ -#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ -#define OWR_KEY 2 /* overwrite key if already exists */ - -/* - * Define READ and WRITE Constants. - */ - -#define VPD_DEV_ID_GENESIS 0x4300 - -#define VPD_SIZE_YUKON 256 -#define VPD_SIZE_GENESIS 512 -#define VPD_SIZE 512 -#define VPD_READ 0x0000 -#define VPD_WRITE 0x8000 - -#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE) - -#define VPD_GET_RES_LEN(p) ((unsigned int) \ - (* (SK_U8 *)&(p)[1]) |\ - ((* (SK_U8 *)&(p)[2]) << 8)) -#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2])) -#define VPD_GET_VAL(p) ((char *)&(p)[3]) - -#define VPD_MAX_LEN 50 - -/* VPD status */ - /* bit 7..1 reserved */ -#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */ - /* and vpd_free_rw valid */ - -/* - * VPD structs - */ -typedef struct s_vpd_status { - unsigned short Align01; /* Alignment */ - unsigned short vpd_status; /* VPD status, description see above */ - int vpd_free_ro; /* unused bytes in read only area */ - int vpd_free_rw; /* bytes available in read/write area */ -} SK_VPD_STATUS; - -typedef struct s_vpd { - SK_VPD_STATUS v; /* VPD status structure */ - char vpd_buf[VPD_SIZE]; /* VPD buffer */ - int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */ - int vpd_size; /* saved VPD-size */ -} SK_VPD; - -typedef struct s_vpd_para { - unsigned int p_len; /* parameter length */ - char *p_val; /* points to the value */ -} SK_VPD_PARA; - -/* - * structure of Large Resource Type Identifiers - */ - -/* was removed because of alignment problems */ - -/* - * structure of VPD keywords - */ -typedef struct s_vpd_key { - char p_key[2]; /* 2 bytes ID string */ - unsigned char p_len; /* 1 byte length */ - char p_val; /* start of the value string */ -} SK_VPD_KEY; - - -/* - * System specific VPD macros - */ -#ifndef SKDIAG -#ifndef VPD_DO_IO -#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val) -#define VPD_OUT32(pAC,IoC,Addr,Val) (void)SkPciWriteCfgDWord(pAC,Addr,Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal) -#else /* VPD_DO_IO */ -#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val) -#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal) -#endif /* VPD_DO_IO */ -#else /* SKDIAG */ -#define VPD_OUT8(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgByte(pAC,Addr,Val); \ - else \ - SK_OUT8(pAC,PCI_C(Addr),Val); \ - } -#define VPD_OUT16(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgWord(pAC,Addr,Val); \ - else \ - SK_OUT16(pAC,PCI_C(Addr),Val); \ - } -#define VPD_OUT32(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgDWord(pAC,Addr,Val); \ - else \ - SK_OUT32(pAC,PCI_C(Addr),Val); \ - } -#define VPD_IN8(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgByte(pAC,Addr,pVal); \ - else \ - SK_IN8(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN16(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgWord(pAC,Addr,pVal); \ - else \ - SK_IN16(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN32(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgDWord(pAC,Addr,pVal); \ - else \ - SK_IN32(pAC,PCI_C(Addr),pVal); \ - } -#endif /* nSKDIAG */ - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO -#ifdef SKDIAG -extern SK_U32 VpdReadDWord( - SK_AC *pAC, - SK_IOC IoC, - int addr); -#endif /* SKDIAG */ - -extern int VpdSetupPara( - SK_AC *pAC, - const char *key, - const char *buf, - int len, - int type, - int op); - -extern SK_VPD_STATUS *VpdStat( - SK_AC *pAC, - SK_IOC IoC); - -extern int VpdKeys( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int *len, - int *elements); - -extern int VpdRead( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - char *buf, - int *len); - -extern SK_BOOL VpdMayWrite( - char *key); - -extern int VpdWrite( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - const char *buf); - -extern int VpdDelete( - SK_AC *pAC, - SK_IOC IoC, - char *key); - -extern int VpdUpdate( - SK_AC *pAC, - SK_IOC IoC); - -extern void VpdErrLog( - SK_AC *pAC, - SK_IOC IoC, - char *msg); - -#ifdef SKDIAG -extern int VpdReadBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); - -extern int VpdWriteBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); -#endif /* SKDIAG */ -#else /* SK_KR_PROTO */ -extern SK_U32 VpdReadDWord(); -extern int VpdSetupPara(); -extern SK_VPD_STATUS *VpdStat(); -extern int VpdKeys(); -extern int VpdRead(); -extern SK_BOOL VpdMayWrite(); -extern int VpdWrite(); -extern int VpdDelete(); -extern int VpdUpdate(); -extern void VpdErrLog(); -#endif /* SK_KR_PROTO */ - -#endif /* __INC_SKVPD_H_ */ diff --git a/drivers/sk98lin/h/xmac_ii.h b/drivers/sk98lin/h/xmac_ii.h deleted file mode 100644 index 2ef903a87d..0000000000 --- a/drivers/sk98lin/h/xmac_ii.h +++ /dev/null @@ -1,1738 +0,0 @@ -/****************************************************************************** - * - * Name: xmac_ii.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.46 $ - * Date: $Date: 2003/01/28 09:47:45 $ - * Purpose: Defines and Macros for Gigabit Ethernet Controller - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: xmac_ii.h,v $ - * Revision 1.46 2003/01/28 09:47:45 rschmidt - * Added defines for copper MDI/MDIX configuration - * Added defines for LED Control Register - * Editorial changes - * - * Revision 1.45 2002/12/10 14:35:13 rschmidt - * Corrected defines for Extended PHY Specific Control - * Added defines for Ext. PHY Specific Ctrl 2 Reg. (Fiber specific) - * - * Revision 1.44 2002/12/09 14:58:41 rschmidt - * Added defines for Ext. PHY Specific Ctrl Reg. (downshift feature) - * Added 'GMR_FS_UN_SIZE'-Bit to Rx GMAC FIFO Flush Mask - * - * Revision 1.43 2002/12/05 10:14:45 rschmidt - * Added define for GMAC's Half Duplex Burst Mode - * Added define for Rx GMAC FIFO Flush Mask (default) - * - * Revision 1.42 2002/11/12 16:48:19 rschmidt - * Added defines for Cable Diagnostic Register (GPHY) - * Editorial changes - * - * Revision 1.41 2002/10/21 11:20:22 rschmidt - * Added bit GMR_FS_GOOD_FC to GMR_FS_ANY_ERR - * Editorial changes - * - * Revision 1.40 2002/10/14 14:54:14 rschmidt - * Added defines for GPHY Specific Status and GPHY Interrupt Status - * Added bits PHY_M_IS_AN_ERROR and PHY_M_IS_FIFO_ERROR to PHY_M_DEF_MSK - * Editorial changes - * - * Revision 1.39 2002/10/10 15:53:44 mkarl - * added some bit definitions for link speed status and LED's - * - * Revision 1.38 2002/08/21 16:23:46 rschmidt - * Added defines for PHY Specific Ctrl Reg - * Editorial changes - * - * Revision 1.37 2002/08/16 14:50:33 rschmidt - * Added defines for Auto-Neg. Advertisement YUKON Fiber (88E1011S only) - * Changed define PHY_M_DEF_MSK for GPHY IRQ Mask - * Editorial changes - * - * Revision 1.36 2002/08/12 13:21:10 rschmidt - * Added defines for different Broadcom PHY Ids - * - * Revision 1.35 2002/08/08 15:58:01 rschmidt - * Added defines for Manual LED Override register (YUKON) - * Editorial changes - * - * Revision 1.34 2002/07/31 17:23:36 rwahl - * Added define GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR). - * - * Revision 1.33 2002/07/23 16:03:37 rschmidt - * Added defines for GPHY registers - * Editorial changes - * - * Revision 1.32 2002/07/15 18:14:37 rwahl - * Added GMAC MIB counters definitions. - * Editorial changes. - * - * Revision 1.31 2002/07/15 15:42:50 rschmidt - * Removed defines from PHY specific reg. which are - * common to all PHYs - * Added defines for GMAC MIB Counters - * Editorial changes - * - * Revision 1.30 2002/06/05 08:22:12 rschmidt - * Changed defines for GMAC Rx Control Register and Rx Status - * Editorial changes - * - * Revision 1.29 2002/04/25 11:43:56 rschmidt - * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. - * Added new registers and defines for YUKON (GMAC, GPHY) - * Added Receive Frame Status Encoding for YUKON - * Editorial changes - * - * Revision 1.28 2000/11/09 12:32:49 rassmann - * Renamed variables. - * - * Revision 1.27 2000/05/17 11:00:46 malthoff - * Add bit for enable/disable power management in BCOM chip. - * - * Revision 1.26 1999/11/22 14:03:00 cgoos - * Changed license header to GPL. - * - * Revision 1.25 1999/08/12 19:19:38 malthoff - * Add PHY_B_AC_TX_TST bit according to BCOM A1 errata sheet. - * - * Revision 1.24 1999/07/30 11:27:21 cgoos - * Fixed a missing end-of-comment. - * - * Revision 1.23 1999/07/30 07:03:31 malthoff - * Cut some long comments. - * Correct the XMAC PHY ID definitions. - * - * Revision 1.22 1999/05/19 07:33:18 cgoos - * Changes for 1000Base-T. - * - * Revision 1.21 1999/03/25 07:46:11 malthoff - * Add XM_HW_CFG, XM_TS_READ, and XM_TS_LOAD registers. - * - * Revision 1.20 1999/03/12 13:36:09 malthoff - * Remove __STDC__. - * - * Revision 1.19 1998/12/10 12:22:54 gklug - * fix: RX_PAGE must be in interrupt mask - * - * Revision 1.18 1998/12/10 10:36:36 gklug - * fix: swap of pause bits - * - * Revision 1.17 1998/11/18 13:21:45 gklug - * fix: Default interrupt mask - * - * Revision 1.16 1998/10/29 15:53:21 gklug - * fix: Default mask uses ASS (GP0) signal - * - * Revision 1.15 1998/10/28 13:52:52 malthoff - * Add new bits in RX_CMD register. - * - * Revision 1.14 1998/10/19 15:34:53 gklug - * fix: typos - * - * Revision 1.13 1998/10/14 07:19:03 malthoff - * bug fix: Every define which describes bit 31 - * must be declared as unsigned long 'UL'. - * fix bit definitions of PHY_AN_RFB and PHY_AN_PAUSE. - * Remove ANP defines. Rework the RFB defines. - * - * Revision 1.12 1998/10/14 06:22:44 cgoos - * Changed shifted constant to ULONG. - * - * Revision 1.11 1998/10/14 05:43:26 gklug - * add: shift pause coding - * fix: PAUSE bits definition - * - * Revision 1.10 1998/10/13 09:19:21 malthoff - * Again change XMR_FS_ANY_ERR because of new info from XaQti. - * - * Revision 1.9 1998/10/09 07:58:30 malthoff - * Add XMR_FS_FCS_ERR to XMR_FS_ANY_ERR. - * - * Revision 1.8 1998/10/09 07:18:17 malthoff - * bug fix of a bug fix: XM_PAUSE_MODE and XM_DEF_MODE - * are not inverted! Bug XM_DEF_MSK is inverted. - * - * Revision 1.7 1998/10/05 08:04:32 malthoff - * bug fix: XM_PAUSE_MODE and XM_DEF_MODE - * must be inverted declarations. - * - * Revision 1.6 1998/09/28 13:38:18 malthoff - * Add default modes and masks XM_DEF_MSK, - * XM_PAUSE_MODE and XM_DEF_MODE - * - * Revision 1.5 1998/09/16 14:42:04 malthoff - * Bug Fix: XM_GP_PORT is a 32 bit (not a 16 bit) register. - * - * Revision 1.4 1998/08/20 14:59:47 malthoff - * Rework this file after reading the XaQti data sheet - * "Differences between Rev. B2 & Rev. C XMAC II". - * This file is now 100% XMAC II Rev. C complained. - * - * Revision 1.3 1998/06/29 12:18:23 malthoff - * Correct XMR_FS_ANY_ERR definition. - * - * Revision 1.2 1998/06/29 12:10:56 malthoff - * Add define XMR_FS_ANY_ERR. - * - * Revision 1.1 1998/06/19 13:37:17 malthoff - * created. - * - * - ******************************************************************************/ - -#ifndef __INC_XMAC_H -#define __INC_XMAC_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * XMAC II registers - * - * The XMAC registers are 16 or 32 bits wide. - * The XMACs host processor interface is set to 16 bit mode, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the XMAC registers - * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(), - * XM_INHASH(), and XM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ -#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */ - /* 0x0004: reserved */ -#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */ -#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/ -#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */ -#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */ - /* 0x0018 - 0x001e: reserved */ -#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */ -#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */ -#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */ -#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */ -#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */ -#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */ -#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */ - /* 0x003c: reserved */ -#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */ -#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */ -#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */ -#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */ - /* 0x0050 - 0x005e: reserved */ -#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */ -#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */ -#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */ -#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */ -#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */ - /* 0x006e: reserved */ -#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */ -#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */ -#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/ -#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */ - - /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */ - /* use the XM_EXM() macro to address */ -#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */ - - /* - * XM_EXM(Reg) - * - * returns the XMAC address offset of specified Exact Match Addr Reg - * - * para: Reg EXM register to addr (0 .. 15) - * - * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]); - */ -#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3)) - -#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */ -#define XM_SA 0x0108 /* NA reg r/w Station Address Register */ -#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */ -#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */ -#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */ -#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */ -#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */ -#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */ -#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */ - /* 0x012e: reserved */ -#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */ -#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */ - /* 0x0138 - 0x01fe: reserved */ -#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */ -#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */ -#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */ -#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */ -#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */ - /* 0x0204 - 0x027e: reserved */ -#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */ -#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/ -#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */ -#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */ -#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */ -#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */ -#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */ -#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */ -#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ -#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */ -#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */ -#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */ -#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */ -#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */ -#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */ -#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */ -#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */ -#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */ -#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */ - /* 0x02cc - 0x02ce: reserved */ -#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */ -#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */ -#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */ -#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */ -#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ -#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ -#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */ -#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */ -#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/ -#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */ -#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */ -#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */ -#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ -#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */ -#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */ -#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ -#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */ -#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */ -#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */ -#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */ -#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */ -#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */ -#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */ -#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */ -#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */ -#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */ -#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */ -#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ - /* 0x0358 - 0x035a: reserved */ -#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ -#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */ - /* 0x0364 - 0x0366: reserved */ -#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */ -#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */ -#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */ -#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */ -#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ -#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ - - -/*----------------------------------------------------------------------------*/ -/* - * XMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (ro) read only - */ - -/* XM_MMU_CMD 16 bit r/w MMU Command Register */ - /* Bit 15..13: reserved */ -#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */ -#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */ -#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */ -#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */ - /* Bit 8: reserved */ -#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */ -#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */ -#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */ -#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */ -#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */ -#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */ -#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */ -#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */ - - -/* XM_TX_CMD 16 bit r/w Transmit Command Register */ - /* Bit 15..7: reserved */ -#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ -#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */ -#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */ -#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */ -#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */ -#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */ -#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */ - - -/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ - /* Bit 15..5: reserved */ -#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ - - -/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ - /* Bit 15..7: reserved */ -#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ - - -/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ - /* Bit 15..8: reserved */ -#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ - - -/* XM_RX_CMD 16 bit r/w Receive Command Register */ - /* Bit 15..9: reserved */ -#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */ - /* inrange error packets */ -#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */ - /* jumbo packets */ -#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */ -#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */ -#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */ -#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */ -#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */ -#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */ -#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */ - - -/* XM_PHY_ADDR 16 bit r/w PHY Address Register */ - /* Bit 15..5: reserved */ -#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */ - - -/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ - /* Bit 31..7: reserved */ -#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */ -#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */ - /* Bit 4: reserved */ -#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */ -#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */ - /* Bit 1: reserved */ -#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */ - - -/* XM_IMSK 16 bit r/w Interrupt Mask Register */ -/* XM_ISRC 16 bit r/o Interrupt Status Register */ - /* Bit 15: reserved */ -#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */ -#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */ -#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */ -#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */ -#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */ -#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */ -#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */ -#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */ -#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */ -#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */ -#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */ -#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */ -#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */ -#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */ -#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */ - -#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\ - XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR)) - - -/* XM_HW_CFG 16 bit r/w Hardware Config Register */ - /* Bit 15.. 4: reserved */ -#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */ -#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/ - /* Bit 1: reserved */ -#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */ - - -/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ -/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ - /* Bit 15..10 reserved */ -#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ - -/* XM_TX_THR 16 bit r/w Tx Request Threshold */ -/* XM_HT_THR 16 bit r/w Host Request Threshold */ -/* XM_RX_THR 16 bit r/w Rx Request Threshold */ - /* Bit 15..11 reserved */ -#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ - - -/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ -#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */ -#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */ -#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */ -#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */ -#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */ -#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/ -#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */ -#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */ -#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */ -#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */ -#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */ -#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */ -#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */ -#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */ -#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */ - -/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ -/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ - /* Bit 15..11: reserved */ -#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ - - -/* XM_DEV_ID 32 bit r/o Device ID Register */ -#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ -#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ - - -/* XM_MODE 32 bit r/w Mode Register */ - /* Bit 31..27: reserved */ -#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */ -#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */ - /* extern generated */ -#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */ -#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */ - /* intern generated */ -#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */ -#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */ -#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */ -#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */ -#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */ - /* intern generated */ -#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */ - /* intern generated */ -#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */ -#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */ -#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */ -#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */ -#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */ -#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */ -#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */ -#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */ -#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */ -#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */ -#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */ -#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */ -#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */ -#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */ -#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */ -#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */ -#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */ - -#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA) - -/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ - /* Bit 16..6: reserved */ -#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */ -#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */ -#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ -#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */ -#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */ -#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ - - -/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ -/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ -#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/ -#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/ -#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/ -#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */ -#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */ -#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */ -#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */ -#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */ - /* Bit 22: reserved */ -#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */ -#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/ -#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */ -#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/ -#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */ - /* Bit 16: reserved */ -#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */ -#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */ -#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ -#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */ -#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */ -#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */ -#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/ -#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */ -#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ -#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ -#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/ -#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */ -#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */ -#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/ -#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/ -#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */ - -#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) - -/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ -/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ - /* Bit 31..26: reserved */ -#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ -#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/ -#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/ -#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/ -#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */ -#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */ -#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */ -#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */ -#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/ -#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ -#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */ -#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */ -#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */ -#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/ -#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */ -#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */ -#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/ -#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ -#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */ -#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */ -#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */ -#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */ -#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */ -#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/ -#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/ -#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */ - -#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) - -/* - * Receive Frame Status Encoding - */ -#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ -#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/ -#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/ -#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */ -#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */ -#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */ - /* Bit 12: reserved */ -#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */ -#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */ -#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */ -#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */ -#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */ -#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */ -#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */ -#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */ -#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */ -#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */ -#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */ -#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */ - -/* - * XMR_FS_ERR will be set if - * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, - * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR - * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue - * XMR_FS_ERR unless the corresponding bit in the Receive Command - * Register is set. - */ -#define XMR_FS_ANY_ERR XMR_FS_ERR - -/*----------------------------------------------------------------------------*/ -/* - * XMAC-PHY Registers, indirect addressed over the XMAC - */ -#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ -#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ - /* 0x09 - 0x0e: reserved */ -#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ -#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ - -/*----------------------------------------------------------------------------*/ -/* - * Broadcom-PHY Registers, indirect addressed over XMAC - */ -#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ - /* Broadcom-specific registers */ -#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ -#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ -#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ -#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carr Sense Cnt */ -#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ - /* 0x15 - 0x17: reserved */ -#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ -#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */ -#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */ -#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */ - /* 0x1c: reserved */ - /* 0x1d - 0x1f: test registers */ - -/*----------------------------------------------------------------------------*/ -/* - * Marvel-PHY Registers, indirect addressed over GMAC - */ -#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ - /* Marvel-specific registers */ -#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */ -#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */ -#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */ -#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */ -#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */ -#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */ - /* 0x17: reserved */ -#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */ -#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */ -#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */ -#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */ -#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */ - /* 0x1d - 0x1f: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * Level One-PHY Registers, indirect addressed over XMAC - */ -#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner*/ - /* Level One-specific registers */ -#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ -#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/ -#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */ -#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */ -#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */ -#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */ -#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */ - /* 0x17 -0x1c: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * National-PHY Registers, indirect addressed over XMAC - */ -#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ -#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */ - /* National-specific registers */ -#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ -#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */ -#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */ -#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */ -#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */ - /* 0x15 -0x18: reserved */ -#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */ - - -/*----------------------------------------------------------------------------*/ - -/* - * PHY bit definitions - * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are - * Xmac/Broadcom/LevelOne/National-specific. - * All other are general. - */ - -/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ -#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ -#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ -#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */ -#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */ -#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */ -#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */ -#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ -#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */ -#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */ -#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */ - /* Bit 5..0: reserved */ - -#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */ -#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */ -#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */ - - -/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/ - /* Bit 15..9: reserved */ - /* (BC/L1) 100/10 Mbps cap bits ignored*/ -#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */ - /* Bit 7: reserved */ -#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */ -#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */ -#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */ -#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */ -#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */ -#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */ -#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */ - - -/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ -#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */ -#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */ -#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */ - -/* different Broadcom PHY Ids */ -#define PHY_BCOM_ID1_A1 0x6041 -#define PHY_BCOM_ID1_B2 0x6043 -#define PHY_BCOM_ID1_C0 0x6044 -#define PHY_BCOM_ID1_C5 0x6047 - - -/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */ -#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ -#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */ - /* Bit 11.. 9: reserved */ -#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */ -#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */ -#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */ - /* Bit 4.. 0: reserved */ - -/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */ -#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/* field type definition for PHY_x_AN_SEL */ -#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */ - -/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..4: reserved */ -#define PHY_AN_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ -#define PHY_AN_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ -#define PHY_AN_RX_PG (1<<1) /* Bit 1: Page Received */ - /* Bit 0: reserved */ - -/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..5: reserved */ -#define PHY_B_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - -/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -#define PHY_L_AN_BP (1<<5) /* Bit 5: Base Page Indication */ -#define PHY_L_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - - -/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */ -#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack 1, for receiving a message*/ -#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */ -#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack 2, comply with msg content*/ -#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */ -#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */ - -/* - * XMAC-Specific - */ -/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ -#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */ -#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */ - /* Bit 13..0: reserved */ - -/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ - /* Bit 15..9: reserved */ -#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */ -#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ -#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ -#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ -#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability missmatch */ - /* Bit 2..0: reserved */ -/* - * Remote Fault Bits (PHY_X_AN_RFB) encoding - */ -#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */ -#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */ -#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */ -#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */ - -/* - * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding - */ -#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */ -#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */ -#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */ -#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */ - - -/* - * Broadcom-Specific - */ -/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ -#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ -#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */ -#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */ -#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */ -#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */ -#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */ -#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */ -#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */ -#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */ -#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */ -#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */ -#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */ -#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */ -#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */ -#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */ - -/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */ -#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */ -#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */ -#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */ -#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */ -#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */ -#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */ -#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */ -#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */ -#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */ -#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */ -#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */ -#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */ -#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */ - -/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ - /* Bit 15..8: reserved */ -#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */ - -/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ -#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */ -#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */ - -/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ -#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */ -#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */ -#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */ - /* Bit 11: reserved */ -#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */ - /* Bit 9.. 8: reserved */ -#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */ - /* Bit 6: reserved */ -#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */ - /* Bit 4: reserved */ -#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */ - /* Bit 2.. 0: reserved */ - -/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ -#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */ -#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */ -#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */ -#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */ -#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */ -#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */ -#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */ -#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */ -#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */ -#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */ -#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */ -#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */ -#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */ -#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */ - -#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) - -/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ - /* Bit 15: reserved */ -#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */ -#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */ -#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */ -#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */ -#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */ -#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */ -#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */ -#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */ -#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */ -#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */ -#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */ -#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */ -#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */ -#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */ -#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */ - -#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - -/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ -#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - -/* - * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) - */ -#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */ -#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */ -/* others: 100/10: invalid for us */ - -/* - * Level One-Specific - */ -/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ -#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/ -#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */ - /* Bit 14: reserved */ -#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */ -#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */ -#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */ -#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */ -#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */ -#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */ -#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */ -#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */ -#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */ -#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */ -#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */ -#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */ -#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */ - -/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/ -#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */ -#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */ -#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */ -#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */ -#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */ -#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */ -#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */ -#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */ -#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */ -#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */ -#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */ -#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */ -#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */ - -/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/ -/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */ - /* Bit 12: not described */ -#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */ -#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used*/ -#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade*/ -#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */ -#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */ -#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */ -#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */ -#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */ -#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */ -#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */ -#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */ -#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */ - -/* int. mask */ -#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN) - -/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/ -#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */ -#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */ -#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */ -#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */ -#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */ -#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */ -#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */ -#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */ -#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */ - -/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/ -#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */ - /* Bit 14: reserved */ -#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */ -#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */ - /* Bit 11: reserved */ -#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/ - /* Bit 9..0: not described */ - -/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ -#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */ -#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */ - - -/* - * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding - */ -#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - - -/* - * National-Specific - */ -/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ -#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */ - /* Bit 6..0: reserved */ - -/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ -#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ -#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */ - /* Bit 8: reserved */ -#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/* todo: those are still missing */ -/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/ -/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/ -/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/ -/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/ - -/* - * Marvell-Specific - */ -/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/ -#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */ -#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */ -#define PHY_M_AN_RF BIT_13 /* Remote Fault */ - /* Bit 12: reserved */ -#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */ -#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */ -#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */ -#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */ -#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */ -#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */ - -/* special defines for FIBER (88E1011S only) */ -#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */ -#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */ -#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */ -#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */ - -/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ -#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */ -#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */ -#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */ -#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */ - -/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */ -#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */ -#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */ -#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ - -#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ -#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ -#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ -#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */ -#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ -#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */ -#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ -#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */ -#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */ -#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */ -#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ -#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ - -#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) -#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ -#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ -#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */ - -/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ -#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */ -#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */ -#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ -#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */ -#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */ -#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */ -#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */ -#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */ -#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */ -#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */ -#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */ -#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */ -#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */ -#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */ -#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) - -/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ -/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */ -#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */ -#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */ -#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */ -#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */ -#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */ -#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */ -#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */ -#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */ -#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */ -#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */ -#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */ - /* Bit 3..2: reserved */ -#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */ -#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) - -/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ -#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ -#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ - -#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define MAC_TX_CLK_0_MHZ 2 -#define MAC_TX_CLK_2_5_MHZ 6 -#define MAC_TX_CLK_25_MHZ 7 - -/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */ -#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ -#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ - /* Bit 7.. 5: reserved */ -#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ -#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */ -#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */ -#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */ - -#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */ - -#define PULS_NO_STR 0 /* no pulse stretching */ -#define PULS_21MS 1 /* 21 ms to 42 ms */ -#define PULS_42MS 2 /* 42 ms to 84 ms */ -#define PULS_84MS 3 /* 84 ms to 170 ms */ -#define PULS_170MS 4 /* 170 ms to 340 ms */ -#define PULS_340MS 5 /* 340 ms to 670 ms */ -#define PULS_670MS 6 /* 670 ms to 1.3 s */ -#define PULS_1300MS 7 /* 1.3 s to 2.7 s */ - -#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */ - -#define BLINK_42MS 0 /* 42 ms */ -#define BLINK_84MS 1 /* 84 ms */ -#define BLINK_170MS 2 /* 170 ms */ -#define BLINK_340MS 3 /* 340 ms */ -#define BLINK_670MS 4 /* 670 ms */ - /* values 5 - 7: reserved */ - -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */ - -#define MO_LED_NORM 0 -#define MO_LED_BLINK 1 -#define MO_LED_OFF 2 -#define MO_LED_ON 3 - -/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ - /* Bit 15.. 7: reserved */ -#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */ -#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */ -#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */ -#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ -#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ - -/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ -#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ - /* Bit 12.. 8: reserved */ -#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */ - -/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ -#define CABD_STAT_NORMAL 0 -#define CABD_STAT_SHORT 1 -#define CABD_STAT_OPEN 2 -#define CABD_STAT_FAIL 3 - - -/* - * GMAC registers - * - * The GMAC registers are 16 or 32 bits wide. - * The GMACs host processor interface is 16 bits wide, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the GMAC registers - * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(), - * GM_INHASH(), and GM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ - -/* Port Registers */ -#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */ -#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */ -#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */ -#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */ -#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow Control */ -#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */ -#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */ - -/* Source Address Registers */ -#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */ -#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */ -#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */ -#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */ -#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */ -#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */ - -/* Multicast Address Hash Registers */ -#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */ -#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */ -#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */ -#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */ - -/* Interrupt Source Registers */ -#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */ -#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */ -#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */ - -/* Interrupt Mask Registers */ -#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */ -#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */ -#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */ - -/* Serial Management Interface (SMI) Registers */ -#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */ -#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */ -#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */ - -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ - -/* - * MIB Counters base address definitions (low word) - - * use offset 4 for access to high word (32 bit r/o) - */ -#define GM_RXF_UC_OK \ - (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */ -#define GM_RXF_BC_OK \ - (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */ -#define GM_RXF_MPAUSE \ - (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */ -#define GM_RXF_MC_OK \ - (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */ -#define GM_RXF_FCS_ERR \ - (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ -#define GM_RXO_OK_LO \ - (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */ -#define GM_RXO_OK_HI \ - (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */ -#define GM_RXO_ERR_LO \ - (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */ -#define GM_RXO_ERR_HI \ - (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */ -#define GM_RXF_SHT \ - (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ -#define GM_RXE_FRAG \ - (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Receeived with FCS Err */ -#define GM_RXF_64B \ - (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ -#define GM_RXF_127B \ - (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */ -#define GM_RXF_255B \ - (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */ -#define GM_RXF_511B \ - (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */ -#define GM_RXF_1023B \ - (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */ -#define GM_RXF_1518B \ - (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */ -#define GM_RXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */ -#define GM_RXF_LNG_ERR \ - (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */ -#define GM_RXF_JAB_PKT \ - (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ -#define GM_RXE_FIFO_OV \ - (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ -#define GM_TXF_UC_OK \ - (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */ -#define GM_TXF_BC_OK \ - (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */ -#define GM_TXF_MPAUSE \ - (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */ -#define GM_TXF_MC_OK \ - (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */ -#define GM_TXO_OK_LO \ - (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */ -#define GM_TXO_OK_HI \ - (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */ -#define GM_TXF_64B \ - (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */ -#define GM_TXF_127B \ - (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */ -#define GM_TXF_255B \ - (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */ -#define GM_TXF_511B \ - (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */ -#define GM_TXF_1023B \ - (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */ -#define GM_TXF_1518B \ - (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */ -#define GM_TXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */ - /* GM_MIB_CNT_BASE + 296: reserved */ -#define GM_TXF_COL \ - (GM_MIB_CNT_BASE + 304) /* Tx Collision */ -#define GM_TXF_LAT_COL \ - (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */ -#define GM_TXF_ABO_COL \ - (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */ -#define GM_TXF_MUL_COL \ - (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */ -#define GM_TXF_SNG_COL \ - (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */ -#define GM_TXE_FIFO_UR \ - (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */ - -/*----------------------------------------------------------------------------*/ -/* - * GMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (r/o) read only - */ - -/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ - -#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ -#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ -#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow Control Mode Disabled */ -#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */ -#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */ -#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */ -#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */ -#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */ - /* Bit 7..6: reserved */ -#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */ -#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ -#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */ -#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow Control Mode Disabled */ -#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */ - /* Bit 0: reserved */ - -/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ - /* Bit 15: reserved */ -#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */ -#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow Control Mode */ -#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */ -#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */ -#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */ -#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */ -#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */ -#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */ -#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */ -#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */ -#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow Control Mode */ -#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */ -#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update for Duplex */ -#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update for Flow-c. */ -#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update for Speed */ - -#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) -#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\ - GM_GPCR_AU_SPD_DIS) - -/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ - -#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ -#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ -#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ -#define GM_TXCR_COL_THR (4<<10) /* Bit 12..10: Collision Threshold */ - -/* GM_RX_CTRL 16 bit r/w Receive Control Register */ -#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ -#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */ -#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */ -#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */ - -/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */ -#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ -#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ - /* Bit 3..0: reserved */ -#define JAM_LEN_VAL(x) SHIFT14(x) -#define JAM_IPG_VAL(x) SHIFT9(x) -#define IPG_JAM_DATA(x) SHIFT4(x) - -/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder */ -#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive transmit trials */ -#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Length) */ -#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Length) */ - /* Bit 7..5: reserved */ -#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ - -#define DATA_BLIND_VAL(x) SHIFT11(x) -#define DATA_BLIND_FAST_ETH 0x1c -#define DATA_BLIND_GIGABIT 4 - -#define IPG_VAL_FAST_ETH 0x1e -#define IPG_VAL_GIGABIT 6 - -/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ - -#define GM_SMI_CT_PHY_AD(x) SHIFT11(x) -#define GM_SMI_CT_REG_AD(x) SHIFT6(x) -#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ -#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ -#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ - /* Bit 2..0: reserved */ - -/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ - /* Bit 15..6: reserved */ -#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ -#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ - /* Bit 3..0: reserved */ - -/* Receive Frame Status Encoding */ -#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ - /* Bit 15..14: reserved */ -#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */ -#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */ -#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */ -#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */ -#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */ -#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */ -#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */ -#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */ -#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */ -#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */ -#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */ - /* Bit 2: reserved */ -#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */ -#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */ - -/* - * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) - */ -#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \ - GMR_FS_LONG_ERR | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_JABBER) - -/* Rx GMAC FIFO Flush Mask (default) */ -#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \ - GMR_FS_RX_FF_OV | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_UN_SIZE | \ - GMR_FS_JABBER) - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_XMAC_H */ diff --git a/drivers/sk98lin/skaddr.c b/drivers/sk98lin/skaddr.c deleted file mode 100644 index ed79c049bb..0000000000 --- a/drivers/sk98lin/skaddr.c +++ /dev/null @@ -1,1879 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.48 $ - * Date: $Date: 2003/02/12 17:09:37 $ - * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skaddr.c,v $ - * Revision 1.48 2003/02/12 17:09:37 tschilli - * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses - * in case that both addresses are identical. - * - * Revision 1.47 2002/09/17 06:31:10 tschilli - * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate() - * and SkAddrGmacPromiscuousChange() fixed. - * Editorial changes. - * - * Revision 1.46 2002/08/22 07:55:41 tschilli - * New function SkGmacMcHash() for GMAC multicast hashing algorithm added. - * Editorial changes. - * - * Revision 1.45 2002/08/15 12:29:35 tschilli - * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed. - * - * Revision 1.44 2002/08/14 12:18:03 rschmidt - * Replaced direct handling of MAC Hashing (XMAC and GMAC) - * with routine SkMacHashing(). - * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode(). - * - * Revision 1.43 2002/08/13 09:37:43 rschmidt - * Corrected some SK_DBG_MSG outputs. - * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode(). - * Editorial changes. - * - * Revision 1.42 2002/08/12 11:24:36 rschmidt - * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit(). - * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC) - * with routine SkMacPromiscMode(). - * Editorial changes. - * - * Revision 1.41 2002/06/10 13:52:18 tschilli - * Changes for handling YUKON. - * All changes are internally and not visible to the programmer - * using this module. - * - * Revision 1.40 2001/02/14 14:04:59 rassmann - * Editorial changes. - * - * Revision 1.39 2001/01/30 10:30:04 rassmann - * Editorial changes. - * - * Revision 1.38 2001/01/25 16:26:52 rassmann - * Ensured that logical address overrides are done on net's active port. - * - * Revision 1.37 2001/01/22 13:41:34 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.36 2000/08/07 11:10:39 rassmann - * Editorial changes. - * - * Revision 1.35 2000/05/04 09:38:41 rassmann - * Editorial changes. - * Corrected multicast address hashing. - * - * Revision 1.34 1999/11/22 13:23:44 cgoos - * Changed license header to GPL. - * - * Revision 1.33 1999/05/28 10:56:06 rassmann - * Editorial changes. - * - * Revision 1.32 1999/03/31 10:59:20 rassmann - * Returning Success instead of DupAddr if address shall be overridden - * with same value. - * - * Revision 1.31 1999/01/14 16:18:17 rassmann - * Corrected multicast initialization. - * - * Revision 1.30 1999/01/04 10:30:35 rassmann - * SkAddrOverride only possible after SK_INIT_IO phase. - * - * Revision 1.29 1998/12/29 13:13:10 rassmann - * An address override is now preserved in the SK_INIT_IO phase. - * All functions return an int now. - * Extended parameter checking. - * - * Revision 1.28 1998/12/01 11:45:53 rassmann - * Code cleanup. - * - * Revision 1.27 1998/12/01 09:22:49 rassmann - * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT - * too often. - * - * Revision 1.26 1998/11/24 12:39:44 rassmann - * Reserved multicast entry for BPDU address. - * 13 multicast entries left for protocol. - * - * Revision 1.25 1998/11/17 16:54:23 rassmann - * Using exact match for up to 14 multicast addresses. - * Still receiving all multicasts if more addresses are added. - * - * Revision 1.24 1998/11/13 17:24:31 rassmann - * Changed return value of SkAddrOverride to int. - * - * Revision 1.23 1998/11/13 16:56:18 rassmann - * Added macro SK_ADDR_COMPARE. - * Changed return type of SkAddrOverride to SK_BOOL. - * - * Revision 1.22 1998/11/04 17:06:17 rassmann - * Corrected McUpdate and PromiscuousChange functions. - * - * Revision 1.21 1998/10/29 14:34:04 rassmann - * Clearing SK_ADDR struct at startup. - * - * Revision 1.20 1998/10/28 18:16:34 rassmann - * Avoiding I/Os before SK_INIT_RUN level. - * Aligning InexactFilter. - * - * Revision 1.19 1998/10/28 11:29:28 rassmann - * Programming physical address in SkAddrMcUpdate. - * Corrected programming of exact match entries. - * - * Revision 1.18 1998/10/28 10:34:48 rassmann - * Corrected reading of physical addresses. - * - * Revision 1.17 1998/10/28 10:26:13 rassmann - * Getting ports' current MAC addresses from EPROM now. - * Added debug output. - * - * Revision 1.16 1998/10/27 16:20:12 rassmann - * Reading MAC address byte by byte. - * - * Revision 1.15 1998/10/22 11:39:09 rassmann - * Corrected signed/unsigned mismatches. - * - * Revision 1.14 1998/10/19 17:12:35 rassmann - * Syntax corrections. - * - * Revision 1.13 1998/10/19 17:02:19 rassmann - * Now reading permanent MAC addresses from CRF. - * - * Revision 1.12 1998/10/15 15:15:48 rassmann - * Changed Flags Parameters from SK_U8 to int. - * Checked with lint. - * - * Revision 1.11 1998/09/24 19:15:12 rassmann - * Code cleanup. - * - * Revision 1.10 1998/09/18 20:18:54 rassmann - * Added HW access. - * Implemented swapping. - * - * Revision 1.9 1998/09/16 11:32:00 rassmann - * Including skdrv1st.h again. :( - * - * Revision 1.8 1998/09/16 11:09:34 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/14 17:06:34 rassmann - * Minor changes. - * - * Revision 1.6 1998/09/07 08:45:41 rassmann - * Syntax corrections. - * - * Revision 1.5 1998/09/04 19:40:19 rassmann - * Interface enhancements. - * - * Revision 1.4 1998/09/04 12:14:12 rassmann - * Interface cleanup. - * - * Revision 1.3 1998/09/02 16:56:40 rassmann - * Updated interface. - * - * Revision 1.2 1998/08/27 14:26:09 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:30:22 rassmann - * First public version. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses, address override, - * and promiscuous mode on GEnesis and Yukon adapters. - * - * Address Layout: - * port address: physical MAC address - * 1st exact match: logical MAC address (GEnesis only) - * 2nd exact match: RLMT multicast (GEnesis only) - * exact match 3-13: OS-specific multicasts (GEnesis only) - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect."; -#endif /* !defined(lint) */ - -#define __SKADDR_C - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - - -#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ -#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */ -#define HASH_BITS 6 /* #bits in hash */ -#define SK_MC_BIT 0x01 - -/* Error numbers and messages. */ - -#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0) -#define SKERR_ADDR_E001MSG "Bad Flags." -#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1) -#define SKERR_ADDR_E002MSG "New Error." - -/* typedefs *******************************************************************/ - -/* None. */ - -/* global variables ***********************************************************/ - -/* 64-bit hash values with all bits set. */ - -SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; - -/* local variables ************************************************************/ - -#ifdef DEBUG -static int Next0[SK_MAX_MACS] = {0, 0}; -#endif /* DEBUG */ - -/* functions ******************************************************************/ - -/****************************************************************************** - * - * SkAddrInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine clears the multicast tables and resets promiscuous mode. - * Some entries are reserved for the "logical MAC address", the - * SK-RLMT multicast address, and the BPDU multicast address. - * - * - * SK_INIT_IO - * ========== - * - * All permanent MAC addresses are read from EPROM. - * If the current MAC addresses are not already set in software, - * they are set to the values of the permanent addresses. - * The current addresses are written to the corresponding MAC. - * - * - * SK_INIT_RUN - * =========== - * - * Nothing. - * - * Context: - * init, pageable - * - * Returns: - * SK_ADDR_SUCCESS - */ -int SkAddrInit( -SK_AC *pAC, /* the adapter context */ -SK_IOC IoC, /* I/O context */ -int Level) /* initialization level */ -{ - int j; - SK_U32 i; - SK_U8 *InAddr; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - switch (Level) { - case SK_INIT_DATA: - SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAPort = &pAC->Addr.Port[i]; - pAPort->PromMode = SK_PROM_MODE_NONE; - - pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 4; - } - } -#endif /* DEBUG */ - /* pAC->Addr.InitDone = SK_INIT_DATA; */ - break; - - case SK_INIT_IO: - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort; - } -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 8; - } - } -#endif /* DEBUG */ - - /* Read permanent logical MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_1 + j, InAddr); - } - - if (!pAC->Addr.Net[0].CurrentMacAddressSet) { - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[0].CurrentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE; - } - - /* Set the current logical MAC address. */ - pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] = - pAC->Addr.Net[0].CurrentMacAddress; -#if SK_MAX_NETS > 1 - /* Set logical MAC address for net 2 to (log | 3). */ - if (!pAC->Addr.Net[1].CurrentMacAddressSet) { - pAC->Addr.Net[1].PermanentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3; - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[1].CurrentMacAddress = - pAC->Addr.Net[1].PermanentMacAddress; - pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE; - } -#endif /* SK_MAX_NETS > 1 */ - -#ifdef DEBUG - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].PermanentMacAddress.a[0], - pAC->Addr.Net[i].PermanentMacAddress.a[1], - pAC->Addr.Net[i].PermanentMacAddress.a[2], - pAC->Addr.Net[i].PermanentMacAddress.a[3], - pAC->Addr.Net[i].PermanentMacAddress.a[4], - pAC->Addr.Net[i].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].CurrentMacAddress.a[0], - pAC->Addr.Net[i].CurrentMacAddress.a[1], - pAC->Addr.Net[i].CurrentMacAddress.a[2], - pAC->Addr.Net[i].CurrentMacAddress.a[3], - pAC->Addr.Net[i].CurrentMacAddress.a[4], - pAC->Addr.Net[i].CurrentMacAddress.a[5])) - } -#endif /* DEBUG */ - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - pAPort = &pAC->Addr.Port[i]; - - /* Read permanent port addresses from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr); - } - - if (!pAPort->CurrentMacAddressSet) { - /* - * Set the current and previous physical MAC address - * of this port to its permanent MAC address. - */ - pAPort->CurrentMacAddress = pAPort->PermanentMacAddress; - pAPort->PreviousMacAddress = pAPort->PermanentMacAddress; - pAPort->CurrentMacAddressSet = SK_TRUE; - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - XM_OUTADDR(IoC, i, XM_SA, OutAddr); - } - else { - GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr); - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->PermanentMacAddress.a[0], - pAPort->PermanentMacAddress.a[1], - pAPort->PermanentMacAddress.a[2], - pAPort->PermanentMacAddress.a[3], - pAPort->PermanentMacAddress.a[4], - pAPort->PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - } - /* pAC->Addr.InitDone = SK_INIT_IO; */ - break; - - case SK_INIT_RUN: -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 16; - } - } -#endif /* DEBUG */ - - /* pAC->Addr.InitDone = SK_INIT_RUN; */ - break; - - default: /* error */ - break; - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrInit */ - - -/****************************************************************************** - * - * SkAddrMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according - * to the adapter in use. The real work is done there. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags); - } - else { - ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcClear */ - - -/****************************************************************************** - * - * SkAddrXmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table - * (either entry 2 or entries 3-16 and InexactFilter) of the given port. - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrXmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Clear RLMT multicast addresses. */ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - } - else { /* not permanent => DRV */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - /* Clear DRV multicast addresses. */ - - pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacMcClear */ - - -/****************************************************************************** - * - * SkAddrGmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast hashing table (InexactFilter) - * (either the RLMT or the driver bits) of the given port. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrGmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Copy DRV bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - - /* Clear InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0; - - } - } - else { /* not permanent => DRV */ - - /* Copy RLMT bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - - /* Clear InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0; - } - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacMcClear */ - -#ifndef SK_ADDR_CHEAT - -/****************************************************************************** - * - * SkXmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC32 algorithm is used. - * - * Notes: - * The code was adapted from the XaQti data sheet. - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -SK_U32 SkXmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Idx; - SK_U32 Bit; - SK_U32 Data; - SK_U32 Crc; - - Crc = 0xFFFFFFFFUL; - for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) { - Data = *pMc++; - for (Bit = 0; Bit < 8; Bit++, Data >>= 1) { - Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0); - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkXmacMcHash */ - - -/****************************************************************************** - * - * SkGmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC16 algorithm is used. - * - * Notes: - * - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -SK_U32 SkGmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Data; - SK_U32 TmpData; - SK_U32 Crc; - int Byte; - int Bit; - - Crc = 0xFFFFFFFFUL; - for (Byte = 0; Byte < 6; Byte++) { - /* Get next byte. */ - Data = (SK_U32) pMc[Byte]; - - /* Change bit order in byte. */ - TmpData = Data; - for (Bit = 0; Bit < 8; Bit++) { - if (TmpData & 1L) { - Data |= 1L << (7 - Bit); - } - else { - Data &= ~(1L << (7 - Bit)); - } - TmpData >>= 1; - } - - Crc ^= (Data << 24); - for (Bit = 0; Bit < 8; Bit++) { - if (Crc & 0x80000000) { - Crc = (Crc << 1) ^ GMAC_POLY; - } - else { - Crc <<= 1; - } - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkGmacMcHash */ - -#endif /* not SK_ADDR_CHEAT */ - -/****************************************************************************** - * - * SkAddrMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the - * adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_ILLEGAL_PORT - * SK_MC_RLMT_OVERFLOW - */ -int SkAddrMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - else { - ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcAdd */ - - -/****************************************************************************** - * - * SkAddrXmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * The multicast bit is only checked if there are no free exact match - * entries. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_RLMT_OVERFLOW - */ -int SkAddrXmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; - SK_U8 Inexact; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[PortNumber] |= 1; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt > - SK_ADDR_LAST_MATCH_RLMT) { - return (SK_MC_RLMT_OVERFLOW); - } - - /* Set a RLMT multicast address. */ - - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc; - - return (SK_MC_FILTERING_EXACT); - } - -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv < - SK_ADDR_FIRST_MATCH_DRV) { - Next0[PortNumber] |= 2; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - /* Set exact match entry. */ - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc; - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - } - else { - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses. */ - return (SK_MC_ILLEGAL_ADDRESS); - } -#ifndef SK_ADDR_CHEAT - /* Compute hash value of address. */ - HashBit = 63 - SkXmacMcHash(&pMc->a[0]); - - /* Add bit to InexactFilter. */ - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); -#else /* SK_ADDR_CHEAT */ - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - - if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcAdd */ - - -/****************************************************************************** - * - * SkAddrGmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - */ -int SkAddrGmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses. */ - return (SK_MC_ILLEGAL_ADDRESS); - } - -#ifndef SK_ADDR_CHEAT - - /* Compute hash value of address. */ - HashBit = SkGmacMcHash(&pMc->a[0]); - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Add bit to InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])) -#endif /* DEBUG */ - } - else { /* not permanent => DRV */ - - /* Add bit to InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])) -#endif /* DEBUG */ - } - -#else /* SK_ADDR_CHEAT */ - - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - - return (SK_MC_FILTERING_INEXACT); - -} /* SkAddrGmacMcAdd */ - - -/****************************************************************************** - * - * SkAddrMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according - * to the adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } - else { - ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } - - return (ReturnCode); - -} /* SkAddrMcUpdate */ - - -/****************************************************************************** - * - * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrXmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - SK_U32 i; - SK_U8 Inexact; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - - /* Start with 0 to also program the logical MAC address. */ - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - /* Set exact match address i on XMAC */ - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt, - SK_ADDR_LAST_MATCH_RLMT); - } - - for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) { - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other non-permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv, - SK_ADDR_LAST_MATCH_DRV); - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - else if (Inexact != 0) { - - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - else { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - -#ifdef xDEBUG - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - SK_U8 InAddr8[6]; - SK_U16 *InAddr; - - /* Get exact match address i from port PortNumber. */ - InAddr = (SK_U16 *) &InAddr8[0]; - - XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr); - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate: MC address %d on Port %u: ", - "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n", - i, - PortNumber, - InAddr8[0], - InAddr8[1], - InAddr8[2], - InAddr8[3], - InAddr8[4], - InAddr8[5], - pAPort->Exact[i].a[0], - pAPort->Exact[i].a[1], - pAPort->Exact[i].a[2], - pAPort->Exact[i].a[3], - pAPort->Exact[i].a[4], - pAPort->Exact[i].a[5])) - } -#endif /* DEBUG */ - - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcUpdate */ - - -/****************************************************************************** - * - * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrGmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - SK_U32 i; - SK_U8 Inexact; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAPort->InexactFilter.Bytes[0]); - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - else { - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - - /* Set port's current logical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr); - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->Exact[0].a[0], - pAPort->Exact[0].a[1], - pAPort->Exact[0].a[2], - pAPort->Exact[0].a[3], - pAPort->Exact[0].a[4], - pAPort->Exact[0].a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrGmacMcUpdate */ - - -/****************************************************************************** - * - * SkAddrOverride - override a port's MAC address - * - * Description: - * This routine overrides the MAC address of one port. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS if successful. - * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address. - * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address. - * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before. - */ -int SkAddrOverride( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pNewAddr, /* new MAC address */ -int Flags) /* logical/physical MAC address */ -{ - SK_EVPARA Para; - SK_U32 NetNumber; - SK_U32 i; - SK_U16 *OutAddr; - - NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) { - return (SK_ADDR_MULTICAST_ADDRESS); - } - - if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } - - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - - pAC->Addr.Port[PortNumber].Exact[0] = - pAC->Addr.Net[NetNumber].CurrentMacAddress; - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_CLEAR_LOGICAL) { - /* Deactivate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } - - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - - for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) { - pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0; - } - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - if (i == PortNumber) { - return (SK_ADDR_SUCCESS); - } - else { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - } - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - - /* Change port's physical MAC address. */ - OutAddr = (SK_U16 *) pNewAddr; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - } - else { - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - } - - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); - } - else { /* Logical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_SUCCESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - - /* - * In case that the physical and the logical MAC addresses are equal - * we must also change the physical MAC address here. - * In this case we have an adapter which initially was programmed with - * two identical MAC addresses. - */ - if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a, - pAC->Addr.Port[PortNumber].Exact[0].a)) { - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); - } - - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - - pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr; - pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr; -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])) -#endif /* DEBUG */ - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrOverride */ - - -/****************************************************************************** - * - * SkAddrPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * It calls either SkAddrXmacPromiscuousChange or - * SkAddrGmacPromiscuousChange, according to the adapter in use. - * The real work is done there. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } - else { - ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } - - return (ReturnCode); - -} /* SkAddrPromiscuousChange */ - - -/****************************************************************************** - * - * SkAddrXmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrXmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int i; - SK_BOOL InexactModeBit; - SK_U8 Inexact; - SK_U8 HwInexact; - SK_FILTER64 HwInexactFilter; - SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - if ((LoMode & XM_MD_ENA_PROM) != 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - for (Inexact = 0xFF, i = 0; i < 8; i++) { - Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0xFF) { - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - else { - /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0; - - /* Read 64-bit hash register from XMAC */ - XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]); - - for (HwInexact = 0xFF, i = 0; i < 8; i++) { - HwInexact &= HwInexactFilter.Bytes[i]; - } - - if (InexactModeBit && (HwInexact == 0xFF)) { - CurPromMode |= SK_PROM_MODE_ALL_MC; - } - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */ - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */ - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0) { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); - } - else { - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - /* Set the MAC in Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */ - /* Clear Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacPromiscuousChange */ - - -/****************************************************************************** - * - * SkAddrGmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrGmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - SK_U16 ReceiveControl; /* GMAC Receive Control Register */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl); - - if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) { - /* All Multicast mode! */ - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */ - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - - if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */ - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - - /* Set the MAC to Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */ - - /* Clear Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacPromiscuousChange */ - - -/****************************************************************************** - * - * SkAddrSwap - swap address info - * - * Description: - * This routine swaps address info of two ports. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrSwap( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 FromPortNumber, /* Port1 Index */ -SK_U32 ToPortNumber) /* Port2 Index */ -{ - int i; - SK_U8 Byte; - SK_MAC_ADDR MacAddr; - SK_U32 DWord; - - if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) { - return (SK_ADDR_ILLEGAL_PORT); - } - - /* - * Swap: - * - Exact Match Entries (GEnesis and Yukon) - * Yukon uses first entry for the logical MAC - * address (stored in the second GMAC register). - * - FirstExactMatchRlmt (GEnesis only) - * - NextExactMatchRlmt (GEnesis only) - * - FirstExactMatchDrv (GEnesis only) - * - NextExactMatchDrv (GEnesis only) - * - 64-bit filter (InexactFilter) - * - Promiscuous Mode - * of ports. - */ - - for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) { - MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i]; - pAC->Addr.Port[FromPortNumber].Exact[i] = - pAC->Addr.Port[ToPortNumber].Exact[i]; - pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr; - } - - for (i = 0; i < 8; i++) { - Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] = - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte; - } - - i = pAC->Addr.Port[FromPortNumber].PromMode; - pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode; - pAC->Addr.Port[ToPortNumber].PromMode = i; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv = - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv; - pAC->Addr.Port[FromPortNumber].NextExactMatchDrv = - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv; - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord; - } - - /* CAUTION: Solution works if only ports of one adapter are in use. */ - for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber]. - Net->NetNumber].NumPorts; i++) { - if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - Port[i]->PortNumber == ToPortNumber) { - pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - ActivePort = i; - /* 20001207 RA: Was "ToPortNumber;". */ - } - } - - (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber); - (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber); - - return (SK_ADDR_SUCCESS); - -} /* SkAddrSwap */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skcsum.c b/drivers/sk98lin/skcsum.c deleted file mode 100644 index a5dc572587..0000000000 --- a/drivers/sk98lin/skcsum.c +++ /dev/null @@ -1,929 +0,0 @@ -/****************************************************************************** - * - * Name: skcsum.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.10 $ - * Date: $Date: 2002/04/11 10:02:04 $ - * Purpose: Store/verify Internet checksum in send/receive packets. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skcsum.c,v $ - * Revision 1.10 2002/04/11 10:02:04 rwahl - * Fix in SkCsGetSendInfo(): - * - function did not return ProtocolFlags in every case. - * - pseudo header csum calculated wrong for big endian. - * - * Revision 1.9 2001/06/13 07:42:08 gklug - * fix: NetNumber was wrong in CLEAR_STAT event - * add: check for good NetNumber in Clear STAT - * - * Revision 1.8 2001/02/06 11:15:36 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.7 2000/06/29 13:17:05 rassmann - * Corrected reception of a packet with UDP checksum == 0 (which means there - * is no UDP checksum). - * - * Revision 1.6 2000/02/21 12:35:10 cgoos - * Fixed license header comment. - * - * Revision 1.5 2000/02/21 11:05:19 cgoos - * Merged changes back to common source. - * Fixed rx path for BIG ENDIAN architecture. - * - * Revision 1.1 1999/07/26 15:28:12 mkarl - * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and - * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester - * changed from common source to windows specific source - * therefore restarting with v1.0 - * - * Revision 1.3 1999/05/10 08:39:33 mkarl - * prevent overflows in SKCS_HTON16 - * fixed a bug in pseudo header checksum calculation - * added some comments - * - * Revision 1.2 1998/10/22 11:53:28 swolf - * Now using SK_DBG_MSG. - * - * Revision 1.1 1998/09/01 15:35:41 swolf - * initial revision - * - * 13-May-1998 sw Created. - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#ifdef SK_USE_CSUM /* Check if CSUM is to be used. */ - -#ifndef lint -static const char SysKonnectFileId[] = "@(#)" - "$Id: skcsum.c,v 1.10 2002/04/11 10:02:04 rwahl Exp $" - " (C) SysKonnect."; -#endif /* !lint */ - -/****************************************************************************** - * - * Description: - * - * This is the "GEnesis" common module "CSUM". - * - * This module contains the code necessary to calculate, store, and verify the - * Internet Checksum of IP, TCP, and UDP frames. - * - * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" - * and is the code name of this SysKonnect project. - * - * Compilation Options: - * - * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an - * empty module. - * - * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id - * definitions. In this case, all SKCS_PROTO_xxx definitions must be made - * external. - * - * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status - * definitions. In this case, all SKCS_STATUS_xxx definitions must be made - * external. - * - * Include File Hierarchy: - * - * "h/skdrv1st.h" - * "h/skcsum.h" - * "h/sktypes.h" - * "h/skqueue.h" - * "h/skdrv2nd.h" - * - ******************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skcsum.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - -/* The size of an Ethernet MAC header. */ -#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2) - -/* The size of the used topology's MAC header. */ -#define SKCS_MAC_HEADER_SIZE SKCS_ETHERNET_MAC_HEADER_SIZE - -/* The size of the IP header without any option fields. */ -#define SKCS_IP_HEADER_SIZE 20 - -/* - * Field offsets within the IP header. - */ - -/* "Internet Header Version" and "Length". */ -#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH 0 - -/* "Total Length". */ -#define SKCS_OFS_IP_TOTAL_LENGTH 2 - -/* "Flags" "Fragment Offset". */ -#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET 6 - -/* "Next Level Protocol" identifier. */ -#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9 - -/* Source IP address. */ -#define SKCS_OFS_IP_SOURCE_ADDRESS 12 - -/* Destination IP address. */ -#define SKCS_OFS_IP_DESTINATION_ADDRESS 16 - - -/* - * Field offsets within the UDP header. - */ - -/* UDP checksum. */ -#define SKCS_OFS_UDP_CHECKSUM 6 - -/* IP "Next Level Protocol" identifiers (see RFC 790). */ -#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */ -#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */ - -/* IP "Don't Fragment" bit. */ -#define SKCS_IP_DONT_FRAGMENT SKCS_HTON16(0x4000) - -/* Add a byte offset to a pointer. */ -#define SKCS_IDX(pPtr, Ofs) ((void *) ((char *) (pPtr) + (Ofs))) - -/* - * Macros that convert host to network representation and vice versa, i.e. - * little/big endian conversion on little endian machines only. - */ -#ifdef SK_LITTLE_ENDIAN -#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xFF) << 8)) -#endif /* SK_LITTLE_ENDIAN */ -#ifdef SK_BIG_ENDIAN -#define SKCS_HTON16(Val16) (Val16) -#endif /* SK_BIG_ENDIAN */ -#define SKCS_NTOH16(Val16) SKCS_HTON16(Val16) - -/* typedefs *******************************************************************/ - -/* function prototypes ********************************************************/ - -/****************************************************************************** - * - * SkCsGetSendInfo - get checksum information for a send packet - * - * Description: - * Get all checksum information necessary to send a TCP or UDP packet. The - * function checks the IP header passed to it. If the high-level protocol - * is either TCP or UDP the pseudo header checksum is calculated and - * returned. - * - * The function returns the total length of the IP header (including any - * IP option fields), which is the same as the start offset of the IP data - * which in turn is the start offset of the TCP or UDP header. - * - * The function also returns the TCP or UDP pseudo header checksum, which - * should be used as the start value for the hardware checksum calculation. - * (Note that any actual pseudo header checksum can never calculate to - * zero.) - * - * Note: - * There is a bug in the ASIC which may lead to wrong checksums. - * - * Arguments: - * pAc - A pointer to the adapter context struct. - * - * pIpHeader - Pointer to IP header. Must be at least the IP header *not* - * including any option fields, i.e. at least 20 bytes. - * - * Note: This pointer will be used to address 8-, 16-, and 32-bit - * variables with the respective alignment offsets relative to the pointer. - * Thus, the pointer should point to a 32-bit aligned address. If the - * target system cannot address 32-bit variables on non 32-bit aligned - * addresses, then the pointer *must* point to a 32-bit aligned address. - * - * pPacketInfo - A pointer to the packet information structure for this - * packet. Before calling this SkCsGetSendInfo(), the following field must - * be initialized: - * - * ProtocolFlags - Initialize with any combination of - * SKCS_PROTO_XXX bit flags. SkCsGetSendInfo() will only work on - * the protocols specified here. Any protocol(s) not specified - * here will be ignored. - * - * Note: Only one checksum can be calculated in hardware. Thus, if - * SKCS_PROTO_IP is specified in the 'ProtocolFlags', - * SkCsGetSendInfo() must calculate the IP header checksum in - * software. It might be a better idea to have the calling - * protocol stack calculate the IP header checksum. - * - * Returns: N/A - * On return, the following fields in 'pPacketInfo' may or may not have - * been filled with information, depending on the protocol(s) found in the - * packet: - * - * ProtocolFlags - Returns the SKCS_PROTO_XXX bit flags of the protocol(s) - * that were both requested by the caller and actually found in the packet. - * Protocol(s) not specified by the caller and/or not found in the packet - * will have their respective SKCS_PROTO_XXX bit flags reset. - * - * Note: For IP fragments, TCP and UDP packet information is ignored. - * - * IpHeaderLength - The total length in bytes of the complete IP header - * including any option fields is returned here. This is the start offset - * of the IP data, i.e. the TCP or UDP header if present. - * - * IpHeaderChecksum - If IP has been specified in the 'ProtocolFlags', the - * 16-bit Internet Checksum of the IP header is returned here. This value - * is to be stored into the packet's 'IP Header Checksum' field. - * - * PseudoHeaderChecksum - If this is a TCP or UDP packet and if TCP or UDP - * has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum - * of the TCP or UDP pseudo header is returned here. - */ -#if 0 -void SkCsGetSendInfo( -SK_AC *pAc, /* Adapter context struct. */ -void *pIpHeader, /* IP header. */ -SKCS_PACKET_INFO *pPacketInfo, /* Packet information struct. */ -int NetNumber) /* Net number */ -{ - /* Internet Header Version found in IP header. */ - unsigned InternetHeaderVersion; - - /* Length of the IP header as found in IP header. */ - unsigned IpHeaderLength; - - /* Bit field specifiying the desired/found protocols. */ - unsigned ProtocolFlags; - - /* Next level protocol identifier found in IP header. */ - unsigned NextLevelProtocol; - - /* Length of IP data portion. */ - unsigned IpDataLength; - - /* TCP/UDP pseudo header checksum. */ - unsigned long PseudoHeaderChecksum; - - /* Pointer to next level protocol statistics structure. */ - SKCS_PROTO_STATS *NextLevelProtoStats; - - /* Temporary variable. */ - unsigned Tmp; - - Tmp = *(SK_U8 *) - SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH); - - /* Get the Internet Header Version (IHV). */ - /* Note: The IHV is stored in the upper four bits. */ - - InternetHeaderVersion = Tmp >> 4; - - /* Check the Internet Header Version. */ - /* Note: We currently only support IP version 4. */ - - if (InternetHeaderVersion != 4) { /* IPv4? */ - SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX, - ("Tx: Unknown Internet Header Version %u.\n", - InternetHeaderVersion)); - pPacketInfo->ProtocolFlags = 0; - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++; - return; - } - - /* Get the IP header length (IHL). */ - /* - * Note: The IHL is stored in the lower four bits as the number of - * 4-byte words. - */ - - IpHeaderLength = (Tmp & 0xf) * 4; - pPacketInfo->IpHeaderLength = IpHeaderLength; - - /* Check the IP header length. */ - - /* 04-Aug-1998 sw - Really check the IHL? Necessary? */ - - if (IpHeaderLength < 5*4) { - SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX, - ("Tx: Invalid IP Header Length %u.\n", IpHeaderLength)); - pPacketInfo->ProtocolFlags = 0; - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++; - return; - } - - /* This is an IPv4 frame with a header of valid length. */ - - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxOkCts++; - - /* Check if we should calculate the IP header checksum. */ - - ProtocolFlags = pPacketInfo->ProtocolFlags; - - if (ProtocolFlags & SKCS_PROTO_IP) { - pPacketInfo->IpHeaderChecksum = - SkCsCalculateChecksum(pIpHeader, IpHeaderLength); - } - - /* Get the next level protocol identifier. */ - - NextLevelProtocol = - *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL); - - /* - * Check if this is a TCP or UDP frame and if we should calculate the - * TCP/UDP pseudo header checksum. - * - * Also clear all protocol bit flags of protocols not present in the - * frame. - */ - - if ((ProtocolFlags & SKCS_PROTO_TCP) != 0 && - NextLevelProtocol == SKCS_PROTO_ID_TCP) { - /* TCP/IP frame. */ - ProtocolFlags &= SKCS_PROTO_TCP | SKCS_PROTO_IP; - NextLevelProtoStats = - &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP]; - } - else if ((ProtocolFlags & SKCS_PROTO_UDP) != 0 && - NextLevelProtocol == SKCS_PROTO_ID_UDP) { - /* UDP/IP frame. */ - ProtocolFlags &= SKCS_PROTO_UDP | SKCS_PROTO_IP; - NextLevelProtoStats = - &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP]; - } - else { - /* - * Either not a TCP or UDP frame and/or TCP/UDP processing not - * specified. - */ - pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP; - return; - } - - /* Check if this is an IP fragment. */ - - /* - * Note: An IP fragment has a non-zero "Fragment Offset" field and/or - * the "More Fragments" bit set. Thus, if both the "Fragment Offset" - * and the "More Fragments" are zero, it is *not* a fragment. We can - * easily check both at the same time since they are in the same 16-bit - * word. - */ - - if ((*(SK_U16 *) - SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) & - ~SKCS_IP_DONT_FRAGMENT) != 0) { - /* IP fragment; ignore all other protocols. */ - pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP; - NextLevelProtoStats->TxUnableCts++; - return; - } - - /* - * Calculate the TCP/UDP pseudo header checksum. - */ - - /* Get total length of IP header and data. */ - - IpDataLength = - *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH); - - /* Get length of IP data portion. */ - - IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength; - - /* Calculate the sum of all pseudo header fields (16-bit). */ - - PseudoHeaderChecksum = - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_SOURCE_ADDRESS + 0) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_SOURCE_ADDRESS + 2) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_DESTINATION_ADDRESS + 0) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_DESTINATION_ADDRESS + 2) + - (unsigned long) SKCS_HTON16(NextLevelProtocol) + - (unsigned long) SKCS_HTON16(IpDataLength); - - /* Add-in any carries. */ - - SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0); - - /* Add-in any new carry. */ - - SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0); - - pPacketInfo->ProtocolFlags = ProtocolFlags; - NextLevelProtoStats->TxOkCts++; /* Success. */ -} /* SkCsGetSendInfo */ - - -/****************************************************************************** - * - * SkCsGetReceiveInfo - verify checksum information for a received packet - * - * Description: - * Verify a received frame's checksum. The function returns a status code - * reflecting the result of the verification. - * - * Note: - * Before calling this function you have to verify that the frame is - * not padded and Checksum1 and Checksum2 are bigger than 1. - * - * Arguments: - * pAc - Pointer to adapter context struct. - * - * pIpHeader - Pointer to IP header. Must be at least the length in bytes - * of the received IP header including any option fields. For UDP packets, - * 8 additional bytes are needed to access the UDP checksum. - * - * Note: The actual length of the IP header is stored in the lower four - * bits of the first octet of the IP header as the number of 4-byte words, - * so it must be multiplied by four to get the length in bytes. Thus, the - * maximum IP header length is 15 * 4 = 60 bytes. - * - * Checksum1 - The first 16-bit Internet Checksum calculated by the - * hardware starting at the offset returned by SkCsSetReceiveFlags(). - * - * Checksum2 - The second 16-bit Internet Checksum calculated by the - * hardware starting at the offset returned by SkCsSetReceiveFlags(). - * - * Returns: - * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. - * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. - * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. - * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame - * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). - * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). - * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). - * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). - * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. - * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. - * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. - * - * Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values - * returned here can be defined in some header file by the module using CSUM. - * In this way, the calling module can assign return values for its own needs, - * e.g. by assigning bit flags to the individual protocols. - */ -SKCS_STATUS SkCsGetReceiveInfo( -SK_AC *pAc, /* Adapter context struct. */ -void *pIpHeader, /* IP header. */ -unsigned Checksum1, /* Hardware checksum 1. */ -unsigned Checksum2, /* Hardware checksum 2. */ -int NetNumber) /* Net number */ -{ - /* Internet Header Version found in IP header. */ - unsigned InternetHeaderVersion; - - /* Length of the IP header as found in IP header. */ - unsigned IpHeaderLength; - - /* Length of IP data portion. */ - unsigned IpDataLength; - - /* IP header checksum. */ - unsigned IpHeaderChecksum; - - /* IP header options checksum, if any. */ - unsigned IpOptionsChecksum; - - /* IP data checksum, i.e. TCP/UDP checksum. */ - unsigned IpDataChecksum; - - /* Next level protocol identifier found in IP header. */ - unsigned NextLevelProtocol; - - /* The checksum of the "next level protocol", i.e. TCP or UDP. */ - unsigned long NextLevelProtocolChecksum; - - /* Pointer to next level protocol statistics structure. */ - SKCS_PROTO_STATS *NextLevelProtoStats; - - /* Temporary variable. */ - unsigned Tmp; - - Tmp = *(SK_U8 *) - SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH); - - /* Get the Internet Header Version (IHV). */ - /* Note: The IHV is stored in the upper four bits. */ - - InternetHeaderVersion = Tmp >> 4; - - /* Check the Internet Header Version. */ - /* Note: We currently only support IP version 4. */ - - if (InternetHeaderVersion != 4) { /* IPv4? */ - SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX, - ("Rx: Unknown Internet Header Version %u.\n", - InternetHeaderVersion)); - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++; - return (SKCS_STATUS_UNKNOWN_IP_VERSION); - } - - /* Get the IP header length (IHL). */ - /* - * Note: The IHL is stored in the lower four bits as the number of - * 4-byte words. - */ - - IpHeaderLength = (Tmp & 0xf) * 4; - - /* Check the IP header length. */ - - /* 04-Aug-1998 sw - Really check the IHL? Necessary? */ - - if (IpHeaderLength < 5*4) { - SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX, - ("Rx: Invalid IP Header Length %u.\n", IpHeaderLength)); - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++; - return (SKCS_STATUS_IP_CSUM_ERROR); - } - - /* This is an IPv4 frame with a header of valid length. */ - - /* Get the IP header and data checksum. */ - - IpDataChecksum = Checksum2; - - /* - * The IP header checksum is calculated as follows: - * - * IpHeaderChecksum = Checksum1 - Checksum2 - */ - - SKCS_OC_SUB(IpHeaderChecksum, Checksum1, Checksum2); - - /* Check if any IP header options. */ - - if (IpHeaderLength > SKCS_IP_HEADER_SIZE) { - - /* Get the IP options checksum. */ - - IpOptionsChecksum = SkCsCalculateChecksum( - SKCS_IDX(pIpHeader, SKCS_IP_HEADER_SIZE), - IpHeaderLength - SKCS_IP_HEADER_SIZE); - - /* Adjust the IP header and IP data checksums. */ - - SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum); - - SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum); - } - - /* - * Check if the IP header checksum is ok. - * - * NOTE: We must check the IP header checksum even if the caller just wants - * us to check upper-layer checksums, because we cannot do any further - * processing of the packet without a valid IP checksum. - */ - - /* Get the next level protocol identifier. */ - - NextLevelProtocol = *(SK_U8 *) - SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL); - - if (IpHeaderChecksum != 0xFFFF) { - pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++; - /* the NDIS tester wants to know the upper level protocol too */ - if (NextLevelProtocol == SKCS_PROTO_ID_TCP) { - return(SKCS_STATUS_IP_CSUM_ERROR_TCP); - } - else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) { - return(SKCS_STATUS_IP_CSUM_ERROR_UDP); - } - return (SKCS_STATUS_IP_CSUM_ERROR); - } - - /* - * Check if this is a TCP or UDP frame and if we should calculate the - * TCP/UDP pseudo header checksum. - * - * Also clear all protocol bit flags of protocols not present in the - * frame. - */ - - if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCP) != 0 && - NextLevelProtocol == SKCS_PROTO_ID_TCP) { - /* TCP/IP frame. */ - NextLevelProtoStats = - &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP]; - } - else if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDP) != 0 && - NextLevelProtocol == SKCS_PROTO_ID_UDP) { - /* UDP/IP frame. */ - NextLevelProtoStats = - &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP]; - } - else { - /* - * Either not a TCP or UDP frame and/or TCP/UDP processing not - * specified. - */ - return (SKCS_STATUS_IP_CSUM_OK); - } - - /* Check if this is an IP fragment. */ - - /* - * Note: An IP fragment has a non-zero "Fragment Offset" field and/or - * the "More Fragments" bit set. Thus, if both the "Fragment Offset" - * and the "More Fragments" are zero, it is *not* a fragment. We can - * easily check both at the same time since they are in the same 16-bit - * word. - */ - - if ((*(SK_U16 *) - SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) & - ~SKCS_IP_DONT_FRAGMENT) != 0) { - /* IP fragment; ignore all other protocols. */ - NextLevelProtoStats->RxUnableCts++; - return (SKCS_STATUS_IP_FRAGMENT); - } - - /* - * 08-May-2000 ra - * - * From RFC 768 (UDP) - * If the computed checksum is zero, it is transmitted as all ones (the - * equivalent in one's complement arithmetic). An all zero transmitted - * checksum value means that the transmitter generated no checksum (for - * debugging or for higher level protocols that don't care). - */ - - if (NextLevelProtocol == SKCS_PROTO_ID_UDP && - *(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) { - - NextLevelProtoStats->RxOkCts++; - - return (SKCS_STATUS_IP_CSUM_OK_NO_UDP); - } - - /* - * Calculate the TCP/UDP checksum. - */ - - /* Get total length of IP header and data. */ - - IpDataLength = - *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH); - - /* Get length of IP data portion. */ - - IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength; - - NextLevelProtocolChecksum = - - /* Calculate the pseudo header checksum. */ - - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_SOURCE_ADDRESS + 0) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_SOURCE_ADDRESS + 2) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_DESTINATION_ADDRESS + 0) + - (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader, - SKCS_OFS_IP_DESTINATION_ADDRESS + 2) + - (unsigned long) SKCS_HTON16(NextLevelProtocol) + - (unsigned long) SKCS_HTON16(IpDataLength) + - - /* Add the TCP/UDP header checksum. */ - - (unsigned long) IpDataChecksum; - - /* Add-in any carries. */ - - SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0); - - /* Add-in any new carry. */ - - SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0); - - /* Check if the TCP/UDP checksum is ok. */ - - if ((unsigned) NextLevelProtocolChecksum == 0xFFFF) { - - /* TCP/UDP checksum ok. */ - - NextLevelProtoStats->RxOkCts++; - - return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? - SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK); - } - - /* TCP/UDP checksum error. */ - - NextLevelProtoStats->RxErrCts++; - - return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? - SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR); -} /* SkCsGetReceiveInfo */ -#endif - - -/****************************************************************************** - * - * SkCsSetReceiveFlags - set checksum receive flags - * - * Description: - * Use this function to set the various receive flags. According to the - * protocol flags set by the caller, the start offsets within received - * packets of the two hardware checksums are returned. These offsets must - * be stored in all receive descriptors. - * - * Arguments: - * pAc - Pointer to adapter context struct. - * - * ReceiveFlags - Any combination of SK_PROTO_XXX flags of the protocols - * for which the caller wants checksum information on received frames. - * - * pChecksum1Offset - The start offset of the first receive descriptor - * hardware checksum to be calculated for received frames is returned - * here. - * - * pChecksum2Offset - The start offset of the second receive descriptor - * hardware checksum to be calculated for received frames is returned - * here. - * - * Returns: N/A - * Returns the two hardware checksum start offsets. - */ -void SkCsSetReceiveFlags( -SK_AC *pAc, /* Adapter context struct. */ -unsigned ReceiveFlags, /* New receive flags. */ -unsigned *pChecksum1Offset, /* Offset for hardware checksum 1. */ -unsigned *pChecksum2Offset, /* Offset for hardware checksum 2. */ -int NetNumber) -{ - /* Save the receive flags. */ - - pAc->Csum.ReceiveFlags[NetNumber] = ReceiveFlags; - - /* First checksum start offset is the IP header. */ - *pChecksum1Offset = SKCS_MAC_HEADER_SIZE; - - /* - * Second checksum start offset is the IP data. Note that this may vary - * if there are any IP header options in the actual packet. - */ - *pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE; -} /* SkCsSetReceiveFlags */ - -#ifndef SkCsCalculateChecksum - -/****************************************************************************** - * - * SkCsCalculateChecksum - calculate checksum for specified data - * - * Description: - * Calculate and return the 16-bit Internet Checksum for the specified - * data. - * - * Arguments: - * pData - Pointer to data for which the checksum shall be calculated. - * Note: The pointer should be aligned on a 16-bit boundary. - * - * Length - Length in bytes of data to checksum. - * - * Returns: - * The 16-bit Internet Checksum for the specified data. - * - * Note: The checksum is calculated in the machine's natural byte order, - * i.e. little vs. big endian. Thus, the resulting checksum is different - * for the same input data on little and big endian machines. - * - * However, when written back to the network packet, the byte order is - * always in correct network order. - */ -unsigned SkCsCalculateChecksum( -void *pData, /* Data to checksum. */ -unsigned Length) /* Length of data. */ -{ - SK_U16 *pU16; /* Pointer to the data as 16-bit words. */ - unsigned long Checksum; /* Checksum; must be at least 32 bits. */ - - /* Sum up all 16-bit words. */ - - pU16 = (SK_U16 *) pData; - for (Checksum = 0; Length > 1; Length -= 2) { - Checksum += *pU16++; - } - - /* If this is an odd number of bytes, add-in the last byte. */ - - if (Length > 0) { -#ifdef SK_BIG_ENDIAN - /* Add the last byte as the high byte. */ - Checksum += ((unsigned) *(SK_U8 *) pU16) << 8; -#else /* !SK_BIG_ENDIAN */ - /* Add the last byte as the low byte. */ - Checksum += *(SK_U8 *) pU16; -#endif /* !SK_BIG_ENDIAN */ - } - - /* Add-in any carries. */ - - SKCS_OC_ADD(Checksum, Checksum, 0); - - /* Add-in any new carry. */ - - SKCS_OC_ADD(Checksum, Checksum, 0); - - /* Note: All bits beyond the 16-bit limit are now zero. */ - - return ((unsigned) Checksum); -} /* SkCsCalculateChecksum */ - -#endif /* SkCsCalculateChecksum */ - -/****************************************************************************** - * - * SkCsEvent - the CSUM event dispatcher - * - * Description: - * This is the event handler for the CSUM module. - * - * Arguments: - * pAc - Pointer to adapter context. - * - * Ioc - I/O context. - * - * Event - Event id. - * - * Param - Event dependent parameter. - * - * Returns: - * The 16-bit Internet Checksum for the specified data. - * - * Note: The checksum is calculated in the machine's natural byte order, - * i.e. little vs. big endian. Thus, the resulting checksum is different - * for the same input data on little and big endian machines. - * - * However, when written back to the network packet, the byte order is - * always in correct network order. - */ -int SkCsEvent( -SK_AC *pAc, /* Pointer to adapter context. */ -SK_IOC Ioc, /* I/O context. */ -SK_U32 Event, /* Event id. */ -SK_EVPARA Param) /* Event dependent parameter. */ -{ - int ProtoIndex; - int NetNumber; - - switch (Event) { - /* - * Clear protocol statistics. - * - * Param - Protocol index, or -1 for all protocols. - * - Net number. - */ - case SK_CSUM_EVENT_CLEAR_PROTO_STATS: - - ProtoIndex = (int)Param.Para32[1]; - NetNumber = (int)Param.Para32[0]; - if (ProtoIndex < 0) { /* Clear for all protocols. */ - if (NetNumber >= 0) { - memset(&pAc->Csum.ProtoStats[NetNumber][0], 0, - sizeof(pAc->Csum.ProtoStats[NetNumber])); - } - } - else { /* Clear for individual protocol. */ - memset(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0, - sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex])); - } - break; - default: - break; - } - return (0); /* Success. */ -} /* SkCsEvent */ - -#endif /* SK_USE_CSUM */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skge.c b/drivers/sk98lin/skge.c deleted file mode 100644 index 61a6094230..0000000000 --- a/drivers/sk98lin/skge.c +++ /dev/null @@ -1,4864 +0,0 @@ -/****************************************************************************** - * - * Name: skge.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.46 $ - * Date: $Date: 2003/02/25 14:16:36 $ - * Purpose: The main driver source module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * Driver for SysKonnect Gigabit Ethernet Server Adapters: - * - * SK-9871 (single link 1000Base-ZX) - * SK-9872 (dual link 1000Base-ZX) - * SK-9861 (single link 1000Base-SX, VF45 Volition Plug) - * SK-9862 (dual link 1000Base-SX, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX) - * SK-9842 (dual link 1000Base-LX) - * SK-9843 (single link 1000Base-SX) - * SK-9844 (dual link 1000Base-SX) - * SK-9821 (single link 1000Base-T) - * SK-9822 (dual link 1000Base-T) - * SK-9881 (single link 1000Base-SX V2 LC) - * SK-9871 (single link 1000Base-ZX V2) - * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX V2) - * SK-9843 (single link 1000Base-SX V2) - * SK-9821 (single link 1000Base-T V2) - * - * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * Author: Christoph Goos (cgoos@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) - * - * Address all question to: linux@syskonnect.de - * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * Goto "Support" and search Knowledge Base for "manual". - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skge.c,v $ - * Revision 1.46 2003/02/25 14:16:36 mlindner - * Fix: Copyright statement - * - * Revision 1.45 2003/02/25 13:25:55 mlindner - * Add: Performance improvements - * Add: Support for various vendors - * Fix: Init function - * - * Revision 1.44 2003/01/09 09:25:26 mlindner - * Fix: Remove useless init_module/cleanup_module forward declarations - * - * Revision 1.43 2002/11/29 08:42:41 mlindner - * Fix: Boot message - * - * Revision 1.42 2002/11/28 13:30:23 mlindner - * Add: New frame check - * - * Revision 1.41 2002/11/27 13:55:18 mlindner - * Fix: Drop wrong csum packets - * Fix: Initialize proc_entry after hw check - * - * Revision 1.40 2002/10/31 07:50:37 tschilli - * Function SkGeInitAssignRamToQueues() from common module inserted. - * Autonegotiation is set to ON for all adapters. - * LinkSpeedUsed is used in link up status report. - * Role parameter will show up for 1000 Mbps links only. - * GetConfiguration() inserted after init level 1 in SkGeChangeMtu(). - * All return values of SkGeInit() and SkGeInitPort() are checked. - * - * Revision 1.39 2002/10/02 12:56:05 mlindner - * Add: Support for Yukon - * Add: Support for ZEROCOPY, scatter-gather and hw checksum - * Add: New transmit ring function (use SG and TCP/UDP hardware checksumming) - * Add: New init function - * Add: Speed check and setup - * Add: Merge source for kernel 2.2.x and 2.4.x - * Add: Opcode check for tcp - * Add: Frame length check - * Fix: Transmit complete interrupt - * Fix: Interrupt moderation - * - * Revision 1.29.2.13 2002/01/14 12:44:52 mlindner - * Fix: Rlmt modes - * - * Revision 1.29.2.12 2001/12/07 12:06:18 mlindner - * Fix: malloc -> slab changes - * - * Revision 1.29.2.11 2001/12/06 15:19:20 mlindner - * Add: DMA attributes - * Fix: Module initialisation - * Fix: pci_map_single and pci_unmap_single replaced - * - * Revision 1.29.2.10 2001/12/06 09:56:50 mlindner - * Corrected some printk's - * - * Revision 1.29.2.9 2001/09/05 12:15:34 mlindner - * Add: LBFO Changes - * Fix: Counter Errors (Jumbo == to long errors) - * Fix: Changed pAC->PciDev declaration - * Fix: too short counters - * - * Revision 1.29.2.8 2001/06/25 12:10:44 mlindner - * fix: ReceiveIrq() changed. - * - * Revision 1.29.2.7 2001/06/25 08:07:05 mlindner - * fix: RLMT locking in ReceiveIrq() changed. - * - * Revision 1.29.2.6 2001/05/21 07:59:29 mlindner - * fix: MTU init problems - * - * Revision 1.29.2.5 2001/05/08 11:25:08 mlindner - * fix: removed VLAN error message - * - * Revision 1.29.2.4 2001/05/04 13:31:43 gklug - * fix: do not handle eth_copy on bad fragments received. - * - * Revision 1.29.2.3 2001/04/23 08:06:43 mlindner - * Fix: error handling - * - * Revision 1.29.2.2 2001/03/15 12:04:54 mlindner - * Fixed memory problem - * - * Revision 1.29.2.1 2001/03/12 16:41:44 mlindner - * add: procfs function - * add: dual-net function - * add: RLMT networks - * add: extended PNMI features - * - * Kernel 2.4.x specific: - * Revision 1.xx 2000/09/12 13:31:56 cgoos - * Fixed missign "dev=NULL in skge_probe. - * Added counting for jumbo frames (corrects error statistic). - * Removed VLAN tag check (enables VLAN support). - * - * Kernel 2.2.x specific: - * Revision 1.29 2000/02/21 13:31:56 cgoos - * Fixed "unused" warning for UltraSPARC change. - * - * Partially kernel 2.2.x specific: - * Revision 1.28 2000/02/21 10:32:36 cgoos - * Added fixes for UltraSPARC. - * Now printing RlmtMode and PrefPort setting at startup. - * Changed XmitFrame return value. - * Fixed rx checksum calculation for BIG ENDIAN systems. - * Fixed rx jumbo frames counted as ierrors. - * - * - * Revision 1.27 1999/11/25 09:06:28 cgoos - * Changed base_addr to unsigned long. - * - * Revision 1.26 1999/11/22 13:29:16 cgoos - * Changed license header to GPL. - * Changes for inclusion in linux kernel (2.2.13). - * Removed 2.0.x defines. - * Changed SkGeProbe to skge_probe. - * Added checks in SkGeIoctl. - * - * Revision 1.25 1999/10/07 14:47:52 cgoos - * Changed 984x to 98xx. - * - * Revision 1.24 1999/09/30 07:21:01 cgoos - * Removed SK_RLMT_SLOW_LOOKAHEAD option. - * Giving spanning tree packets also to OS now. - * - * Revision 1.23 1999/09/29 07:36:50 cgoos - * Changed assignment for IsBc/IsMc. - * - * Revision 1.22 1999/09/28 12:57:09 cgoos - * Added CheckQueue also to Single-Port-ISR. - * - * Revision 1.21 1999/09/28 12:42:41 cgoos - * Changed parameter strings for RlmtMode. - * - * Revision 1.20 1999/09/28 12:37:57 cgoos - * Added CheckQueue for fast delivery of RLMT frames. - * - * Revision 1.19 1999/09/16 07:57:25 cgoos - * Copperfield changes. - * - * Revision 1.18 1999/09/03 13:06:30 cgoos - * Fixed RlmtMode=CheckSeg bug: wrong DEV_KFREE_SKB in RLMT_SEND caused - * double allocated skb's. - * FrameStat in ReceiveIrq was accessed via wrong Rxd. - * Queue size for async. standby Tx queue was zero. - * FillRxLimit of 0 could cause problems with ReQueue, changed to 1. - * Removed debug output of checksum statistic. - * - * Revision 1.17 1999/08/11 13:55:27 cgoos - * Transmit descriptor polling was not reenabled after SkGePortInit. - * - * Revision 1.16 1999/07/27 15:17:29 cgoos - * Added some "\n" in output strings (removed while debuging...). - * - * Revision 1.15 1999/07/23 12:09:30 cgoos - * Performance optimization, rx checksumming, large frame support. - * - * Revision 1.14 1999/07/14 11:26:27 cgoos - * Removed Link LED settings (now in RLMT). - * Added status output at NET UP. - * Fixed SMP problems with Tx and SWITCH running in parallel. - * Fixed return code problem at RLMT_SEND event. - * - * Revision 1.13 1999/04/07 10:11:42 cgoos - * Fixed Single Port problems. - * Fixed Multi-Adapter problems. - * Always display startup string. - * - * Revision 1.12 1999/03/29 12:26:37 cgoos - * Reversed locking to fine granularity. - * Fixed skb double alloc problem (caused by incorrect xmit return code). - * Enhanced function descriptions. - * - * Revision 1.11 1999/03/15 13:10:51 cgoos - * Changed device identifier in output string to ethX. - * - * Revision 1.10 1999/03/15 12:12:34 cgoos - * Changed copyright notice. - * - * Revision 1.9 1999/03/15 12:10:17 cgoos - * Changed locking to one driver lock. - * Added check of SK_AC-size (for consistency with library). - * - * Revision 1.8 1999/03/08 11:44:02 cgoos - * Fixed missing dev->tbusy in SkGeXmit. - * Changed large frame (jumbo) buffer number. - * Added copying of short frames. - * - * Revision 1.7 1999/03/04 13:26:57 cgoos - * Fixed spinlock calls for SMP. - * - * Revision 1.6 1999/03/02 09:53:51 cgoos - * Added descriptor revertion for big endian machines. - * - * Revision 1.5 1999/03/01 08:50:59 cgoos - * Fixed SkGeChangeMtu. - * Fixed pci config space accesses. - * - * Revision 1.4 1999/02/18 15:48:44 cgoos - * Corrected some printk's. - * - * Revision 1.3 1999/02/18 12:45:55 cgoos - * Changed SK_MAX_CARD_PARAM to default 16 - * - * Revision 1.2 1999/02/18 10:55:32 cgoos - * Removed SkGeDrvTimeStamp function. - * Printing "ethX:" before adapter type at adapter init. - * - * - * 10-Feb-1999 cg Created, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * - ******************************************************************************/ - -/****************************************************************************** - * - * Possible compiler options (#define xxx / -Dxxx): - * - * debugging can be enable by changing SK_DEBUG_CHKMOD and - * SK_DEBUG_CHKCAT in makefile (described there). - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the main module of the Linux GE driver. - * - * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h - * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters. - * Those are used for drivers on multiple OS', so some thing may seem - * unnecessary complicated on Linux. Please do not try to 'clean up' - * them without VERY good reasons, because this will make it more - * difficult to keep the Linux driver in synchronisation with the - * other versions. - * - * Include file hierarchy: - * - * - * - * "h/skdrv1st.h" - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * those three depending on kernel version used: - * - * - * - * - * - * "h/skerror.h" - * "h/skdebug.h" - * "h/sktypes.h" - * "h/lm80.h" - * "h/xmac_ii.h" - * - * "h/skdrv2nd.h" - * "h/skqueue.h" - * "h/skgehwt.h" - * "h/sktimer.h" - * "h/ski2c.h" - * "h/skgepnmi.h" - * "h/skvpd.h" - * "h/skgehw.h" - * "h/skgeinit.h" - * "h/skaddr.h" - * "h/skgesirq.h" - * "h/skcsum.h" - * "h/skrlmt.h" - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#include "h/skversion.h" -#if 0 -#include -#include -#include -#endif -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - - -/* defines ******************************************************************/ -/* for debuging on x86 only */ -/* #define BREAKPOINT() asm(" int $3"); */ - -/* use the scatter-gather functionality with sendfile() */ -#if 0 -#define SK_ZEROCOPY -#endif - -/* use of a transmit complete interrupt */ -#define USE_TX_COMPLETE - -/* use interrupt moderation (for tx complete only) */ -#define USE_INT_MOD -#define INTS_PER_SEC 1000 - -/* - * threshold for copying small receive frames - * set to 0 to avoid copying, set to 9001 to copy all frames - */ -#define SK_COPY_THRESHOLD 50 - -/* number of adapters that can be configured via command line params */ -#define SK_MAX_CARD_PARAM 16 - - -/* - * use those defines for a compile-in version of the driver instead - * of command line parameters - */ -/* #define LINK_SPEED_A {"Auto", } */ -/* #define LINK_SPEED_B {"Auto", } */ -/* #define AUTO_NEG_A {"Sense", } */ -/* #define AUTO_NEG_B {"Sense", } */ -/* #define DUP_CAP_A {"Both", } */ -/* #define DUP_CAP_B {"Both", } */ -/* #define FLOW_CTRL_A {"SymOrRem", } */ -/* #define FLOW_CTRL_B {"SymOrRem", } */ -/* #define ROLE_A {"Auto", } */ -/* #define ROLE_B {"Auto", } */ -/* #define PREF_PORT {"A", } */ -/* #define RLMT_MODE {"CheckLinkState", } */ - -#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) -#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) -#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) - -/* function prototypes ******************************************************/ -static void FreeResources(struct SK_NET_DEVICE *dev); -static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC); -static SK_BOOL BoardAllocMem(SK_AC *pAC); -static void BoardFreeMem(SK_AC *pAC); -static void BoardInitMem(SK_AC *pAC); -static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, - int*, SK_BOOL); - -#if 0 -static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); -static int SkGeOpen(struct SK_NET_DEVICE *dev); -static int SkGeClose(struct SK_NET_DEVICE *dev); -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p); -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev); -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev); -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd); -#else -void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); -int SkGeOpen(struct SK_NET_DEVICE *dev); -int SkGeClose(struct SK_NET_DEVICE *dev); -int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); -#endif -static void GetConfiguration(SK_AC*); -static void ProductStr(SK_AC*); -static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*); -static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*); -static void FillRxRing(SK_AC*, RX_PORT*); -static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*); -#if 0 -static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); -#else -void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); -#endif -static void ClearAndStartRx(SK_AC*, int); -static void ClearTxIrq(SK_AC*, int, int); -static void ClearRxRing(SK_AC*, RX_PORT*); -static void ClearTxRing(SK_AC*, TX_PORT*); -#if 0 -static void SetQueueSizes(SK_AC *pAC); - -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); -#endif -static void PortReInitBmu(SK_AC*, int); -#if 0 -static int SkGeIocMib(DEV_NET*, unsigned int, int); -static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); -#endif - -/*Extern */ - -/* external Proc function */ -extern int proc_read( - char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int *eof, - void *data); - -#ifdef DEBUG -static void DumpMsg(struct sk_buff*, char*); -static void DumpData(char*, int); -static void DumpLong(char*, int); -#endif -void dump_frag( SK_U8 *data, int length); - -/* global variables *********************************************************/ -#if 0 -static const char *BootString = BOOT_STRING; -#endif -struct SK_NET_DEVICE *SkGeRootDev = NULL; -static int probed __initdata = 0; - -/* local variables **********************************************************/ -static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; -static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; - - -/* local variables **********************************************************/ -const char SK_Root_Dir_entry[8]; - -#if 0 -static struct proc_dir_entry *pSkRootDir; -#endif - - -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_3COM, 0x1700}, - {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE}, - {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU}, - {} -}; - - -/***************************************************************************** - * - * skge_probe - find all SK-98xx adapters - * - * Description: - * This function scans the PCI bus for SK-98xx adapters. Resources for - * each adapter are allocated and the adapter is brought into Init 1 - * state. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -#if 0 -static int __init skge_probe (void) -#else -int skge_probe (struct eth_device ** ret_dev) -#endif -{ -#if 0 - int proc_root_initialized = 0; -#endif - int boards_found = 0; -#if 0 - int vendor_flag = SK_FALSE; -#endif - SK_AC *pAC; - DEV_NET *pNet = NULL; -#if 0 - struct proc_dir_entry *pProcFile; - struct pci_dev *pdev = NULL; - unsigned long base_address; -#else - u32 base_address; -#endif - struct SK_NET_DEVICE *dev = NULL; -#if 0 - SK_BOOL DeviceFound = SK_FALSE; -#endif - SK_BOOL BootStringCount = SK_FALSE; -#if 1 - pci_dev_t devno; -#endif - - if (probed) - return -ENODEV; - probed++; - - if (!pci_present()) /* is PCI support present? */ - return -ENODEV; - -#if 0 - while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) -#else - while((devno = pci_find_devices (supported, boards_found)) >= 0) -#endif - { - - dev = NULL; - pNet = NULL; - - -#if 0 - SK_PCI_ISCOMPLIANT(vendor_flag, pdev); - if (!vendor_flag) - continue; -#endif - -/* if ((pdev->vendor != PCI_VENDOR_ID_SYSKONNECT) && - ((pdev->device != PCI_DEVICE_ID_SYSKONNECT_GE) || - (pdev->device != PCI_DEVICE_ID_SYSKONNECT_YU))){ - continue; - } -*/ -#if 0 - /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - continue; -#endif - - -#if 0 - if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } -#else - dev = malloc (sizeof *dev); - memset(dev, 0, sizeof(*dev)); - dev->priv = malloc(sizeof(DEV_NET)); -#endif - - if (dev->priv == NULL) { - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (pNet->pAC == NULL){ - kfree(dev->priv); - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - /* Print message */ - if (!BootStringCount) { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - BootStringCount = SK_TRUE; -#ifdef SK98_INFO - printk("%s\n", BootString); -#endif - } - - memset(pNet->pAC, 0, sizeof(SK_AC)); - pAC = pNet->pAC; -#if 0 - pAC->PciDev = pdev; - pAC->PciDevId = pdev->device; - pAC->dev[0] = dev; - pAC->dev[1] = dev; -#else - pAC->PciDev = devno; - ret_dev[0] = pAC->dev[0] = dev; - ret_dev[1] = pAC->dev[1] = dev; -#endif - sprintf(pAC->Name, "SysKonnect SK-98xx"); - pAC->CheckQueue = SK_FALSE; - - pNet->Mtu = 1500; - pNet->Up = 0; -#if 0 - dev->irq = pdev->irq; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; -#endif - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* Use only if yukon hardware */ - /* SK and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - -#if 0 - /* - * Dummy value. - */ - dev->base_addr = 42; - pci_set_master(pdev); - - pci_set_master(pdev); - base_address = pci_resource_start (pdev, 0); -#else - pci_write_config_dword(devno, - PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, - &base_address); -#endif - -#ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { - SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } -#endif - - /* - * Remap the regs into kernel space. - */ -#if 0 - pAC->IoBase = (char*)ioremap(base_address, 0x4000); -#else - pAC->IoBase = (char*)pci_mem_to_phys(devno, base_address); -#endif - - if (!pAC->IoBase){ - printk(KERN_ERR "%s: Unable to map I/O register, " - "SK 98xx No. %i will be disabled.\n", - dev->name, boards_found); - kfree(dev); - break; - } - - pAC->Index = boards_found; - if (SkGeBoardInit(dev, pAC)) { - FreeResources(dev); - kfree(dev); - continue; - } - -#if 0 - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); -#else - memcpy((caddr_t) &dev->enetaddr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); -#endif - -#if 0 - /* First adapter... Create proc and print message */ - if (!DeviceFound) { - DeviceFound = SK_TRUE; - SK_MEMCPY(&SK_Root_Dir_entry, BootString, - sizeof(SK_Root_Dir_entry) - 1); - - /*Create proc (directory)*/ - if(!proc_root_initialized) { - pSkRootDir = create_proc_entry(SK_Root_Dir_entry, - S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); - proc_root_initialized = 1; - } - - pSkRootDir->owner = THIS_MODULE; - } - - - /* Create proc file */ - pProcFile = create_proc_entry(dev->name, - S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, - pSkRootDir); - - - pProcFile->read_proc = proc_read; - pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; -#endif - - pNet->PortNr = 0; - pNet->NetNr = 0; - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - - boards_found++; - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { -#if 0 - if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } -#else - dev = malloc (sizeof *dev); - memset(dev, 0, sizeof(*dev)); - dev->priv = malloc(sizeof(DEV_NET)); -#endif - - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - -#if 0 - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; -#endif - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - -#if 0 - pProcFile = create_proc_entry(dev->name, - S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, - pSkRootDir); - - - pProcFile->read_proc = proc_read; - pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; -#endif - -#if 0 - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); -#else - memcpy((caddr_t) &dev->enetaddr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); -#endif - - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - - } - - - /* Save the hardware revision */ - pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + - (pAC->GIni.GIPciHwRev & 0x0F); - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ -#if 0 -#ifndef MODULE - dev->base_addr = 0; -#endif -#endif - } - - /* - * If we're at this point we're going through skge_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - return boards_found; -} /* skge_probe */ - - -/***************************************************************************** - * - * FreeResources - release resources allocated for adapter - * - * Description: - * This function releases the IRQ, unmaps the IO and - * frees the desriptor ring. - * - * Returns: N/A - * - */ -static void FreeResources(struct SK_NET_DEVICE *dev) -{ -SK_U32 AllocFlag; -DEV_NET *pNet; -SK_AC *pAC; - - if (dev->priv) { - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - AllocFlag = pAC->AllocFlag; -#if 0 - if (AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - if (pAC->IoBase) { - iounmap(pAC->IoBase); - } -#endif - if (pAC->pDescrMem) { - BoardFreeMem(pAC); - } - } - -} /* FreeResources */ - -#if 0 -MODULE_AUTHOR("Mirko Lindner "); -MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -/* not used, just there because every driver should have them: */ -MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); -MODULE_PARM(debug, "i"); -#endif - - -#ifdef LINK_SPEED_A -static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED_A; -#else -static char *Speed_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef LINK_SPEED_B -static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED_B; -#else -static char *Speed_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_A -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A; -#else -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_A -static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A; -#else -static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_A -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A; -#else -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_A -static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A; -#else -static char *Role_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_B -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B; -#else -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_B -static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B; -#else -static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_B -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B; -#else -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_B -static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B; -#else -static char *Role_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef PREF_PORT -static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT; -#else -static char *PrefPort[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef RLMT_MODE -static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; -#else -static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#if 0 -static int debug = 0; /* not used */ -static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ - - -/***************************************************************************** - * - * skge_init_module - module initialization function - * - * Description: - * Very simple, only call skge_probe and return approriate result. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_init_module(void) -{ - int cards; - SkGeRootDev = NULL; - - /* just to avoid warnings ... */ - debug = 0; - options[0] = 0; - - cards = skge_probe(); - if (cards == 0) { - printk("sk98lin: No adapter found.\n"); - } - return cards ? 0 : -ENODEV; -} /* skge_init_module */ - - -/***************************************************************************** - * - * skge_cleanup_module - module unload function - * - * Description: - * Disable adapter if it is still running, free resources, - * free device struct. - * - * Returns: N/A - */ -static void __exit skge_cleanup_module(void) -{ -DEV_NET *pNet; -SK_AC *pAC; -struct SK_NET_DEVICE *next; -unsigned long Flags; -SK_EVPARA EvPara; - - while (SkGeRootDev) { - pNet = (DEV_NET*) SkGeRootDev->priv; - pAC = pNet->pAC; - next = pAC->Next; - - netif_stop_queue(SkGeRootDev); - SkGeYellowLED(pAC, pAC->IoBase, 0); - - if(pAC->BoardLevel == 2) { - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = 0; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if(pAC->BoardLevel == 1) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = 0; - } - - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ - unregister_netdev(pAC->dev[1]); - kfree(pAC->dev[1]); - } - - FreeResources(SkGeRootDev); - - SkGeRootDev->get_stats = NULL; - /* - * otherwise unregister_netdev calls get_stats with - * invalid IO ... :-( - */ - unregister_netdev(SkGeRootDev); - kfree(SkGeRootDev); - kfree(pAC); - SkGeRootDev = next; - } - - /* clear proc-dir */ - remove_proc_entry(pSkRootDir->name, proc_net); - -} /* skge_cleanup_module */ - -module_init(skge_init_module); -module_exit(skge_cleanup_module); -#endif - - -/***************************************************************************** - * - * SkGeBoardInit - do level 0 and 1 initialization - * - * Description: - * This function prepares the board hardware for running. The desriptor - * ring is set up, the IRQ is allocated and the configuration settings - * are examined. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) -{ -short i; -unsigned long Flags; -char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */ -char *VerStr = VER_STRING; -#if 0 -int Ret; /* return code of request_irq */ -#endif -SK_BOOL DualNet; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("IoBase: %08lX\n", (unsigned long)pAC->IoBase)); - for (i=0; iTxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0]; - pAC->TxPort[i][0].PortIndex = i; - pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i]; - pAC->RxPort[i].PortIndex = i; - } - - /* Initialize the mutexes */ - for (i=0; iTxPort[i][0].TxDesRingLock); - spin_lock_init(&pAC->RxPort[i].RxDesRingLock); - } - spin_lock_init(&pAC->SlowPathLock); - - /* level 0 init common modules here */ - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* Does a RESET on board ...*/ - if (SkGeInit(pAC, pAC->IoBase, 0) != 0) { - printk("HWInit (0) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return(-EAGAIN); - } - SkI2cInit( pAC, pAC->IoBase, 0); - SkEventInit(pAC, pAC->IoBase, 0); - SkPnmiInit( pAC, pAC->IoBase, 0); - SkAddrInit( pAC, pAC->IoBase, 0); - SkRlmtInit( pAC, pAC->IoBase, 0); - SkTimerInit(pAC, pAC->IoBase, 0); - - pAC->BoardLevel = 0; - pAC->RxBufSize = ETH_BUF_SIZE; - - SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); - SK_PNMI_SET_DRIVER_VER(pAC, VerStr); - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* level 1 init common modules here (HW init) */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { - printk("HWInit (1) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return(-EAGAIN); - } - SkI2cInit( pAC, pAC->IoBase, 1); - SkEventInit(pAC, pAC->IoBase, 1); - SkPnmiInit( pAC, pAC->IoBase, 1); - SkAddrInit( pAC, pAC->IoBase, 1); - SkRlmtInit( pAC, pAC->IoBase, 1); - SkTimerInit(pAC, pAC->IoBase, 1); - - GetConfiguration(pAC); - if (pAC->RlmtNets == 2) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } - - pAC->BoardLevel = 1; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - -#if 0 - if (pAC->GIni.GIMacsFound == 2) { - Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); - } else if (pAC->GIni.GIMacsFound == 1) { - Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, - pAC->Name, dev); - } else { - printk(KERN_WARNING "%s: Illegal number of ports: %d\n", - dev->name, pAC->GIni.GIMacsFound); - return -EAGAIN; - } - - if (Ret) { - printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n", - dev->name, dev->irq); - return -EAGAIN; - } -#endif - pAC->AllocFlag |= SK_ALLOC_IRQ; - - /* Alloc memory for this board (Mem for RxD/TxD) : */ - if(!BoardAllocMem(pAC)) { - printk("No memory for descriptor rings.\n"); - return(-EAGAIN); - } - - SkCsSetReceiveFlags(pAC, - SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, - &pAC->CsOfs1, &pAC->CsOfs2, 0); - pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1; - - BoardInitMem(pAC); -#if 0 - SetQueueSizes(pAC); -#else - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - BoardFreeMem(pAC); - printk("SkGeInitAssignRamToQueues failed.\n"); - return(-EAGAIN); - } -#endif - - /* Print adapter specific string from vpd */ - ProductStr(pAC); -#ifdef SK98_INFO - printk("%s: %s\n", dev->name, pAC->DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); -#endif - - SkGeYellowLED(pAC, pAC->IoBase, 1); - - /* - * Register the device here - */ - pAC->Next = SkGeRootDev; - SkGeRootDev = dev; - - return (0); -} /* SkGeBoardInit */ - - -/***************************************************************************** - * - * BoardAllocMem - allocate the memory for the descriptor rings - * - * Description: - * This function allocates the memory for all descriptor rings. - * Each ring is aligned for the desriptor alignment and no ring - * has a 4 GByte boundary in it (because the upper 32 bit must - * be constant for all descriptiors in one rings). - * - * Returns: - * SK_TRUE, if all memory could be allocated - * SK_FALSE, if not - */ -static SK_BOOL BoardAllocMem( -SK_AC *pAC) -{ -caddr_t pDescrMem; /* pointer to descriptor memory area */ -size_t AllocLength; /* length of complete descriptor area */ -int i; /* loop counter */ -unsigned long BusAddr; - - - /* rings plus one for alignment (do not cross 4 GB boundary) */ - /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */ -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength, - &pAC->pDescrMemDMA); - - if (pDescrMem == NULL) { - return (SK_FALSE); - } - pAC->pDescrMem = pDescrMem; - BusAddr = (unsigned long) pAC->pDescrMemDMA; - - /* Descriptors need 8 byte alignment, and this is ensured - * by pci_alloc_consistent. - */ - for (i=0; iGIni.GIMacsFound; i++) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - BusAddr)); - pAC->TxPort[i][0].pTxDescrRing = pDescrMem; - pAC->TxPort[i][0].VTxDescrRing = BusAddr; - pDescrMem += TX_RING_SIZE; - BusAddr += TX_RING_SIZE; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - (unsigned long)BusAddr)); - pAC->RxPort[i].pRxDescrRing = pDescrMem; - pAC->RxPort[i].VRxDescrRing = BusAddr; - pDescrMem += RX_RING_SIZE; - BusAddr += RX_RING_SIZE; - } /* for */ - - return (SK_TRUE); -} /* BoardAllocMem */ - - -/**************************************************************************** - * - * BoardFreeMem - reverse of BoardAllocMem - * - * Description: - * Free all memory allocated in BoardAllocMem: adapter context, - * descriptor rings, locks. - * - * Returns: N/A - */ -static void BoardFreeMem( -SK_AC *pAC) -{ -size_t AllocLength; /* length of complete descriptor area */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardFreeMem\n")); -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pci_free_consistent(pAC->PciDev, AllocLength, - pAC->pDescrMem, pAC->pDescrMemDMA); - pAC->pDescrMem = NULL; -} /* BoardFreeMem */ - - -/***************************************************************************** - * - * BoardInitMem - initiate the descriptor rings - * - * Description: - * This function sets the descriptor rings up in memory. - * The adapter is initialized with the descriptor start addresses. - * - * Returns: N/A - */ -static void BoardInitMem( -SK_AC *pAC) /* pointer to adapter context */ -{ -int i; /* loop counter */ -int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ -int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardInitMem\n")); - - RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; - TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; - - for (i=0; iGIni.GIMacsFound; i++) { - SetupRing( - pAC, - pAC->TxPort[i][0].pTxDescrRing, - pAC->TxPort[i][0].VTxDescrRing, - (RXD**)&pAC->TxPort[i][0].pTxdRingHead, - (RXD**)&pAC->TxPort[i][0].pTxdRingTail, - (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, - &pAC->TxPort[i][0].TxdRingFree, - SK_TRUE); - SetupRing( - pAC, - pAC->RxPort[i].pRxDescrRing, - pAC->RxPort[i].VRxDescrRing, - &pAC->RxPort[i].pRxdRingHead, - &pAC->RxPort[i].pRxdRingTail, - &pAC->RxPort[i].pRxdRingPrev, - &pAC->RxPort[i].RxdRingFree, - SK_FALSE); - } -} /* BoardInitMem */ - - -/***************************************************************************** - * - * SetupRing - create one descriptor ring - * - * Description: - * This function creates one descriptor ring in the given memory area. - * The head, tail and number of free descriptors in the ring are set. - * - * Returns: - * none - */ -static void SetupRing( -SK_AC *pAC, -void *pMemArea, /* a pointer to the memory area for the ring */ -uintptr_t VMemArea, /* the virtual bus address of the memory area */ -RXD **ppRingHead, /* address where the head should be written */ -RXD **ppRingTail, /* address where the tail should be written */ -RXD **ppRingPrev, /* address where the tail should be written */ -int *pRingFree, /* address where the # of free descr. goes */ -SK_BOOL IsTx) /* flag: is this a tx ring */ -{ -int i; /* loop counter */ -int DescrSize; /* the size of a descriptor rounded up to alignment*/ -int DescrNum; /* number of descriptors per ring */ -RXD *pDescr; /* pointer to a descriptor (receive or transmit) */ -RXD *pNextDescr; /* pointer to the next descriptor */ -RXD *pPrevDescr; /* pointer to the previous descriptor */ -uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ - - if (IsTx == SK_TRUE) { - DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = TX_RING_SIZE / DescrSize; - } else { - DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = RX_RING_SIZE / DescrSize; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("Descriptor size: %d Descriptor Number: %d\n", - DescrSize,DescrNum)); - - pDescr = (RXD*) pMemArea; - pPrevDescr = NULL; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr = VMemArea + DescrSize; - for(i=0; iVNextRxd = VNextDescr & 0xffffffffULL; - pDescr->pNextRxd = pNextDescr; - pDescr->TcpSumStarts = pAC->CsOfs; - - /* advance one step */ - pPrevDescr = pDescr; - pDescr = pNextDescr; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr += DescrSize; - } - pPrevDescr->pNextRxd = (RXD*) pMemArea; - pPrevDescr->VNextRxd = VMemArea; - pDescr = (RXD*) pMemArea; - *ppRingHead = (RXD*) pMemArea; - *ppRingTail = *ppRingHead; - *ppRingPrev = pPrevDescr; - *pRingFree = DescrNum; -} /* SetupRing */ - - -/***************************************************************************** - * - * PortReInitBmu - re-initiate the descriptor rings for one port - * - * Description: - * This function reinitializes the descriptor rings of one port - * in memory. The port must be stopped before. - * The HW is initialized with the descriptor start addresses. - * - * Returns: - * none - */ -static void PortReInitBmu( -SK_AC *pAC, /* pointer to adapter context */ -int PortIndex) /* index of the port for which to re-init */ -{ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PortReInitBmu ")); - - /* set address of first descriptor of ring in BMU */ - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ - TX_Q_CUR_DESCR_LOW, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & - 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ - TX_Q_DESCR_HIGH, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) >> 32)); -} /* PortReInitBmu */ - - -/**************************************************************************** - * - * SkGeIsr - handle adapter interrupts - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * - * Returns: N/A - * - */ -#if 0 -static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) -#else -void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) -#endif -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IRQ_EOF_RX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } - if (IntSrc & IRQ_EOF_RX2) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX2 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 1); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } - if (IntSrc & IRQ_EOF_AS_TX2) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IRQ_EOF_SY_TX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } - if (IntSrc & IRQ_EOF_SY_TX2) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 1, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IRQ_EOF_RX1) - ClearAndStartRx(pAC, 0); - if (IntSrc & IRQ_EOF_RX2) - ClearAndStartRx(pAC, 1); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); - if (IntSrc & IRQ_EOF_AS_TX2) - ClearTxIrq(pAC, 1, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - */ - - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - - if (pAC->CheckQueue) { - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); - - return; -} /* SkGeIsr */ - - -/**************************************************************************** - * - * SkGeIsrOnePort - handle adapter interrupts for single port adapter - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * This is the same as above, but handles only one port. - * - * Returns: N/A - * - */ -#if 0 -static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) -#else -void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) -#endif -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IRQ_EOF_RX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IRQ_EOF_SY_TX1) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IRQ_EOF_RX1) - ClearAndStartRx(pAC, 0); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - */ - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); - - return; -} /* SkGeIsrOnePort */ - - -/**************************************************************************** - * - * SkGeOpen - handle start of initialized adapter - * - * Description: - * This function starts the initialized adapter. - * The board level variable is set and the adapter is - * brought to full functionality. - * The device flags are set for operation. - * Do all necessary level 2 initialization, enable interrupts and - * give start command to RLMT. - * - * Returns: - * 0 on success - * != 0 on error - */ -#if 0 -static int SkGeOpen( -#else -int SkGeOpen( -#endif -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - SK_AC *pAC; - unsigned long Flags; /* for spin lock */ - int i; - SK_EVPARA EvPara; /* an event parameter union */ - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); - - if (pAC->BoardLevel == 0) { - /* level 1 init common modules here */ - if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { - printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, 1); - SkEventInit (pAC, pAC->IoBase, 1); - SkPnmiInit (pAC, pAC->IoBase, 1); - SkAddrInit (pAC, pAC->IoBase, 1); - SkRlmtInit (pAC, pAC->IoBase, 1); - SkTimerInit (pAC, pAC->IoBase, 1); - pAC->BoardLevel = 1; - } - - if (pAC->BoardLevel != 2) { - /* tschilling: Level 2 init modules here, check return value. */ - if (SkGeInit(pAC, pAC->IoBase, 2) != 0) { - printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, 2); - SkEventInit (pAC, pAC->IoBase, 2); - SkPnmiInit (pAC, pAC->IoBase, 2); - SkAddrInit (pAC, pAC->IoBase, 2); - SkRlmtInit (pAC, pAC->IoBase, 2); - SkTimerInit (pAC, pAC->IoBase, 2); - pAC->BoardLevel = 2; - } - - for (i=0; iGIni.GIMacsFound; i++) { - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - } - SkGeYellowLED(pAC, pAC->IoBase, 1); - -#ifdef USE_INT_MOD -/* moderate only TX complete interrupts (these are not time critical) */ -#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2) - { - unsigned long ModBase; - ModBase = 53125000 / INTS_PER_SEC; - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - } -#endif - - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - EvPara.Para32[0] = pAC->RlmtMode; - EvPara.Para32[1] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, - EvPara); - } - - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - pAC->MaxPorts++; - pNet->Up = 1; - - MOD_INC_USE_COUNT; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen suceeded\n")); - - return (0); -} /* SkGeOpen */ - - -/**************************************************************************** - * - * SkGeClose - Stop initialized adapter - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -#if 0 -static int SkGeClose( -#else -int SkGeClose( -#endif -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - SK_AC *pAC; - - unsigned long Flags; /* for spin lock */ - int i; - int PortIdx; - SK_EVPARA EvPara; - - netif_stop_queue(dev); - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - - /* - * Clear multicast table, promiscuous mode .... - */ - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - - if (pAC->MaxPorts == 1) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* stop the hardware */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = 0; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* Stop port */ - spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, - SK_STOP_ALL, SK_HARD_RST); - spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - } - - if (pAC->RlmtNets == 1) { - /* clear all descriptor rings */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); - } - } else { - /* clear port descriptor rings */ - ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); - ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: done ")); - - pAC->MaxPorts--; - pNet->Up = 0; - MOD_DEC_USE_COUNT; - - return (0); -} /* SkGeClose */ - - -/***************************************************************************** - * - * SkGeXmit - Linux frame transmit function - * - * Description: - * The system calls this function to send frames onto the wire. - * It puts the frame in the tx descriptor ring. If the ring is - * full then, the 'tbusy' flag is set. - * - * Returns: - * 0, if everything is ok - * !=0, on error - * WARNING: returning 1 in 'tbusy' case caused system crashes (double - * allocated skb's) !!! - */ -#if 0 -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) -#else -int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) -#endif -{ -DEV_NET *pNet; -SK_AC *pAC; -int Rc; /* return code of XmitFrame */ - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - -#if 0 - if ((!skb_shinfo(skb)->nr_frags) || -#else - if (1 || -#endif - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { - /* Don't activate scatter-gather and hardware checksum */ - - if (pAC->RlmtNets == 2) - Rc = XmitFrame( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrame( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); - } else { -#if 0 - /* scatter-gather and hardware TCP checksumming anabled*/ - if (pAC->RlmtNets == 2) - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); -#endif - } - - /* Transmitter out of resources? */ - if (Rc <= 0) { - netif_stop_queue(dev); - } - - /* If not taken, give buffer ownership back to the - * queueing layer. - */ - if (Rc < 0) - return (1); - -#if 0 - dev->trans_start = jiffies; -#endif - return (0); -} /* SkGeXmit */ - - -/***************************************************************************** - * - * XmitFrame - fill one socket buffer into the transmit ring - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * Linux skb's consist of only one continuous buffer. - * The first step locks the ring. It is held locked - * all time to avoid problems with SWITCH_../PORT_RESET. - * Then the descriptoris allocated. - * The second part is linking the buffer to the descriptor. - * At the very last, the Control field of the descriptor - * is made valid for the BMU and a start TX command is given - * if necessary. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -static int XmitFrame( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ -TXD *pTxd; /* the rxd to fill */ -unsigned long Flags; -SK_U64 PhysAddr; -int BytesSend; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("X")); - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if (pTxPort->TxdRingFree == 0) { - /* no enough free descriptors in ring at the moment */ - FreeTxDescriptors(pAC, pTxPort); - if (pTxPort->TxdRingFree == 0) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrame failed\n")); - /* this message can not be sent now */ - /* Because tbusy seems to be set, the message should not be freed here */ - /* It will be used by the scheduler of the ethernet handler */ - return (-1); - } - } - /* advance head counter behind descriptor needed for this frame */ - pTxd = pTxPort->pTxdRingHead; - pTxPort->pTxdRingHead = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - /* the needed descriptor is reserved now */ - - /* - * everything allocated ok, so add buffer to descriptor - */ - -#ifdef SK_DUMP_TX - DumpMsg(pMessage, "XmitFrame"); -#endif - - /* set up descriptor and CONTROL dword */ -#if 0 - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & - ~PAGE_MASK), - pMessage->len, - PCI_DMA_TODEVICE); -#else - PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32) pMessage->data); -#endif - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF | - TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE | -#ifdef USE_TX_COMPLETE - TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len; -#else - TX_CTRL_EOF | pMessage->len; -#endif - - if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { - /* previous descriptor already done, so give tx start cmd */ - /* StartTx(pAC, pTxPort->HwAddr); */ - SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); - } - pTxPort->pTxdRingPrev = pTxd; - - - BytesSend = pMessage->len; - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - /* after releasing the lock, the skb may be immidiately freed */ - if (pTxPort->TxdRingFree != 0) - return (BytesSend); - else - return (0); - -} /* XmitFrame */ - -/***************************************************************************** - * - * XmitFrameSG - fill one socket buffer into the transmit ring - * (use SG and TCP/UDP hardware checksumming) - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -#if 0 -static int XmitFrameSG( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ - - int i; - int BytesSend; - int hlength; - int protocol; - skb_frag_t *sk_frag; - TXD *pTxd; - TXD *pTxdFst; - TXD *pTxdLst; - SK_U64 PhysAddr; - unsigned long Flags; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) { - FreeTxDescriptors(pAC, pTxPort); - if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrameSG failed - Ring full\n")); - /* this message can not be sent now */ - return(-1); - } - } - - - pTxd = pTxPort->pTxdRingHead; - pTxdFst = pTxd; - pTxdLst = pTxd; - BytesSend = 0; - protocol = 0; - - /* map first fragment (header) */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & ~PAGE_MASK), - skb_headlen(pMessage), - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - - /* HW checksum? */ - if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = TX_CTRL_STF | - TX_CTRL_ST_FWD | - skb_headlen(pMessage); - - /* We have to use the opcode for tcp here because the opcode for - udp is not working in the hardware yet (revision 2.0)*/ - protocol = ((SK_U8)pMessage->data[23] & 0xf); - if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) - pTxd->TBControl |= BMU_UDP_CHECK; - else - pTxd->TBControl |= BMU_TCP_CHECK ; - - hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4; - pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ - pTxd->TcpSumSt = 14+hlength+16; - pTxd->TcpSumWr = 14+hlength; - - } else { - pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | - TX_CTRL_SOFTWARE | - TX_CTRL_STF | - skb_headlen(pMessage); - } - - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += skb_headlen(pMessage); - - - /* Map SG fragments */ - for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) { - sk_frag = &skb_shinfo(pMessage)->frags[i]; - - /* we already have the proper value in entry */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - sk_frag->page, - sk_frag->page_offset, - sk_frag->size, - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - /* HW checksum */ - if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = TX_CTRL_OWN_BMU | - TX_CTRL_SOFTWARE | - TX_CTRL_ST_FWD; - - /* We have to use the opcode for tcp here because the opcode for - udp is not working in the hardware yet (revision 2.0)*/ - if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) - pTxd->TBControl |= BMU_UDP_CHECK ; - else - pTxd->TBControl |= BMU_TCP_CHECK ; - - } else { - pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | - TX_CTRL_SOFTWARE | - TX_CTRL_OWN_BMU; - } - - /* Last fragment */ - if( (i+1) == skb_shinfo(pMessage)->nr_frags ) { -#ifdef USE_TX_COMPLETE - pTxd->TBControl |= TX_CTRL_EOF | - TX_CTRL_EOF_IRQ | - sk_frag->size; -#else - pTxd->TBControl |= TX_CTRL_EOF | - sk_frag->size; -#endif - pTxdFst->TBControl |= TX_CTRL_OWN_BMU | - TX_CTRL_SOFTWARE; - - } else { - pTxd->TBControl |= sk_frag->size; - } - pTxdLst = pTxd; - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += sk_frag->size; - } - - if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { - /* previous descriptor already done, so give tx start cmd */ - /* StartTx(pAC, pTxPort->HwAddr); */ - SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); - } - - pTxPort->pTxdRingPrev = pTxdLst; - pTxPort->pTxdRingHead = pTxd; - - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - - if (pTxPort->TxdRingFree > 0) - return (BytesSend); - else - return (0); -} -#endif - - -void dump_frag( SK_U8 *data, int length) -{ - int i; - - printk("Length: %d\n", length); - for( i=0; i < length; i++ ) { - printk(" %02x", (SK_U8)*(data + i) ); - if( !((i+1) % 20) ) - printk("\n"); - } - printk("\n\n"); - -} - - -/***************************************************************************** - * - * FreeTxDescriptors - release descriptors from the descriptor ring - * - * Description: - * This function releases descriptors from a transmit ring if they - * have been sent by the BMU. - * If a descriptors is sent, it can be freed and the message can - * be freed, too. - * The SOFTWARE controllable bit is used to prevent running around a - * completely free ring for ever. If this bit is no set in the - * frame (by XmitFrame), this frame has never been sent or is - * already freed. - * The Tx descriptor ring lock must be held while calling this function !!! - * - * Returns: - * none - */ -static void FreeTxDescriptors( -SK_AC *pAC, /* pointer to the adapter context */ -TX_PORT *pTxPort) /* pointer to destination port structure */ -{ -TXD *pTxd; /* pointer to the checked descriptor */ -TXD *pNewTail; /* pointer to 'end' of the ring */ -SK_U32 Control; /* TBControl field of descriptor */ -SK_U64 PhysAddr; /* address of DMA mapping */ - - pNewTail = pTxPort->pTxdRingTail; - pTxd = pNewTail; - /* - * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame - * or TX_CTRL_OWN_BMU bit set in any frame - */ - while (1) { - Control = pTxd->TBControl; - if ((Control & TX_CTRL_SOFTWARE) == 0) { - /* - * software controllable bit is set in first - * fragment when given to BMU. Not set means that - * this fragment was never sent or is already - * freed ( -> ring completely free now). - */ - pTxPort->pTxdRingTail = pTxd; - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - return; - } - if (Control & TX_CTRL_OWN_BMU) { - pTxPort->pTxdRingTail = pTxd; - if (pTxPort->TxdRingFree > 0) { - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - } - return; - } - - /* release the DMA mapping */ - PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; - PhysAddr |= (SK_U64) pTxd->VDataLow; - pci_unmap_page(pAC->PciDev, PhysAddr, - pTxd->pMBuf->len, - PCI_DMA_TODEVICE); - - if (Control & TX_CTRL_EOF) - DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ - - pTxPort->TxdRingFree++; - pTxd->TBControl &= ~TX_CTRL_SOFTWARE; - pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ - } /* while(forever) */ -} /* FreeTxDescriptors */ - -/***************************************************************************** - * - * FillRxRing - fill the receive ring with valid descriptors - * - * Description: - * This function fills the receive ring descriptors with data - * segments and makes them valid for the BMU. - * The active ring is filled completely, if possible. - * The non-active ring is filled only partial to save memory. - * - * Description of rx ring structure: - * head - points to the descriptor which will be used next by the BMU - * tail - points to the next descriptor to give to the BMU - * - * Returns: N/A - */ -static void FillRxRing( -SK_AC *pAC, /* pointer to the adapter context */ -RX_PORT *pRxPort) /* ptr to port struct for which the ring - should be filled */ -{ -unsigned long Flags; - - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { - if(!FillRxDescriptor(pAC, pRxPort)) - break; - } - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* FillRxRing */ - - -/***************************************************************************** - * - * FillRxDescriptor - fill one buffer into the receive ring - * - * Description: - * The function allocates a new receive buffer and - * puts it into the next descriptor. - * - * Returns: - * SK_TRUE - a buffer was added to the ring - * SK_FALSE - a buffer could not be added - */ -static SK_BOOL FillRxDescriptor( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort) /* ptr to port struct of ring to fill */ -{ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ -SK_U64 PhysAddr; /* physical address of a rx buffer */ - - pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); - if (pMsgBlock == NULL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_ENTRY, - ("%s: Allocation of rx buffer failed !\n", - pAC->dev[pRxPort->PortIndex]->name)); - SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex); - return(SK_FALSE); - } - skb_reserve(pMsgBlock, 2); /* to align IP frames */ - /* skb allocated ok, so add buffer */ - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; -#if 0 - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMsgBlock->data), - ((unsigned long) pMsgBlock->data & - ~PAGE_MASK), - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); -#else - PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32)pMsgBlock->data); -#endif - pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pRxd->pMBuf = pMsgBlock; - pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | - RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; - return (SK_TRUE); - -} /* FillRxDescriptor */ - - -/***************************************************************************** - * - * ReQueueRxBuffer - fill one buffer back into the receive ring - * - * Description: - * Fill a given buffer back into the rx ring. The buffer - * has been previously allocated and aligned, and its phys. - * address calculated, so this is no more necessary. - * - * Returns: N/A - */ -static void ReQueueRxBuffer( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort, /* ptr to port struct of ring to fill */ -struct sk_buff *pMsg, /* pointer to the buffer */ -SK_U32 PhysHigh, /* phys address high dword */ -SK_U32 PhysLow) /* phys address low dword */ -{ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ - - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - pRxd->VDataLow = PhysLow; - pRxd->VDataHigh = PhysHigh; - pRxd->pMBuf = pMsg; - pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | - RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; - return; -} /* ReQueueRxBuffer */ - - -/***************************************************************************** - * - * ReceiveIrq - handle a receive IRQ - * - * Description: - * This function is called when a receive IRQ is set. - * It walks the receive descriptor ring and sends up all - * frames that are complete. - * - * Returns: N/A - */ -#if 0 -static void ReceiveIrq( -#else -void ReceiveIrq( -#endif - SK_AC *pAC, /* pointer to adapter context */ - RX_PORT *pRxPort, /* pointer to receive port struct */ - SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ -{ -RXD *pRxd; /* pointer to receive descriptors */ -SK_U32 Control; /* control field of descriptor */ -struct sk_buff *pMsg; /* pointer to message holding frame */ -struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ -int FrameLength; /* total length of received frame */ -SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ -SK_EVPARA EvPara; /* an event parameter union */ -unsigned long Flags; /* for spin lock */ -int PortIndex = pRxPort->PortIndex; -unsigned int Offset; -unsigned int NumBytes; -unsigned int ForRlmt; -SK_BOOL IsBc; -SK_BOOL IsMc; -SK_BOOL IsBadFrame; /* Bad frame */ - -SK_U32 FrameStat; -unsigned short Csum1; -unsigned short Csum2; -unsigned short Type; -#if 0 -int Result; -#endif -SK_U64 PhysAddr; - -rx_start: - /* do forever; exit if RX_CTRL_OWN_BMU found */ - for ( pRxd = pRxPort->pRxdRingHead ; - pRxPort->RxdRingFree < pAC->RxDescrPerRing ; - pRxd = pRxd->pNextRxd, - pRxPort->pRxdRingHead = pRxd, - pRxPort->RxdRingFree ++) { - - /* - * For a better understanding of this loop - * Go through every descriptor beginning at the head - * Please note: the ring might be completely received so the OWN bit - * set is not a good crirteria to leave that loop. - * Therefore the RingFree counter is used. - * On entry of this loop pRxd is a pointer to the Rxd that needs - * to be checked next. - */ - - Control = pRxd->RBControl; - - /* check if this descriptor is ready */ - if ((Control & RX_CTRL_OWN_BMU) != 0) { - /* this descriptor is not yet ready */ - /* This is the usual end of the loop */ - /* We don't need to start the ring again */ - FillRxRing(pAC, pRxPort); - return; - } - - /* get length of frame and check it */ - FrameLength = Control & RX_CTRL_LEN_MASK; - if (FrameLength > pAC->RxBufSize) { - goto rx_failed; - } - - /* check for STF and EOF */ - if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) != - (RX_CTRL_STF | RX_CTRL_EOF)) { - goto rx_failed; - } - - /* here we have a complete frame in the ring */ - pMsg = pRxd->pMBuf; - - FrameStat = pRxd->FrameStat; - - /* check for frame length mismatch */ -#define XMR_FS_LEN_SHIFT 18 -#define GMR_FS_LEN_SHIFT 16 - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - else { - if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - - /* Set Rx Status */ - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - IsBc = (FrameStat & XMR_FS_BC) != 0; - IsMc = (FrameStat & XMR_FS_MC) != 0; - IsBadFrame = (FrameStat & - (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0; - } else { - IsBc = (FrameStat & GMR_FS_BC) != 0; - IsMc = (FrameStat & GMR_FS_MC) != 0; - IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) || - ((FrameStat & GMR_FS_RX_OK) == 0)); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Received frame of length %d on port %d\n", - FrameLength, PortIndex)); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Number of free rx descriptors: %d\n", - pRxPort->RxdRingFree)); -/* DumpMsg(pMsg, "Rx"); */ - - if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID || - (IsBadFrame)) { -#if 0 - (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) { -#endif - /* there is a receive error in this frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Error in received frame, dropped!\n" - "Control: %x\nRxStat: %x\n", - Control, FrameStat)); - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_dma_sync_single(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - - continue; - } - - /* - * if short frame then copy data to reduce memory waste - */ - if ((FrameLength < SK_COPY_THRESHOLD) && - ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) { - /* - * Short frame detected and allocation successfull - */ - /* use new skb and copy data */ - skb_reserve(pNewMsg, 2); - skb_put(pNewMsg, FrameLength); - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - pci_dma_sync_single(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - eth_copy_and_sum(pNewMsg, pMsg->data, - FrameLength, 0); - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - pMsg = pNewMsg; - - } - else { - /* - * if large frame, or SKB allocation failed, pass - * the SKB directly to the networking - */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - /* release the DMA mapping */ - pci_unmap_single(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - - /* set length in message */ - skb_put(pMsg, FrameLength); - /* hardware checksum */ - Type = ntohs(*((short*)&pMsg->data[12])); - if (Type == 0x800) { - Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); - Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff); -#if 0 - if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) && - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) || - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - Result = SkCsGetReceiveInfo(pAC, - &pMsg->data[14], - Csum1, Csum2, pRxPort->PortIndex); - if (Result == - SKCS_STATUS_IP_FRAGMENT || - Result == - SKCS_STATUS_IP_CSUM_OK || - Result == - SKCS_STATUS_TCP_CSUM_OK || - Result == - SKCS_STATUS_UDP_CSUM_OK) { - pMsg->ip_summed = - CHECKSUM_UNNECESSARY; - } else { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: CRC error. Frame dropped!\n")); - goto rx_failed; - } - }/* checksumControl calculation valid */ -#endif - } /* IP frame */ - } /* frame > SK_COPY_TRESHOLD */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); - ForRlmt = SK_RLMT_RX_PROTOCOL; -#if 0 - IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC; -#endif - SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, - IsBc, &Offset, &NumBytes); - if (NumBytes != 0) { -#if 0 - IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC; -#endif - SK_RLMT_LOOKAHEAD(pAC, PortIndex, - &pMsg->data[Offset], - IsBc, IsMc, &ForRlmt); - } - if (ForRlmt == SK_RLMT_RX_PROTOCOL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); - /* send up only frames from active port */ - if ((PortIndex == pAC->ActivePort) || - (pAC->RlmtNets == 2)) { - /* frame for upper layer */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U")); -#ifdef xDEBUG - DumpMsg(pMsg, "Rx"); -#endif - SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, - FrameLength, pRxPort->PortIndex); - -#if 0 - pMsg->dev = pAC->dev[pRxPort->PortIndex]; - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; -#else - NetReceive(pMsg->data, pMsg->len); - dev_kfree_skb_any(pMsg); -#endif - } - else { - /* drop frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("D")); - DEV_KFREE_SKB(pMsg); - } - - } /* if not for rlmt */ - else { - /* packet for rlmt */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, ("R")); - pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, - pAC->IoBase, FrameLength); - if (pRlmtMbuf != NULL) { - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->Length = FrameLength; - pRlmtMbuf->PortIdx = PortIndex; - EvPara.pParaPtr = pRlmtMbuf; - memcpy((char*)(pRlmtMbuf->pData), - (char*)(pMsg->data), - FrameLength); - - /* SlowPathLock needed? */ - if (SlowPathLock == SK_TRUE) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("Q")); - } -#if 0 - if ((pAC->dev[pRxPort->PortIndex]->flags & - (IFF_PROMISC | IFF_ALLMULTI)) != 0 || - (ForRlmt & SK_RLMT_RX_PROTOCOL) == - SK_RLMT_RX_PROTOCOL) { - pMsg->dev = pAC->dev[pRxPort->PortIndex]; - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } -#else - if (0) { - } -#endif - else { - DEV_KFREE_SKB(pMsg); - } - - } /* if packet for rlmt */ - } /* for ... scanning the RXD ring */ - - /* RXD ring is empty -> fill and restart */ - FillRxRing(pAC, pRxPort); - /* do not start if called from Close */ - if (pAC->BoardLevel > 0) { - ClearAndStartRx(pAC, PortIndex); - } - return; - -rx_failed: - /* remove error frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, - ("Schrottdescriptor, length: 0x%x\n", FrameLength)); - - /* release the DMA mapping */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB_IRQ(pRxd->pMBuf); - pRxd->pMBuf = NULL; - pRxPort->RxdRingFree++; - pRxPort->pRxdRingHead = pRxd->pNextRxd; - goto rx_start; - -} /* ReceiveIrq */ - - -/***************************************************************************** - * - * ClearAndStartRx - give a start receive command to BMU, clear IRQ - * - * Description: - * This function sends a start command and a clear interrupt - * command for one receive queue to the BMU. - * - * Returns: N/A - * none - */ -static void ClearAndStartRx( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex) /* index of the receive port (XMAC) */ -{ - SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL, - RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF); -} /* ClearAndStartRx */ - - -/***************************************************************************** - * - * ClearTxIrq - give a clear transmit IRQ command to BMU - * - * Description: - * This function sends a clear tx IRQ command for one - * transmit queue to the BMU. - * - * Returns: N/A - */ -static void ClearTxIrq( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex, /* index of the transmit port (XMAC) */ -int Prio) /* priority or normal queue */ -{ - SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL, - TX_Q_CTRL_CLR_I_EOF); -} /* ClearTxIrq */ - - -/***************************************************************************** - * - * ClearRxRing - remove all buffers from the receive ring - * - * Description: - * This function removes all receive buffers from the ring. - * The receive BMU must be stopped before calling this function. - * - * Returns: N/A - */ -static void ClearRxRing( -SK_AC *pAC, /* pointer to adapter context */ -RX_PORT *pRxPort) /* pointer to rx port struct */ -{ -RXD *pRxd; /* pointer to the current descriptor */ -unsigned long Flags; -SK_U64 PhysAddr; - - if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) { - return; - } - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - pRxd = pRxPort->pRxdRingHead; - do { - if (pRxd->pMBuf != NULL) { - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB(pRxd->pMBuf); - pRxd->pMBuf = NULL; - } - pRxd->RBControl &= RX_CTRL_OWN_BMU; - pRxd = pRxd->pNextRxd; - pRxPort->RxdRingFree++; - } while (pRxd != pRxPort->pRxdRingTail); - pRxPort->pRxdRingTail = pRxPort->pRxdRingHead; - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* ClearRxRing */ - - -/***************************************************************************** - * - * ClearTxRing - remove all buffers from the transmit ring - * - * Description: - * This function removes all transmit buffers from the ring. - * The transmit BMU must be stopped before calling this function - * and transmitting at the upper level must be disabled. - * The BMU own bit of all descriptors is cleared, the rest is - * done by calling FreeTxDescriptors. - * - * Returns: N/A - */ -static void ClearTxRing( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort) /* pointer to tx prt struct */ -{ -TXD *pTxd; /* pointer to the current descriptor */ -int i; -unsigned long Flags; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); - pTxd = pTxPort->pTxdRingHead; - for (i=0; iTxDescrPerRing; i++) { - pTxd->TBControl &= ~TX_CTRL_OWN_BMU; - pTxd = pTxd->pNextTxd; - } - FreeTxDescriptors(pAC, pTxPort); - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); -} /* ClearTxRing */ - - -#if 0 -/***************************************************************************** - * - * SetQueueSizes - configure the sizes of rx and tx queues - * - * Description: - * This function assigns the sizes for active and passive port - * to the appropriate HWinit structure variables. - * The passive port(s) get standard values, all remaining RAM - * is given to the active port. - * The queue sizes are in kbyte and must be multiple of 8. - * The limits for the number of buffers filled into the rx rings - * is also set in this routine. - * - * Returns: - * none - */ -static void SetQueueSizes( -SK_AC *pAC) /* pointer to the adapter context */ -{ -int StandbyRam; /* adapter RAM used for a standby port */ -int RemainingRam; /* adapter RAM available for the active port */ -int RxRam; /* RAM used for the active port receive queue */ -int i; /* loop counter */ - -if (pAC->RlmtNets == 1) { - StandbyRam = SK_RLMT_STANDBY_QRXSIZE + SK_RLMT_STANDBY_QXASIZE + - SK_RLMT_STANDBY_QXSSIZE; - RemainingRam = pAC->GIni.GIRamSize - - (pAC->GIni.GIMacsFound-1) * StandbyRam; - for (i=0; iGIni.GIMacsFound; i++) { - pAC->GIni.GP[i].PRxQSize = SK_RLMT_STANDBY_QRXSIZE; - pAC->GIni.GP[i].PXSQSize = SK_RLMT_STANDBY_QXSSIZE; - pAC->GIni.GP[i].PXAQSize = SK_RLMT_STANDBY_QXASIZE; - } - RxRam = (RemainingRam * 8 / 10) & ~7; - pAC->GIni.GP[pAC->ActivePort].PRxQSize = RxRam; - pAC->GIni.GP[pAC->ActivePort].PXSQSize = 0; - pAC->GIni.GP[pAC->ActivePort].PXAQSize = - (RemainingRam - RxRam) & ~7; - pAC->RxQueueSize = RxRam; - pAC->TxSQueueSize = 0; - pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("queue sizes settings - rx:%d txA:%d txS:%d\n", - pAC->RxQueueSize,pAC->TxAQueueSize, pAC->TxSQueueSize)); -} else { - RemainingRam = pAC->GIni.GIRamSize/pAC->GIni.GIMacsFound; - RxRam = (RemainingRam * 8 / 10) & ~7; - for (i=0; iGIni.GIMacsFound; i++) { - pAC->GIni.GP[i].PRxQSize = RxRam; - pAC->GIni.GP[i].PXSQSize = 0; - pAC->GIni.GP[i].PXAQSize = (RemainingRam - RxRam) & ~7; - } - - pAC->RxQueueSize = RxRam; - pAC->TxSQueueSize = 0; - pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; -} - for (i=0; iRxPort[i].RxFillLimit = pAC->RxDescrPerRing; - } - - if (pAC->RlmtNets == 2) { - for (i=0; iGIni.GIMacsFound; i++) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; - } - } else { - for (i=0; iGIni.GIMacsFound; i++) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; - } - /* - * Do not set the Limit to 0, because this could cause - * wrap around with ReQueue'ed buffers (a buffer could - * be requeued in the same position, made accessable to - * the hardware, and the hardware could change its - * contents! - */ - pAC->RxPort[pAC->ActivePort].RxFillLimit = 1; - } - -#ifdef DEBUG - for (i=0; iGIni.GIMacsFound; i++) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("i: %d, RxQSize: %d, PXSQsize: %d, PXAQSize: %d\n", - i, - pAC->GIni.GP[i].PRxQSize, - pAC->GIni.GP[i].PXSQSize, - pAC->GIni.GP[i].PXAQSize)); - } -#endif -} /* SetQueueSizes */ - - -/***************************************************************************** - * - * SkGeSetMacAddr - Set the hardware MAC address - * - * Description: - * This function sets the MAC address used by the adapter. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) -{ - -DEV_NET *pNet = (DEV_NET*) dev->priv; -SK_AC *pAC = pNet->pAC; - -struct sockaddr *addr = p; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetMacAddr starts now...\n")); - if(netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if (pAC->RlmtNets == 2) - SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - else - SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return 0; -} /* SkGeSetMacAddr */ -#endif - - -/***************************************************************************** - * - * SkGeSetRxMode - set receive mode - * - * Description: - * This function sets the receive mode of an adapter. The adapter - * supports promiscuous mode, allmulticast mode and a number of - * multicast addresses. If more multicast addresses the available - * are selected, a hash function in the hardware is used. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -#if 0 -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev) -{ - -DEV_NET *pNet; -SK_AC *pAC; - -struct dev_mc_list *pMcList; -int i; -int PortIdx; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetRxMode starts now... ")); - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (dev->flags & IFF_PROMISC) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PROMISCUOUS mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_LLC); - } else if (dev->flags & IFF_ALLMULTI) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("ALLMULTI mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_ALL_MC); - } else { - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("Number of MC entries: %d ", dev->mc_count)); - - pMcList = dev->mc_list; - for (i=0; imc_count; i++, pMcList = pMcList->next) { - SkAddrMcAdd(pAC, pAC->IoBase, PortIdx, - (SK_MAC_ADDR*)pMcList->dmi_addr, 0); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA, - ("%02x:%02x:%02x:%02x:%02x:%02x\n", - pMcList->dmi_addr[0], - pMcList->dmi_addr[1], - pMcList->dmi_addr[2], - pMcList->dmi_addr[3], - pMcList->dmi_addr[4], - pMcList->dmi_addr[5])); - } - SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx); - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return; -} /* SkGeSetRxMode */ - - -/***************************************************************************** - * - * SkGeChangeMtu - set the MTU to another value - * - * Description: - * This function sets is called whenever the MTU size is changed - * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard - * ethernet MTU size, long frame support is activated. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) -{ -DEV_NET *pNet; -DEV_NET *pOtherNet; -SK_AC *pAC; -unsigned long Flags; -int i; -SK_EVPARA EvPara; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeChangeMtu starts now...\n")); - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { - return -EINVAL; - } - - if(pAC->BoardLevel != 2) { - return -EINVAL; - } - - pNet->Mtu = NewMtu; - pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv; - if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) { - return(0); - } - - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - - pAC->RxBufSize = NewMtu + 32; - dev->mtu = NewMtu; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("New MTU: %d\n", NewMtu)); - - /* prevent reconfiguration while changing the MTU */ - - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - /* Stop both ports */ - EvPara.Para32[0] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } - - SkEventDispatcher(pAC, pAC->IoBase); - - for (i=0; iGIni.GIMacsFound; i++) { - spin_lock_irqsave( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); - netif_stop_queue(pAC->dev[i]); - - } - - /* - * adjust number of rx buffers allocated - */ - if (NewMtu > 1500) { - /* use less rx buffers */ - for (i=0; iGIni.GIMacsFound; i++) { - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - } else { - if (i == pAC->ActivePort) - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - else - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 10; - } - } - } - else { - /* use normal amount of rx buffers */ - for (i=0; iGIni.GIMacsFound; i++) { - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - if (i == pAC->ActivePort) - pAC->RxPort[i].RxFillLimit = 1; - else - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - } - } - } - - SkGeDeInit(pAC, pAC->IoBase); - - /* - * enable/disable hardware support for long frames - */ - if (NewMtu > 1500) { -/* pAC->JumboActivated = SK_TRUE; /#* is never set back !!! */ - pAC->GIni.GIPortUsage = SK_JUMBO_LINK; - } - else { - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } else { - pAC->GIni.GIPortUsage = SK_RED_LINK; - } - } - - SkGeInit( pAC, pAC->IoBase, 1); - SkI2cInit( pAC, pAC->IoBase, 1); - SkEventInit(pAC, pAC->IoBase, 1); - SkPnmiInit( pAC, pAC->IoBase, 1); - SkAddrInit( pAC, pAC->IoBase, 1); - SkRlmtInit( pAC, pAC->IoBase, 1); - SkTimerInit(pAC, pAC->IoBase, 1); - - /* - * tschilling: - * Speed and others are set back to default in level 1 init! - */ - GetConfiguration(pAC); - - SkGeInit( pAC, pAC->IoBase, 2); - SkI2cInit( pAC, pAC->IoBase, 2); - SkEventInit(pAC, pAC->IoBase, 2); - SkPnmiInit( pAC, pAC->IoBase, 2); - SkAddrInit( pAC, pAC->IoBase, 2); - SkRlmtInit( pAC, pAC->IoBase, 2); - SkTimerInit(pAC, pAC->IoBase, 2); - - /* - * clear and reinit the rx rings here - */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - FillRxRing(pAC, &pAC->RxPort[i]); - - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - }; - - SkGeYellowLED(pAC, pAC->IoBase, 1); - -#ifdef USE_INT_MOD - { - unsigned long ModBase; - ModBase = 53125000 / INTS_PER_SEC; - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - } -#endif - - netif_start_queue(pAC->dev[pNet->PortNr]); - for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { - spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - } - - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - /* Start both ports */ - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - - - EvPara.Para32[1] = -1; - EvPara.Para32[0] = pNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - - if (pOtherNet->Up) { - EvPara.Para32[0] = pOtherNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_START, EvPara); - } - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return 0; -} /* SkGeChangeMtu */ - - -/***************************************************************************** - * - * SkGeStats - return ethernet device statistics - * - * Description: - * This function return statistic data about the ethernet device - * to the operating system. - * - * Returns: - * pointer to the statistic structure. - */ -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) -{ -DEV_NET *pNet = (DEV_NET*) dev->priv; -SK_AC *pAC = pNet->pAC; -SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */ -SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */ -SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */ -unsigned int Size; /* size of pnmi struct */ -unsigned long Flags; /* for spin lock */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeStats starts now...\n")); - pPnmiStruct = &pAC->PnmiStruct; - memset(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pPnmiStat = &pPnmiStruct->Stat[0]; - pPnmiConf = &pPnmiStruct->Conf[0]; - - pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF; - pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF; - pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; - pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; - - if (pNet->Mtu <= 1500) { - pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; - } else { - pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF); - } - - - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12) - pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts; - - pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF; - pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF; - pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF; - pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - - /* detailed rx_errors: */ - pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF; - pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF; - pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF; - pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF; - - /* detailed tx_errors */ - pAC->stats.tx_aborted_errors = (SK_U32) 0; - pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF; - pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_window_errors = (SK_U32) 0; - - return(&pAC->stats); -} /* SkGeStats */ - - -/***************************************************************************** - * - * SkGeIoctl - IO-control function - * - * Description: - * This function is called if an ioctl is issued on the device. - * There are three subfunction for reading, writing and test-writing - * the private MIB data structure (usefull for SysKonnect-internal tools). - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd) -{ -DEV_NET *pNet; -SK_AC *pAC; - -SK_GE_IOCTL Ioctl; -unsigned int Err = 0; -int Size; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIoctl starts now...\n")); - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - - switch(cmd) { - case SK_IOCTL_SETMIB: - case SK_IOCTL_PRESETMIB: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - case SK_IOCTL_GETMIB: - if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, - Ioctl.LenPnmiStruct)? - Ioctl.Len : sizeof(pAC->PnmiStruct))) { - return -EFAULT; - } - Size = SkGeIocMib(pNet, Ioctl.Len, cmd); - if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct, - Ioctl.Lenifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - break; - default: - Err = -EOPNOTSUPP; - } - return(Err); -} /* SkGeIoctl */ - - -/***************************************************************************** - * - * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message - * - * Description: - * This function reads/writes the MIB data using PNMI (Private Network - * Management Interface). - * The destination for the data must be provided with the - * ioctl call and is given to the driver in the form of - * a user space address. - * Copying from the user-provided data area into kernel messages - * and back is done by copy_from_user and copy_to_user calls in - * SkGeIoctl. - * - * Returns: - * returned size from PNMI call - */ -static int SkGeIocMib( -DEV_NET *pNet, /* pointer to the adapter context */ -unsigned int Size, /* length of ioctl data */ -int mode) /* flag for set/preset */ -{ -unsigned long Flags; /* for spin lock */ -SK_AC *pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIocMib starts now...\n")); - pAC = pNet->pAC; - /* access MIB */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - switch(mode) { - case SK_IOCTL_GETMIB: - SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_PRESETMIB: - SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_SETMIB: - SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - default: - break; - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("MIB data access succeeded\n")); - return (Size); -} /* SkGeIocMib */ -#endif - - -/***************************************************************************** - * - * GetConfiguration - read configuration information - * - * Description: - * This function reads per-adapter configuration information from - * the options provided on the command line. - * - * Returns: - * none - */ -static void GetConfiguration( -SK_AC *pAC) /* pointer to the adapter context structure */ -{ -SK_I32 Port; /* preferred port */ -int LinkSpeed; /* Link speed */ -int AutoNeg; /* auto negotiation off (0) or on (1) */ -int DuplexCap; /* duplex capabilities (0=both, 1=full, 2=half */ -int MSMode; /* master / slave mode selection */ -SK_BOOL AutoSet; -SK_BOOL DupSet; -/* - * The two parameters AutoNeg. and DuplexCap. map to one configuration - * parameter. The mapping is described by this table: - * DuplexCap -> | both | full | half | - * AutoNeg | | | | - * ----------------------------------------------------------------- - * Off | illegal | Full | Half | - * ----------------------------------------------------------------- - * On | AutoBoth | AutoFull | AutoHalf | - * ----------------------------------------------------------------- - * Sense | AutoSense | AutoSense | AutoSense | - */ -int Capabilities[3][3] = - { { -1, SK_LMODE_FULL, SK_LMODE_HALF}, - {SK_LMODE_AUTOBOTH, SK_LMODE_AUTOFULL, SK_LMODE_AUTOHALF}, - {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} }; -#define DC_BOTH 0 -#define DC_FULL 1 -#define DC_HALF 2 -#define AN_OFF 0 -#define AN_ON 1 -#define AN_SENS 2 - - /* settings for port A */ - /* settings link speed */ - LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ - if (Speed_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Speed_A[pAC->Index],"")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_A[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } - else if (strcmp(Speed_A[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } - else if (strcmp(Speed_A[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } - else printk("%s: Illegal value for Speed_A\n", - pAC->dev[0]->name); - } - - /* Check speed parameter */ - /* Only copper type adapter and GE V2 cards */ - if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || - (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_A. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[0]->name); - LinkSpeed = SK_LSPEED_1000MBPS; - } - pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; - - /* Autonegotiation */ - AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */ - AutoSet = SK_FALSE; - if (AutoNeg_A != NULL && pAC->IndexIndex] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_A[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } - else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } - else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } - else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } - else printk("%s: Illegal value for AutoNeg_A\n", - pAC->dev[0]->name); - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_A != NULL && pAC->IndexIndex] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_A[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } - else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } - else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } - else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } - else printk("%s: Illegal value for DupCap_A\n", - pAC->dev[0]->name); - } - - /* check for illegal combinations */ - if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port A: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[0]->name); - } - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port A: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[0]->name); - - DuplexCap = DC_FULL; - } - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("%s, Port A: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[0]->name); - AutoNeg = AN_ON; - } - - /* set the desired mode */ - pAC->GIni.GP[0].PLinkModeConf = - Capabilities[AutoNeg][DuplexCap]; - - pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - if (FlowCtrl_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) { - } - else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_SYM_OR_REM; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_SYMMETRIC; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_LOC_SEND; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_NONE; - } - else printk("Illegal value for FlowCtrl_A\n"); - } - if (AutoNeg==AN_OFF && pAC->GIni.GP[0].PFlowCtrlMode!= - SK_FLOW_MODE_NONE) { - printk("%s, Port A: FlowControl" - " impossible without AutoNegotiation," - " disabled\n", pAC->dev[0]->name); - pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_NONE; - } - - MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ - if (Role_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Role_A[pAC->Index],"")==0) { - } - else if (strcmp(Role_A[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } - else if (strcmp(Role_A[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } - else if (strcmp(Role_A[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } - else printk("%s: Illegal value for Role_A\n", - pAC->dev[0]->name); - } - pAC->GIni.GP[0].PMSMode = MSMode; - - - /* settings for port B */ - /* settings link speed */ - LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ - if (Speed_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Speed_B[pAC->Index],"")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_B[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } - else if (strcmp(Speed_B[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } - else if (strcmp(Speed_B[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } - else printk("%s: Illegal value for Speed_B\n", - pAC->dev[1]->name); - } - - /* Check speed parameter */ - /* Only copper type adapter and GE V2 cards */ - if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || - (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_B. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[1]->name); - LinkSpeed = SK_LSPEED_1000MBPS; - } - pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; - - /* Auto negotiation */ - AutoNeg = AN_SENS; /* default: do auto Sense */ - AutoSet = SK_FALSE; - if (AutoNeg_B != NULL && pAC->IndexIndex] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_B[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } - else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } - else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } - else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } - else printk("Illegal value for AutoNeg_B\n"); - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_B != NULL && pAC->IndexIndex] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_B[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } - else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } - else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } - else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } - else printk("Illegal value for DupCap_B\n"); - } - - /* check for illegal combinations */ - if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port B: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[1]->name); - } - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port B: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[1]->name); - - DuplexCap = DC_FULL; - } - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("%s, Port B: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[1]->name); - AutoNeg = AN_ON; - } - - /* set the desired mode */ - pAC->GIni.GP[1].PLinkModeConf = - Capabilities[AutoNeg][DuplexCap]; - - pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - if (FlowCtrl_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) { - } - else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_SYM_OR_REM; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_SYMMETRIC; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_LOC_SEND; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_NONE; - } - else printk("Illegal value for FlowCtrl_B\n"); - } - if (AutoNeg==AN_OFF && pAC->GIni.GP[1].PFlowCtrlMode!= - SK_FLOW_MODE_NONE) { - printk("%s, Port B: FlowControl" - " impossible without AutoNegotiation," - " disabled\n", pAC->dev[1]->name); - pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_NONE; - } - - MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ - if (Role_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Role_B[pAC->Index],"")==0) { - } - else if (strcmp(Role_B[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } - else if (strcmp(Role_B[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } - else if (strcmp(Role_B[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } - else printk("%s: Illegal value for Role_B\n", - pAC->dev[1]->name); - } - pAC->GIni.GP[1].PMSMode = MSMode; - - - /* settings for both ports */ - pAC->ActivePort = 0; - if (PrefPort != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } - else if (strcmp(PrefPort[pAC->Index],"A") == 0) { - /* - * do not set ActivePort here, thus a port - * switch is issued after net up. - */ - Port = 0; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } - else if (strcmp(PrefPort[pAC->Index],"B") == 0) { - /* - * do not set ActivePort here, thus a port - * switch is issued after net up. - */ - Port = 1; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } - else printk("%s: Illegal value for PrefPort\n", - pAC->dev[0]->name); - } - - pAC->RlmtNets = 1; - - if (RlmtMode != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(RlmtMode[pAC->Index], "") == 0) { - pAC->RlmtMode = 0; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK | - SK_RLMT_CHECK_SEG; - } - else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && - (pAC->GIni.GIMacsFound == 2)) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - pAC->RlmtNets = 2; - } - else { - printk("%s: Illegal value for" - " RlmtMode, using default\n", pAC->dev[0]->name); - pAC->RlmtMode = 0; - } - } - else { - pAC->RlmtMode = 0; - } -} /* GetConfiguration */ - - -/***************************************************************************** - * - * ProductStr - return a adapter identification string from vpd - * - * Description: - * This function reads the product name string from the vpd area - * and puts it the field pAC->DeviceString. - * - * Returns: N/A - */ -static void ProductStr( -SK_AC *pAC /* pointer to adapter context */ -) -{ -int StrLen = 80; /* length of the string, defined in SK_AC */ -char Keyword[] = VPD_NAME; /* vpd productname identifier */ -int ReturnCode; /* return code from vpd_read */ -unsigned long Flags; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr, - &StrLen); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - if (ReturnCode != 0) { - /* there was an error reading the vpd data */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, - ("Error reading VPD data: %d\n", ReturnCode)); - pAC->DeviceStr[0] = '\0'; - } -} /* ProductStr */ - - -/****************************************************************************/ -/* functions for common modules *********************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf - * - * Description: - * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure - * is embedded into a socket buff data area. - * - * Context: - * runtime - * - * Returns: - * NULL or pointer to Mbuf. - */ -SK_MBUF *SkDrvAllocRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -unsigned BufferSize) /* size of the requested buffer */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ - - pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC); - if (pMsgBlock == NULL) { - return (NULL); - } - pRlmtMbuf = (SK_MBUF*) pMsgBlock->data; - skb_reserve(pMsgBlock, sizeof(SK_MBUF)); - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->pOs = pMsgBlock; - pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */ - pRlmtMbuf->Size = BufferSize; /* Data buffer size. */ - pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */ - return (pRlmtMbuf); - -} /* SkDrvAllocRlmtMbuf */ - - -/***************************************************************************** - * - * SkDrvFreeRlmtMbuf - free an RLMT mbuf - * - * Description: - * This routine frees one or more RLMT mbuf(s). - * - * Context: - * runtime - * - * Returns: - * Nothing - */ -void SkDrvFreeRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -SK_MBUF *pMbuf) /* size of the requested buffer */ -{ -SK_MBUF *pFreeMbuf; -SK_MBUF *pNextMbuf; - - pFreeMbuf = pMbuf; - do { - pNextMbuf = pFreeMbuf->pNext; - DEV_KFREE_SKB_ANY(pFreeMbuf->pOs); - pFreeMbuf = pNextMbuf; - } while ( pFreeMbuf != NULL ); -} /* SkDrvFreeRlmtMbuf */ - - -/***************************************************************************** - * - * SkOsGetTime - provide a time value - * - * Description: - * This routine provides a time value. The unit is 1/HZ (defined by Linux). - * It is not used for absolute time, but only for time differences. - * - * - * Returns: - * Time value - */ -SK_U64 SkOsGetTime(SK_AC *pAC) -{ -#if 0 - return jiffies; -#else - return get_timer(0); -#endif -} /* SkOsGetTime */ - - -/***************************************************************************** - * - * SkPciReadCfgDWord - read a 32 bit value from pci config space - * - * Description: - * This routine reads a 32 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 *pVal) /* pointer to store the read value */ -{ - pci_read_config_dword(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgDWord */ - - -/***************************************************************************** - * - * SkPciReadCfgWord - read a 16 bit value from pci config space - * - * Description: - * This routine reads a 16 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 *pVal) /* pointer to store the read value */ -{ - pci_read_config_word(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgWord */ - - -/***************************************************************************** - * - * SkPciReadCfgByte - read a 8 bit value from pci config space - * - * Description: - * This routine reads a 8 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 *pVal) /* pointer to store the read value */ -{ - pci_read_config_byte(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgByte */ - - -/***************************************************************************** - * - * SkPciWriteCfgDWord - write a 32 bit value to pci config space - * - * Description: - * This routine writes a 32 bit value to the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 Val) /* pointer to store the read value */ -{ - pci_write_config_dword(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgDWord */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 16 bit value to pci config space - * - * Description: - * This routine writes a 16 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 Val) /* pointer to store the read value */ -{ - pci_write_config_word(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgWord */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 8 bit value to pci config space - * - * Description: - * This routine writes a 8 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 Val) /* pointer to store the read value */ -{ - pci_write_config_byte(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgByte */ - - -/***************************************************************************** - * - * SkDrvEvent - handle driver events - * - * Description: - * This function handles events from all modules directed to the driver - * - * Context: - * Is called under protection of slow path lock. - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -int SkDrvEvent( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* io-context */ -SK_U32 Event, /* event-id */ -SK_EVPARA Param) /* event-parameter */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ -struct sk_buff *pMsg; /* pointer to a message block */ -int FromPort; /* the port from which we switch away */ -int ToPort; /* the port we switch to */ -SK_EVPARA NewPara; /* parameter for further events */ -#if 0 -int Stat; -#endif -unsigned long Flags; -SK_BOOL DualNet; - - switch (Event) { - case SK_DRV_ADAP_FAIL: - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("ADAPTER FAIL EVENT\n")); - printk("%s: Adapter failed.\n", pAC->dev[0]->name); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* cgoos */ - break; - case SK_DRV_PORT_FAIL: - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT FAIL EVENT, Port: %d\n", FromPort)); - if (FromPort == 0) { - printk("%s: Port A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: Port B failed.\n", pAC->dev[1]->name); - } - /* cgoos */ - break; - case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */ - /* action list 4 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT RESET EVENT, Port: %d ", FromPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); -#if 0 - pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; -#endif - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* clear rx ring from received frames */ - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* tschilling: Handling of return value inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort)) { - if (FromPort == 0) { - printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); - } - } - SkAddrMcUpdate(pAC,IoC, FromPort); - PortReInitBmu(pAC, FromPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_NET_UP: /* SK_U32 PortIdx */ - /* action list 5 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET UP EVENT, Port: %d ", Param.Para32[0])); -#ifdef SK98_INFO - printk("%s: network connection up using" - " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); - - /* tschilling: Values changed according to LinkSpeedUsed. */ - Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; - if (Stat == SK_LSPEED_STAT_10MBPS) { - printk(" speed: 10\n"); - } else if (Stat == SK_LSPEED_STAT_100MBPS) { - printk(" speed: 100\n"); - } else if (Stat == SK_LSPEED_STAT_1000MBPS) { - printk(" speed: 1000\n"); - } else { - printk(" speed: unknown\n"); - } - - Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_AUTOFULL) { - printk(" autonegotiation: yes\n"); - } - else { - printk(" autonegotiation: no\n"); - } - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_HALF) { - printk(" duplex mode: half\n"); - } - else { - printk(" duplex mode: full\n"); - } - Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; - if (Stat == SK_FLOW_STAT_REM_SEND ) { - printk(" flowctrl: remote send\n"); - } - else if (Stat == SK_FLOW_STAT_LOC_SEND ){ - printk(" flowctrl: local send\n"); - } - else if (Stat == SK_FLOW_STAT_SYMMETRIC ){ - printk(" flowctrl: symmetric\n"); - } - else { - printk(" flowctrl: none\n"); - } - - /* tschilling: Check against CopperType now. */ - if ((pAC->GIni.GICopperType == SK_TRUE) && - (pAC->GIni.GP[FromPort].PLinkSpeedUsed == - SK_LSPEED_STAT_1000MBPS)) { - Stat = pAC->GIni.GP[FromPort].PMSStatus; - if (Stat == SK_MS_STAT_MASTER ) { - printk(" role: master\n"); - } - else if (Stat == SK_MS_STAT_SLAVE ) { - printk(" role: slave\n"); - } - else { - printk(" role: ???\n"); - } - } - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) - printk(" scatter-gather: enabled\n"); - else - printk(" scatter-gather: disabled\n"); - -#else - printk(" scatter-gather: disabled\n"); -#endif -#endif /* SK98_INFO */ - - if ((Param.Para32[0] != pAC->ActivePort) && - (pAC->RlmtNets == 1)) { - NewPara.Para32[0] = pAC->ActivePort; - NewPara.Para32[1] = Param.Para32[0]; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, - NewPara); - } - - /* Inform the world that link protocol is up. */ -#if 0 - pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING; -#endif - - break; - case SK_DRV_NET_DOWN: /* SK_U32 Reason */ - /* action list 7 */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET DOWN EVENT ")); -#ifdef SK98_INFO - printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name); -#endif -#if 0 - pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; -#endif - break; - case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH HARD ")); - case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - /* action list 6 */ - printk("%s: switching to port %c\n", pAC->dev[0]->name, - 'A'+Param.Para32[1]); - case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - FromPort = Param.Para32[0]; - ToPort = Param.Para32[1]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ", - FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - NewPara.Para64 = ToPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); - SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ - ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - pAC->ActivePort = ToPort; -#if 0 - SetQueueSizes(pAC); -#else - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - printk("SkGeInitAssignRamToQueues failed.\n"); - break; - } -#endif - /* tschilling: Handling of return values inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort) || - SkGeInitPort(pAC, IoC, ToPort)) { - printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); - } - if (Event == SK_DRV_SWITCH_SOFT) { - SkMacRxTxEnable(pAC, IoC, FromPort); - } - SkMacRxTxEnable(pAC, IoC, ToPort); - SkAddrSwap(pAC, IoC, FromPort, ToPort); - SkAddrMcUpdate(pAC, IoC, FromPort); - SkAddrMcUpdate(pAC, IoC, ToPort); - PortReInitBmu(pAC, FromPort); - PortReInitBmu(pAC, ToPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - ClearAndStartRx(pAC, ToPort); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("RLS ")); - pRlmtMbuf = (SK_MBUF*) Param.pParaPtr; - pMsg = (struct sk_buff*) pRlmtMbuf->pOs; - skb_put(pMsg, pRlmtMbuf->Length); - if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], - pMsg) < 0) - - DEV_KFREE_SKB_ANY(pMsg); - break; - default: - break; - } - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("END EVENT ")); - - return (0); -} /* SkDrvEvent */ - - -/***************************************************************************** - * - * SkErrorLog - log errors - * - * Description: - * This function logs errors to the system buffer and to the console - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -void SkErrorLog( -SK_AC *pAC, -int ErrClass, -int ErrNum, -char *pErrorMsg) -{ -char ClassStr[80]; - - switch (ErrClass) { - case SK_ERRCL_OTHER: - strcpy(ClassStr, "Other error"); - break; - case SK_ERRCL_CONFIG: - strcpy(ClassStr, "Configuration error"); - break; - case SK_ERRCL_INIT: - strcpy(ClassStr, "Initialization error"); - break; - case SK_ERRCL_NORES: - strcpy(ClassStr, "Out of resources error"); - break; - case SK_ERRCL_SW: - strcpy(ClassStr, "internal Software error"); - break; - case SK_ERRCL_HW: - strcpy(ClassStr, "Hardware failure"); - break; - case SK_ERRCL_COMM: - strcpy(ClassStr, "Communication error"); - break; - } - printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n" - " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name, - ClassStr, ErrNum, pErrorMsg); - -} /* SkErrorLog */ - -#ifdef DEBUG -/****************************************************************************/ -/* "debug only" section *****************************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * DumpMsg - print a frame - * - * Description: - * This function prints frames to the system logfile/to the console. - * - * Returns: N/A - * - */ -static void DumpMsg(struct sk_buff *skb, char *str) -{ - int msglen; - - if (skb == NULL) { - printk("DumpMsg(): NULL-Message\n"); - return; - } - - if (skb->data == NULL) { - printk("DumpMsg(): Message empty\n"); - return; - } - - msglen = skb->len; - if (msglen > 64) - msglen = 64; - - printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len); - - DumpData((char *)skb->data, msglen); - - printk("------- End of message ---------\n"); -} /* DumpMsg */ - - -/***************************************************************************** - * - * DumpData - print a data area - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpData(char *p, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - for (i=0; i < size; ) { - if (*p >= '0' && *p <='z') - asc_buffer[addr] = *p; - else - asc_buffer[addr] = '.'; - addr++; - asc_buffer[addr] = 0; - hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4]; - haddr++; - hex_buffer[haddr] = HEXCHAR[*p & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%16 == 0) { - printk("%s %s\n", hex_buffer, asc_buffer); - addr = 0; - haddr = 0; - } - } -} /* DumpData */ - - -/***************************************************************************** - * - * DumpLong - print a data area as long values - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpLong(char *pc, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; -long *p; -int l; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - p = (long*) pc; - for (i=0; i < size; ) { - l = (long) *p; - hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[l & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%8 == 0) { - printk("%4x %s\n", (i-8)*4, hex_buffer); - haddr = 0; - } - } - printk("------------------------\n"); -} /* DumpLong */ - -#endif - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skgehwt.c b/drivers/sk98lin/skgehwt.c deleted file mode 100644 index f8681a8b0f..0000000000 --- a/drivers/sk98lin/skgehwt.c +++ /dev/null @@ -1,220 +0,0 @@ -/****************************************************************************** - * - * Name: skgehwt.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.13 $ - * Date: $Date: 1999/11/22 13:31:12 $ - * Purpose: Hardware Timer. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgehwt.c,v $ - * Revision 1.13 1999/11/22 13:31:12 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/10/15 15:11:34 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.11 1998/10/08 15:27:51 gklug - * chg: correction factor is host clock dependent - * - * Revision 1.10 1998/09/15 14:18:31 cgoos - * Changed more BOOLEANs to SK_xxx - * - * Revision 1.9 1998/09/15 14:16:06 cgoos - * Changed line 107: FALSE to SK_FALSE - * - * Revision 1.8 1998/08/24 13:04:44 gklug - * fix: typo - * - * Revision 1.7 1998/08/19 09:50:49 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.6 1998/08/17 09:59:02 gklug - * fix: typos - * - * Revision 1.5 1998/08/14 07:09:10 gklug - * fix: chg pAc -> pAC - * - * Revision 1.4 1998/08/10 14:14:52 gklug - * rmv: unneccessary SK_ADDR macro - * - * Revision 1.3 1998/08/07 12:53:44 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:19:29 gklug - * adapt functions to the C coding conventions - * rmv unneccessary functions. - * - * Revision 1.1 1998/08/05 11:28:36 gklug - * first version: adapted from SMT/FDDI - * - * - * - * - ******************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -/* - Event queue and dispatcher -*/ -static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skgehwt.c,v 1.13 1999/11/22 13:31:12 cgoos Exp $" ; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Hardware Timer function queue management. - - General Description: - - */ -intro() -{} -#endif - -/* - * Prototypes of local functions. - */ -#define SK_HWT_MAX (65000) - -/* correction factor */ -#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100) - -/* - * Initialize hardware timer. - * - * Must be called during init level 1. - */ -void SkHwtInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - pAC->Hwt.TStart = 0 ; - pAC->Hwt.TStop = 0 ; - pAC->Hwt.TActive = SK_FALSE ; - - SkHwtStop(pAC,Ioc) ; -} - -/* - * - * Start hardware timer (clock ticks are 16us). - * - */ -void SkHwtStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_U32 Time) /* Time in units of 16us to load the timer with. */ -{ - SK_U32 Cnt ; - - if (Time > SK_HWT_MAX) - Time = SK_HWT_MAX ; - - pAC->Hwt.TStart = Time ; - pAC->Hwt.TStop = 0L ; - - Cnt = Time ; - - /* - * if time < 16 us - * time = 16 us - */ - if (!Cnt) { - Cnt++ ; - } - - SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_START) ; /* Start timer. */ - - pAC->Hwt.TActive = SK_TRUE ; -} - -/* - * Stop hardware timer. - * and clear the timer IRQ - */ -void SkHwtStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_OUT16(Ioc, B2_TI_CRTL, TIM_STOP) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_CLR_IRQ) ; - - pAC->Hwt.TActive = SK_FALSE ; -} - - -/* - * Stop hardware timer and read time elapsed since last start. - * - * returns - * The elapsed time since last start in units of 16us. - * - */ -SK_U32 SkHwtRead( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_U32 TRead ; - SK_U32 IStatus ; - - if (pAC->Hwt.TActive) { - SkHwtStop(pAC,Ioc) ; - - SK_IN32(Ioc, B2_TI_VAL, &TRead); - TRead /= SK_HWT_FAC; - - SK_IN32(Ioc, B0_ISRC, &IStatus); - - /* Check if timer expired (or wraparound). */ - if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { - SkHwtStop(pAC,Ioc) ; - pAC->Hwt.TStop = pAC->Hwt.TStart ; - } else { - pAC->Hwt.TStop = pAC->Hwt.TStart - TRead ; - } - } - return (pAC->Hwt.TStop) ; -} - -/* - * interrupt source= timer - */ -void SkHwtIsr( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SkHwtStop(pAC,Ioc); - pAC->Hwt.TStop = pAC->Hwt.TStart; - SkTimerDone(pAC,Ioc) ; -} - -#endif /* CONFIG_SK98 */ - -/* End of file */ diff --git a/drivers/sk98lin/skgeinit.c b/drivers/sk98lin/skgeinit.c deleted file mode 100644 index a18dc0a488..0000000000 --- a/drivers/sk98lin/skgeinit.c +++ /dev/null @@ -1,2372 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.85 $ - * Date: $Date: 2003/02/05 15:30:33 $ - * Purpose: Contains functions to initialize the GE HW - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgeinit.c,v $ - * Revision 1.85 2003/02/05 15:30:33 rschmidt - * Corrected setting of GIHstClkFact (Host Clock Factor) and - * GIPollTimerVal (Descr. Poll Timer Init Value) for YUKON. - * Editorial changes. - * - * Revision 1.84 2003/01/28 09:57:25 rschmidt - * Added detection of YUKON-Lite Rev. A0 (stored in GIYukonLite). - * Disabled Rx GMAC FIFO Flush for YUKON-Lite Rev. A0. - * Added support for CLK_RUN (YUKON-Lite). - * Added additional check of PME from D3cold for setting GIVauxAvail. - * Editorial changes. - * - * Revision 1.83 2002/12/17 16:15:41 rschmidt - * Added default setting of PhyType (Copper) for YUKON. - * Added define around check for HW self test results. - * Editorial changes. - * - * Revision 1.82 2002/12/05 13:40:21 rschmidt - * Added setting of Rx GMAC FIFO Flush Mask register. - * Corrected PhyType with new define SK_PHY_MARV_FIBER when - * YUKON Fiber board was found. - * Editorial changes. - * - * Revision 1.81 2002/11/15 12:48:35 rschmidt - * Replaced message SKERR_HWI_E018 with SKERR_HWI_E024 for Rx queue error - * in SkGeStopPort(). - * Added init for pAC->GIni.GIGenesis with SK_FALSE in YUKON-branch. - * Editorial changes. - * - * Revision 1.80 2002/11/12 17:28:30 rschmidt - * Initialized GIPciSlot64 and GIPciClock66 in SkGeInit1(). - * Reduced PCI FIFO watermarks for 32bit/33MHz bus in SkGeInitBmu(). - * Editorial changes. - * - * Revision 1.79 2002/10/21 09:31:02 mkarl - * Changed SkGeInitAssignRamToQueues(), removed call to - * SkGeInitAssignRamToQueues in SkGeInit1 and fixed compiler warning in - * SkGeInit1. - * - * Revision 1.78 2002/10/16 15:55:07 mkarl - * Fixed a bug in SkGeInitAssignRamToQueues. - * - * Revision 1.77 2002/10/14 15:07:22 rschmidt - * Corrected timeout handling for Rx queue in SkGeStopPort() (#10748) - * Editorial changes. - * - * Revision 1.76 2002/10/11 09:24:38 mkarl - * Added check for HW self test results. - * - * Revision 1.75 2002/10/09 16:56:44 mkarl - * Now call SkGeInitAssignRamToQueues() in Init Level 1 in order to assign - * the adapter memory to the queues. This default assignment is not suitable - * for dual net mode. - * - * Revision 1.74 2002/09/12 08:45:06 rwahl - * Set defaults for PMSCap, PLinkSpeed & PLinkSpeedCap dependent on PHY. - * - * Revision 1.73 2002/08/16 15:19:45 rschmidt - * Corrected check for Tx queues in SkGeCheckQSize(). - * Added init for new entry GIGenesis and GICopperType - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. - * - * Revision 1.72 2002/08/12 13:38:55 rschmidt - * Added check if VAUX is available (stored in GIVauxAvail) - * Initialized PLinkSpeedCap in Port struct with SK_LSPEED_CAP_1000MBPS - * Editorial changes. - * - * Revision 1.71 2002/08/08 16:32:58 rschmidt - * Added check for Tx queues in SkGeCheckQSize(). - * Added start of Time Stamp Timer (YUKON) in SkGeInit2(). - * Editorial changes. - * - * Revision 1.70 2002/07/23 16:04:26 rschmidt - * Added init for GIWolOffs (HW-Bug in YUKON 1st rev.) - * Minor changes - * - * Revision 1.69 2002/07/17 17:07:08 rwahl - * - SkGeInit1(): fixed PHY type debug output; corrected init of GIFunc - * table & GIMacType. - * - Editorial changes. - * - * Revision 1.68 2002/07/15 18:38:31 rwahl - * Added initialization for MAC type dependent function table. - * - * Revision 1.67 2002/07/15 15:45:39 rschmidt - * Added Tx Store & Forward for YUKON (GMAC Tx FIFO is only 1 kB) - * Replaced SK_PHY_MARV by SK_PHY_MARV_COPPER - * Editorial changes - * - * Revision 1.66 2002/06/10 09:35:08 rschmidt - * Replaced C++ comments (//) - * Editorial changes - * - * Revision 1.65 2002/06/05 08:33:37 rschmidt - * Changed GIRamSize and Reset sequence for YUKON. - * SkMacInit() replaced by SkXmInitMac() resp. SkGmInitMac() - * - * Revision 1.64 2002/04/25 13:03:20 rschmidt - * Changes for handling YUKON. - * Removed reference to xmac_ii.h (not necessary). - * Moved all defines into header file. - * Replaced all SkXm...() functions with SkMac...() to handle also - * YUKON's GMAC. - * Added handling for GMAC FIFO in SkGeInitMacFifo(), SkGeStopPort(). - * Removed 'goto'-directive from SkGeCfgSync(), SkGeCheckQSize(). - * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), - * SkMacFlushTxFifo(). - * Optimized timeout handling in SkGeStopPort(). - * Initialized PLinkSpeed in Port struct with SK_LSPEED_AUTO. - * Release of GMAC Link Control reset in SkGeInit1(). - * Initialized GIChipId and GIChipRev in GE Init structure. - * Added GIRamSize and PhyType values for YUKON. - * Removed use of PRxCmd to setup XMAC. - * Moved setting of XM_RX_DIS_CEXT to SkXmInitMac(). - * Use of SkGeXmitLED() only for GENESIS. - * Changes for V-CPU support. - * Editorial changes. - * - * Revision 1.63 2001/04/05 11:02:09 rassmann - * Stop Port check of the STOP bit did not take 2/18 sec as wanted. - * - * Revision 1.62 2001/02/07 07:54:21 rassmann - * Corrected copyright. - * - * Revision 1.61 2001/01/31 15:31:40 gklug - * fix: problem with autosensing an SR8800 switch - * - * Revision 1.60 2000/10/18 12:22:21 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.59 2000/10/10 11:22:06 gklug - * add: in manual half duplex mode ignore carrier extension errors - * - * Revision 1.58 2000/10/02 14:10:27 rassmann - * Reading BCOM PHY after releasing reset until it returns a valid value. - * - * Revision 1.57 2000/08/03 14:55:28 rassmann - * Waiting for I2C to be ready before de-initializing adapter - * (prevents sensors from hanging up). - * - * Revision 1.56 2000/07/27 12:16:48 gklug - * fix: Stop Port check of the STOP bit does now take 2/18 sec as wanted - * - * Revision 1.55 1999/11/22 13:32:26 cgoos - * Changed license header to GPL. - * - * Revision 1.54 1999/10/26 07:32:54 malthoff - * Initialize PHWLinkUp with SK_FALSE. Required for Diagnostics. - * - * Revision 1.53 1999/08/12 19:13:50 malthoff - * Fix for 1000BT. Do not owerwrite XM_MMU_CMD when - * disabling receiver and transmitter. Other bits - * may be lost. - * - * Revision 1.52 1999/07/01 09:29:54 gklug - * fix: DoInitRamQueue needs pAC - * - * Revision 1.51 1999/07/01 08:42:21 gklug - * chg: use Store & forward for RAM buffer when Jumbos are used - * - * Revision 1.50 1999/05/27 13:19:38 cgoos - * Added Tx PCI watermark initialization. - * Removed Tx RAM queue Store & Forward setting. - * - * Revision 1.49 1999/05/20 14:32:45 malthoff - * SkGeLinkLED() is completly removed now. - * - * Revision 1.48 1999/05/19 07:28:24 cgoos - * SkGeLinkLED no more available for drivers. - * Changes for 1000Base-T. - * - * Revision 1.47 1999/04/08 13:57:45 gklug - * add: Init of new port struct fiels PLinkResCt - * chg: StopPort Timer check - * - * Revision 1.46 1999/03/25 07:42:15 malthoff - * SkGeStopPort(): Add workaround for cache incoherency. - * Create error log entry, disable port, and - * exit loop if it does not terminate. - * Add XM_RX_LENERR_OK to the default value for the - * XMAC receive command register. - * - * Revision 1.45 1999/03/12 16:24:47 malthoff - * Remove PPollRxD and PPollTxD. - * Add check for GIPollTimerVal. - * - * Revision 1.44 1999/03/12 13:40:23 malthoff - * Fix: SkGeXmitLED(), SK_LED_TST mode does not work. - * Add: Jumbo frame support. - * Chg: Resolution of parameter IntTime in SkGeCfgSync(). - * - * Revision 1.43 1999/02/09 10:29:46 malthoff - * Bugfix: The previous modification again also for the second location. - * - * Revision 1.42 1999/02/09 09:35:16 malthoff - * Bugfix: The bits '66 MHz Capable' and 'NEWCAP are reset while - * clearing the error bits in the PCI status register. - * - * Revision 1.41 1999/01/18 13:07:02 malthoff - * Bugfix: Do not use CFG cycles after during Init- or Runtime, because - * they may not be available after Boottime. - * - * Revision 1.40 1999/01/11 12:40:49 malthoff - * Bug fix: PCI_STATUS: clearing error bits sets the UDF bit. - * - * Revision 1.39 1998/12/11 15:17:33 gklug - * chg: Init LipaAutoNeg with Unknown - * - * Revision 1.38 1998/12/10 11:02:57 malthoff - * Disable Error Log Message when calling SkGeInit(level 2) - * more than once. - * - * Revision 1.37 1998/12/07 12:18:25 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.36 1998/12/07 07:10:39 gklug - * fix: init values of LinkBroken/ Capabilities for management - * - * Revision 1.35 1998/12/02 10:56:20 gklug - * fix: do NOT init LoinkSync Counter. - * - * Revision 1.34 1998/12/01 10:53:21 gklug - * add: init of additional Counters for workaround - * - * Revision 1.33 1998/12/01 10:00:49 gklug - * add: init PIsave var in Port struct - * - * Revision 1.32 1998/11/26 14:50:40 gklug - * chg: Default is autosensing with AUTOFULL mode - * - * Revision 1.31 1998/11/25 15:36:16 gklug - * fix: do NOT stop LED Timer when port should be stopped - * - * Revision 1.30 1998/11/24 13:15:28 gklug - * add: Init PCkeckPar struct member - * - * Revision 1.29 1998/11/18 13:19:27 malthoff - * Disable packet arbiter timeouts on receive side. - * Use maximum timeout value for packet arbiter - * transmit timeouts. - * Add TestStopBit() function to handle stop RX/TX - * problem with active descriptor poll timers. - * Bug Fix: Descriptor Poll Timer not started, because - * GIPollTimerVal was initialized with 0. - * - * Revision 1.28 1998/11/13 14:24:26 malthoff - * Bug Fix: SkGeStopPort() may hang if a Packet Arbiter Timout - * is pending or occurs while waiting for TX_STOP and RX_STOP. - * The PA timeout is cleared now while waiting for TX- or RX_STOP. - * - * Revision 1.27 1998/11/02 11:04:36 malthoff - * fix the last fix - * - * Revision 1.26 1998/11/02 10:37:03 malthoff - * Fix: SkGePollTxD() enables always the synchronounous poll timer. - * - * Revision 1.25 1998/10/28 07:12:43 cgoos - * Fixed "LED_STOP" in SkGeLnkSyncCnt, "== SK_INIT_IO" in SkGeInit. - * Removed: Reset of RAM Interface in SkGeStopPort. - * - * Revision 1.24 1998/10/27 08:13:12 malthoff - * Remove temporary code. - * - * Revision 1.23 1998/10/26 07:45:03 malthoff - * Add Address Calculation Workaround: If the EPROM byte - * Id is 3, the address offset is 512 kB. - * Initialize default values for PLinkMode and PFlowCtrlMode. - * - * Revision 1.22 1998/10/22 09:46:47 gklug - * fix SysKonnectFileId typo - * - * Revision 1.21 1998/10/20 12:11:56 malthoff - * Don't dendy the Queue config if the size of the unused - * Rx qeueu is zero. - * - * Revision 1.20 1998/10/19 07:27:58 malthoff - * SkGeInitRamIface() is public to be called by diagnostics. - * - * Revision 1.19 1998/10/16 13:33:45 malthoff - * Fix: enabling descriptor polling is not allowed until - * the descriptor addresses are set. Descriptor polling - * must be handled by the driver. - * - * Revision 1.18 1998/10/16 10:58:27 malthoff - * Remove temp. code for Diag prototype. - * Remove lint warning for dummy reads. - * Call SkGeLoadLnkSyncCnt() during SkGeInitPort(). - * - * Revision 1.17 1998/10/14 09:16:06 malthoff - * Change parameter LimCount and programming of - * the limit counter in SkGeCfgSync(). - * - * Revision 1.16 1998/10/13 09:21:16 malthoff - * Don't set XM_RX_SELF_RX in RxCmd Reg, because it's - * like a Loopback Mode in half duplex. - * - * Revision 1.15 1998/10/09 06:47:40 malthoff - * SkGeInitMacArb(): set recovery counters init value - * to zero although this counters are not uesd. - * Bug fix in Rx Upper/Lower Pause Threshold calculation. - * Add XM_RX_SELF_RX to RxCmd. - * - * Revision 1.14 1998/10/06 15:15:53 malthoff - * Make sure no pending IRQ is cleared in SkGeLoadLnkSyncCnt(). - * - * Revision 1.13 1998/10/06 14:09:36 malthoff - * Add SkGeLoadLnkSyncCnt(). Modify - * the 'port stopped' condition according - * to the current problem report. - * - * Revision 1.12 1998/10/05 08:17:21 malthoff - * Add functions: SkGePollRxD(), SkGePollTxD(), - * DoCalcAddr(), SkGeCheckQSize(), - * DoInitRamQueue(), and SkGeCfgSync(). - * Add coding for SkGeInitMacArb(), SkGeInitPktArb(), - * SkGeInitMacFifo(), SkGeInitRamBufs(), - * SkGeInitRamIface(), and SkGeInitBmu(). - * - * Revision 1.11 1998/09/29 08:26:29 malthoff - * bug fix: SkGeInit0() 'i' should be increment. - * - * Revision 1.10 1998/09/28 13:19:01 malthoff - * Coding time: Save the done work. - * Modify SkGeLinkLED(), add SkGeXmitLED(), - * define SkGeCheckQSize(), SkGeInitMacArb(), - * SkGeInitPktArb(), SkGeInitMacFifo(), - * SkGeInitRamBufs(), SkGeInitRamIface(), - * and SkGeInitBmu(). Do coding for SkGeStopPort(), - * SkGeInit1(), SkGeInit2(), and SkGeInit3(). - * Do coding for SkGeDinit() and SkGeInitPort(). - * - * Revision 1.9 1998/09/16 14:29:05 malthoff - * Some minor changes. - * - * Revision 1.8 1998/09/11 05:29:14 gklug - * add: init state of a port - * - * Revision 1.7 1998/09/04 09:26:25 malthoff - * Short temporary modification. - * - * Revision 1.6 1998/09/04 08:27:59 malthoff - * Remark the do-while in StopPort() because it never ends - * without a GE adapter. - * - * Revision 1.5 1998/09/03 14:05:45 malthoff - * Change comment for SkGeInitPort(). Do not - * repair the queue sizes if invalid. - * - * Revision 1.4 1998/09/03 10:03:19 malthoff - * Implement the new interface according to the - * reviewed interface specification. - * - * Revision 1.3 1998/08/19 09:11:25 gklug - * fix: struct are removed from c-source (see CCC) - * - * Revision 1.2 1998/07/28 12:33:58 malthoff - * Add 'IoC' parameter in function declaration and SK IO macros. - * - * Revision 1.1 1998/07/23 09:48:57 malthoff - * Creation. First dummy 'C' file. - * SkGeInit(Level 0) is card_start for GE. - * SkGeDeInit() is card_stop for GE. - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* global variables ***********************************************************/ - -/* local variables ************************************************************/ - -static const char SysKonnectFileId[] = - "@(#)$Id: skgeinit.c,v 1.85 2003/02/05 15:30:33 rschmidt Exp $ (C) SK "; - -struct s_QOffTab { - int RxQOff; /* Receive Queue Address Offset */ - int XsQOff; /* Sync Tx Queue Address Offset */ - int XaQOff; /* Async Tx Queue Address Offset */ -}; -static struct s_QOffTab QOffTab[] = { - {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2} -}; - - -/****************************************************************************** - * - * SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring - * - * Description: - * Enable or disable the descriptor polling of the receive descriptor - * ring (RxD) for port 'Port'. - * The new configuration is *not* saved over any SkGeStopPort() and - * SkGeInitPort() calls. - * - * Returns: - * nothing - */ -void SkGePollRxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ? - CSR_ENA_POL : CSR_DIS_POL); -} /* SkGePollRxD */ - - -/****************************************************************************** - * - * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings - * - * Description: - * Enable or disable the descriptor polling of the transmit descriptor - * ring(s) (TxD) for port 'Port'. - * The new configuration is *not* saved over any SkGeStopPort() and - * SkGeInitPort() calls. - * - * Returns: - * nothing - */ -void SkGePollTxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - DWord = (PollTxD) ? CSR_ENA_POL : CSR_DIS_POL; - - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord); - } -} /* SkGePollTxD */ - - -/****************************************************************************** - * - * SkGeYellowLED() - Switch the yellow LED on or off. - * - * Description: - * Switch the yellow LED on or off. - * - * Note: - * This function may be called any time after SkGeInit(Level 1). - * - * Returns: - * nothing - */ -void SkGeYellowLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int State) /* yellow LED state, 0 = OFF, 0 != ON */ -{ - if (State == 0) { - /* Switch yellow LED OFF */ - SK_OUT8(IoC, B0_LED, LED_STAT_OFF); - } - else { - /* Switch yellow LED ON */ - SK_OUT8(IoC, B0_LED, LED_STAT_ON); - } -} /* SkGeYellowLED */ - - -/****************************************************************************** - * - * SkGeXmitLED() - Modify the Operational Mode of a transmission LED. - * - * Description: - * The Rx or Tx LED which is specified by 'Led' will be - * enabled, disabled or switched on in test mode. - * - * Note: - * 'Led' must contain the address offset of the LEDs INI register. - * - * Usage: - * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - * - * Returns: - * nothing - */ -void SkGeXmitLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Led, /* offset to the LED Init Value register */ -int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ -{ - SK_U32 LedIni; - - switch (Mode) { - case SK_LED_ENA: - LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_TST: - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON); - SK_OUT32(IoC, Led + XMIT_LED_CNT, 100); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_DIS: - default: - /* - * Do NOT stop the LED Timer here. The LED might be - * in on state. But it needs to go off. - */ - SK_OUT32(IoC, Led + XMIT_LED_CNT, 0); - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF); - break; - } - - /* - * 1000BT: The Transmit LED is driven by the PHY. - * But the default LED configuration is used for - * Level One and Broadcom PHYs. - * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.) - * (In this case it has to be added here. But we will see. XXX) - */ -} /* SkGeXmitLED */ - - -/****************************************************************************** - * - * DoCalcAddr() - Calculates the start and the end address of a queue. - * - * Description: - * This function calculates the start and the end address of a queue. - * Afterwards the 'StartVal' is incremented to the next start position. - * If the port is already initialized the calculated values - * will be checked against the configured values and an - * error will be returned, if they are not equal. - * If the port is not initialized the values will be written to - * *StartAdr and *EndAddr. - * - * Returns: - * 0: success - * 1: configuration error - */ -static int DoCalcAddr( -SK_AC *pAC, /* adapter context */ -SK_GEPORT *pPrt, /* port index */ -int QuSize, /* size of the queue to configure in kB */ -SK_U32 *StartVal, /* start value for address calculation */ -SK_U32 *QuStartAddr, /* start addr to calculate */ -SK_U32 *QuEndAddr) /* end address to calculate */ -{ - SK_U32 EndVal; - SK_U32 NextStart; - int Rtv; - - Rtv = 0; - if (QuSize == 0) { - EndVal = *StartVal; - NextStart = EndVal; - } - else { - EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1; - NextStart = EndVal + 1; - } - - if (pPrt->PState >= SK_PRT_INIT) { - if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) { - Rtv = 1; - } - } - else { - *QuStartAddr = *StartVal; - *QuEndAddr = EndVal; - } - - *StartVal = NextStart; - return(Rtv); -} /* DoCalcAddr */ - -/****************************************************************************** - * - * SkGeInitAssignRamToQueues() - allocate default queue sizes - * - * Description: - * This function assigns the memory to the different queues and ports. - * When DualNet is set to SK_TRUE all ports get the same amount of memory. - * Otherwise the first port gets most of the memory and all the - * other ports just the required minimum. - * This function can only be called when pAC->GIni.GIRamSize and - * pAC->GIni.GIMacsFound have been initialized, usually this happens - * at init level 1 - * - * Returns: - * 0 - ok - * 1 - invalid input values - * 2 - not enough memory - */ - -int SkGeInitAssignRamToQueues( -SK_AC *pAC, /* Adapter context */ -int ActivePort, /* Active Port in RLMT mode */ -SK_BOOL DualNet) /* adapter context */ -{ - int i; - int UsedKilobytes; /* memory already assigned */ - int ActivePortKilobytes; /* memory available for active port */ - SK_GEPORT *pGePort; - - UsedKilobytes = 0; - - if (ActivePort >= pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n", - ActivePort)); - return(1); - } - if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) + - ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n", - pAC->GIni.GIRamSize)); - return(2); - } - - - if (DualNet) { - /* every port gets the same amount of memory */ - ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pGePort = &pAC->GIni.GP[i]; - - /* take away the minimum memory for active queues */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - - /* receive queue gets the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB(( - ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100)) - + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes + - SK_MIN_TXQ_SIZE); - } - } - else { - /* Rlmt Mode or single link adapter */ - - /* Set standby queue size defaults for all standby ports */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - if (i != ActivePort) { - pGePort = &pAC->GIni.GP[i]; - - pGePort->PRxQSize = SK_MIN_RXQ_SIZE; - pGePort->PXAQSize = SK_MIN_TXQ_SIZE; - pGePort->PXSQSize = 0; - - /* Count used RAM */ - UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize; - } - } - /* what's left? */ - ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes; - - /* assign it to the active port */ - /* first take away the minimum memory */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - pGePort = &pAC->GIni.GP[ActivePort]; - - /* receive queue get's the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes * - (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) + - SK_MIN_TXQ_SIZE; - } -#ifdef VCPU - VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n", - pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize); -#endif /* VCPU */ - - return(0); -} /* SkGeInitAssignRamToQueues */ - -/****************************************************************************** - * - * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration - * - * Description: - * This function verifies the Queue Size Configuration specified - * in the variables PRxQSize, PXSQSize, and PXAQSize of all - * used ports. - * This requirements must be fullfilled to have a valid configuration: - * - The size of all queues must not exceed GIRamSize. - * - The queue sizes must be specified in units of 8 kB. - * - The size of Rx queues of available ports must not be - * smaller than 16 kB. - * - The size of at least one Tx queue (synch. or asynch.) - * of available ports must not be smaller than 16 kB - * when Jumbo Frames are used. - * - The RAM start and end addresses must not be changed - * for ports which are already initialized. - * Furthermore SkGeCheckQSize() defines the Start and End Addresses - * of all ports and stores them into the HWAC port structure. - * - * Returns: - * 0: Queue Size Configuration valid - * 1: Queue Size Configuration invalid - */ -static int SkGeCheckQSize( -SK_AC *pAC, /* adapter context */ -int Port) /* port index */ -{ - SK_GEPORT *pPrt; - int UsedMem; /* total memory used (max. found ports) */ - int i; - int Rtv; - int Rtv2; - SK_U32 StartAddr; - - UsedMem = 0; - Rtv = 0; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - if ((pPrt->PRxQSize & QZ_UNITS) != 0 || - (pPrt->PXSQSize & QZ_UNITS) != 0 || - (pPrt->PXAQSize & QZ_UNITS) != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } - - if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG); - return(1); - } - - /* - * the size of at least one Tx queue (synch. or asynch.) has to be > 0. - * if Jumbo Frames are used, this size has to be >= 16 kB. - */ - if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) || - (pAC->GIni.GIPortUsage == SK_JUMBO_LINK && - ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || - (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG); - return(1); - } - - UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize; - } - - if (UsedMem > pAC->GIni.GIRamSize) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } - - /* Now start address calculation */ - StartAddr = pAC->GIni.GIRamOffs; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - /* Calculate/Check values for the receive queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr, - &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the synchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr, - &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the asynchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr, - &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd); - Rtv |= Rtv2; - - if (Rtv) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG); - return(1); - } - } - - return(0); -} /* SkGeCheckQSize */ - - -/****************************************************************************** - * - * SkGeInitMacArb() - Initialize the MAC Arbiter - * - * Description: - * This function initializes the MAC Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitMacArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53); - - SK_OUT8(IoC, B3_MA_RCINI_RX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_RX2, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX2, 0); - - /* recovery values are needed for XMAC II Rev. B2 only */ - /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */ - - /* - * There is no start or enable button to push, therefore - * the MAC arbiter is configured and enabled now. - */ -} /* SkGeInitMacArb */ - - -/****************************************************************************** - * - * SkGeInitPktArb() - Initialize the Packet Arbiter - * - * Description: - * This function initializes the Packet Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitPktArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR); - - /* configure timeout values */ - SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); - - /* - * enable timeout timers if jumbo frames not used - * NOTE: the packet arbiter timeout interrupt is needed for - * half duplex hangup workaround - */ - if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) { - if (pAC->GIni.GIMacsFound == 1) { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1); - } - else { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2); - } - } -} /* SkGeInitPktArb */ - - -/****************************************************************************** - * - * SkGeInitMacFifo() - Initialize the MAC FIFOs - * - * Description: - * Initialize all MAC FIFOs of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitMacFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; -#ifdef VCPU - SK_U32 DWord; -#endif /* VCPU */ - /* - * For each FIFO: - * - release local reset - * - use default value for MAC FIFO size - * - setup defaults for the control register - * - enable the FIFO - */ - - Word = GMF_RX_CTRL_DEF; - - if (pAC->GIni.GIGenesis) { - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Enable frame flushing if jumbo frames used */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH); - } - } - else { - /* set Rx GMAC FIFO Flush Mask */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); - - if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { - - Word &= ~GMF_RX_F_FL_ON; - } - - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word); - - /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF); - -#ifdef VCPU - SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord); - SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord); -#endif /* VCPU */ - - /* set Tx GMAC FIFO Almost Empty Threshold */ -/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */ - } -} /* SkGeInitMacFifo */ - - -/****************************************************************************** - * - * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting - * - * Description: - * This function starts the Link Sync Counter of the specified - * port and enables the generation of an Link Sync IRQ. - * The Link Sync Counter may be used to detect an active link, - * if autonegotiation is not used. - * - * Note: - * o To ensure receiving the Link Sync Event the LinkSyncCounter - * should be initialized BEFORE clearing the XMAC's reset! - * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this - * function. - * - * Returns: - * nothing - */ -void SkGeLoadLnkSyncCnt( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 CntVal) /* Counter value */ -{ - SK_U32 OrgIMsk; - SK_U32 NewIMsk; - SK_U32 ISrc; - SK_BOOL IrqPend; - - /* stop counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP); - - /* - * ASIC problem: - * Each time starting the Link Sync Counter an IRQ is generated - * by the adapter. See problem report entry from 21.07.98 - * - * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ - * if no IRQ is already pending. - */ - IrqPend = SK_FALSE; - SK_IN32(IoC, B0_ISRC, &ISrc); - SK_IN32(IoC, B0_IMSK, &OrgIMsk); - if (Port == MAC_1) { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1; - if ((ISrc & IS_LNK_SYNC_M1) != 0) { - IrqPend = SK_TRUE; - } - } - else { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2; - if ((ISrc & IS_LNK_SYNC_M2) != 0) { - IrqPend = SK_TRUE; - } - } - if (!IrqPend) { - SK_OUT32(IoC, B0_IMSK, NewIMsk); - } - - /* load counter */ - SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal); - - /* start counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START); - - if (!IrqPend) { - /* clear the unexpected IRQ, and restore the interrupt mask */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ); - SK_OUT32(IoC, B0_IMSK, OrgIMsk); - } -} /* SkGeLoadLnkSyncCnt*/ - - -/****************************************************************************** - * - * SkGeCfgSync() - Configure synchronous bandwidth for this port. - * - * Description: - * This function may be used to configure synchronous bandwidth - * to the specified port. This may be done any time after - * initializing the port. The configuration values are NOT saved - * in the HWAC port structure and will be overwritten any - * time when stopping and starting the port. - * Any values for the synchronous configuration will be ignored - * if the size of the synchronous queue is zero! - * - * The default configuration for the synchronous service is - * TXA_ENA_FSYNC. This means if the size of - * the synchronous queue is unequal zero but no specific - * synchronous bandwidth is configured, the synchronous queue - * will always have the 'unlimited' transmit priority! - * - * This mode will be restored if the synchronous bandwidth is - * deallocated ('IntTime' = 0 and 'LimCount' = 0). - * - * Returns: - * 0: success - * 1: parameter configuration error - * 2: try to configure quality of service although no - * synchronous queue is configured - */ -int SkGeCfgSync( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 IntTime, /* Interval Timer Value in units of 8ns */ -SK_U32 LimCount, /* Number of bytes to transfer during IntTime */ -int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ -{ - int Rtv; - - Rtv = 0; - - /* check the parameters */ - if (LimCount > IntTime || - (LimCount == 0 && IntTime != 0) || - (LimCount != 0 && IntTime == 0)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - if (pAC->GIni.GP[Port].PXSQSize == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG); - return(2); - } - - /* calculate register values */ - IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100; - LimCount = LimCount / 8; - - if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - /* - * - Enable 'Force Sync' to ensure the synchronous queue - * has the priority while configuring the new values. - * - Also 'disable alloc' to ensure the settings complies - * to the SyncMode parameter. - * - Disable 'Rate Control' to configure the new values. - * - write IntTime and LimCount - * - start 'Rate Control' and disable 'Force Sync' - * if Interval Timer or Limit Counter not zero. - */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount); - - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC))); - - if (IntTime != 0 || LimCount != 0) { - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC); - } - - return(0); -} /* SkGeCfgSync */ - - -/****************************************************************************** - * - * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue - * - * Desccription: - * If the queue is used, enable and initialize it. - * Make sure the queue is still reset, if it is not used. - * - * Returns: - * nothing - */ -static void DoInitRamQueue( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int QuIoOffs, /* Queue IO Address Offset */ -SK_U32 QuStartAddr, /* Queue Start Address */ -SK_U32 QuEndAddr, /* Queue End Address */ -int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ -{ - SK_U32 RxUpThresVal; - SK_U32 RxLoThresVal; - - if (QuStartAddr != QuEndAddr) { - /* calculate thresholds, assume we have a big Rx queue */ - RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8; - RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8; - - /* build HW address format */ - QuStartAddr = QuStartAddr / 8; - QuEndAddr = QuEndAddr / 8; - - /* release local reset */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR); - - /* configure addresses */ - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr); - - switch (QuType) { - case SK_RX_SRAM_Q: - /* configure threshold for small Rx Queue */ - RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8; - - /* continue with SK_RX_BRAM_Q */ - case SK_RX_BRAM_Q: - /* write threshold for Rx Queue */ - - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal); - - /* the high priority threshold not used */ - break; - case SK_TX_RAM_Q: - /* - * Do NOT use Store & Forward under normal operation due to - * performance optimization (GENESIS only). - * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB) - * or YUKON is used ((GMAC Tx FIFO is only 1 kB) - * we NEED Store & Forward of the RAM buffer. - */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK || - !pAC->GIni.GIGenesis) { - /* enable Store & Forward Mode for the Tx Side */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD); - } - break; - } - - /* set queue operational */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD); - } - else { - /* ensure the queue is still disabled */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET); - } -} /* DoInitRamQueue */ - - -/****************************************************************************** - * - * SkGeInitRamBufs() - Initialize the RAM Buffer Queues - * - * Description: - * Initialize all RAM Buffer Queues of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitRamBufs( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int RxQType; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) { - RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ - } - else { - RxQType = SK_RX_BRAM_Q; /* big Rx Queue */ - } - - DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart, - pPrt->PRxQRamEnd, RxQType); - - DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart, - pPrt->PXsQRamEnd, SK_TX_RAM_Q); - - DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart, - pPrt->PXaQRamEnd, SK_TX_RAM_Q); - -} /* SkGeInitRamBufs */ - - -/****************************************************************************** - * - * SkGeInitRamIface() - Initialize the RAM Interface - * - * Description: - * This function initializes the Adapters RAM Interface. - * - * Note: - * This function is used in the diagnostics. - * - * Returns: - * nothing - */ -void SkGeInitRamIface( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53); - -} /* SkGeInitRamIface */ - - -/****************************************************************************** - * - * SkGeInitBmu() - Initialize the BMU state machines - * - * Description: - * Initialize all BMU state machines of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitBmu( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 RxWm; - SK_U32 TxWm; - - pPrt = &pAC->GIni.GP[Port]; - - RxWm = SK_BMU_RX_WM; - TxWm = SK_BMU_TX_WM; - - if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { - /* for better performance */ - RxWm /= 2; - TxWm /= 2; - } - - /* Rx Queue: Release all local resets and set the watermark */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); - - /* - * Tx Queue: Release all local resets if the queue is used ! - * set watermark - */ - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); - } - /* - * Do NOT enable the descriptor poll timers here, because - * the descriptor addresses are not specified yet. - */ -} /* SkGeInitBmu */ - - -/****************************************************************************** - * - * TestStopBit() - Test the stop bit of the queue - * - * Description: - * Stopping a queue is not as simple as it seems to be. - * If descriptor polling is enabled, it may happen - * that RX/TX stop is done and SV idle is NOT set. - * In this case we have to issue another stop command. - * - * Returns: - * The queues control status register - */ -static SK_U32 TestStopBit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int QuIoOffs) /* Queue IO Address Offset */ -{ - SK_U32 QuCsr; /* CSR contents */ - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - - if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { - /* Stop Descriptor overridden by start command */ - SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - } - - return(QuCsr); -} /* TestStopBit */ - - -/****************************************************************************** - * - * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'. - * - * Description: - * After calling this function the descriptor rings and Rx and Tx - * queues of this port may be reconfigured. - * - * It is possible to stop the receive and transmit path separate or - * both together. - * - * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC. - * The receive queue is still active and - * the pending Rx frames may be still transferred - * into the RxD. - * SK_STOP_RX Stop the receive path. The tansmit path - * has to be stopped once before. - * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX - * - * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. - * SK_HARD_RST Resets the MAC and the PHY. - * - * Example: - * 1) A Link Down event was signaled for a port. Therefore the activity - * of this port should be stopped and a hardware reset should be issued - * to enable the workaround of XMAC errata #2. But the received frames - * should not be discarded. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); - * (transfer all pending Rx frames) - * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST); - * ... - * - * 2) An event was issued which request the driver to switch - * the 'virtual active' link to an other already active port - * as soon as possible. The frames in the receive queue of this - * port may be lost. But the PHY must not be reset during this - * event. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST); - * ... - * - * Extended Description: - * If SK_STOP_TX is set, - * o disable the MAC's receive and transmitter to prevent - * from sending incomplete frames - * o stop the port's transmit queues before terminating the - * BMUs to prevent from performing incomplete PCI cycles - * on the PCI bus - * - The network Rx and Tx activity and PCI Tx transfer is - * disabled now. - * o reset the MAC depending on the RstMode - * o Stop Interval Timer and Limit Counter of Tx Arbiter, - * also disable Force Sync bit and Enable Alloc bit. - * o perform a local reset of the port's Tx path - * - reset the PCI FIFO of the async Tx queue - * - reset the PCI FIFO of the sync Tx queue - * - reset the RAM Buffer async Tx queue - * - reset the RAM Buffer sync Tx queue - * - reset the MAC Tx FIFO - * o switch Link and Tx LED off, stop the LED counters - * - * If SK_STOP_RX is set, - * o stop the port's receive queue - * - The path data transfer activity is fully stopped now. - * o perform a local reset of the port's Rx path - * - reset the PCI FIFO of the Rx queue - * - reset the RAM Buffer receive queue - * - reset the MAC Rx FIFO - * o switch Rx LED off, stop the LED counter - * - * If all ports are stopped, - * o reset the RAM Interface. - * - * Notes: - * o This function may be called during the driver states RESET_PORT and - * SWITCH_PORT. - */ -void SkGeStopPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -int Port, /* port to stop (MAC_1 + n) */ -int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ -int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ -{ -#ifndef SK_DIAG - SK_EVPARA Para; -#endif /* !SK_DIAG */ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U32 XsCsr; - SK_U32 XaCsr; - SK_U64 ToutStart; - int i; - int ToutCnt; - - pPrt = &pAC->GIni.GP[Port]; - - if ((Dir & SK_STOP_TX) != 0) { - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* stop both transmit queues */ - /* - * If the BMU is in the reset state CSR_STOP will terminate - * immediately. - */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); - - ToutStart = SkOsGetTime(pAC); - ToutCnt = 0; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate. - */ - SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_TX1 : - PA_CLR_TO_TX2); - - /* - * If the transfer stucks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - SkMacFlushTxFifo(pAC, IoC, Port); - - XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); - XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); - - if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { - /* - * Timeout of 1/18 second reached. - * This needs to be checked at 1/18 sec only. - */ - ToutCnt++; - if (ToutCnt > 1) { - /* Might be a problem when the driver event handler - * calls StopPort again. XXX. - */ - - /* Fatal Error, Loop aborted */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, - SKERR_HWI_E018MSG); -#ifndef SK_DIAG - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); -#endif /* !SK_DIAG */ - return; - } - /* - * Cache incoherency workaround: Assume a start command - * has been lost while sending the frame. - */ - ToutStart = SkOsGetTime(pAC); - - if ((XsCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); - } - if ((XaCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); - } - } - - /* - * Because of the ASIC problem report entry from 21.08.1998 it is - * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. - */ - } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || - (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* Reset the MAC depending on the RstMode */ - if (RstMode == SK_SOFT_RST) { - SkMacSoftRst(pAC, IoC, Port); - } - else { - SkMacHardRst(pAC, IoC, Port); - } - - /* Disable Force Sync bit and Enable Alloc bit */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); - - /* Perform a local reset of the port's Tx path */ - - /* Reset the PCI FIFO of the async Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); - /* Reset the PCI FIFO of the sync Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer async Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); - /* Reset the RAM Buffer sync Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); - - /* Reset Tx MAC FIFO */ - if (pAC->GIni.GIGenesis) { - /* Note: MFF_RST_SET does NOT reset the XMAC ! */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); - - /* switch Link and Tx LED off, stop the LED counters */ - /* Link LED is switched off by the RLMT and the Diag itself */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); - } - else { - /* Reset TX MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } - } - - if ((Dir & SK_STOP_RX) != 0) { - /* - * The RX Stop Command will not terminate if no buffers - * are queued in the RxD ring. But it will always reach - * the Idle state. Therefore we can use this feature to - * stop the transfer of received packets. - */ - /* stop the port's receive queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); - - i = 100; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate - */ - SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_RX1 : - PA_CLR_TO_RX2); - - DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); - - /* timeout if i==0 (bug fix for #10748) */ - if (--i == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, - SKERR_HWI_E024MSG); - break; - } - /* - * because of the ASIC problem report entry from 21.08.98 - * it is required to wait until CSR_STOP is reset and - * CSR_SV_IDLE is set. - */ - } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* The path data transfer activity is fully stopped now */ - - /* Perform a local reset of the port's Rx path */ - - /* Reset the PCI FIFO of the Rx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer receive queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); - - /* Reset Rx MAC FIFO */ - if (pAC->GIni.GIGenesis) { - - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); - - /* switch Rx LED off, stop the LED counter */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); - } - else { - /* Reset Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } - } -} /* SkGeStopPort */ - - -/****************************************************************************** - * - * SkGeInit0() - Level 0 Initialization - * - * Description: - * - Initialize the BMU address offsets - * - * Returns: - * nothing - */ -static void SkGeInit0( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_GEPORT *pPrt; - - for (i = 0; i < SK_MAX_MACS; i++) { - pPrt = &pAC->GIni.GP[i]; - - pPrt->PState = SK_PRT_RESET; - pPrt->PRxQOff = QOffTab[i].RxQOff; - pPrt->PXsQOff = QOffTab[i].XsQOff; - pPrt->PXaQOff = QOffTab[i].XaQOff; - pPrt->PCheckPar = SK_FALSE; - pPrt->PIsave = 0; - pPrt->PPrevShorts = 0; - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PRxLim = SK_DEF_RX_WA_LIM; - pPrt->PLinkMode = SK_LMODE_AUTOFULL; - pPrt->PLinkSpeedCap = SK_LSPEED_CAP_1000MBPS; - pPrt->PLinkSpeed = SK_LSPEED_1000MBPS; - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_UNKNOWN; - pPrt->PLinkModeConf = SK_LMODE_AUTOSENSE; - pPrt->PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - pPrt->PLinkBroken = SK_TRUE; /* See WA code */ - pPrt->PLinkCap = (SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | - SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlCap = SK_FLOW_MODE_SYM_OR_REM; - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - pPrt->PMSCap = 0; - pPrt->PMSMode = SK_MS_MODE_AUTO; - pPrt->PMSStatus = SK_MS_STAT_UNSET; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - pPrt->PHWLinkUp = SK_FALSE; - } - - pAC->GIni.GIPortUsage = SK_RED_LINK; - -} /* SkGeInit0*/ - -#ifdef SK_PCI_RESET - -/****************************************************************************** - * - * SkGePciReset() - Reset PCI interface - * - * Description: - * o Read PCI configuration. - * o Change power state to 3. - * o Change power state to 0. - * o Restore PCI configuration. - * - * Returns: - * 0: Success. - * 1: Power state could not be changed to 3. - */ -static int SkGePciReset( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_U16 PmCtlSts; - SK_U32 Bp1; - SK_U32 Bp2; - SK_U16 PciCmd; - SK_U8 Cls; - SK_U8 Lat; - SK_U8 ConfigSpace[PCI_CFG_SIZE]; - - /* - * Note: Switching to D3 state is like a software reset. - * Switching from D3 to D0 is a hardware reset. - * We have to save and restore the configuration space. - */ - for (i = 0; i < PCI_CFG_SIZE; i++) { - SkPciReadCfgDWord(pAC, i*4, &ConfigSpace[i]); - } - - /* We know the RAM Interface Arbiter is enabled. */ - SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3); - SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); - - if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) { - return(1); - } - - /* Return to D0 state. */ - SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D0); - - /* Check for D0 state. */ - SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); - - if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) { - return(1); - } - - /* Check PCI Config Registers. */ - SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd); - SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls); - SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1); - SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2); - SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat); - - if (PciCmd != 0 || Cls != 0 || (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1 || - Lat != 0) { - return(1); - } - - /* Restore PCI Config Space. */ - for (i = 0; i < PCI_CFG_SIZE; i++) { - SkPciWriteCfgDWord(pAC, i*4, ConfigSpace[i]); - } - - return(0); -} /* SkGePciReset */ - -#endif /* SK_PCI_RESET */ - -/****************************************************************************** - * - * SkGeInit1() - Level 1 Initialization - * - * Description: - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Read the number of MACs/Ports. - * + Read the RAM size. - * + Read the PCI Revision Id. - * + Find out the adapters host clock speed - * + Read and check the PHY type - * - * Returns: - * 0: success - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -static int SkGeInit1( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - SK_U8 Byte; - SK_U16 Word; - SK_U16 CtrlStat; - SK_U32 FlashAddr; - int RetVal; - int i; - - RetVal = 0; - - /* save CLK_RUN bits (YUKON-Lite) */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - -#ifdef SK_PCI_RESET - (void)SkGePciReset(pAC, IoC); -#endif /* SK_PCI_RESET */ - - /* do the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - - /* release the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_CLR); - - /* reset all error bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* release Master Reset */ - SK_OUT8(IoC, B0_CTST, CS_MRST_CLR); - -#ifdef CLK_RUN - CtrlStat |= CS_CLK_RUN_ENA; -#endif /* CLK_RUN */ - - /* restore CLK_RUN bits */ - SK_OUT16(IoC, B0_CTST, CtrlStat & - (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)); - - /* read Chip Identification Number */ - SK_IN8(IoC, B2_CHIP_ID, &Byte); - pAC->GIni.GIChipId = Byte; - - /* read number of MACs */ - SK_IN8(IoC, B2_MAC_CFG, &Byte); - pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; - - /* get Chip Revision Number */ - pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4); - - /* get diff. PCI parameters */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - - /* read the adapters RAM size */ - SK_IN8(IoC, B2_E_0, &Byte); - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - - pAC->GIni.GIGenesis = SK_TRUE; - - if (Byte == 3) { - /* special case: 4 x 64k x 36, offset = 0x80000 */ - pAC->GIni.GIRamSize = 1024; - pAC->GIni.GIRamOffs = (SK_U32)512 * 1024; - } - else { - pAC->GIni.GIRamSize = (int)Byte * 512; - pAC->GIni.GIRamOffs = 0; - } - /* all GE adapters work with 53.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_53; - - /* set Descr. Poll Timer Init Value to 250 ms */ - pAC->GIni.GIPollTimerVal = - SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100; - } - else { - pAC->GIni.GIGenesis = SK_FALSE; - -#ifndef VCPU - pAC->GIni.GIRamSize = (Byte == 0) ? 128 : (int)Byte * 4; -#else - pAC->GIni.GIRamSize = 128; -#endif - pAC->GIni.GIRamOffs = 0; - - /* WA for chip Rev. A */ - pAC->GIni.GIWolOffs = (pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; - - /* get PM Capabilities of PCI config space */ - SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word); - - /* check if VAUX is available */ - if (((CtrlStat & CS_VAUX_AVAIL) != 0) && - /* check also if PME from D3cold is set */ - ((Word & PCI_PME_D3C_SUP) != 0)) { - /* set entry in GE init struct */ - pAC->GIni.GIVauxAvail = SK_TRUE; - } - - /* save Flash-Address Register */ - SK_IN32(IoC, B2_FAR, &FlashAddr); - - /* test Flash-Address Register */ - SK_OUT8(IoC, B2_FAR + 3, 0xff); - SK_IN8(IoC, B2_FAR + 3, &Byte); - - pAC->GIni.GIYukonLite = (SK_BOOL)(Byte != 0); - - /* restore Flash-Address Register */ - SK_OUT32(IoC, B2_FAR, FlashAddr); - - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - /* set GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); - - /* clear GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - } - /* all YU chips work with 78.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_78; - - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ - } - - /* check if 64-bit PCI Slot is present */ - pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); - - /* check if 66 MHz PCI Clock is active */ - pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); - - /* read PCI HW Revision Id. */ - SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte); - pAC->GIni.GIPciHwRev = Byte; - - /* read the PMD type */ - SK_IN8(IoC, B2_PMD_TYP, &Byte); - pAC->GIni.GICopperType = (SK_U8)(Byte == 'T'); - - /* read the PHY type */ - SK_IN8(IoC, B2_E_1, &Byte); - - Byte &= 0x0f; /* the PHY type is stored in the lower nibble */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - if (pAC->GIni.GIGenesis) { - switch (Byte) { - case SK_PHY_XMAC: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC; - break; - case SK_PHY_BCOM: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM; - pAC->GIni.GP[i].PMSCap = - SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE; - break; - case SK_PHY_NAT: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT; - break; -#endif /* OTHER_PHY */ - default: - /* ERROR: unexpected PHY type detected */ - RetVal = 5; - break; - } - } - else { - if (Byte == 0) { - /* if this field is not initialized */ - Byte = SK_PHY_MARV_COPPER; - pAC->GIni.GICopperType = SK_TRUE; - } - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV; - - if (pAC->GIni.GICopperType) { - pAC->GIni.GP[i].PLinkSpeedCap = SK_LSPEED_CAP_AUTO | - SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS | - SK_LSPEED_CAP_1000MBPS; - pAC->GIni.GP[i].PLinkSpeed = SK_LSPEED_AUTO; - pAC->GIni.GP[i].PMSCap = - SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; - } - else { - Byte = SK_PHY_MARV_FIBER; - } - } - - pAC->GIni.GP[i].PhyType = Byte; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("PHY type: %d PHY addr: %04x\n", Byte, - pAC->GIni.GP[i].PhyAddr)); - } - - /* get Mac Type & set function pointers dependent on */ - if (pAC->GIni.GIGenesis) { - pAC->GIni.GIMacType = SK_MAC_XMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus; - } - else { - pAC->GIni.GIMacType = SK_MAC_GMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus; - -#ifdef SPECIAL_HANDLING - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* check HW self test result */ - SK_IN8(IoC, B2_E_3, &Byte); - if ((Byte & B2_E3_RES_MASK) != 0) { - RetVal = 6; - } - } -#endif - } - return(RetVal); -} /* SkGeInit1 */ - - -/****************************************************************************** - * - * SkGeInit2() - Level 2 Initialization - * - * Description: - * - start the Blink Source Counter - * - start the Descriptor Poll Timer - * - configure the MAC-Arbiter - * - configure the Packet-Arbiter - * - enable the Tx Arbiters - * - enable the RAM Interface Arbiter - * - * Returns: - * nothing - */ -static void SkGeInit2( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - SK_U32 DWord; - int i; - - /* start the Descriptor Poll Timer */ - if (pAC->GIni.GIPollTimerVal != 0) { - if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) { - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG); - } - SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal); - SK_OUT8(IoC, B28_DPT_CTRL, DPT_START); - } - - if (pAC->GIni.GIGenesis) { - /* start the Blink Source Counter */ - DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - - SK_OUT32(IoC, B2_BSC_INI, DWord); - SK_OUT8(IoC, B2_BSC_CTRL, BSC_START); - - /* - * Configure the MAC Arbiter and the Packet Arbiter. - * They will be started once and never be stopped. - */ - SkGeInitMacArb(pAC, IoC); - - SkGeInitPktArb(pAC, IoC); - } - else { - /* start Time Stamp Timer */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START); - } - - /* enable the Tx Arbiters */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB); - } - - /* enable the RAM Interface Arbiter */ - SkGeInitRamIface(pAC, IoC); - -} /* SkGeInit2 */ - -/****************************************************************************** - * - * SkGeInit() - Initialize the GE Adapter with the specified level. - * - * Description: - * Level 0: Initialize the Module structures. - * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has - * to be set before calling this level. - * - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Set GIMacsFound with the number of MACs. - * + Store the RAM size in GIRamSize. - * + Save the PCI Revision ID in GIPciHwRev. - * o return an error - * if Number of MACs > SK_MAX_MACS - * - * After returning from Level 0 the adapter - * may be accessed with IO operations. - * - * Level 2: start the Blink Source Counter - * - * Returns: - * 0: success - * 1: Number of MACs exceeds SK_MAX_MACS (after level 1) - * 2: Adapter not present or not accessible - * 3: Illegal initialization level - * 4: Initialization Level 1 Call missing - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -int SkGeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Level) /* initialization level */ -{ - int RetVal; /* return value */ - SK_U32 DWord; - - RetVal = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInit(Level %d)\n", Level)); - - switch (Level) { - case SK_INIT_DATA: - /* Initialization Level 0 */ - SkGeInit0(pAC, IoC); - pAC->GIni.GILevel = SK_INIT_DATA; - break; - - case SK_INIT_IO: - /* Initialization Level 1 */ - RetVal = SkGeInit1(pAC, IoC); - if (RetVal != 0) { - break; - } - - /* check if the adapter seems to be accessible */ - SK_OUT32(IoC, B2_IRQM_INI, 0x11335577L); - SK_IN32(IoC, B2_IRQM_INI, &DWord); - SK_OUT32(IoC, B2_IRQM_INI, 0L); - - if (DWord != 0x11335577L) { - RetVal = 2; - break; - } - - /* check if the number of GIMacsFound matches SK_MAX_MACS */ - if (pAC->GIni.GIMacsFound > SK_MAX_MACS) { - RetVal = 1; - break; - } - - /* Level 1 successfully passed */ - pAC->GIni.GILevel = SK_INIT_IO; - break; - - case SK_INIT_RUN: - /* Initialization Level 2 */ - if (pAC->GIni.GILevel != SK_INIT_IO) { -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG); -#endif /* !SK_DIAG */ - RetVal = 4; - break; - } - SkGeInit2(pAC, IoC); - - /* Level 2 successfully passed */ - pAC->GIni.GILevel = SK_INIT_RUN; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG); - RetVal = 3; - break; - } - - return(RetVal); -} /* SkGeInit */ - - -/****************************************************************************** - * - * SkGeDeInit() - Deinitialize the adapter - * - * Description: - * All ports of the adapter will be stopped if not already done. - * Do a software reset and switch off all LEDs. - * - * Returns: - * nothing - */ -void SkGeDeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_U16 Word; - -#ifndef VCPU - /* ensure I2C is ready */ - SkI2cWaitIrq(pAC, IoC); -#endif - - /* stop all current transfer activity */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - if (pAC->GIni.GP[i].PState != SK_PRT_STOP && - pAC->GIni.GP[i].PState != SK_PRT_RESET) { - - SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); - } - } - - /* Reset all bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* do the reset, all LEDs are switched off now */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); -} /* SkGeDeInit */ - - -/****************************************************************************** - * - * SkGeInitPort() Initialize the specified port. - * - * Description: - * PRxQSize, PXSQSize, and PXAQSize has to be - * configured for the specified port before calling this function. - * The descriptor rings has to be initialized too. - * - * o (Re)configure queues of the specified port. - * o configure the MAC of the specified port. - * o put ASIC and MAC(s) in operational mode. - * o initialize Rx/Tx and Sync LED - * o initialize RAM Buffers and MAC FIFOs - * - * The port is ready to connect when returning. - * - * Note: - * The MAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * 0: success - * 1: Queue size initialization error. The configured values - * for PRxQSize, PXSQSize, or PXAQSize are invalid for one - * or more queues. The specified port was NOT initialized. - * An error log entry was generated. - * 2: The port has to be stopped before it can be initialized again. - */ -int SkGeInitPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port to configure */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (SkGeCheckQSize(pAC, Port) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG); - return(1); - } - - if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG); - return(2); - } - - /* configuration ok, initialize the Port now */ - - if (pAC->GIni.GIGenesis) { - /* initialize Rx, Tx and Link LED */ - /* - * If 1000BT Phy needs LED initialization than swap - * LED and XMAC initialization order - */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA); - /* The Link LED is initialized by RLMT or Diagnostics itself */ - - SkXmInitMac(pAC, IoC, Port); - } - else { - - SkGmInitMac(pAC, IoC, Port); - } - - /* do NOT initialize the Link Sync Counter */ - - SkGeInitMacFifo(pAC, IoC, Port); - - SkGeInitRamBufs(pAC, IoC, Port); - - if (pPrt->PXSQSize != 0) { - /* enable Force Sync bit if synchronous queue available */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC); - } - - SkGeInitBmu(pAC, IoC, Port); - - /* mark port as initialized */ - pPrt->PState = SK_PRT_INIT; - - return(0); -} /* SkGeInitPort */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skgemib.c b/drivers/sk98lin/skgemib.c deleted file mode 100644 index 4a9e9e6af1..0000000000 --- a/drivers/sk98lin/skgemib.c +++ /dev/null @@ -1,1060 +0,0 @@ -/***************************************************************************** - * - * Name: skgemib.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.7 $ - * Date: $Date: 2002/12/16 09:04:34 $ - * Purpose: Private Network Management Interface Management Database - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgemib.c,v $ - * Revision 1.7 2002/12/16 09:04:34 tschilli - * Code for VCT handling added. - * - * Revision 1.6 2002/08/09 15:40:21 rwahl - * Editorial change (renamed ConfSpeedCap). - * - * Revision 1.5 2002/08/09 11:05:34 rwahl - * Added oid handling for link speed cap. - * - * Revision 1.4 2002/08/09 09:40:27 rwahl - * Added support for NDIS OID_PNP_xxx. - * - * Revision 1.3 2002/07/17 19:39:54 rwahl - * Added handler for OID_SKGE_SPEED_MODE & OID_SKGE_SPEED_STATUS. - * - * Revision 1.2 2002/05/22 08:59:00 rwahl - * - static functions only for release build. - * - Source file must be included. - * - * Revision 1.1 2002/05/22 08:12:42 rwahl - * Initial version. - * - ****************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -/* - * PRIVATE OID handler function prototypes - */ -PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int* pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); - -#ifdef SK_POWER_MGMT -PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -#endif - - -/* defines *******************************************************************/ -#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0])) - - -/* global variables **********************************************************/ - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { - {OID_GEN_XMIT_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX}, - {OID_GEN_RCV_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX}, - {OID_GEN_XMIT_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_NO_BUFFER, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_DIRECTED_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST}, - {OID_GEN_DIRECTED_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST}, - {OID_GEN_RCV_CRC_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS}, - {OID_GEN_TRANSMIT_QUEUE_LENGTH, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_802_3_PERMANENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_CURRENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_RCV_ERROR_ALIGNMENT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING}, - {OID_802_3_XMIT_ONE_COLLISION, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL}, - {OID_802_3_XMIT_MORE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL}, - {OID_802_3_XMIT_DEFERRED, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL}, - {OID_802_3_XMIT_MAX_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL}, - {OID_802_3_RCV_OVERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW}, - {OID_802_3_XMIT_UNDERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN}, - {OID_802_3_XMIT_TIMES_CRS_LOST, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER}, - {OID_802_3_XMIT_LATE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL}, -#ifdef SK_POWER_MGMT - {OID_PNP_CAPABILITIES, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_SET_POWER, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_QUERY_POWER, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_ADD_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_REMOVE_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_ENABLE_WAKE_UP, - 0, - 0, - 0, - SK_PNMI_RW, PowerManagement, 0}, -#endif /* SK_POWER_MGMT */ - {OID_SKGE_MDB_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(MgmtDBVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SUPPORTED_LIST, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_SKGE_ALL_DATA, - 0, - 0, - 0, - SK_PNMI_RW, OidStruct, 0}, - {OID_SKGE_VPD_FREE_BYTES, - 1, - 0, - SK_PNMI_MAI_OFF(VpdFreeBytes), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_LIST, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesList), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesNumber), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_KEY, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_VALUE, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACCESS, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACTION, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction), - SK_PNMI_RW, Vpd, 0}, - {OID_SKGE_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(PortNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DEVICE_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(DeviceType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(DriverDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(DriverVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(HwDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(HwVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHIPSET, - 1, - 0, - SK_PNMI_MAI_OFF(Chipset), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ACTION, - 1, - 0, - SK_PNMI_MAI_OFF(Action), - SK_PNMI_RW, Perform, 0}, - {OID_SKGE_RESULT, - 1, - 0, - SK_PNMI_MAI_OFF(TestResult), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(BusType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_SPEED, - 1, - 0, - SK_PNMI_MAI_OFF(BusSpeed), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_WIDTH, - 1, - 0, - SK_PNMI_MAI_OFF(BusWidth), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_LEN, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueLen), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_MAX, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueMax), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_RETRY, - 1, - 0, - SK_PNMI_MAI_OFF(TxRetryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_USED_DESCR_NO, - 1, - 0, - SK_PNMI_MAI_OFF(TxUsedDescrNo), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_DELIVERED_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_OCTETS_DELIV_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxOctetsDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_IN_ERRORS_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(InErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_OUT_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(OutErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ERR_RECOVERY_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(ErrRecoveryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SYSUPTIME, - 1, - 0, - SK_PNMI_MAI_OFF(SysUpTime), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(SensorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_INDEX, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_DESCR, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_TYPE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_VALUE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_STATUS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_CHKSM_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(ChecksumNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHKSM_RX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_ERR_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_STAT_TX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX}, - {OID_SKGE_STAT_TX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET}, - {OID_SKGE_STAT_TX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST}, - {OID_SKGE_STAT_TX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST}, - {OID_SKGE_STAT_TX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST}, - {OID_SKGE_STAT_TX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES}, - {OID_SKGE_STAT_TX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST}, - {OID_SKGE_STAT_TX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC}, - {OID_SKGE_STAT_TX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC}, - {OID_SKGE_STAT_TX_SINGLE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL}, - {OID_SKGE_STAT_TX_MULTI_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL}, - {OID_SKGE_STAT_TX_EXCESS_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL}, - {OID_SKGE_STAT_TX_LATE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL}, - {OID_SKGE_STAT_TX_DEFFERAL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL}, - {OID_SKGE_STAT_TX_EXCESS_DEF, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF}, - {OID_SKGE_STAT_TX_UNDERRUN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN}, - {OID_SKGE_STAT_TX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER}, -/* {OID_SKGE_STAT_TX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_TX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64}, - {OID_SKGE_STAT_TX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127}, - {OID_SKGE_STAT_TX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255}, - {OID_SKGE_STAT_TX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511}, - {OID_SKGE_STAT_TX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023}, - {OID_SKGE_STAT_TX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX}, - {OID_SKGE_STAT_TX_SYNC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC}, - {OID_SKGE_STAT_TX_SYNC_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET}, - {OID_SKGE_STAT_RX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX}, - {OID_SKGE_STAT_RX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET}, - {OID_SKGE_STAT_RX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST}, - {OID_SKGE_STAT_RX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST}, - {OID_SKGE_STAT_RX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST}, - {OID_SKGE_STAT_RX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES}, - {OID_SKGE_STAT_RX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC}, - {OID_SKGE_STAT_RX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC}, - {OID_SKGE_STAT_RX_PFLOWC_ERR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR}, - {OID_SKGE_STAT_RX_FLOWC_UNKWN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN}, - {OID_SKGE_STAT_RX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST}, - {OID_SKGE_STAT_RX_MISSED, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED}, - {OID_SKGE_STAT_RX_FRAMING, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING}, - {OID_SKGE_STAT_RX_OVERFLOW, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW}, - {OID_SKGE_STAT_RX_JABBER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER}, - {OID_SKGE_STAT_RX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER}, - {OID_SKGE_STAT_RX_IR_LENGTH, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH}, - {OID_SKGE_STAT_RX_SYMBOL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL}, - {OID_SKGE_STAT_RX_SHORTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS}, - {OID_SKGE_STAT_RX_RUNT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT}, - {OID_SKGE_STAT_RX_CEXT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT}, - {OID_SKGE_STAT_RX_TOO_LONG, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG}, - {OID_SKGE_STAT_RX_FCS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS}, -/* {OID_SKGE_STAT_RX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_RX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64}, - {OID_SKGE_STAT_RX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127}, - {OID_SKGE_STAT_RX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255}, - {OID_SKGE_STAT_RX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511}, - {OID_SKGE_STAT_RX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023}, - {OID_SKGE_STAT_RX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX}, - {OID_SKGE_PHYS_CUR_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr), - SK_PNMI_RW, Addr, 0}, - {OID_SKGE_PHYS_FAC_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr), - SK_PNMI_RO, Addr, 0}, - {OID_SKGE_PMD, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_CONNECTOR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_SPEED_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_TRAP, - 1, - 0, - SK_PNMI_MAI_OFF(Trap), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TRAP_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(TrapNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MODE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMode), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortNumber), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_ACTIVE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortActive), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_PREFERRED, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortPreferred), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeCts), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_TIME, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeTime), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_ESTIM, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeEstimate), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_THRES, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeThreshold), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_INDEX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_SP_REQ_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_SP_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_MONITOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMonitorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MONITOR_INDEX, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADDR, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ERRS, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_TIMESTAMP, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADMIN, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin), - SK_PNMI_RW, Monitor, 0}, - {OID_SKGE_MTU, - 1, - 0, - SK_PNMI_MAI_OFF(MtuSize), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_VCT_GET, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, - {OID_SKGE_VCT_SET, - 0, - 0, - 0, - SK_PNMI_WO, Vct, 0}, - {OID_SKGE_VCT_STATUS, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, -}; - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skgepnmi.c b/drivers/sk98lin/skgepnmi.c deleted file mode 100644 index b5d32b04c1..0000000000 --- a/drivers/sk98lin/skgepnmi.c +++ /dev/null @@ -1,8310 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.102 $ - * Date: $Date: 2002/12/16 14:03:24 $ - * Purpose: Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgepnmi.c,v $ - * Revision 1.102 2002/12/16 14:03:24 tschilli - * VCT code in Vct() changed. - * - * Revision 1.101 2002/12/16 09:04:10 tschilli - * Code for VCT handling added. - * - * Revision 1.100 2002/09/26 14:28:13 tschilli - * For XMAC the values in the SK_PNMI_PORT Port struct are copied to - * the new SK_PNMI_PORT BufPort struct during a MacUpdate() call. - * These values are used when GetPhysStatVal() is called. With this - * mechanism you get the best results when software corrections for - * counters are needed. Example: RX_LONGFRAMES. - * - * Revision 1.99 2002/09/17 12:31:19 tschilli - * OID_SKGE_TX_HW_ERROR_CTS, OID_SKGE_OUT_ERROR_CTS, OID_GEN_XMIT_ERROR: - * Double count of SK_PNMI_HTX_EXCESS_COL in function General() removed. - * OID_PNP_CAPABILITIES: sizeof(SK_PM_WAKE_UP_CAPABILITIES) changed to - * sizeof(SK_PNP_CAPABILITIES) in function PowerManagement(). - * - * Revision 1.98 2002/09/10 09:00:03 rwahl - * Adapted boolean definitions according sktypes. - * - * Revision 1.97 2002/09/05 15:07:03 rwahl - * Editorial changes. - * - * Revision 1.96 2002/09/05 11:04:14 rwahl - * - Rx/Tx packets statistics of virtual port were zero on link down (#10750) - * - For GMAC the overflow IRQ for Rx longframe counter was not counted. - * - Incorrect calculation for oids OID_SKGE_RX_HW_ERROR_CTS, - * OID_SKGE_IN_ERRORS_CTS, OID_GEN_RCV_ERROR. - * - Moved correction for OID_SKGE_STAT_RX_TOO_LONG to GetPhysStatVal(). - * - Editorial changes. - * - * Revision 1.95 2002/09/04 08:53:37 rwahl - * - Incorrect statistics for Rx_too_long counter with jumbo frame (#10751) - * - StatRxFrameTooLong & StatRxPMaccErr counters were not reset. - * - Fixed compiler warning for debug msg arg types. - * - * Revision 1.94 2002/08/09 15:42:14 rwahl - * - Fixed StatAddr table for GMAC. - * - VirtualConf(): returned indeterminated status for speed oids if no - * active port. - * - * Revision 1.93 2002/08/09 11:04:59 rwahl - * Added handler for link speed caps. - * - * Revision 1.92 2002/08/09 09:43:03 rwahl - * - Added handler for NDIS OID_PNP_xxx ids. - * - * Revision 1.91 2002/07/17 19:53:03 rwahl - * - Added StatOvrflwBit table for XMAC & GMAC. - * - Extended StatAddr table for GMAC. Added check of number of counters - * in enumeration and size of StatAddr table on init level. - * - Added use of GIFunc table. - * - ChipSet is not static anymore, - * - Extended SIRQ event handler for both mac types. - * - Fixed rx short counter bug (#10620) - * - Added handler for oids SKGE_SPEED_MODE & SKGE_SPEED_STATUS. - * - Extendet GetPhysStatVal() for GMAC. - * - Editorial changes. - * - * Revision 1.90 2002/05/22 08:56:25 rwahl - * - Moved OID table to separate source file. - * - Fix: TX_DEFFERAL counter incremented in full-duplex mode. - * - Use string definitions for error msgs. - * - * Revision 1.89 2001/09/18 10:01:30 mkunz - * some OID's fixed for dualnetmode - * - * Revision 1.88 2001/08/02 07:58:08 rwahl - * - Fixed NetIndex to csum module at ResetCounter(). - * - * Revision 1.87 2001/04/06 13:35:09 mkunz - * -Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's - * - * Revision 1.86 2001/03/09 09:18:03 mkunz - * Changes in SK_DBG_MSG - * - * Revision 1.85 2001/03/08 09:37:31 mkunz - * Bugfix in ResetCounter for Pnmi.Port structure - * - * Revision 1.84 2001/03/06 09:04:55 mkunz - * Made some changes in instance calculation - * - * Revision 1.83 2001/02/15 09:15:32 mkunz - * Necessary changes for dual net mode added - * - * Revision 1.82 2001/02/07 08:24:19 mkunz - * -Made changes in handling of OID_SKGE_MTU - * - * Revision 1.81 2001/02/06 09:58:00 mkunz - * -Vpd bug fixed - * -OID_SKGE_MTU added - * -pnmi support for dual net mode. Interface function and macros extended - * - * Revision 1.80 2001/01/22 13:41:35 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.79 2000/12/05 14:57:40 cgoos - * SetStruct failed before first Link Up (link mode of virtual - * port "INDETERMINATED"). - * - * Revision 1.78 2000/09/12 10:44:58 cgoos - * Fixed SK_PNMI_STORE_U32 calls with typecasted argument. - * - * Revision 1.77 2000/09/07 08:10:19 rwahl - * - Modified algorithm for 64bit NDIS statistic counters; - * returns 64bit or 32bit value depending on passed buffer - * size. Indicate capability for 64bit NDIS counter, if passed - * buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, - * and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too. - * - corrected OID_SKGE_RLMT_PORT_PREFERRED. - * - * Revision 1.76 2000/08/03 15:23:39 rwahl - * - Correction for FrameTooLong counter has to be moved to OID handling - * routines (instead of statistic counter routine). - * - Fix in XMAC Reset Event handling: Only offset counter for hardware - * statistic registers are updated. - * - * Revision 1.75 2000/08/01 16:46:05 rwahl - * - Added StatRxLongFrames counter and correction of FrameTooLong counter. - * - Added directive to control width (default = 32bit) of NDIS statistic - * counters (SK_NDIS_64BIT_CTR). - * - * Revision 1.74 2000/07/04 11:41:53 rwahl - * - Added volition connector type. - * - * Revision 1.73 2000/03/15 16:33:10 rwahl - * Fixed bug 10510; wrong reset of virtual port statistic counters. - * - * Revision 1.72 1999/12/06 16:15:53 rwahl - * Fixed problem of instance range for current and factory MAC address. - * - * Revision 1.71 1999/12/06 10:14:20 rwahl - * Fixed bug 10476; set operation for PHY_OPERATION_MODE. - * - * Revision 1.70 1999/11/22 13:33:34 cgoos - * Changed license header to GPL. - * - * Revision 1.69 1999/10/18 11:42:15 rwahl - * Added typecasts for checking event dependent param (debug only). - * - * Revision 1.68 1999/10/06 09:35:59 cgoos - * Added state check to PHY_READ call (hanged if called during startup). - * - * Revision 1.67 1999/09/22 09:53:20 rwahl - * - Read Broadcom register for updating fcs error counter (1000Base-T). - * - * Revision 1.66 1999/08/26 13:47:56 rwahl - * Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap. - * - * Revision 1.65 1999/07/26 07:49:35 cgoos - * Added two typecasts to avoid compiler warnings. - * - * Revision 1.64 1999/05/20 09:24:12 cgoos - * Changes for 1000Base-T (sensors, Master/Slave). - * - * Revision 1.63 1999/04/13 15:11:58 mhaveman - * Moved include of rlmt.h to header skgepnmi.h because some macros - * are needed there. - * - * Revision 1.62 1999/04/13 15:08:07 mhaveman - * Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK - * to grant unified interface by only using the PNMI header file. - * SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK. - * - * Revision 1.61 1999/04/13 15:02:48 mhaveman - * Changes caused by review: - * -Changed some comments - * -Removed redundant check for OID_SKGE_PHYS_FAC_ADDR - * -Optimized PRESET check. - * -Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same - * address will now not cause this error. Removed corresponding check. - * - * Revision 1.60 1999/03/23 10:41:23 mhaveman - * Added comments. - * - * Revision 1.59 1999/02/19 08:01:28 mhaveman - * Fixed bug 10372 that after counter reset all ports were displayed - * as inactive. - * - * Revision 1.58 1999/02/16 18:04:47 mhaveman - * Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME. - * - * Revision 1.56 1999/01/27 12:29:11 mhaveman - * SkTimerStart was called with time value in milli seconds but needs - * micro seconds. - * - * Revision 1.55 1999/01/25 15:00:38 mhaveman - * Added support to allow multiple ports to be active. If this feature in - * future will be used, the Management Data Base variables PORT_ACTIVE - * and PORT_PREFERED should be moved to the port specific part of RLMT. - * Currently they return the values of the first active physical port - * found. A set to the virtual port will actually change all active - * physical ports. A get returns the melted values of all active physical - * ports. If the port values differ a return value INDETERMINATED will - * be returned. This effects especially the CONF group. - * - * Revision 1.54 1999/01/19 10:10:22 mhaveman - * -Fixed bug 10354: Counter values of virtual port were wrong after port - * switches - * -Added check if a switch to the same port is notified. - * - * Revision 1.53 1999/01/07 09:25:21 mhaveman - * Forgot to initialize a variable. - * - * Revision 1.52 1999/01/05 10:34:33 mhaveman - * Fixed little error in RlmtChangeEstimate calculation. - * - * Revision 1.51 1999/01/05 09:59:07 mhaveman - * -Moved timer start to init level 2 - * -Redesigned port switch average calculation to avoid 64bit - * arithmetic. - * - * Revision 1.50 1998/12/10 15:13:59 mhaveman - * -Fixed: PHYS_CUR_ADDR returned wrong addresses - * -Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned - * always BAD_VALUE. - * -Fixed: TRAP buffer seemed to sometimes suddenly empty - * - * Revision 1.49 1998/12/09 16:17:07 mhaveman - * Fixed: Couldnot delete VPD keys on UNIX. - * - * Revision 1.48 1998/12/09 14:11:10 mhaveman - * -Add: Debugmessage for XMAC_RESET supressed to minimize output. - * -Fixed: RlmtChangeThreshold will now be initialized. - * -Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char. - * -Fixed: On VPD key creation an invalid key name could be created - * (e.g. A5) - * -Some minor changes in comments and code. - * - * Revision 1.47 1998/12/08 16:00:31 mhaveman - * -Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port - * is active. - * -Fixed: For the RLMT statistics group only the last value was - * returned and the rest of the buffer was filled with 0xff - * -Fixed: Mysteriously the preset on RLMT_MODE still returned - * BAD_VALUE. - * Revision 1.46 1998/12/08 10:04:56 mhaveman - * -Fixed: Preset on RLMT_MODE returned always BAD_VALUE error. - * -Fixed: Alignment error in GetStruct - * -Fixed: If for Get/Preset/SetStruct the buffer size is equal or - * larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored - * to the buffer. In this case the caller should always return - * ok to its upper routines. Only if the buffer size is less - * than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal - * to 0, an error should be returned by the caller. - * -Fixed: Wrong number of instances with RLMT statistic. - * -Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0. - * - * Revision 1.45 1998/12/03 17:17:24 mhaveman - * -Removed for VPD create action the buffer size limitation to 4 bytes. - * -Pass now physical/active physical port to ADDR for CUR_ADDR set - * - * Revision 1.44 1998/12/03 15:14:35 mhaveman - * Another change to Vpd instance evaluation. - * - * Revision 1.43 1998/12/03 14:18:10 mhaveman - * -Fixed problem in PnmiSetStruct. It was impossible to set any value. - * -Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION. - * - * Revision 1.42 1998/12/03 11:31:47 mhaveman - * Inserted cast to satisfy lint. - * - * Revision 1.41 1998/12/03 11:28:16 mhaveman - * Removed SK_PNMI_CHECKPTR - * - * Revision 1.40 1998/12/03 11:19:07 mhaveman - * Fixed problems - * -A set to virtual port will now be ignored. A set with broadcast - * address to any port will be ignored. - * -GetStruct function made VPD instance calculation wrong. - * -Prefered port returned -1 instead of 0. - * - * Revision 1.39 1998/11/26 15:30:29 mhaveman - * Added sense mode to link mode. - * - * Revision 1.38 1998/11/23 15:34:00 mhaveman - * -Fixed bug for RX counters. On an RX overflow interrupt the high - * words of all RX counters were incremented. - * -SET operations on FLOWCTRL_MODE and LINK_MODE accept now the - * value 0, which has no effect. It is usefull for multiple instance - * SETs. - * - * Revision 1.37 1998/11/20 08:02:04 mhaveman - * -Fixed: Ports were compared with MAX_SENSORS - * -Fixed: Crash in GetTrapEntry with MEMSET macro - * -Fixed: Conversions between physical, logical port index and instance - * - * Revision 1.36 1998/11/16 07:48:53 mhaveman - * Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings - * on Solaris. - * - * Revision 1.35 1998/11/16 07:45:34 mhaveman - * SkAddrOverride now returns value and will be checked. - * - * Revision 1.34 1998/11/10 13:40:37 mhaveman - * Needed to change interface, because NT driver needs a return value - * of needed buffer space on TOO_SHORT errors. Therefore all - * SkPnmiGet/Preset/Set functions now have a pointer to the length - * parameter, where the needed space on error is returned. - * - * Revision 1.33 1998/11/03 13:52:46 mhaveman - * Made file lint conform. - * - * Revision 1.32 1998/11/03 13:19:07 mhaveman - * The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in - * Para32[0] the physical MAC index and in Para32[1] the new mode. - * - * Revision 1.31 1998/11/03 12:30:40 gklug - * fix: compiler warning memset - * - * Revision 1.30 1998/11/03 12:04:46 mhaveman - * Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end - * Fixed alignment problem with CHIPSET. - * - * Revision 1.29 1998/11/02 11:23:54 mhaveman - * Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry. - * - * Revision 1.28 1998/11/02 10:47:16 mhaveman - * Added syslog messages for internal errors. - * - * Revision 1.27 1998/10/30 15:48:06 mhaveman - * Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and - * RlmtChangeThreshold calculation. - * - * Revision 1.26 1998/10/29 15:36:55 mhaveman - * -Fixed bug in trap buffer handling. - * -OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR, - * OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY, - * OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with - * a leading octet before each string storing the string length. - * -Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize - * RlmtUpdate calls in GetStatVal. - * -Inserted SK_PNMI_CHECKFLAGS macro increase readability. - * - * Revision 1.25 1998/10/29 08:50:36 mhaveman - * Fixed problems after second event simulation. - * - * Revision 1.24 1998/10/28 08:44:37 mhaveman - * -Fixed alignment problem - * -Fixed problems during event simulation - * -Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT) - * -Changed type of parameter Instance back to SK_U32 because of VPD - * -Updated new VPD function calls - * - * Revision 1.23 1998/10/23 10:16:37 mhaveman - * Fixed bugs after buffer test simulation. - * - * Revision 1.22 1998/10/21 13:23:52 mhaveman - * -Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc). - * -Changed calculation of hundrets of seconds. - * - * Revision 1.20 1998/10/20 07:30:45 mhaveman - * Made type changes to unsigned integer where possible. - * - * Revision 1.19 1998/10/19 10:51:30 mhaveman - * -Made Bug fixes after simulation run - * -Renamed RlmtMAC... to RlmtPort... - * -Marked workarounds with Errata comments - * - * Revision 1.18 1998/10/14 07:50:08 mhaveman - * -For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT - * to HWACCESS. - * -Provided all MEMCPY/MEMSET macros with (char *) pointers, because - * Solaris throwed warnings when mapping to bcopy/bset. - * - * Revision 1.17 1998/10/13 07:42:01 mhaveman - * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA - * -Removed old cvs history entries - * -Renamed MacNumber to PortNumber - * - * Revision 1.16 1998/10/07 10:52:49 mhaveman - * -Inserted handling of some OID_GEN_ Ids for windows - * -Fixed problem with 803.2 statistic. - * - * Revision 1.15 1998/10/01 09:16:29 mhaveman - * Added Debug messages for function call and UpdateFlag tracing. - * - * Revision 1.14 1998/09/30 13:39:09 mhaveman - * -Reduced namings of 'MAC' by replacing them with 'PORT'. - * -Completed counting of OID_SKGE_RX_HW_ERROR_CTS, - * OID_SKGE_TX_HW_ERROR_CTS, - * OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS. - * -SET check for RlmtMode - * - * Revision 1.13 1998/09/28 13:13:08 mhaveman - * Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN, - * and SK_STRNCPY. (Same reasons as for mem.. and MEM..) - * - * Revision 1.12 1998/09/16 08:18:36 cgoos - * Fix: XM_INxx and XM_OUTxx called with different parameter order: - * sometimes IoC,Mac,... sometimes Mac,IoC,... Now always first variant. - * Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version. - * Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY - * - * Revision 1.11 1998/09/04 17:01:45 mhaveman - * Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to - * OID_SKGE_RX_NO_BUF_CTS. - * - * Revision 1.10 1998/09/04 14:35:35 mhaveman - * Added macro counters, that are counted by driver. - * - ****************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -static const char SysKonnectFileId[] = - "@(#) $Id: skgepnmi.c,v 1.102 2002/12/16 14:03:24 tschilli Exp $" - " (C) SysKonnect."; - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/xmac_ii.h" -#include "h/skdebug.h" -#include "h/skqueue.h" -#include "h/skgepnmi.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skdrv2nd.h" -#include "h/skgepnm2.h" -#ifdef SK_POWER_MGMT -#include "h/skgepmgt.h" -#endif -/* defines *******************************************************************/ - -#ifndef DEBUG -#define PNMI_STATIC static -#else /* DEBUG */ -#define PNMI_STATIC -#endif /* DEBUG */ - -/* - * Public Function prototypes - */ -int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); -int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); - - -/* - * Private Function prototypes - */ - -PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac); -PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf); -PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC, - unsigned int PhysPortIndex, unsigned int StatIndex); -PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex, - unsigned int StatIndex, SK_U32 NetIndex); -PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size); -PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen, - unsigned int *pEntries); -PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr, - unsigned int KeyArrLen, unsigned int *pKeyNo); -PNMI_STATIC int LookupId(SK_U32 Id); -PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac, - unsigned int LastMac); -PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac); -PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int PortIndex); -PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int SensorIndex); -PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId); -PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); -PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, - unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -#include "skgemib.c" - -/* global variables **********************************************************/ - -/* - * Overflow status register bit table and corresponding counter - * dependent on MAC type - the number relates to the size of overflow - * mask returned by the pFnMacOverflow function - */ -PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = { -/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST}, -/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST}, -/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC}, -/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST}, -/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW}, -/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH}, -/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64}, -/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127}, -/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255}, -/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511}, -/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023}, -/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX}, -/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES}, -/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED}, -/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL}, -/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL}, -/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL}, -/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL}, -/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL}, -/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN}, -/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED}, -/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED}, -/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED}, -/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED}, -/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED}, -/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED}, -/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST}, -/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST}, -/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC}, -/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST}, -/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS}, -/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED}, -/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW}, -/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH}, -/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW}, -/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH}, -/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE}, -/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT}, -/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64}, -/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127}, -/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255}, -/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511}, -/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023}, -/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX}, -/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES}, -/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG}, -/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER}, -/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED}, -/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW}, -/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED}, -/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED}, -/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED}, -/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED}, -/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED}, -/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED}, -/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED}, -/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED}, -/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED} -}; - -/* - * Table for hardware register saving on resets and port switches - */ -PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = { - /* SK_PNMI_HTX */ - {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_OCTETHIGH */ - {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HTX_OCTETLOW */ - {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HTX_BROADCAST */ - {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_MULTICAST */ - {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_UNICAST */ - {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_BURST */ - {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_PMACC */ - {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HTX_MACC */ - {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_COL */ - {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}}, - /* SK_PNMI_HTX_SINGLE_COL */ - {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}}, - /* SK_PNMI_HTX_MULTI_COL */ - {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}}, - /* SK_PNMI_HTX_EXCESS_COL */ - {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}}, - /* SK_PNMI_HTX_LATE_COL */ - {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}}, - /* SK_PNMI_HTX_DEFFERAL */ - {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_EXCESS_DEF */ - {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UNDERRUN */ - {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}}, - /* SK_PNMI_HTX_CARRIER */ - {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_64 */ - {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}}, - /* SK_PNMI_HTX_127 */ - {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}}, - /* SK_PNMI_HTX_255 */ - {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}}, - /* SK_PNMI_HTX_511 */ - {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}}, - /* SK_PNMI_HTX_1023 */ - {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}}, - /* SK_PNMI_HTX_MAX */ - {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}}, - /* SK_PNMI_HTX_LONGFRAMES */ - {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HTX_SYNC */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_SYNC_OCTET */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX */ - {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_OCTETHIGH */ - {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HRX_OCTETLOW */ - {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HRX_BADOCTETHIGH */ - {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}}, - /* SK_PNMI_HRX_BADOCTETLOW */ - {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}}, - /* SK_PNMI_HRX_BROADCAST */ - {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_MULTICAST */ - {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_UNICAST */ - {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_PMACC */ - {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HRX_MACC */ - {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_PMACC_ERR */ - {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MACC_UNKWN */ - {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_BURST */ - {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MISSED */ - {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_FRAMING */ - {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UNDERSIZE */ - {{0, SK_FALSE},{GM_RXF_SHT, SK_TRUE}}, - /* SK_PNMI_HRX_OVERFLOW */ - {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, - /* SK_PNMI_HRX_JABBER */ - {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}}, - /* SK_PNMI_HRX_CARRIER */ - {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_IRLENGTH */ - {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SYMBOL */ - {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SHORTS */ - {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_RUNT */ - {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}}, - /* SK_PNMI_HRX_TOO_LONG */ - {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_FCS */ - {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_CEXT */ - {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_64 */ - {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}}, - /* SK_PNMI_HRX_127 */ - {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}}, - /* SK_PNMI_HRX_255 */ - {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}}, - /* SK_PNMI_HRX_511 */ - {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}}, - /* SK_PNMI_HRX_1023 */ - {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}}, - /* SK_PNMI_HRX_MAX */ - {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}}, - /* SK_PNMI_HRX_LONGFRAMES */ - {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HRX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}} -}; - - -/***************************************************************************** - * - * Public functions - * - */ - -/***************************************************************************** - * - * SkPnmiInit - Init function of PNMI - * - * Description: - * SK_INIT_DATA: Initialises the data structures - * SK_INIT_IO: Resets the XMAC statistics, determines the device and - * connector type. - * SK_INIT_RUN: Starts a timer event for port switch per hour - * calculation. - * - * Returns: - * Always 0 - */ -int SkPnmiInit( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Level) /* Initialization level */ -{ - unsigned int PortMax; /* Number of ports */ - unsigned int PortIndex; /* Current port index in loop */ - SK_U16 Val16; /* Multiple purpose 16 bit variable */ - SK_U8 Val8; /* Mulitple purpose 8 bit variable */ - SK_EVPARA EventParam; /* Event struct for timer event */ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); - - switch (Level) { - - case SK_INIT_DATA: - SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); - pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; - pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; - for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { - - pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - -#ifdef SK_PNMI_CHECK - if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, - ("CounterOffset struct size (%d) differs from" - "SK_PNMI_MAX_IDX (%d)\n", - SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); - BRK; - } - - if (SK_PNMI_MAX_IDX != - (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, - ("StatAddr table size (%d) differs from " - "SK_PNMI_MAX_IDX (%d)\n", - (sizeof(StatAddr) / - (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)), - SK_PNMI_MAX_IDX)); - BRK; - } -#endif /* SK_PNMI_CHECK */ - break; - - case SK_INIT_IO: - /* - * Reset MAC counters - */ - PortMax = pAC->GIni.GIMacsFound; - - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - - pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); - } - - /* Initialize DSP variables for Vct() to 0xff => Never written! */ - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - pPrt = &pAC->GIni.GP[PortIndex]; - pPrt->PCableLen =0xff; - pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; - pVctBackupData->PCableLen = 0xff; - } - - /* - * Get pci bus speed - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_CLOCK) == 0) { - - pAC->Pnmi.PciBusSpeed = 33; - } - else { - pAC->Pnmi.PciBusSpeed = 66; - } - - /* - * Get pci bus width - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_SLOT_SZ) == 0) { - - pAC->Pnmi.PciBusWidth = 32; - } - else { - pAC->Pnmi.PciBusWidth = 64; - } - - /* - * Get chipset - */ - switch (pAC->GIni.GIChipId) { - case CHIP_ID_GENESIS: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; - break; - - case CHIP_ID_YUKON: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; - break; - - default: - break; - } - - /* - * Get PMD and DeviceType - */ - SK_IN8(IoC, B2_PMD_TYP, &Val8); - switch (Val8) { - case 'S': - pAC->Pnmi.PMD = 3; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020002; - } - else { - pAC->Pnmi.DeviceType = 0x00020001; - } - break; - - case 'L': - pAC->Pnmi.PMD = 2; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020004; - } - else { - pAC->Pnmi.DeviceType = 0x00020003; - } - break; - - case 'C': - pAC->Pnmi.PMD = 4; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020006; - } - else { - pAC->Pnmi.DeviceType = 0x00020005; - } - break; - - case 'T': - pAC->Pnmi.PMD = 5; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020008; - } - else { - pAC->Pnmi.DeviceType = 0x00020007; - } - break; - - default : - pAC->Pnmi.PMD = 1; - pAC->Pnmi.DeviceType = 0; - break; - } - - /* - * Get connector - */ - SK_IN8(IoC, B2_CONN_TYP, &Val8); - switch (Val8) { - case 'C': - pAC->Pnmi.Connector = 2; - break; - - case 'D': - pAC->Pnmi.Connector = 3; - break; - - case 'F': - pAC->Pnmi.Connector = 4; - break; - - case 'J': - pAC->Pnmi.Connector = 5; - break; - - case 'V': - pAC->Pnmi.Connector = 6; - break; - - default: - pAC->Pnmi.Connector = 1; - break; - } - break; - - case SK_INIT_RUN: - /* - * Start timer for RLMT change counter - */ - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - default: - break; /* Nothing todo */ - } - - return (0); -} - -/***************************************************************************** - * - * SkPnmiGetVar - Retrieves the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. If the instance - * -1 is passed, the values of all instances are returned in an - * array of values. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiGetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiPreSetVar - Presets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. - * If as instance a -1 is passed, an array of values is supposed and - * all instance of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiPreSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - - return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetVar - Sets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. - * If as instance a -1 is passed, an array of values is supposed and - * all instance of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Runs through the IdTable, queries the single OIDs and stores the - * returned data into the management database structure - * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure - * is stored in the IdTable. The return value of the function will also - * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -int SkPnmiGetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which will store the retrieved data */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - unsigned int TmpLen; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Check NetIndex - */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - /* Update statistic */ - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); - - if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != - SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - /* - * Increment semaphores to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Get vpd keys for instance calculation */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - - /* Retrieve values */ - SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - InstanceNo = IdTable[TableIndex].InstanceNo; - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * For the VPD the instance is not an index number - * but the key itself. Determin with the instance - * counter the VPD key to be used. - */ - if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY || - IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) { - - SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4); - } - else { - Instance = (SK_U32)InstanceCnt; - } - - TmpLen = *pLen - DstOffset; - Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, - IdTable[TableIndex].Id, (char *)pBuf + - DstOffset, &TmpLen, Instance, TableIndex, NetIndex); - - /* - * An unknown instance error means that we reached - * the last instance of that variable. Proceed with - * the next OID in the table and ignore the return - * code. - */ - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - } - } - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - *pLen = SK_PNMI_STRUCT_SIZE; - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is usefull to check if a set might be successfull. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * preset. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiPreSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The return value - * of the function will also be stored in SK_PNMI_STRUCT_DATA if the - * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * set. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiEvent - Event handler - * - * Description: - * Handles the following events: - * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an - * interrupt will be generated which is - * first handled by SIRQ which generates a - * this event. The event increments the - * upper 32 bit of the 64 bit counter. - * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module - * when a sensor reports a warning or - * error. The event will store a trap - * message in the trap buffer. - * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this - * module and is used to calculate the - * port switches per hour. - * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and - * timestamps. - * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver - * before a hard reset of the XMAC is - * performed. All counters will be saved - * and added to the hardware counter - * values after reset to grant continuous - * counter values. - * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port - * went logically up. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port - * went logically down. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two - * spanning tree root bridges were - * detected. A trap message will be stored - * to the trap buffer. - * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went - * down. PNMI will not further add the - * statistic values to the virtual port. - * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and - * is now an active port. PNMI will now - * add the statistic data of this port to - * the virtual port. - * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first Parameter - * contains the number of nets. 1 means single net, 2 means - * dual net. The second Parameter is -1 - * - * Returns: - * Always 0 - */ -int SkPnmiEvent( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Event, /* Event-Id */ -SK_EVPARA Param) /* Event dependent parameter */ -{ - unsigned int PhysPortIndex; - unsigned int MaxNetNumber; - int CounterIndex; - int Ret; - SK_U16 MacStatus; - SK_U64 OverflowStatus; - SK_U64 Mask; - int MacType; - SK_U64 Value; - SK_U32 Val32; - SK_U16 Register; - SK_EVPARA EventParam; - SK_U64 NewestValue; - SK_U64 OldestValue; - SK_U64 Delta; - SK_PNMI_ESTIMATE *pEst; - SK_U32 NetIndex; - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 RetCode; - int i; - SK_U32 CableLength; - - -#ifdef DEBUG - if (Event != SK_PNMI_EVT_XMAC_RESET) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", - (unsigned int)Event, (unsigned int)Param.Para64)); - } -#endif - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); - - MacType = pAC->GIni.GIMacType; - - switch (Event) { - - case SK_PNMI_EVT_SIRQ_OVERFLOW: - PhysPortIndex = (int)Param.Para32[0]; - MacStatus = (SK_U16)Param.Para32[1]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter" - " wrong, PhysPortIndex=0x%x\n", - PhysPortIndex)); - return (0); - } -#endif - OverflowStatus = 0; - - /* - * Check which source caused an overflow interrupt. - */ - if ((pAC->GIni.GIFunc.pFnMacOverflow( - pAC, IoC, PhysPortIndex, MacStatus, &OverflowStatus) != 0) || - (OverflowStatus == 0)) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - - /* - * Check the overflow status register and increment - * the upper dword of corresponding counter. - */ - for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8; - CounterIndex ++) { - - Mask = (SK_U64)1 << CounterIndex; - if ((OverflowStatus & Mask) == 0) { - - continue; - } - - switch (StatOvrflwBit[CounterIndex][MacType]) { - - case SK_PNMI_HTX_UTILUNDER: - case SK_PNMI_HTX_UTILOVER: - XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, - &Register); - Register |= XM_TX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, - Register); - break; - - case SK_PNMI_HRX_UTILUNDER: - case SK_PNMI_HRX_UTILOVER: - XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, - &Register); - Register |= XM_RX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, - Register); - break; - - case SK_PNMI_HTX_OCTETHIGH: - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HTX_RESERVED: - case SK_PNMI_HRX_OCTETHIGH: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_RESERVED: - - /* - * the following counters aren't be handled (id > 63) - */ - case SK_PNMI_HTX_SYNC: - case SK_PNMI_HTX_SYNC_OCTET: - break; - - case SK_PNMI_HRX_LONGFRAMES: - if (MacType == SK_MAC_GMAC) { - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - break; - - default: - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - } - break; - - case SK_PNMI_EVT_SEN_WAR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_WAR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR:SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_CHG_EST_TIMER: - /* - * Calculate port switch average on a per hour basis - * Time interval for check : 28125 ms - * Number of values for average : 8 - * - * Be careful in changing these values, on change check - * - typedef of SK_PNMI_ESTIMATE (Size of EstValue - * array one less than value number) - * - Timer initilization SkTimerStart() in SkPnmiInit - * - Delta value below must be multiplicated with - * power of 2 - * - */ - pEst = &pAC->Pnmi.RlmtChangeEstimate; - CounterIndex = pEst->EstValueIndex + 1; - if (CounterIndex == 7) { - - CounterIndex = 0; - } - pEst->EstValueIndex = CounterIndex; - - NewestValue = pAC->Pnmi.RlmtChangeCts; - OldestValue = pEst->EstValue[CounterIndex]; - pEst->EstValue[CounterIndex] = NewestValue; - - /* - * Calculate average. Delta stores the number of - * port switches per 28125 * 8 = 225000 ms - */ - if (NewestValue >= OldestValue) { - - Delta = NewestValue - OldestValue; - } - else { - /* Overflow situation */ - Delta = (SK_U64)(0 - OldestValue) + NewestValue; - } - - /* - * Extrapolate delta to port switches per hour. - * Estimate = Delta * (3600000 / 225000) - * = Delta * 16 - * = Delta << 4 - */ - pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4; - - /* - * Check if threshold is exceeded. If the threshold is - * permanently exceeded every 28125 ms an event will be - * generated to remind the user of this condition. - */ - if ((pAC->Pnmi.RlmtChangeThreshold != 0) && - (pAC->Pnmi.RlmtChangeEstimate.Estimate >= - pAC->Pnmi.RlmtChangeThreshold)) { - - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - } - - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - case SK_PNMI_EVT_CLEAR_COUNTER: - /* - * Param.Para32[0] contains the NetIndex (0 ..1). - * Param.Para32[1] is reserved, contains -1. - */ - NetIndex = (SK_U32)Param.Para32[0]; - -#ifdef DEBUG - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n", - NetIndex)); - - return (0); - } -#endif - - /* - * Set all counters and timestamps to zero - */ - ResetCounter(pAC, IoC, NetIndex); /* the according NetIndex is required - as a Parameter of the Event */ - break; - - case SK_PNMI_EVT_XMAC_RESET: - /* - * To grant continuous counter values store the current - * XMAC statistic values to the entries 1..n of the - * CounterOffset array. XMAC Errata #2 - */ -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - PhysPortIndex = (unsigned int)Param.Para64; - - /* - * Update XMAC statistic to get fresh values - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - /* - * Increment semaphore to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - pAC->Pnmi.Port[PhysPortIndex]. - CounterOffset[CounterIndex] = GetPhysStatVal( - pAC, IoC, PhysPortIndex, CounterIndex); - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] = 0; - } - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_PORT_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix for XMAC errata (#10620)*/ - if (pAC->GIni.GIMacType == SK_MAC_XMAC){ - - /* Add incremental difference to offset (#10620)*/ - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - - Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += - Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; - } - - /* Tell VctStatus() that a link was up meanwhile. */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; - break; - - case SK_PNMI_EVT_RLMT_PORT_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix #10620 - get zero level for incremental difference */ - if ((pAC->GIni.GIMacType == SK_MAC_XMAC)) { - - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = - (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - } - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already inactive - */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was already - * done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. The virtual port consists of all currently - * active ports. The port down event indicates that a port is removed - * from the virtual port. Therefore add the counter value of the removed - * port to the CounterOffset for the virtual port to grant the same - * counter value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; - } - - /* - * Set port to inactive - */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already active - */ - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Statistic maintenance - */ - pAC->Pnmi.RlmtChangeCts ++; - pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtNewMacTrap(pAC, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was - * already done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. A new port is added to the virtual port. - * Therefore substract the counter value of the new port from the - * CounterOffset for the virtual port to grant the same value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; - } - - /* - * Set port to active - */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_SEGMENTATION: - /* - * Para.Para32[0] contains the NetIndex. - */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_RLMT_SET_NETS: - /* - * Param.Para32[0] contains the number of Nets. - * Param.Para32[1] is reserved, contains -1. - */ - /* - * Check number of nets - */ - MaxNetNumber = pAC->GIni.GIMacsFound; - if (((unsigned int)Param.Para32[0] < 1) - || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - else { /* dual net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_TRUE; - } - break; - - case SK_PNMI_EVT_VCT_RESET: - PhysPortIndex = Param.Para32[0]; - pPrt = &pAC->GIni.GP[PhysPortIndex]; - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { - /* - * VCT test is still running. - * Start VCT timer counter again. - */ - SK_MEMSET((char *) &Param, 0, sizeof(Param)); - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); - break; - } - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairLen[i] > 35) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); - SkEventDispatcher(pAC, IoC); - } - - break; - - default: - break; - } - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); -} - - -/****************************************************************************** - * - * Private functions - * - */ - -/***************************************************************************** - * - * PnmiVar - Gets, presets, and sets single OIDs - * - * Description: - * Looks up the requested OID, calls the corresponding handler - * function, and passes the parameters with the get, preset, or - * set command. The function is called by SkGePnmiGetVar, - * SkGePnmiPreSetVar, or SkGePnmiSetVar. - * - * Returns: - * SK_PNMI_ERR_XXX. For details have a look to the description of the - * calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int TableIndex; - int Ret; - - - if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_OID); - } - - /* - * Check NetIndex - */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiVar: On call"); - - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen, - Instance, TableIndex, NetIndex); - - SK_PNMI_CHECKFLAGS("PnmiVar: On return"); - - return (Ret); -} - -/***************************************************************************** - * - * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA - * - * Description: - * The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable, - * checks which OIDs are able to set, and calls the handler function of - * the OID to perform the set. The return value of the function will - * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called - * by SkGePnmiPreSetStruct and SkGePnmiSetStruct. - * - * Returns: - * SK_PNMI_ERR_XXX. The codes are described in the calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Set action to be performed */ -char *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int Len; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - SK_U32 Id; - - - /* Check if the passed buffer has the right size */ - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - /* Check if we can return the error within the buffer */ - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Check NetIndex - */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); - - /* - * Update the values of RLMT and SIRQ and increment semaphores to - * indicate that an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Preset/Set values */ - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - if ((IdTable[TableIndex].Access != SK_PNMI_RW) && - (IdTable[TableIndex].Access != SK_PNMI_WO)) { - - continue; - } - - InstanceNo = IdTable[TableIndex].InstanceNo; - Id = IdTable[TableIndex].Id; - - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * Because VPD multiple instance variables are - * not setable we do not need to evaluate VPD - * instances. Have a look to VPD instance - * calculation in SkPnmiGetStruct(). - */ - Instance = (SK_U32)InstanceCnt; - - /* - * Evaluate needed buffer length - */ - Len = 0; - Ret = IdTable[TableIndex].Func(pAC, IoC, - SK_PNMI_GET, IdTable[TableIndex].Id, - NULL, &Len, Instance, TableIndex, NetIndex); - - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - if (Ret != SK_PNMI_ERR_TOO_SHORT) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, - SK_PNMI_ERR_GENERAL, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - if (Id == OID_SKGE_VPD_ACTION) { - - switch (*(pBuf + DstOffset)) { - - case SK_PNMI_VPD_CREATE: - Len = 3 + *(pBuf + DstOffset + 3); - break; - - case SK_PNMI_VPD_DELETE: - Len = 3; - break; - - default: - Len = 1; - break; - } - } - - /* Call the OID handler function */ - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, - IdTable[TableIndex].Id, pBuf + DstOffset, - &Len, Instance, TableIndex, NetIndex); - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, - DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - } - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * LookupId - Lookup an OID in the IdTable - * - * Description: - * Scans the IdTable to find the table entry of an OID. - * - * Returns: - * The table index or -1 if not found. - */ -PNMI_STATIC int LookupId( -SK_U32 Id) /* Object identifier to be searched */ -{ - int i; - - for (i = 0; i < ID_TABLE_SIZE; i++) { - - if (IdTable[i].Id == Id) { - - return i; - } - } - - return (-1); -} - -/***************************************************************************** - * - * OidStruct - Handler of OID_SKGE_ALL_DATA - * - * Description: - * This OID performs a Get/Preset/SetStruct call and returns all data - * in a SK_PNMI_STRUCT_DATA structure. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int OidStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - if (Id != OID_SKGE_ALL_DATA) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, - SK_PNMI_ERR003MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - switch (Action) { - - case SK_PNMI_GET: - return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_PRESET: - return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_SET: - return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); -} - -/***************************************************************************** - * - * Perform - OID handler of OID_SKGE_ACTION - * - * Description: - * None. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Perform( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - SK_U32 ActionOp; - - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Check if a get should be performed */ - if (Action == SK_PNMI_GET) { - - /* A get is easy. We always return the same value */ - ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; - SK_PNMI_STORE_U32(pBuf, ActionOp); - *pLen = sizeof(SK_U32); - - return (SK_PNMI_ERR_OK); - } - - /* Continue with PRESET/SET action */ - if (*pLen > sizeof(SK_U32)) { - - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* Check if the command is a known one */ - SK_PNMI_READ_U32(pBuf, ActionOp); - if (*pLen > sizeof(SK_U32) || - (ActionOp != SK_PNMI_ACT_IDLE && - ActionOp != SK_PNMI_ACT_RESET && - ActionOp != SK_PNMI_ACT_SELFTEST && - ActionOp != SK_PNMI_ACT_RESETCNT)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - switch (ActionOp) { - - case SK_PNMI_ACT_IDLE: - /* Nothing to do */ - break; - - case SK_PNMI_ACT_RESET: - /* - * Perform a driver reset or something that comes near - * to this. - */ - Ret = SK_DRIVER_RESET(pAC, IoC); - if (Ret != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, - SK_PNMI_ERR005MSG); - - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_ACT_SELFTEST: - /* - * Perform a driver selftest or something similar to this. - * Currently this feature is not used and will probably - * implemented in another way. - */ - Ret = SK_DRIVER_SELFTEST(pAC, IoC); - pAC->Pnmi.TestResult = Ret; - break; - - case SK_PNMI_ACT_RESETCNT: - /* Set all counters and timestamps to zero */ - ResetCounter(pAC, IoC, NetIndex); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, - SK_PNMI_ERR006MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX - * - * Description: - * Retrieves the statistic values of the virtual port (logical - * index 0). Only special OIDs of NDIS are handled which consist - * of a 32 bit instead of a 64 bit value. The OIDs are public - * because perhaps some other platform can use them too. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Mac8023Stat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - SK_U64 StatVal; - SK_U32 StatVal32; - SK_BOOL Is64BitReq = SK_FALSE; - - /* - * Only the active Mac is returned - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action type - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check length - */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: - if (*pLen < sizeof(SK_MAC_ADDR)) { - - *pLen = sizeof(SK_MAC_ADDR); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* - * for compatibility, at least 32bit are required for oid - */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - } - - /* - * Update all statistics, because we retrieve virtual MAC, which - * consists of multiple physical statistics and increment semaphore - * to indicate that an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if ( Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Get value (MAC Index 0 identifies the virtual MAC) - */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - case OID_802_3_CURRENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - default: - StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - StatVal32 = (SK_U32)StatVal; - SK_PNMI_STORE_U32(pBuf, StatVal32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, StatVal); - *pLen = sizeof(SK_U64); - } - break; - } - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX - * - * Description: - * Retrieves the XMAC statistic data. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortMax; - unsigned int Limit; - unsigned int Offset; - int Ret; - SK_U64 StatVal; - - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check length - */ - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Update XMAC statistic and increment semaphore to indicate that - * an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_TX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_RX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ - case OID_SKGE_STAT_RX: - case OID_SKGE_STAT_TX: - switch (pAC->GIni.GIMacType) { - case SK_MAC_XMAC: - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - break; - - case SK_MAC_GMAC: - if (Id == OID_SKGE_STAT_TX) { - - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_UNICAST, NetIndex); - } - else { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNDERSIZE, NetIndex); - } - break; - - default: - StatVal = 0; - break; - } - - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - break; - - default: - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - break; - } - - Offset += sizeof(SK_U64); - } - *pLen = Offset; - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR - * - * Description: - * Get/Presets/Sets the current and factory MAC address. The MAC - * address of the virtual port, which is reported to the OS, may - * not be changed, but the physical ones. A set to the virtual port - * will be ignored. No error should be reported because otherwise - * a multiple instance set (-1) would always fail. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Addr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - unsigned int LogPortMax; - unsigned int PhysPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset = 0; - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform Action - */ - if (Action == SK_PNMI_GET) { - - /* - * Check length - */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_PHYS_CUR_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); - } - Offset += 6; - break; - - case OID_SKGE_PHYS_FAC_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, - &pAC->Addr.Net[NetIndex].PermanentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); - } - Offset += 6; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, - SK_PNMI_ERR008MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - *pLen = Offset; - } - else { - /* - * The logical MAC address may not be changed only - * the physical ones - */ - if (Id == OID_SKGE_PHYS_FAC_ADDR) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Only the current address may be changed - */ - if (Id != OID_SKGE_PHYS_CUR_ADDR) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, - SK_PNMI_ERR009MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Check length - */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > (Limit - LogPortIndex) * 6) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* - * Check Action - */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Set OID_SKGE_MAC_CUR_ADDR - */ - for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { - - /* - * A set to virtual port and set of broadcast - * address will be ignored - */ - if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, - "\xff\xff\xff\xff\xff\xff", 6) == 0) { - - continue; - } - - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, - LogPortIndex); - - Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, - (SK_MAC_ADDR *)(pBuf + Offset), - (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : - SK_ADDR_PHYSICAL_ADDRESS)); - if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { - - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX - * - * Description: - * Retrieves the statistic values of the CSUM module. The CSUM data - * structure must be available in the SK_AC even if the CSUM module - * is not included, because PNMI reads the statistic data from the - * CSUM part of SK_AC directly. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int CsumStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset = 0; - SK_U64 StatVal; - - - /* - * Calculate instance if wished - */ - if (Instance != (SK_U32)(-1)) { - - if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - Index = (unsigned int)Instance - 1; - Limit = Index + 1; - } - else { - Index = 0; - Limit = SKCS_NUM_PROTOCOLS; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check length - */ - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_CHKSM_RX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; - break; - - case OID_SKGE_CHKSM_RX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; - break; - - case OID_SKGE_CHKSM_RX_ERR_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; - break; - - case OID_SKGE_CHKSM_TX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; - break; - - case OID_SKGE_CHKSM_TX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, - SK_PNMI_ERR010MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - Offset += sizeof(SK_U64); - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX - * - * Description: - * Retrieves the statistic values of the I2C module, which handles - * the temperature and voltage sensors. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int SensorStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int i; - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Len; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Calculate instance if wished - */ - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance -1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = (unsigned int) pAC->I2c.MaxSens; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check length - */ - switch (Id) { - - case OID_SKGE_SENSOR_VALUE: - case OID_SKGE_SENSOR_WAR_THRES_LOW: - case OID_SKGE_SENSOR_WAR_THRES_UPP: - case OID_SKGE_SENSOR_ERR_THRES_LOW: - case OID_SKGE_SENSOR_ERR_THRES_UPP: - if (*pLen < (Limit - Index) * sizeof(SK_U32)) { - - *pLen = (Limit - Index) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_DESCR: - for (Offset = 0, i = Index; i < Limit; i ++) { - - Len = (unsigned int) - SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; - if (Len >= SK_PNMI_STRINGLEN2) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, - SK_PNMI_ERR011MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Offset += Len; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_INDEX: - case OID_SKGE_SENSOR_TYPE: - case OID_SKGE_SENSOR_STATUS: - if (*pLen < Limit - Index) { - - *pLen = Limit - Index; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_WAR_CTS: - case OID_SKGE_SENSOR_WAR_TIME: - case OID_SKGE_SENSOR_ERR_CTS: - case OID_SKGE_SENSOR_ERR_TIME: - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, - SK_PNMI_ERR012MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Get value - */ - for (Offset = 0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_SENSOR_INDEX: - *(pBuf + Offset) = (char)Index; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_DESCR: - Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); - SK_MEMCPY(pBuf + Offset + 1, - pAC->I2c.SenTable[Index].SenDesc, Len); - *(pBuf + Offset) = (char)Len; - Offset += Len + 1; - break; - - case OID_SKGE_SENSOR_TYPE: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenType; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_VALUE: - Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_UPP: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreErrLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_UPP: - Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_STATUS: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenErrFlag; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_WAR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenWarnCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenErrCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_WAR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegWarnTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegErrTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("SensorStat: Unknown OID should be handled before")); - - return (SK_PNMI_ERR_GENERAL); - } - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Vpd - OID handler function of OID_SKGE_VPD_XXX - * - * Description: - * Get/preset/set of VPD data. As instance the name of a VPD key - * can be passed. The Instance parameter is a SK_U32 and can be - * used as a string buffer for the VPD key, because their maximum - * length is 4 byte. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Vpd( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_VPD_STATUS *pVpdStatus; - unsigned int BufLen; - char Buf[256]; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - char KeyStr[SK_PNMI_VPD_KEY_SIZE]; - unsigned int KeyNo; - unsigned int Offset; - unsigned int Index; - unsigned int FirstIndex; - unsigned int LastIndex; - unsigned int Len; - int Ret; - SK_U32 Val32; - - /* - * Get array of all currently stored VPD keys - */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), - &KeyNo); - if (Ret != SK_PNMI_ERR_OK) { - *pLen = 0; - return (Ret); - } - - /* - * If instance is not -1, try to find the requested VPD key for - * the multiple instance variables. The other OIDs as for example - * OID VPD_ACTION are single instance variables and must be - * handled separatly. - */ - FirstIndex = 0; - LastIndex = KeyNo; - - if ((Instance != (SK_U32)(-1))) { - - if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - SK_STRNCPY(KeyStr, (char *)&Instance, 4); - KeyStr[4] = 0; - - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - FirstIndex = Index; - LastIndex = Index+1; - break; - } - } - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - else if (Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - - /* - * Get value, if a query should be performed - */ - if (Action == SK_PNMI_GET) { - - switch (Id) { - - case OID_SKGE_VPD_FREE_BYTES: - /* Check length of buffer */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Get number of free bytes */ - pVpdStatus = VpdStat(pAC, IoC); - if (pVpdStatus == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, - SK_PNMI_ERR017MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, - SK_PNMI_ERR018MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Val32 = (SK_U32)pVpdStatus->vpd_free_rw; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_ENTRIES_LIST: - /* Check length */ - for (Len = 0, Index = 0; Index < KeyNo; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Get value */ - *(pBuf) = (char)Len - 1; - for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); - - Offset += Len; - - if (Index < KeyNo - 1) { - - *(pBuf + Offset) = ' '; - Offset ++; - } - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ENTRIES_NUMBER: - /* Check length */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Val32 = (SK_U32)KeyNo; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_KEY: - /* Check buffer length, if it is large enough */ - for (Len = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the key to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - - *(pBuf + Offset) = (char)Len; - SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], - Len); - Offset += Len + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_VALUE: - /* Check the buffer length if it is large enough */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR021, - SK_PNMI_ERR021MSG); - - return (SK_PNMI_ERR_GENERAL); - } - Offset += BufLen + 1; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the value to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR022, - SK_PNMI_ERR022MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - *(pBuf + Offset) = (char)BufLen; - SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); - Offset += BufLen + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACCESS: - if (*pLen < LastIndex - FirstIndex) { - - *pLen = LastIndex - FirstIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - if (VpdMayWrite(KeyArr[Index])) { - - *(pBuf + Offset) = SK_PNMI_VPD_RW; - } - else { - *(pBuf + Offset) = SK_PNMI_VPD_RO; - } - Offset ++; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACTION: - Offset = LastIndex - FirstIndex; - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - SK_MEMSET(pBuf, 0, Offset); - *pLen = Offset; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, - SK_PNMI_ERR023MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - else { - /* The only OID which can be set is VPD_ACTION */ - if (Id != OID_SKGE_VPD_ACTION) { - - if (Id == OID_SKGE_VPD_FREE_BYTES || - Id == OID_SKGE_VPD_ENTRIES_LIST || - Id == OID_SKGE_VPD_ENTRIES_NUMBER || - Id == OID_SKGE_VPD_KEY || - Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, - SK_PNMI_ERR024MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * From this point we handle VPD_ACTION. Check the buffer - * length. It should at least have the size of one byte. - */ - if (*pLen < 1) { - - *pLen = 1; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * The first byte contains the VPD action type we should - * perform. - */ - switch (*pBuf) { - - case SK_PNMI_VPD_IGNORE: - /* Nothing to do */ - break; - - case SK_PNMI_VPD_CREATE: - /* - * We have to create a new VPD entry or we modify - * an existing one. Check first the buffer length. - */ - if (*pLen < 4) { - - *pLen = 4; - return (SK_PNMI_ERR_TOO_SHORT); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* - * Is the entry writable or does it belong to the - * read-only area? - */ - if (!VpdMayWrite(KeyStr)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - Offset = (int)pBuf[3] & 0xFF; - - SK_MEMCPY(Buf, pBuf + 4, Offset); - Buf[Offset] = 0; - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Write the new entry or modify an existing one */ - Ret = VpdWrite(pAC, IoC, KeyStr, Buf); - if (Ret == SK_PNMI_VPD_NOWRITE ) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - else if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, - SK_PNMI_ERR025MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, - SK_PNMI_ERR026MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_VPD_DELETE: - /* Check if the buffer size is plausible */ - if (*pLen < 3) { - - *pLen = 3; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > 3) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* Find the passed key in the array */ - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - - break; - } - } - /* - * If we cannot find the key it is wrong, so we - * return an appropriate error value. - */ - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Ok, you wanted it and you will get it */ - Ret = VpdDelete(pAC, IoC, KeyStr); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, - SK_PNMI_ERR027MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, - SK_PNMI_ERR028MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * General - OID handler function of various single instance OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int General( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - unsigned int Index; - unsigned int Len; - unsigned int Offset; - unsigned int Val; - SK_U8 Val8; - SK_U16 Val16; - SK_U32 Val32; - SK_U64 Val64; - SK_U64 Val64RxHwErrs = 0; - SK_U64 Val64TxHwErrs = 0; - SK_BOOL Is64BitReq = SK_FALSE; - char Buf[256]; - int MacType; - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action. We only allow get requests. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - MacType = pAC->GIni.GIMacType; - - /* - * Check length for the various supported OIDs - */ - switch (Id) { - - case OID_GEN_XMIT_ERROR: - case OID_GEN_RCV_ERROR: - case OID_GEN_RCV_NO_BUFFER: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* - * for compatibility, at least 32bit are required for oid - */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - - case OID_SKGE_PORT_NUMBER: - case OID_SKGE_DEVICE_TYPE: - case OID_SKGE_RESULT: - case OID_SKGE_RLMT_MONITOR_NUMBER: - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - case OID_SKGE_TRAP_NUMBER: - case OID_SKGE_MDB_VERSION: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_CHIPSET: - if (*pLen < sizeof(SK_U16)) { - - *pLen = sizeof(SK_U16); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_BUS_TYPE: - case OID_SKGE_BUS_SPEED: - case OID_SKGE_BUS_WIDTH: - case OID_SKGE_SENSOR_NUMBER: - case OID_SKGE_CHKSM_NUMBER: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - case OID_SKGE_TX_SW_QUEUE_MAX: - case OID_SKGE_TX_RETRY: - case OID_SKGE_RX_INTR_CTS: - case OID_SKGE_TX_INTR_CTS: - case OID_SKGE_RX_NO_BUF_CTS: - case OID_SKGE_TX_NO_BUF_CTS: - case OID_SKGE_TX_USED_DESCR_NO: - case OID_SKGE_RX_DELIVERED_CTS: - case OID_SKGE_RX_OCTETS_DELIV_CTS: - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_SKGE_ERR_RECOVERY_CTS: - case OID_SKGE_SYSUPTIME: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - /* Checked later */ - break; - } - - /* Update statistic */ - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - /* Force the XMAC to update its statistic counters and - * Increment semaphore to indicate that an update was - * already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Some OIDs consist of multiple hardware counters. Those - * values which are contained in all of them will be added - * now. - */ - switch (Id) { - - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_GEN_RCV_ERROR: - Val64RxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex)+ - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex)+ - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_GEN_XMIT_ERROR: - Val64TxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex)+ - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex)+ - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); - break; - } - } - - /* - * Retrieve value - */ - switch (Id) { - - case OID_SKGE_SUPPORTED_LIST: - Len = ID_TABLE_SIZE * sizeof(SK_U32); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - for (Offset = 0, Index = 0; Offset < Len; - Offset += sizeof(SK_U32), Index ++) { - - Val32 = (SK_U32)IdTable[Index].Id; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - } - *pLen = Len; - break; - - case OID_SKGE_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DEVICE_TYPE: - Val32 = (SK_U32)pAC->Pnmi.DeviceType; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DRIVER_DESCR: - if (pAC->Pnmi.pDriverDescription == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, - SK_PNMI_ERR007MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, - SK_PNMI_ERR029MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_VERSION: - if (pAC->Pnmi.pDriverVersion == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR030MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR031MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_DESCR: - /* - * The hardware description is located in the VPD. This - * query may move to the initialisation routine. But - * the VPD data is cached and therefore a call here - * will not make much difference. - */ - Len = 256; - if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, - SK_PNMI_ERR032MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Len ++; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, - SK_PNMI_ERR033MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, Buf, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_VERSION: - /* Oh, I love to do some string manipulation */ - if (*pLen < 5) { - - *pLen = 5; - return (SK_PNMI_ERR_TOO_SHORT); - } - Val8 = (SK_U8)pAC->GIni.GIPciHwRev; - pBuf[0] = 4; - pBuf[1] = 'v'; - pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); - pBuf[3] = '.'; - pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); - *pLen = 5; - break; - - case OID_SKGE_CHIPSET: - Val16 = pAC->Pnmi.Chipset; - SK_PNMI_STORE_U16(pBuf, Val16); - *pLen = sizeof(SK_U16); - break; - - case OID_SKGE_BUS_TYPE: - *pBuf = (char)SK_PNMI_BUS_PCI; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_SPEED: - *pBuf = pAC->Pnmi.PciBusSpeed; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_WIDTH: - *pBuf = pAC->Pnmi.PciBusWidth; - *pLen = sizeof(char); - break; - - case OID_SKGE_RESULT: - Val32 = pAC->Pnmi.TestResult; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_NUMBER: - *pBuf = (char)pAC->I2c.MaxSens; - *pLen = sizeof(char); - break; - - case OID_SKGE_CHKSM_NUMBER: - *pBuf = SKCS_NUM_PROTOCOLS; - *pLen = sizeof(char); - break; - - case OID_SKGE_TRAP_NUMBER: - GetTrapQueueLen(pAC, &Len, &Val); - Val32 = (SK_U32)Val; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TRAP: - GetTrapQueueLen(pAC, &Len, &Val); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - CopyTrapQueue(pAC, pBuf); - *pLen = Len; - break; - - case OID_SKGE_RLMT_MONITOR_NUMBER: -/* XXX Not yet implemented by RLMT therefore we return zero elements */ - Val32 = 0; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + - pAC->Pnmi.BufPort[1].TxSwQueueLen; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + - pAC->Pnmi.Port[1].TxSwQueueLen; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - - case OID_SKGE_TX_SW_QUEUE_MAX: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + - pAC->Pnmi.BufPort[1].TxSwQueueMax; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + - pAC->Pnmi.Port[1].TxSwQueueMax; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_RETRY: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + - pAC->Pnmi.BufPort[1].TxRetryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxRetryCts + - pAC->Pnmi.Port[1].TxRetryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + - pAC->Pnmi.BufPort[1].RxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxIntrCts + - pAC->Pnmi.Port[1].RxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + - pAC->Pnmi.BufPort[1].TxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxIntrCts + - pAC->Pnmi.Port[1].TxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_USED_DESCR_NO: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + - pAC->Pnmi.BufPort[1].TxUsedDescrNo; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + - pAC->Pnmi.Port[1].TxUsedDescrNo; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_DELIVERED_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + - pAC->Pnmi.BufPort[1].RxDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + - pAC->Pnmi.Port[1].RxDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_OCTETS_DELIV_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + - pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + - pAC->Pnmi.Port[1].RxOctetsDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_IN_ERRORS_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_OUT_ERROR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_ERR_RECOVERY_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + - pAC->Pnmi.BufPort[1].ErrRecoveryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + - pAC->Pnmi.Port[1].ErrRecoveryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_SYSUPTIME: - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - Val64 -= pAC->Pnmi.StartUpTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_MDB_VERSION: - Val32 = SK_PNMI_MDB_VERSION; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_GEN_RCV_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_XMIT_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - else { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_RCV_NO_BUFFER: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, - SK_PNMI_ERR034MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - pAC->Pnmi.MacUpdatedFlag --; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. - * - * Description: - * Get/Presets/Sets the RLMT OIDs. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Rlmt( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - int Ret; - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_EVPARA EventParam; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Check instance. Only single instance OIDs are allowed here. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Perform the requested action - */ - if (Action == SK_PNMI_GET) { - - /* - * Check if the buffer length is large enough. - */ - - switch (Id) { - - case OID_SKGE_RLMT_MODE: - case OID_SKGE_RLMT_PORT_ACTIVE: - case OID_SKGE_RLMT_PORT_PREFERRED: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - case OID_SKGE_RLMT_CHANGE_TIME: - case OID_SKGE_RLMT_CHANGE_ESTIM: - case OID_SKGE_RLMT_CHANGE_THRES: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, - SK_PNMI_ERR035MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update RLMT statistic and increment semaphores to indicate - * that an update was already done. Maybe RLMT will hold its - * statistic always up to date some time. Then we can - * remove this type of call. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Retrieve Value - */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_PORT_ACTIVE: - *pBuf = 0; - /* - * If multiple ports may become active this OID - * doesn't make sense any more. A new variable in - * the port structure should be created. However, - * for this variable the first active port is - * returned. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); - break; - } - } - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - Val64 = pAC->Pnmi.RlmtChangeCts; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_TIME: - Val64 = pAC->Pnmi.RlmtChangeTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_ESTIM: - Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - Val64 = pAC->Pnmi.RlmtChangeThreshold; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("Rlmt: Unknown OID should be handled before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - pAC->Pnmi.RlmtUpdatedFlag --; - } - else { - /* Perform a preset or set */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || - (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || - *(SK_U8 *)pBuf > 15) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* Send an event to RLMT to change the mode */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] |= (SK_U32)(*pBuf); - EventParam.Para32[1] = 0; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, - SK_PNMI_ERR037MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > - (SK_U8)pAC->GIni.GIMacsFound) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Send an event to RLMT change the preferred port. - * A param of -1 means automatic mode. RLMT will - * make the decision which is the preferred port. - */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; - EventParam.Para32[1] = NetIndex; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, - SK_PNMI_ERR038MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* - * There are not many restrictions to the - * value range. - */ - if (*pLen != sizeof(SK_U64)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* - * Store the new threshold, which will be taken - * on the next timer event. - */ - SK_PNMI_READ_U64(pBuf, Val64); - pAC->Pnmi.RlmtChangeThreshold = Val64; - break; - - default: - /* The other OIDs are not be able for set */ - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. - * - * Description: - * Performs get requests on multiple instance variables. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int RlmtStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset; - int Ret; - SK_U32 Val32; - SK_U64 Val64; - - /* - * Calculate the port indexes from the instance - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - if ((Instance != (SK_U32)(-1))) { - /* Check instance range */ - if ((Instance < 1) || (Instance > PhysPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* Single net mode */ - PhysPortIndex = Instance - 1; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - - /* Both net modes */ - Limit = PhysPortIndex + 1; - } - else { - /* Single net mode */ - PhysPortIndex = 0; - Limit = PhysPortMax; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - Limit = PhysPortIndex + 1; - } - } - - /* - * Currently only get requests are allowed. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check if the buffer length is large enough. - */ - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - case OID_SKGE_RLMT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - case OID_SKGE_RLMT_RX_HELLO_CTS: - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - case OID_SKGE_RLMT_RX_SP_CTS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, - SK_PNMI_ERR039MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Update statistic and increment semaphores to indicate that - * an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex ++) { - - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - Val32 = PhysPortIndex; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_STATUS: - if (pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_INIT || - pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_DOWN) { - - Val32 = SK_PNMI_RLMT_STATUS_ERROR; - } - else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; - } - else { - Val32 = SK_PNMI_RLMT_STATUS_STANDBY; - } - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_SP_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("RlmtStat: Unknown OID should be errored before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - - pAC->Pnmi.RlmtUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateConf - OID handler function of OIDs concerning the configuration - * - * Description: - * Get/Presets/Sets the OIDs concerning the configuration. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int Limit; - unsigned int Offset; - char Val8; - int Ret; - SK_EVPARA EventParam; - SK_U32 Val32; - - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* - * Check length - */ - switch (Id) { - - case OID_SKGE_PMD: - case OID_SKGE_CONNECTOR: - case OID_SKGE_LINK_CAP: - case OID_SKGE_LINK_MODE: - case OID_SKGE_LINK_MODE_STATUS: - case OID_SKGE_LINK_STATUS: - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_FLOWCTRL_STATUS: - case OID_SKGE_PHY_OPERATION_CAP: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_PHY_OPERATION_STATUS: - case OID_SKGE_SPEED_CAP: - case OID_SKGE_SPEED_MODE: - case OID_SKGE_SPEED_STATUS: - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { - - *pLen = (Limit - LogPortIndex) * - sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, - SK_PNMI_ERR041MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update statistic and increment semaphore to indicate - * that an update was already done. - */ - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.SirqUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_PMD: - *(pBuf + Offset) = pAC->Pnmi.PMD; - Offset += sizeof(char); - break; - - case OID_SKGE_CONNECTOR: - *(pBuf + Offset) = pAC->Pnmi.Connector; - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkCap; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkCap; - Offset += sizeof(char); - } - break; - - case OID_SKGE_LINK_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkModeConf; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkModeConf; - Offset += sizeof(char); - } - break; - - case OID_SKGE_LINK_MODE_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = - CalculateLinkModeStatus(pAC, - IoC, PhysPortIndex); - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - *(pBuf + Offset) = CalculateLinkModeStatus(pAC, IoC, NetIndex); - Offset += sizeof(char); - } - break; - - case OID_SKGE_LINK_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = - CalculateLinkStatus(pAC, - IoC, PhysPortIndex); - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = CalculateLinkStatus(pAC, IoC, NetIndex); - Offset += sizeof(char); - } - break; - - case OID_SKGE_FLOWCTRL_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlCap; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlCap; - Offset += sizeof(char); - } - break; - - case OID_SKGE_FLOWCTRL_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlMode; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlMode; - Offset += sizeof(char); - } - break; - - case OID_SKGE_FLOWCTRL_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlStatus; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; - Offset += sizeof(char); - } - break; - - case OID_SKGE_PHY_OPERATION_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSCap; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSCap; - Offset += sizeof(char); - } - break; - - case OID_SKGE_PHY_OPERATION_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSMode; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSMode; - Offset += sizeof(char); - } - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSStatus; - } - Offset += sizeof(char); - } - else { - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSStatus; - Offset += sizeof(char); - } - break; - - case OID_SKGE_SPEED_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeedCap; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedCap; - Offset += sizeof(char); - } - break; - - case OID_SKGE_SPEED_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeed; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeed; - Offset += sizeof(char); - } - break; - - case OID_SKGE_SPEED_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeedUsed; - } - Offset += sizeof(char); - } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; - Offset += sizeof(char); - } - break; - - case OID_SKGE_MTU: - Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before")); - - pAC->Pnmi.SirqUpdatedFlag --; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - pAC->Pnmi.SirqUpdatedFlag --; - - return (SK_PNMI_ERR_OK); - } - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - switch (Id) { - - case OID_SKGE_LINK_MODE: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_SPEED_MODE: - if (*pLen < Limit - LogPortIndex) { - - *pLen = Limit - LogPortIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != Limit - LogPortIndex) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != sizeof(SK_U32)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Perform preset or set - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_LINK_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_LMODE_HALF || - (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || - (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new link mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new link mode to - * the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_FLOW_MODE_NONE || - (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || - (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, EventParam) - > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_MODE : - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - /* mode of this port remains unchanged */ - Offset += sizeof(char); - break; - } - if (Val8 < SK_MS_MODE_AUTO || - (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || - (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with new master/slave (role) mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new master/slave - * (role) mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < (SK_LSPEED_AUTO) || - (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || - (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_MTU : - /* Check the value range */ - Val32 = *(SK_U32*)(pBuf + Offset); - if (Val32 == 0) { - /* mtu of this port remains unchanged */ - Offset += sizeof(SK_U32); - break; - } - if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - return (SK_PNMI_ERR_GENERAL); - } - - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before set")); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Monitor - OID handler function for RLMT_MONITOR_XXX - * - * Description: - * Because RLMT currently does not support the monitoring of - * remote adapter cards, we return always an empty table. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Monitor( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Entries; - - - /* - * Calculate instance if wished. - */ -/* XXX Not yet implemented. Return always an empty table. */ - Entries = 0; - - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > Entries)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance - 1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = Entries; - } - - /* - * Get/Set value - */ - if (Action == SK_PNMI_GET) { - - for (Offset=0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_RLMT_MONITOR_INDEX: - case OID_SKGE_RLMT_MONITOR_ADDR: - case OID_SKGE_RLMT_MONITOR_ERRS: - case OID_SKGE_RLMT_MONITOR_TIMESTAMP: - case OID_SKGE_RLMT_MONITOR_ADMIN: - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, - SK_PNMI_ERR046MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - else { - /* Only MONITOR_ADMIN can be set */ - if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check if the length is plausible */ - if (*pLen < (Limit - Index)) { - - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Okay, we have a wide value range */ - if (*pLen != (Limit - Index)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } -/* - for (Offset=0; Index < Limit; Index ++) { - } -*/ -/* - * XXX Not yet implemented. Return always BAD_VALUE, because the table - * is empty. - */ - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * VirtualConf - Calculates the values of configuration OIDs for virtual port - * - * Description: - * We handle here the get of the configuration group OIDs, which are - * a little bit complicated. The virtual port consists of all currently - * active physical ports. If multiple ports are active and configured - * differently we get in some trouble to return a single value. So we - * get the value of the first active port and compare it with that of - * the other active ports. If they are not the same, we return a value - * that indicates that the state is indeterminated. - * - * Returns: - * Nothing - */ -PNMI_STATIC void VirtualConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf) /* Buffer to which to mgmt data will be retrieved */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - SK_U8 Val8; - SK_BOOL PortActiveFlag; - - - *pBuf = 0; - PortActiveFlag = SK_FALSE; - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - /* Check if the physical port is active */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - PortActiveFlag = SK_TRUE; - - switch (Id) { - - case OID_SKGE_LINK_CAP: - - /* - * Different capabilities should not happen, but - * in the case of the cases OR them all together. - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PLinkCap; - break; - - case OID_SKGE_LINK_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; - continue; - } - - /* - * If we find an active port with a different link - * mode than the first one we return a value that - * indicates that the link mode is indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkModeConf - ) { - - *pBuf = SK_LMODE_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_MODE_STATUS: - /* Get the link mode of the physical port */ - Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * mode status than the first one we return a value - * that indicates that the link mode status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_LMODE_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_STATUS: - /* Get the link status of the physical port */ - Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * status than the first one, we return a value - * that indicates that the link status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode) { - - *pBuf = SK_FLOW_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus) { - - *pBuf = SK_FLOW_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PMSCap; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSMode; - continue; - } - - /* - * If we find an active port with a different master/ - * slave mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSMode) { - - *pBuf = SK_MS_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSStatus; - continue; - } - - /* - * If we find an active port with a different master/ - * slave status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSStatus) { - - *pBuf = SK_MS_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeed) { - - *pBuf = SK_LSPEED_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed) { - - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - } - break; - } - } - - /* - * If no port is active return an indeterminated answer - */ - if (!PortActiveFlag) { - - switch (Id) { - - case OID_SKGE_LINK_CAP: - *pBuf = SK_LMODE_CAP_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE: - *pBuf = SK_LMODE_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE_STATUS: - *pBuf = SK_LMODE_STAT_INDETERMINATED; - break; - - case OID_SKGE_LINK_STATUS: - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - *pBuf = SK_FLOW_MODE_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_STATUS: - *pBuf = SK_FLOW_STAT_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_CAP: - *pBuf = SK_MS_CAP_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - *pBuf = SK_MS_MODE_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - *pBuf = SK_MS_STAT_INDETERMINATED; - break; - case OID_SKGE_SPEED_CAP: - *pBuf = SK_LSPEED_CAP_INDETERMINATED; - break; - - case OID_SKGE_SPEED_MODE: - *pBuf = SK_LSPEED_INDETERMINATED; - break; - - case OID_SKGE_SPEED_STATUS: - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - break; - } - } -} - -/***************************************************************************** - * - * CalculateLinkStatus - Determins the link status of a physical port - * - * Description: - * Determins the link status the following way: - * LSTAT_PHY_DOWN: Link is down - * LSTAT_AUTONEG: Auto-negotiation failed - * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port - * logically up. - * LSTAT_LOG_UP: RLMT marked the port as up - * - * Returns: - * Link status of physical port - */ -PNMI_STATIC SK_U8 CalculateLinkStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - - if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { - - Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { - - Result = SK_PNMI_RLMT_LSTAT_AUTONEG; - } - else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { - - Result = SK_PNMI_RLMT_LSTAT_LOG_UP; - } - else { - Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; - } - - return (Result); -} - -/***************************************************************************** - * - * CalculateLinkModeStatus - Determins the link mode status of a phys. port - * - * Description: - * The COMMON module only tells us if the mode is half or full duplex. - * But in the decade of auto sensing it is usefull for the user to - * know if the mode was negotiated or forced. Therefore we have a - * look to the mode, which was last used by the negotiation process. - * - * Returns: - * The link mode status - */ -PNMI_STATIC SK_U8 CalculateLinkModeStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - - /* Get the current mode, which can be full or half duplex */ - Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; - - /* Check if no valid mode could be found (link is down) */ - if (Result < SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_UNKNOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { - - /* - * Auto-negotiation was used to bring up the link. Change - * the already found duplex status that it indicates - * auto-negotiation was involved. - */ - if (Result == SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_AUTOHALF; - } - else if (Result == SK_LMODE_STAT_FULL) { - - Result = SK_LMODE_STAT_AUTOFULL; - } - } - - return (Result); -} - -/***************************************************************************** - * - * GetVpdKeyArr - Obtain an array of VPD keys - * - * Description: - * Read the VPD keys and build an array of VPD keys, which are - * easy to access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int GetVpdKeyArr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -char *pKeyArr, /* Ptr KeyArray */ -unsigned int KeyArrLen, /* Length of array in bytes */ -unsigned int *pKeyNo) /* Number of keys */ -{ - unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE; - char BufKeys[SK_PNMI_VPD_BUFSIZE]; - unsigned int StartOffset; - unsigned int Offset; - int Index; - int Ret; - - - SK_MEMSET(pKeyArr, 0, KeyArrLen); - - /* - * Get VPD key list - */ - Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, - (int *)pKeyNo); - if (Ret > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, - SK_PNMI_ERR014MSG); - - return (SK_PNMI_ERR_GENERAL); - } - /* If no keys are available return now */ - if (*pKeyNo == 0 || BufKeysLen == 0) { - - return (SK_PNMI_ERR_OK); - } - /* - * If the key list is too long for us trunc it and give a - * errorlog notification. This case should not happen because - * the maximum number of keys is limited due to RAM limitations - */ - if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, - SK_PNMI_ERR015MSG); - - *pKeyNo = SK_PNMI_VPD_ENTRIES; - } - - /* - * Now build an array of fixed string length size and copy - * the keys together. - */ - for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; - Offset ++) { - - if (BufKeys[Offset] != 0) { - - continue; - } - - if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, - SK_PNMI_ERR016MSG); - return (SK_PNMI_ERR_GENERAL); - } - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - - Index ++; - StartOffset = Offset + 1; - } - - /* Last key not zero terminated? Get it anyway */ - if (StartOffset < Offset) { - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SirqUpdate - Let the SIRQ update its internal values - * - * Description: - * Just to be sure that the SIRQ module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int SirqUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC) /* IO context handle */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.SirqUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, - SK_PNMI_ERR047MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtUpdate - Let the RLMT update its internal values - * - * Description: - * Just to be sure that the RLMT module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int RlmtUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.RlmtUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, - SK_PNMI_ERR048MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacUpdate - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values we send a command so that the statistic data will - * be written to apredefined memory area on the adapter. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int MacUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int FirstMac, /* Index of the first Mac to be updated */ -unsigned int LastMac) /* Index of the last Mac to be updated */ -{ - unsigned int MacIndex; - - /* - * Were the statistics already updated during the - * current PNMI call? - */ - if (pAC->Pnmi.MacUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an update command to all MACs specified */ - for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { - - /* - * 2002-09-13 pweber: Freeze the current sw counters. - * (That should be done as close as - * possible to the update of the - * hw counters) - */ - if (pAC->GIni.GIMacType == SK_MAC_XMAC) { - pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; - } - - /* 2002-09-13 pweber: Update the hw counter */ - if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { - - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * GetStatVal - Retrieve an XMAC statistic counter - * - * Description: - * Retrieves the statistic counter of a virtual or physical port. The - * virtual port is identified by the index 0. It consists of all - * currently active ports. To obtain the counter value for this port - * we must add the statistic counter of all active ports. To grant - * continuous counter values for the virtual port even when port - * switches occur we must additionally add a delta value, which was - * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. - * - * Returns: - * Requested statistic value - */ -PNMI_STATIC SK_U64 GetStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int LogPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex, /* Index to statistic value */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_U64 Val = 0; - - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - - PhysPortIndex = NetIndex; - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - else { /* Single Net mode */ - - if (LogPortIndex == 0) { - - PhysPortMax = pAC->GIni.GIMacsFound; - - /* Add counter of all active ports */ - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, - StatIndex); - } - } - - /* Correct value because of port switches */ - Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; - } - else { - /* Get counter value of physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - } - return (Val); -} - -/***************************************************************************** - * - * GetPhysStatVal - Get counter value for physical port - * - * Description: - * Builds a 64bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * in software by monitoring counter overflow interrupts in the - * event handler. To grant continous counter values during XMAC - * resets (caused by a workaround) we must add a delta value. - * The delta was calculated in the event handler when a - * SK_PNMI_EVT_XMAC_RESET was received. - * - * Returns: - * Counter value - */ -PNMI_STATIC SK_U64 GetPhysStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex) /* Index to statistic value */ -{ - SK_U64 Val = 0; - SK_U32 LowVal = 0; - SK_U32 HighVal = 0; - SK_U16 Word; - int MacType; - - SK_PNMI_PORT *pPnmiPrt; - SK_GEMACFUNC *pFnMac; - - MacType = pAC->GIni.GIMacType; - - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (pAC->GIni.GIMacType == SK_MAC_XMAC) { - pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; - } - else { - pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; - } - - pFnMac = &pAC->GIni.GIFunc; - - switch (StatIndex) { - case SK_PNMI_HTX: - case SK_PNMI_HRX: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_OCTET: - case SK_PNMI_HRX_OCTET: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_BURST: - case SK_PNMI_HTX_EXCESS_DEF: - case SK_PNMI_HTX_CARRIER: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_MACC: - /* GMAC only supports PAUSE MAC control frames */ - if (MacType == SK_MAC_GMAC) { - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, SK_PNMI_HTX_PMACC); - - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_COL: - case SK_PNMI_HRX_UNDERSIZE: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - - case SK_PNMI_HTX_DEFFERAL: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - /* - * XMAC counts frames with deferred transmission - * even in full-duplex mode. - * - * In full-duplex mode the counter remains constant! - */ - if ((pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || - (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_FULL)) { - - LowVal = 0; - HighVal = 0; - } - else { - /* Otherwise get contents of hardware register. */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_DEFFERAL][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - case SK_PNMI_HRX_BADOCTET: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_BADOCTETLOW: - return (Val); - - case SK_PNMI_HRX_LONGFRAMES: - /* For XMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_XMAC) { - return (pPnmiPrt->StatRxLongFrameCts); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_TOO_LONG: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - switch (MacType) { - case SK_MAC_GMAC: - /* For GMAC the SW counter is additionally managed by PNMI */ - Val += pPnmiPrt->StatRxFrameTooLongCts; - break; - - case SK_MAC_XMAC: - /* - * Frames longer than IEEE 802.3 frame max size are counted - * by XMAC in frame_too_long counter even reception of long - * frames was enabled and the frame was correct. - * So correct the value by subtracting RxLongFrame counter. - */ - Val -= pPnmiPrt->StatRxLongFrameCts; - break; - - default: - break; - } - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - break; - - case SK_PNMI_HRX_SHORTS: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - /* GM_RXE_FRAG?? */ - return (Val); - } - - /* - * XMAC counts short frame errors even if link down (#10620) - * - * If link-down the counter remains constant - */ - if (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { - - /* Otherwise get incremental difference */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - Val -= pPnmiPrt->RxShortZeroMark; - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - } - break; - - case SK_PNMI_HRX_MACC: - case SK_PNMI_HRX_MACC_UNKWN: - case SK_PNMI_HRX_BURST: - case SK_PNMI_HRX_MISSED: - case SK_PNMI_HRX_FRAMING: - case SK_PNMI_HRX_CARRIER: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_SYMBOL: - case SK_PNMI_HRX_CEXT: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - /* GM_RXE_FRAG?? */ - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_PMACC_ERR: - /* For GMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_GMAC) { - return (pPnmiPrt->StatRxPMaccErr); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC: - LowVal = (SK_U32)pPnmiPrt->StatSyncCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC_OCTET: - LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); - break; - - case SK_PNMI_HRX_FCS: - /* - * Broadcom filters fcs errors and counts it in - * Receive Error Counter register - */ - if (pAC->GIni.GP[PhysPortIndex].PhyType == SK_PHY_BCOM) { - /* do not read while not initialized (PHY_READ hangs!)*/ - if (pAC->GIni.GP[PhysPortIndex].PState) { - PHY_READ(IoC, &pAC->GIni.GP[PhysPortIndex], - PhysPortIndex, PHY_BCOM_RE_CTR, - &Word); - - LowVal = Word; - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - default: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - } - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - /* Correct value because of possible XMAC reset. XMAC Errata #2 */ - Val += pPnmiPrt->CounterOffset[StatIndex]; - - return (Val); -} - -/***************************************************************************** - * - * ResetCounter - Set all counters and timestamps to zero - * - * Description: - * Notifies other common modules which store statistic data to - * reset their counters and finally reset our own counters. - * - * Returns: - * Nothing - */ -PNMI_STATIC void ResetCounter( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) -{ - unsigned int PhysPortIndex; - SK_EVPARA EventParam; - - - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - - /* Notify sensor module */ - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); - - /* Notify RLMT module */ - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); - EventParam.Para32[1] = 0; - - /* Notify SIRQ module */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); - - /* Notify CSUM module */ -#ifdef SK_USE_CSUM - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, - EventParam); -#endif - - /* Clear XMAC statistic */ - for (PhysPortIndex = 0; PhysPortIndex < - (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { - - (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); - - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - CounterOffset, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].CounterOffset)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatSyncOctetsCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxLongFrameCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxFrameTooLongCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxPMaccErr)); - } - - /* - * Clear local statistics - */ - SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, - sizeof(pAC->Pnmi.VirtualCounterOffset)); - pAC->Pnmi.RlmtChangeCts = 0; - pAC->Pnmi.RlmtChangeTime = 0; - SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, - sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); - pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; - pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; - pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; - pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; - pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; - pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; -} - -/***************************************************************************** - * - * GetTrapEntry - Get an entry in the trap buffer - * - * Description: - * The trap buffer stores various events. A user application somehow - * gets notified that an event occured and retrieves the trap buffer - * contens (or simply polls the buffer). The buffer is organized as - * a ring which stores the newest traps at the beginning. The oldest - * traps are overwritten by the newest ones. Each trap entry has a - * unique number, so that applications may detect new trap entries. - * - * Returns: - * A pointer to the trap entry - */ -PNMI_STATIC char* GetTrapEntry( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* SNMP ID of the trap */ -unsigned int Size) /* Space needed for trap entry */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int BufFree = pAC->Pnmi.TrapBufFree; - unsigned int Beg = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - int Wrap; - unsigned int NeededSpace; - unsigned int EntrySize; - SK_U32 Val32; - SK_U64 Val64; - - - /* Last byte of entry will get a copy of the entry length */ - Size ++; - - /* - * Calculate needed buffer space */ - if (Beg >= Size) { - - NeededSpace = Size; - Wrap = SK_FALSE; - } - else { - NeededSpace = Beg + Size; - Wrap = SK_TRUE; - } - - /* - * Check if enough buffer space is provided. Otherwise - * free some entries. Leave one byte space between begin - * and end of buffer to make it possible to detect whether - * the buffer is full or empty - */ - while (BufFree < NeededSpace + 1) { - - if (End == 0) { - - End = SK_PNMI_TRAP_QUEUE_LEN; - } - - EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); - BufFree += EntrySize; - End -= EntrySize; -#ifdef DEBUG - SK_MEMSET(pBuf + End, (char)(-1), EntrySize); -#endif - if (End == BufPad) { -#ifdef DEBUG - SK_MEMSET(pBuf, (char)(-1), End); -#endif - BufFree += End; - End = 0; - BufPad = 0; - } - } - - /* - * Insert new entry as first entry. Newest entries are - * stored at the beginning of the queue. - */ - if (Wrap) { - - BufPad = Beg; - Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; - } - else { - Beg = Beg - Size; - } - BufFree -= NeededSpace; - - /* Save the current offsets */ - pAC->Pnmi.TrapQueueBeg = Beg; - pAC->Pnmi.TrapQueueEnd = End; - pAC->Pnmi.TrapBufPad = BufPad; - pAC->Pnmi.TrapBufFree = BufFree; - - /* Initialize the trap entry */ - *(pBuf + Beg + Size - 1) = (char)Size; - *(pBuf + Beg) = (char)Size; - Val32 = (pAC->Pnmi.TrapUnique) ++; - SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); - SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); - - return (pBuf + Beg); -} - -/***************************************************************************** - * - * CopyTrapQueue - Copies the trap buffer for the TRAP OID - * - * Description: - * On a query of the TRAP OID the trap buffer contents will be - * copied continuously to the request buffer, which must be large - * enough. No length check is performed. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyTrapQueue( -SK_AC *pAC, /* Pointer to adapter context */ -char *pDstBuf) /* Buffer to which the queued traps will be copied */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int DstOff = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - - /* - * Last byte containing a copy of the length will - * not be copied. - */ - *(pDstBuf + DstOff) = (char)(Len - 1); - SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); - DstOff += Len - 1; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } -} - -/***************************************************************************** - * - * GetTrapQueueLen - Get the length of the trap buffer - * - * Description: - * Evaluates the number of currently stored traps and the needed - * buffer size to retrieve them. - * - * Returns: - * Nothing - */ -PNMI_STATIC void GetTrapQueueLen( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int *pLen, /* Length in Bytes of all queued traps */ -unsigned int *pEntries) /* Returns number of trapes stored in queue */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int Entries = 0; - unsigned int TotalLen = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - TotalLen += Len - 1; - Entries ++; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } - - *pEntries = Entries; - *pLen = TotalLen; -} - -/***************************************************************************** - * - * QueueSimpleTrap - Store a simple trap to the trap buffer - * - * Description: - * A simple trap is a trap with now additional data. It consists - * simply of a trap code. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSimpleTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId) /* Type of sensor trap */ -{ - GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); -} - -/***************************************************************************** - * - * QueueSensorTrap - Stores a sensor trap in the trap buffer - * - * Description: - * Gets an entry in the trap buffer and fills it with sensor related - * data. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSensorTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of sensor trap */ -unsigned int SensorIndex) /* Index of sensor which caused the trap */ -{ - char *pBuf; - unsigned int Offset; - unsigned int DescrLen; - SK_U32 Val32; - - - /* Get trap buffer entry */ - DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); - pBuf = GetTrapEntry(pAC, TrapId, - SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); - Offset = SK_PNMI_TRAP_SIMPLE_LEN; - - /* Store additionally sensor trap related data */ - Val32 = OID_SKGE_SENSOR_INDEX; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)SensorIndex; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); - Offset += 9; - - Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = (char)DescrLen; - SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, - DescrLen); - Offset += DescrLen + 5; - - Val32 = OID_SKGE_SENSOR_TYPE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 1; - *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; - Offset += 6; - - Val32 = OID_SKGE_SENSOR_VALUE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); -} - -/***************************************************************************** - * - * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtNewMacTrap( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int ActiveMac) /* Index (0..n) of the currently active port */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, - SK_PNMI_TRAP_RLMT_CHANGE_LEN); - - Val32 = OID_SKGE_RLMT_PORT_ACTIVE; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; -} - -/***************************************************************************** - * - * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtPortTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of RLMT port trap */ -unsigned int PortIndex) /* Index of the port, which changed its state */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); - - Val32 = OID_SKGE_RLMT_PORT_INDEX; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; -} - -/***************************************************************************** - * - * CopyMac - Copies a MAC address - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyMac( -char *pDst, /* Pointer to destination buffer */ -SK_MAC_ADDR *pMac) /* Pointer of Source */ -{ - int i; - - - for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { - - *(pDst + i) = pMac->a[i]; - } -} - - -#ifdef SK_POWER_MGMT -/***************************************************************************** - * - * PowerManagement - OID handler function of PowerManagement OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ - -PNMI_STATIC int PowerManagement( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* - * Check length - */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { - - *pLen = sizeof(SK_PNP_CAPABILITIES); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_QUERY_POWER: - case OID_PNP_ENABLE_WAKE_UP: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_SET_POWER: - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, - SK_PNMI_ERR040MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Get value - */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_QUERY_POWER: - /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests - the miniport to indicate whether it can transition its NIC - to the low-power state. - A miniport driver must always return NDIS_STATUS_SUCCESS - to a query of OID_PNP_QUERY_POWER. */ - RetCode = SK_PNMI_ERR_OK; - break; - - /* NDIS handles these OIDs as write-only. - * So in case of get action the buffer with written length = 0 - * is returned - */ - case OID_PNP_SET_POWER: - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - *pLen = 0; - RetCode = SK_PNMI_ERR_OK; - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - break; - } - - return (RetCode); - } - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - switch (Id) { - case OID_PNP_SET_POWER: - case OID_PNP_ENABLE_WAKE_UP: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != sizeof(SK_U32)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Perform preset or set - */ - - /* POWER module does not support PRESET action */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - switch (Id) { - case OID_PNP_SET_POWER: - RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - } - - return (RetCode); -} -#endif /* SK_POWER_MGMT */ - - -/***************************************************************************** - * - * Vct - OID handler function of OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was performed successfully. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter). - * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. - * - */ - -PNMI_STATIC int Vct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which the mgmt data will be copied */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 LogPortMax; - SK_U32 PhysPortMax; - SK_U32 PhysPortIndex; - SK_U32 Limit; - SK_U32 Offset; - SK_BOOL Link; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - int i; - SK_EVPARA Para; - SK_U32 CableLength; - - /* - * Calculate the port indexes from the instance. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - /* Dual net mode? */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - LogPortMax--; - } - - if ((Instance != (SK_U32) (-1))) { - /* Check instance range. */ - if ((Instance < 2) || (Instance > LogPortMax)) { - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - else { - PhysPortIndex = Instance - 2; - } - Limit = PhysPortIndex + 1; - } - else { /* - * Instance == (SK_U32) (-1), get all Instances of that OID. - * - * Not implemented yet. May be used in future releases. - */ - PhysPortIndex = 0; - Limit = PhysPortMax; - } - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - if (pPrt->PHWLinkUp) { - Link = SK_TRUE; - } - else { - Link = SK_FALSE; - } - - /* - * Check MAC type. - */ - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Initialize backup data pointer. */ - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - /* - * Check action type. - */ - if (Action == SK_PNMI_GET) { - /* - * Check length. - */ - switch (Id) { - - case OID_SKGE_VCT_GET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_VCT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Get value. - */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - - case OID_SKGE_VCT_GET: - if ((Link == SK_FALSE) && - (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 0) { - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - SkEventDispatcher(pAC, IoC); - } - else { - ; /* VCT test is running. */ - } - } - - /* Get all results. */ - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - *(pBuf + Offset) = pPrt->PCableLen; - Offset += sizeof(SK_U8); - for (i = 0; i < 4; i++) { - SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); - Offset += sizeof(SK_U32); - } - for (i = 0; i < 4; i++) { - *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; - Offset += sizeof(SK_U8); - } - - RetCode = SK_PNMI_ERR_OK; - break; - - case OID_SKGE_VCT_STATUS: - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - RetCode = SK_PNMI_ERR_OK; - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - - } /* if SK_PNMI_GET */ - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - - /* - * Check length. - */ - switch (Id) { - case OID_SKGE_VCT_SET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform preset or set. - */ - - /* VCT does not support PRESET action. */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - case OID_SKGE_VCT_SET: /* Start VCT test. */ - if (Link == SK_FALSE) { - SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); - - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); - if (RetCode == 0) { /* RetCode: 0 => Start! */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; - - /* - * Start VCT timer counter. - */ - SK_MEMSET((char *) &Para, 0, sizeof(Para)); - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - else { /* RetCode: 2 => Running! */ - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - } - else { /* RetCode: 4 => Link! */ - RetCode = 4; - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - Offset += sizeof(SK_U32); - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - -} /* Vct */ - - -PNMI_STATIC void CheckVctStatus( -SK_AC *pAC, -SK_IOC IoC, -char *pBuf, -SK_U32 Offset, -SK_U32 PhysPortIndex) -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctData; - SK_U32 RetCode; - SK_U8 LinkSpeedUsed; - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - pVctData = (SK_PNMI_VCT *) (pBuf + Offset); - pVctData->VctStatus = SK_PNMI_VCT_NONE; - - if (!pPrt->PHWLinkUp) { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - else { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - /* Check VCT test status. */ - RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { /* VCT test is running. */ - pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; - } - else { /* VCT data was copied to pAC here. Check PENDING state. */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ - pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; - } - } - else { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - - /* DSP only valid in 100/1000 modes. */ - LinkSpeedUsed = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; - if (LinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; - } - } - -} /* CheckVctStatus */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skgesirq.c b/drivers/sk98lin/skgesirq.c deleted file mode 100644 index e5a4f7ec10..0000000000 --- a/drivers/sk98lin/skgesirq.c +++ /dev/null @@ -1,2417 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.83 $ - * Date: $Date: 2003/02/05 15:10:59 $ - * Purpose: Special IRQ module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgesirq.c,v $ - * Revision 1.83 2003/02/05 15:10:59 rschmidt - * Fixed setting of PLinkSpeedUsed in SkHWLinkUp() when - * auto-negotiation is disabled. - * Editorial changes. - * - * Revision 1.82 2003/01/29 13:34:33 rschmidt - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.81 2002/12/05 10:49:51 rschmidt - * Fixed missing Link Down Event for fiber (Bug Id #10768) - * Added reading of cable length when link is up - * Removed testing of unused error bits in PHY ISR - * Editorial changes. - * - * Revision 1.80 2002/11/12 17:15:21 rschmidt - * Replaced SkPnmiGetVar() by ...MacStatistic() in SkMacParity(). - * Editorial changes. - * - * Revision 1.79 2002/10/14 15:14:51 rschmidt - * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in - * SkMacParity() depending on GIChipRev (HW-Bug #8). - * Added error messages for GPHY Auto-Negotiation Error and - * FIFO Overflow/Underrun in SkPhyIsrGmac(). - * Editorial changes. - * - * Revision 1.78 2002/10/10 15:54:29 mkarl - * changes for PLinkSpeedUsed - * - * Revision 1.77 2002/09/12 08:58:51 rwahl - * Retrieve counters needed for XMAC errata workarounds directly because - * PNMI returns corrected counter values (e.g. #10620). - * - * Revision 1.76 2002/08/16 15:21:54 rschmidt - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. - * Editorial changes. - * - * Revision 1.75 2002/08/12 13:50:47 rschmidt - * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in - * SkMacParity() by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE (HW-Bug #8). - * Added clearing of IS_IRQ_TIST_OV and IS_IRQ_SENSOR in SkGeHwErr(). - * Corrected handling of Link Up and Auto-Negotiation Over for GPHY. - * in SkGePortCheckUpGmac(). - * Editorial changes. - * - * Revision 1.74 2002/08/08 16:17:04 rschmidt - * Added PhyType check for SK_HWEV_SET_ROLE event (copper only) - * Changed Link Up check reading PHY Specific Status (YUKON) - * Editorial changes - * - * Revision 1.73 2002/07/15 18:36:53 rwahl - * Editorial changes. - * - * Revision 1.72 2002/07/15 15:46:26 rschmidt - * Added new event: SK_HWEV_SET_SPEED - * Editorial changes - * - * Revision 1.71 2002/06/10 09:34:19 rschmidt - * Editorial changes - * - * Revision 1.70 2002/06/05 08:29:18 rschmidt - * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). - * Editorial changes. - * - * Revision 1.69 2002/04/25 13:03:49 rschmidt - * Changes for handling YUKON. - * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. - * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), - * SkMacIrqDisable(). - * Added handling for GMAC FIFO in SkMacParity(). - * Replaced all SkXm...() functions with SkMac...() to handle also - * YUKON's GMAC. - * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced - * by functions SkXmPhyRead(), SkXmPhyWrite(). - * Disabling all PHY interrupts moved to SkMacIrqDisable(). - * Added handling for GPHY IRQ in SkGeSirqIsr(). - * Removed status parameter from MAC IRQ handler SkMacIrq(). - * Added SkGePortCheckUpGmac(), SkPhyIsrGmac() for GMAC. - * Editorial changes - * - * Revision 1.68 2002/02/26 15:24:53 rwahl - * Fix: no link with manual configuration (#10673). The previous fix for - * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to - * misconfigured port. It should not occur for the other RLMT modes. - * - * Revision 1.67 2001/11/20 09:19:58 rwahl - * Reworked bugfix #10639 (no dependency to RLMT mode). - * - * Revision 1.66 2001/10/26 07:52:53 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.65 2001/02/23 13:41:51 gklug - * fix: PHYS2INST should be used correctly for Dual Net operation - * chg: do no longer work with older PNMI - * - * Revision 1.64 2001/02/15 11:27:04 rassmann - * Working with RLMT v1 if SK_MAX_NETS undefined. - * - * Revision 1.63 2001/02/06 10:44:23 mkunz - * - NetIndex added to interface functions of pnmi V4 with dual net support - * - * Revision 1.62 2001/01/31 15:31:41 gklug - * fix: problem with autosensing an SR8800 switch - * - * Revision 1.61 2000/11/09 11:30:09 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.60 2000/10/18 12:37:48 cgoos - * Reinserted the comment for version 1.56. - * - * Revision 1.59 2000/10/18 12:22:20 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.58 2000/09/28 13:06:04 gklug - * fix: BCom may NOT be touched if XMAC is in RESET state - * - * Revision 1.57 2000/09/08 12:38:39 cgoos - * Added forgotten variable declaration. - * - * Revision 1.56 2000/09/08 08:12:13 cgoos - * Changed handling of parity errors in SkGeHwErr (correct reset of error). - * - * Revision 1.55 2000/06/19 08:36:25 cgoos - * Changed comment. - * - * Revision 1.54 2000/05/22 08:45:57 malthoff - * Fix: #10523 is valid for all BCom PHYs. - * - * Revision 1.53 2000/05/19 10:20:30 cgoos - * Removed Solaris debug output code. - * - * Revision 1.52 2000/05/19 10:19:37 cgoos - * Added PHY state check in HWLinkDown. - * Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr. - * - * Revision 1.51 2000/05/18 05:56:20 cgoos - * Fixed typo. - * - * Revision 1.50 2000/05/17 12:49:49 malthoff - * Fixes BCom link bugs (#10523). - * - * Revision 1.49 1999/12/17 11:02:50 gklug - * fix: read PHY_STAT of Broadcom chip more often to assure good status - * - * Revision 1.48 1999/12/06 10:01:17 cgoos - * Added SET function for Role. - * - * Revision 1.47 1999/11/22 13:34:24 cgoos - * Changed license header to GPL. - * - * Revision 1.46 1999/09/16 10:30:07 cgoos - * Removed debugging output statement from Linux. - * - * Revision 1.45 1999/09/16 07:32:55 cgoos - * Fixed dual-port copperfield bug (PHY_READ from resetted port). - * Removed some unused variables. - * - * Revision 1.44 1999/08/03 15:25:04 cgoos - * Removed workaround for disabled interrupts in half duplex mode. - * - * Revision 1.43 1999/08/03 14:27:58 cgoos - * Removed SENSE mode code from SkGePortCheckUpBcom. - * - * Revision 1.42 1999/07/26 09:16:54 cgoos - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.41 1999/05/19 07:28:59 cgoos - * Changes for 1000Base-T. - * - * Revision 1.40 1999/04/08 13:59:39 gklug - * fix: problem with 3Com switches endless RESTARTs - * - * Revision 1.39 1999/03/08 10:10:52 gklug - * fix: AutoSensing did switch to next mode even if LiPa indicated offline - * - * Revision 1.38 1999/03/08 09:49:03 gklug - * fix: Bug using pAC instead of IoC, causing AIX problems - * fix: change compare for Linux compiler bug workaround - * - * Revision 1.37 1999/01/28 14:51:33 gklug - * fix: monitor for autosensing and extra RESETS the RX on wire counters - * - * Revision 1.36 1999/01/22 09:19:55 gklug - * fix: Init DupMode and InitPauseMd are now called in RxTxEnable - * - * Revision 1.35 1998/12/11 15:22:59 gklug - * chg: autosensing: check for receive if manual mode was guessed - * chg: simplified workaround for XMAC errata - * chg: wait additional 100 ms before link goes up. - * chg: autoneg timeout to 600 ms - * chg: restart autoneg even if configured to autonegotiation - * - * Revision 1.34 1998/12/10 10:33:14 gklug - * add: more debug messages - * fix: do a new InitPhy if link went down (AutoSensing problem) - * chg: Check for zero shorts if link is NOT up - * chg: reset Port if link goes down - * chg: wait additional 100 ms when link comes up to check shorts - * fix: dummy read extended autoneg status to prevent link going down immediately - * - * Revision 1.33 1998/12/07 12:18:29 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.32 1998/12/07 07:11:21 gklug - * fix: compiler warning - * - * Revision 1.31 1998/12/02 09:29:05 gklug - * fix: WA XMAC Errata: FCSCt check was not correct. - * fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks. - * fix: Clear Stat : now clears the Prev counters of all known Ports - * - * Revision 1.30 1998/12/01 10:54:15 gklug - * dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too. - * - * Revision 1.29 1998/12/01 10:01:53 gklug - * fix: if MAC IRQ occurs during port down, this will be handled correctly - * - * Revision 1.28 1998/11/26 16:22:11 gklug - * fix: bug in autosense if manual modes are used - * - * Revision 1.27 1998/11/26 15:50:06 gklug - * fix: PNMI needs to set PLinkModeConf - * - * Revision 1.26 1998/11/26 14:51:58 gklug - * add: AutoSensing functionalty - * - * Revision 1.25 1998/11/26 07:34:37 gklug - * fix: Init PrevShorts when restarting port due to Link connection - * - * Revision 1.24 1998/11/25 10:57:32 gklug - * fix: remove unreferenced local vars - * - * Revision 1.23 1998/11/25 08:26:40 gklug - * fix: don't do a RESET on a starting or stopping port - * - * Revision 1.22 1998/11/24 13:29:44 gklug - * add: Workaround for MAC parity errata - * - * Revision 1.21 1998/11/18 15:31:06 gklug - * fix: lint bugs - * - * Revision 1.20 1998/11/18 12:58:54 gklug - * fix: use PNMI query instead of hardware access - * - * Revision 1.19 1998/11/18 12:54:55 gklug - * chg: add new workaround for XMAC Errata - * add: short event counter monitoring on active link too - * - * Revision 1.18 1998/11/13 14:27:41 malthoff - * Bug Fix: Packet Arbiter Timeout was not cleared correctly - * for timeout on TX1 and TX2. - * - * Revision 1.17 1998/11/04 07:01:59 cgoos - * Moved HW link poll sequence. - * Added call to SkXmRxTxEnable. - * - * Revision 1.16 1998/11/03 13:46:03 gklug - * add: functionality of SET_LMODE and SET_FLOW_MODE - * fix: send RLMT LinkDown event when Port stop is given with LinkUp - * - * Revision 1.15 1998/11/03 12:56:47 gklug - * fix: Needs more events - * - * Revision 1.14 1998/10/30 07:36:35 gklug - * rmv: unnecessary code - * - * Revision 1.13 1998/10/29 15:21:57 gklug - * add: Poll link feature for activating HW link - * fix: Deactivate HWLink when Port STOP is given - * - * Revision 1.12 1998/10/28 07:38:57 cgoos - * Checking link status at begin of SkHWLinkUp. - * - * Revision 1.11 1998/10/22 09:46:50 gklug - * fix SysKonnectFileId typo - * - * Revision 1.10 1998/10/14 13:57:47 gklug - * add: Port start/stop event - * - * Revision 1.9 1998/10/14 05:48:29 cgoos - * Added definition for Para. - * - * Revision 1.8 1998/10/14 05:40:09 gklug - * add: Hardware Linkup signal used - * - * Revision 1.7 1998/10/09 06:50:20 malthoff - * Remove ID_sccs by SysKonnectFileId. - * - * Revision 1.6 1998/10/08 09:11:49 gklug - * add: clear IRQ commands - * - * Revision 1.5 1998/10/02 14:27:35 cgoos - * Fixed some typos and wrong event names. - * - * Revision 1.4 1998/10/02 06:24:17 gklug - * add: HW error function - * fix: OUT macros - * - * Revision 1.3 1998/10/01 07:03:00 gklug - * add: ISR for the usual interrupt source register - * - * Revision 1.2 1998/09/03 13:50:33 gklug - * add: function prototypes - * - * Revision 1.1 1998/08/27 11:50:21 gklug - * initial revision - * - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -/* - * Special Interrupt handler - * - * The following abstract should show how this module is included - * in the driver path: - * - * In the ISR of the driver the bits for frame transmission complete and - * for receive complete are checked and handled by the driver itself. - * The bits of the slow path mask are checked after that and then the - * entry into the so-called "slow path" is prepared. It is an implementors - * decision whether this is executed directly or just scheduled by - * disabling the mask. In the interrupt service routine some events may be - * generated, so it would be a good idea to call the EventDispatcher - * right after this ISR. - * - * The Interrupt source register of the adapter is NOT read by this module. - * SO if the drivers implementor needs a while loop around the - * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for - * each loop entered. - * - * However, the MAC Interrupt status registers are read in a while loop. - * - */ - -static const char SysKonnectFileId[] = - "$Id: skgesirq.c,v 1.83 2003/02/05 15:10:59 rschmidt Exp $" ; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skgepnmi.h" /* PNMI Definitions */ -#include "h/skrlmt.h" /* RLMT Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */ - -/* local function prototypes */ -static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int); -static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); -static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); -#ifdef OTHER_PHY -static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int); -static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); -#endif /* OTHER_PHY */ - -/* - * array of Rx counter from XMAC which are checked - * in AutoSense mode to check whether a link is not able to auto-negotiate. - */ -static const SK_U16 SkGeRxRegs[]= { - XM_RXF_64B, - XM_RXF_127B, - XM_RXF_255B, - XM_RXF_511B, - XM_RXF_1023B, - XM_RXF_MAX_SZ -} ; - -#ifdef __C2MAN__ -/* - * Special IRQ function - * - * General Description: - * - */ -intro() -{} -#endif - -/* Define return codes of SkGePortCheckUp and CheckShort */ -#define SK_HW_PS_NONE 0 /* No action needed */ -#define SK_HW_PS_RESTART 1 /* Restart needed */ -#define SK_HW_PS_LINK 2 /* Link Up actions needed */ - -/****************************************************************************** - * - * SkHWInitDefSense() - Default Autosensing mode initialization - * - * Description: sets the PLinkMode for HWInit - * - * Returns: N/A - */ -static void SkHWInitDefSense( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { - pPrt->PLinkMode = pPrt->PLinkModeConf; - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: First mode %d on Port %d\n", - (int)SK_LMODE_AUTOFULL, Port)); - - pPrt->PLinkMode = SK_LMODE_AUTOFULL; - - return; -} /* SkHWInitDefSense */ - - -/****************************************************************************** - * - * SkHWSenseGetNext() - Get Next Autosensing Mode - * - * Description: gets the appropriate next mode - * - * Note: - * - */ -SK_U8 SkHWSenseGetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { - /* Leave all as configured */ - return(pPrt->PLinkModeConf); - } - - if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) { - /* Return next mode AUTOBOTH */ - return(SK_LMODE_AUTOBOTH); - } - - /* Return default autofull */ - return(SK_LMODE_AUTOFULL); -} /* SkHWSenseGetNext */ - - -/****************************************************************************** - * - * SkHWSenseSetNext() - Autosensing Set next mode - * - * Description: sets the appropriate next mode - * - * Returns: N/A - */ -void SkHWSenseSetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U8 NewMode) /* New Mode to be written in sense mode */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: next mode %d on Port %d\n", - (int)NewMode, Port)); - - pPrt->PLinkMode = NewMode; - - return; -} /* SkHWSenseSetNext */ - - -/****************************************************************************** - * - * SkHWLinkDown() - Link Down handling - * - * Description: handles the hardware link down signal - * - * Returns: N/A - */ -void SkHWLinkDown( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Disable all MAC interrupts */ - SkMacIrqDisable(pAC, IoC, Port); - - /* Disable Receiver and Transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* Init default sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - if (!pPrt->PHWLinkUp) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link down Port %d\n", Port)); - - /* Set Link to DOWN */ - pPrt->PHWLinkUp = SK_FALSE; - - /* Reset Port stati */ - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED; - - /* Re-init Phy especially when the AutoSense default is set now */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - - /* GP0: used for workaround of Rev. C Errata 2 */ - - /* Do NOT signal to RLMT */ - - /* Do NOT start the timer here */ -} /* SkHWLinkDown */ - - -/****************************************************************************** - * - * SkHWLinkUp() - Link Up handling - * - * Description: handles the hardware link up signal - * - * Returns: N/A - */ -void SkHWLinkUp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - /* We do NOT need to proceed on active link */ - return; - } - - pPrt->PHWLinkUp = SK_TRUE; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - - if (pPrt->PLinkMode != SK_LMODE_AUTOHALF && - pPrt->PLinkMode != SK_LMODE_AUTOFULL && - pPrt->PLinkMode != SK_LMODE_AUTOBOTH) { - /* Link is up and no Auto-negotiation should be done */ - - /* Link speed should be the configured one */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - /* default is 1000 Mbps */ - case SK_LSPEED_1000MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; - break; - case SK_LSPEED_100MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; - break; - case SK_LSPEED_10MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; - break; - } - - /* Set Link Mode Status */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; - } - else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF; - } - - /* No flow control without auto-negotiation */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - - /* enable Rx/Tx */ - SkMacRxTxEnable(pAC, IoC, Port); - } -} /* SkHWLinkUp */ - - -/****************************************************************************** - * - * SkMacParity() - MAC parity workaround - * - * Description: handles MAC parity errors correctly - * - * Returns: N/A - */ -static void SkMacParity( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index of the port failed */ -{ - SK_EVPARA Para; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 TxMax; /* TxMax Counter */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Clear IRQ Tx Parity Error */ - if (pAC->GIni.GIGenesis) { - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); - } - else { - /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), - (SK_U8)((pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); - } - - if (pPrt->PCheckPar) { - if (Port == MAC_1) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); - } - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - return; - } - - /* Check whether frames with a size of 1k were sent */ - if (pAC->GIni.GIGenesis) { - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, Port); - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); - } - else { - (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); - } - - if (TxMax > 0) { - /* From now on check the parity */ - pPrt->PCheckPar = SK_TRUE; - } -} /* SkMacParity */ - - -/****************************************************************************** - * - * SkGeHwErr() - Hardware Error service routine - * - * Description: handles all HW Error interrupts - * - * Returns: N/A - */ -static void SkGeHwErr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 HwStatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U16 Word; - - if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { - /* PCI Errors occured */ - if ((HwStatus & IS_IRQ_STAT) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); - } - - /* Reset all bits in the PCI STATUS register */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if (pAC->GIni.GIGenesis) { - if ((HwStatus & IS_NO_STAT_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_STAT_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_TIST_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - - if ((HwStatus & IS_NO_TIST_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - } - else { /* YUKON */ - /* This is necessary only for Rx timing measurements */ - if ((HwStatus & IS_IRQ_TIST_OV) != 0) { - /* Clear Time Stamp Timer IRQ */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); - } - - if ((HwStatus & IS_IRQ_SENSOR) != 0) { - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - } - } - - if ((HwStatus & IS_RAM_RD_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_RAM_WR_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_M1_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_1); - } - - if ((HwStatus & IS_M2_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_2); - } - - if ((HwStatus & IS_R1_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((HwStatus & IS_R2_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } -} /* SkGeHwErr */ - - -/****************************************************************************** - * - * SkGeSirqIsr() - Special Interrupt Service Routine - * - * Description: handles all non data transfer specific interrupts (slow path) - * - * Returns: N/A - */ -void SkGeSirqIsr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 Istatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U32 RegVal32; /* Read register value */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - unsigned Len; - SK_U64 Octets; - SK_U16 PhyInt; - SK_U16 PhyIMsk; - int i; - - if ((Istatus & IS_HW_ERR) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - - SkGeHwErr(pAC, IoC, RegVal32); - } - - /* - * Packet Timeout interrupts - */ - /* Check whether MACs are correctly initialized */ - if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && - pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { - /* MAC 1 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, - SKERR_SIRQ_E004MSG); - } - - if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && - pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { - /* MAC 2 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, - SKERR_SIRQ_E005MSG); - } - - if ((Istatus & IS_PA_TO_RX1) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, - SKERR_SIRQ_E002MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - if ((Istatus & IS_PA_TO_RX2) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, - SKERR_SIRQ_E003MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if ((Istatus & IS_PA_TO_TX1) != 0) { - - pPrt = &pAC->GIni.GP[0]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); - - /* - * workaround: if in half duplex mode, check for Tx hangup. - * Read number of TX'ed bytes, wait for 10 ms, then compare - * the number with current value. If nothing changed, we assume - * that Tx is hanging and do a FIFO flush (see event routine). - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - /* - * many more pack. arb. timeouts may come in between, - * we ignore those - */ - pPrt->HalfDupTimerActive = SK_TRUE; - - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0), - pAC->Rlmt.Port[0].Net->NetNumber); - - pPrt->LastOctets = Octets; - - Para.Para32[0] = 0; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } - - if ((Istatus & IS_PA_TO_TX2) != 0) { - - pPrt = &pAC->GIni.GP[1]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); - - /* workaround: see above */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - pPrt->HalfDupTimerActive = SK_TRUE; - - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1), - pAC->Rlmt.Port[1].Net->NetNumber); - - pPrt->LastOctets = Octets; - - Para.Para32[0] = 1; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } - - /* Check interrupts of the particular queues */ - if ((Istatus & IS_R1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, - SKERR_SIRQ_E006MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_R2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, - SKERR_SIRQ_E007MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, - SKERR_SIRQ_E008MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, - SKERR_SIRQ_E009MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, - SKERR_SIRQ_E010MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, - SKERR_SIRQ_E011MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - /* External reg interrupt */ - if ((Istatus & IS_EXT_REG) != 0) { - /* Test IRQs from PHY */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pPrt = &pAC->GIni.GP[i]; - - if (pPrt->PState == SK_PRT_RESET) { - continue; - } - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - break; - - case SK_PHY_BCOM: - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_MASK, &PhyIMsk); - - if ((PhyInt & ~PhyIMsk) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Bcom Int: 0x%04X Mask: 0x%04X\n", - i, PhyInt, PhyIMsk)); - SkPhyIsrBcom(pAC, IoC, i, PhyInt); - } - break; - - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); - SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_MASK, &PhyIMsk); - - if ((PhyInt & PhyIMsk) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Marv Int: 0x%04X Mask: 0x%04X\n", - i, PhyInt, PhyIMsk)); - SkPhyIsrGmac(pAC, IoC, i, PhyInt); - } - break; - -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_ENAB, &PhyIMsk); - - if ((PhyInt & PhyIMsk) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Lone Int: %x Mask: %x\n", - i, PhyInt, PhyIMsk)); - SkPhyIsrLone(pAC, IoC, i, PhyInt); - } - break; - case SK_PHY_NAT: - /* todo: National */ - break; -#endif /* OTHER_PHY */ - } - } - } - - /* I2C Ready interrupt */ - if ((Istatus & IS_I2C_READY) != 0) { - SkI2cIsr(pAC, IoC); - } - - if ((Istatus & IS_LNK_SYNC_M1) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC1) != 0) { - /* IRQ from MAC 1 */ - SkMacIrq(pAC, IoC, MAC_1); - } - - if ((Istatus & IS_LNK_SYNC_M2) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC2) != 0) { - /* IRQ from MAC 2 */ - SkMacIrq(pAC, IoC, MAC_2); - } - - /* Timer interrupt (served last) */ - if ((Istatus & IS_TIMINT) != 0) { - SkHwtIsr(pAC, IoC); - } -} /* SkGeSirqIsr */ - - -/****************************************************************************** - * - * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - */ -static int SkGePortCheckShorts( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_U32 CheckShorts; /* Check value for Short Event Counter */ - SK_U64 RxCts; /* Rx Counter (packets on network) */ - SK_U32 RxTmp; /* Rx temp. Counter */ - SK_U32 FcsErrCts; /* FCS Error Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Rtv; /* Return value */ - int i; - - pPrt = &pAC->GIni.GP[Port]; - - /* Default: no action */ - Rtv = SK_HW_PS_NONE; - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* Extra precaution: check for short Event counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - - /* - * Read Rx counter (packets seen on the network and not necessarily - * really received. - */ - RxCts = 0; - - for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { - (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); - RxCts += (SK_U64)RxTmp; - } - - /* On default: check shorts against zero */ - CheckShorts = 0; - - /* Extra precaution on active links */ - if (pPrt->PHWLinkUp) { - /* Reset Link Restart counter */ - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - - /* If link is up check for 2 */ - CheckShorts = 2; - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && - (pPrt->PLinkMode == SK_LMODE_HALF || - pPrt->PLinkMode == SK_LMODE_FULL)) { - /* - * This is autosensing and we are in the fallback - * manual full/half duplex mode. - */ - if (RxCts == pPrt->PPrevRx) { - /* Nothing received, restart link */ - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_RESTART); - } - else { - pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; - } - } - - if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || - (!(FcsErrCts - pPrt->PPrevFcs))) { - /* - * Note: The compare with zero above has to be done the way shown, - * otherwise the Linux driver will have a problem. - */ - /* - * We received a bunch of frames or no CRC error occured on the - * network -> ok. - */ - pPrt->PPrevRx = RxCts; - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_NONE); - } - - pPrt->PPrevFcs = FcsErrCts; - } - - - if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Short Event Count Restart Port %d \n", Port)); - Rtv = SK_HW_PS_RESTART; - } - - pPrt->PPrevShorts = Shorts; - pPrt->PPrevRx = RxCts; - - return(Rtv); -} /* SkGePortCheckShorts */ - - -/****************************************************************************** - * - * SkGePortCheckUp() - Check if the link is up - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - switch (pAC->GIni.GP[Port].PhyType) { - case SK_PHY_XMAC: - return(SkGePortCheckUpXmac(pAC, IoC, Port)); - case SK_PHY_BCOM: - return(SkGePortCheckUpBcom(pAC, IoC, Port)); - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - return(SkGePortCheckUpGmac(pAC, IoC, Port)); -#ifdef OTHER_PHY - case SK_PHY_LONE: - return(SkGePortCheckUpLone(pAC, IoC, Port)); - case SK_PHY_NAT: - return(SkGePortCheckUpNat(pAC, IoC, Port)); -#endif /* OTHER_PHY */ - } - return(SK_HW_PS_NONE); -} /* SkGePortCheckUp */ - - -/****************************************************************************** - * - * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpXmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U32 GpReg; /* General Purpose register value */ - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 IsrcSum; /* Interrupt source register sum */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - if (pPrt->PhyType != SK_PHY_XMAC) { - return(SK_HW_PS_NONE); - } - else { - return(SkGePortCheckShorts(pAC, IoC, Port)); - } - } - - IsrcSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - if (pPrt->PLinkBroken) { - /* Link was broken */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* The Link is in sync */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((Isrc & XM_IS_INP_ASS) == 0) { - /* It has been in sync since last time */ - /* Restart the PORT */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link in sync Restart Port %d\n", Port)); - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* We now need to reinitialize the PrevShorts counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - pPrt->PPrevShorts = Shorts; - - pPrt->PLinkBroken = SK_FALSE; - - /* - * Link Restart Workaround: - * it may be possible that the other Link side - * restarts its link as well an we detect - * another LinkBroken. To prevent this - * happening we check for a maximum number - * of consecutive restart. If those happens, - * we do NOT restart the active link and - * check whether the link is now o.k. - */ - pPrt->PLinkResCt++; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkResCt < SK_MAX_LRESTART) { - return(SK_HW_PS_RESTART); - } - - pPrt->PLinkResCt = 0; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); - } - else { - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); - - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - } - else { - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - - } - else { - /* Link was not broken, check if it is */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - pPrt->PLinkBroken = SK_TRUE; - /* Re-Init Link partner Autoneg flag */ - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link broken Port %d\n", Port)); - - /* Cable removed-> reinit sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - return(SK_HW_PS_RESTART); - } - } - } - else { - SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); - if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { - return(SK_HW_PS_RESTART); - } - } - } - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* Save Auto-negotiation Done interrupt only if link is in sync */ - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - } -#ifdef DEBUG - if ((pPrt->PIsave & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((IsrcSum & XM_IS_AND) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", - Port, LpAb, ResAb)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - } - /* - * Dummy Read extended status to prevent extra link down/ups - * (clear Page Received bit if set) - */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Increase the Timeout counter */ - pPrt->PAutoNegTOCt++; - - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_AUTO && - pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { - /* - * This is rather complicated. - * we need to check here whether the LIPA_AUTO - * we saw before is false alert. We saw at one - * switch ( SR8800) that on boot time it sends - * just one auto-neg packet and does no further - * auto-negotiation. - * Solution: we restart the autosensing after - * a few timeouts. - */ - pPrt->PAutoNegTOCt = 0; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SkHWInitDefSense(pAC, IoC, Port); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - /* - * Link sync (GP) and so assume a good connection. But if not received - * a bunch of frames received in a time slot (maybe broken tx cable) - * the port is restart. - */ - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpXmac */ - - -/****************************************************************************** - * - * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_U16 Ctrl; /* Broadcom control flags */ -#ifdef DEBUG - SK_U16 LpAb; - SK_U16 ExtStat; -#endif /* DEBUG */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Check for No HCD Link events (#10523) */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); - -#ifdef xDEBUG - if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) == - (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { - - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1 - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { - /* - * Workaround BCom Errata: - * enable and disable loopback mode if "NO HCD" occurs. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl | PHY_CT_LOOP)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl & ~PHY_CT_LOOP)); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("No HCD Link event, Port %d\n", Port)); -#ifdef xDEBUG - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "No HCD link event, port %d.", - (void *)Port, - (void *)NULL); -#endif /* DEBUG */ - } - - /* Not obsolete: link status bit is latched to 0 and autoclearing! */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - -#ifdef xDEBUG - { - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1a - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - Stat1 = Stat1 << 16 | PhyStat; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - Stat2 = Stat2 << 16 | ResAb; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - /* - * Here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - return(SK_HW_PS_NONE); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); - - if (AutoNeg) { - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { -#ifdef DEBUG - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); -#endif /* DEBUG */ - return(SK_HW_PS_RESTART); - } - else { -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp2 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); - } - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more. */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp3 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpBcom */ - - -/****************************************************************************** - * - * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source */ - SK_U16 PhyStat; /* Phy Status */ - SK_U16 PhySpecStat;/* Phy Specific Status */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &Isrc); - - if ((Isrc & PHY_M_IS_AN_COMPL) != 0) { - /* TBD */ - } - - if ((Isrc & PHY_M_IS_DOWNSH_DET) != 0) { - /* TBD */ - } - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhySpecStat: 0x%04x\n", AutoNeg, PhySpecStat)); - - if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { - return(SK_HW_PS_NONE); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); - - if (AutoNeg) { - /* Auto-Negotiation Over ? */ - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - - SkHWLinkUp(pAC, IoC, Port); - - Done = SkMacAutoNegDone(pAC, IoC, Port); - - if (Done != SK_AND_OK) { - return(SK_HW_PS_RESTART); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync, Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpGmac */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkGePortCheckUpLone() - Check if the link is up on Level One PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 StatSum; - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - StatSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* Now wait for each ports link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); - StatSum |= PhyStat; - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - /* Save Auto-negotiation Done bit */ - pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); -#ifdef DEBUG - if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((StatSum & PHY_ST_AN_OVER) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - - } - else { - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); - } - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpLone */ - - -/****************************************************************************** - * - * SkGePortCheckUpNat() - Check if the link is up on National PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpNat( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - /* todo: National */ - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkGeSirqEvent() - Event Service Routine - * - * Description: - * - * Notes: - */ -int SkGeSirqEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - SK_U64 Octets; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 Port; - SK_U32 Time; - unsigned Len; - int PortStat; - SK_U8 Val8; - - Port = Para.Para32[0]; - pPrt = &pAC->GIni.GP[Port]; - - switch (Event) { - case SK_HWEV_WATIM: - /* Check whether port came up */ - PortStat = SkGePortCheckUp(pAC, IoC, Port); - - switch (PortStat) { - case SK_HW_PS_RESTART: - if (pPrt->PHWLinkUp) { - /* - * Set Link to down. - */ - SkHWLinkDown(pAC, IoC, Port); - - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Restart needed */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - break; - - case SK_HW_PS_LINK: - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); - break; - - } - - /* Start again the check Timer */ - if (pPrt->PHWLinkUp) { - Time = SK_WA_ACT_TIME; - } - else { - Time = SK_WA_INA_TIME; - } - - /* Todo: still needed for non-XMAC PHYs??? */ - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Time, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_START: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - SkHWLinkDown(pAC, IoC, Port); - - /* Schedule Port RESET */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_STOP: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Stop Workaround Timer */ - SkTimerStop(pAC, IoC, &pPrt->PWaTimer); - - SkHWLinkDown(pAC, IoC, Port); - break; - - case SK_HWEV_UPDATE_STAT: - /* We do NOT need to update any statistics */ - break; - - case SK_HWEV_CLEAR_STAT: - /* We do NOT need to clear any statistics */ - for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PPrevShorts = 0; - } - break; - - case SK_HWEV_SET_LMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkModeConf != Val8) { - /* Set New link mode */ - pPrt->PLinkModeConf = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_FLOWMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PFlowCtrlMode != Val8) { - /* Set New Flow Control mode */ - pPrt->PFlowCtrlMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_ROLE: - /* not possible for fiber */ - if (!pAC->GIni.GICopperType) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PMSMode != Val8) { - /* Set New link mode */ - pPrt->PMSMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_SPEED: - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkSpeed != Val8) { - /* Set New Speed parameter */ - pPrt->PLinkSpeed = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_HALFDUP_CHK: - /* - * half duplex hangup workaround. - * See packet arbiter timeout interrupt for description - */ - pPrt->HalfDupTimerActive = SK_FALSE; - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { - - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), - pAC->Rlmt.Port[Port].Net->NetNumber); - - if (pPrt->LastOctets == Octets) { - /* Tx hanging, a FIFO flush restarts it */ - SkMacFlushTxFifo(pAC, IoC, Port); - } - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); - break; - } - - return(0); -} /* SkGeSirqEvent */ - - -/****************************************************************************** - * - * SkPhyIsrBcom() - PHY interrupt service routine - * - * Description: handles all interrupts from BCom PHY - * - * Returns: N/A - */ -static void SkPhyIsrBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & PHY_B_IS_PSE) != 0) { - /* Incorrectable pair swap error */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022, - SKERR_SIRQ_E022MSG); - } - - if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { - Para.Para32[0] = (SK_U32)Port; - - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - -} /* SkPhyIsrBcom */ - - -/****************************************************************************** - * - * SkPhyIsrGmac() - PHY interrupt service routine - * - * Description: handles all interrupts from Marvell PHY - * - * Returns: N/A - */ -static void SkPhyIsrGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { - Para.Para32[0] = (SK_U32)Port; - - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { - /* Auto-Negotiation Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); - } - - if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) { - /* TBD */ - } - - if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { - /* FIFO Overflow/Underrun Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); - } -} /* SkPhyIsrGmac */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkPhyIsrLone() - PHY interrupt service routine - * - * Description: handles all interrupts from LONE PHY - * - * Returns: N/A - */ -static void SkPhyIsrLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_EVPARA Para; - - if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - Para.Para32[0] = (SK_U32)Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - -} /* SkPhyIsrLone */ -#endif /* OTHER_PHY */ - -#endif /* CONFIG_SK98 */ - -/* End of File */ diff --git a/drivers/sk98lin/ski2c.c b/drivers/sk98lin/ski2c.c deleted file mode 100644 index 2ab635a229..0000000000 --- a/drivers/sk98lin/ski2c.c +++ /dev/null @@ -1,1505 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.57 $ - * Date: $Date: 2003/01/28 09:17:38 $ - * Purpose: Functions to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: ski2c.c,v $ - * Revision 1.57 2003/01/28 09:17:38 rschmidt - * Fixed handling for sensors on YUKON Fiber. - * Editorial changes. - * - * Revision 1.56 2002/12/19 14:20:41 rschmidt - * Added debugging code in SkI2cWait(). - * Replaced all I2C-write operations with function SkI2cWrite(). - * Fixed compiler warning because of uninitialized 'Time' in SkI2cEvent(). - * Editorial changes. - * - * Revision 1.55 2002/10/15 07:23:55 rschmidt - * Added setting of the GIYukon32Bit bool variable to distinguish - * 32-bit adapters. - * Editorial changes (TWSI). - * - * Revision 1.54 2002/08/13 09:05:06 rschmidt - * Added new thresholds if VAUX is not available (GIVauxAvail). - * Merged defines for PHY PLL 3V3 voltage (A and B). - * Editorial changes. - * - * Revision 1.53 2002/08/08 11:04:53 rwahl - * Added missing comment for revision 1.51 - * - * Revision 1.52 2002/08/08 10:09:02 jschmalz - * Sensor init state caused wrong error log entry - * - * Revision 1.51 2002/08/06 09:43:03 jschmalz - * Extensions and changes for Yukon - * - * Revision 1.50 2002/08/02 12:09:22 rschmidt - * Added support for YUKON sensors. - * Editorial changes. - * - * Revision 1.49 2002/07/30 11:07:52 rschmidt - * Replaced MaxSens init by update for Copper in SkI2cInit1(), - * because it was already initialized in SkI2cInit0(). - * Editorial changes. - * - * Revision 1.48 2001/08/16 12:44:33 afischer - * LM80 sensor init values corrected - * - * Revision 1.47 2001/04/05 11:38:09 rassmann - * Set SenState to idle in SkI2cWaitIrq(). - * Changed error message in SkI2cWaitIrq(). - * - * Revision 1.46 2001/04/02 14:03:35 rassmann - * Changed pAC to IoC in SK_IN32(). - * - * Revision 1.45 2001/03/21 12:12:49 rassmann - * Resetting I2C_READY interrupt in SkI2cInit1(). - * - * Revision 1.44 2000/08/07 15:49:03 gklug - * Fix: SK_INFAST only in NetWare driver. - * - * Revision 1.43 2000/08/03 14:28:17 rassmann - * Added function to wait for I2C being ready before resetting the board. - * Replaced one duplicate "out of range" message with correct one. - * - * Revision 1.42 1999/11/22 13:35:12 cgoos - * Changed license header to GPL. - * - * Revision 1.41 1999/09/14 14:11:30 malthoff - * The 1000BT Dual Link adapter has got only one Fan. - * The second Fan has been removed. - * - * Revision 1.40 1999/05/27 13:37:27 malthoff - * Set divisor of 1 for fan count calculation. - * - * Revision 1.39 1999/05/20 14:54:43 malthoff - * I2c.DummyReads is not used in Diagnostics. - * - * Revision 1.38 1999/05/20 09:20:56 cgoos - * Changes for 1000Base-T (up to 9 sensors and fans). - * - * Revision 1.37 1999/03/25 15:11:36 gklug - * fix: reset error flag if sensor reads correct value - * - * Revision 1.36 1999/01/07 14:11:16 gklug - * fix: break added - * - * Revision 1.35 1999/01/05 15:31:49 gklug - * fix: CLEAR STAT command is now added correctly - * - * Revision 1.34 1998/12/01 13:45:16 gklug - * fix: introduced Init level, because we don't need reinits - * - * Revision 1.33 1998/11/09 14:54:25 malthoff - * Modify I2C Transfer Timeout handling for Diagnostics. - * - * Revision 1.32 1998/11/03 06:54:35 gklug - * fix: Need dummy reads at the beginning to init sensors - * - * Revision 1.31 1998/11/03 06:42:42 gklug - * fix: select correctVIO range only if between warning levels - * - * Revision 1.30 1998/11/02 07:36:53 gklug - * fix: Error should not include WARNING message - * - * Revision 1.29 1998/10/30 15:07:43 malthoff - * Disable 'I2C does not compelete' error log for diagnostics. - * - * Revision 1.28 1998/10/22 09:48:11 gklug - * fix: SysKonnectFileId typo - * - * Revision 1.27 1998/10/20 09:59:46 gklug - * add: parameter to SkOsGetTime - * - * Revision 1.26 1998/10/09 06:10:59 malthoff - * Remove ID_sccs by SysKonnectFileId. - * - * Revision 1.25 1998/09/08 12:40:26 gklug - * fix: syntax error in if clause - * - * Revision 1.24 1998/09/08 12:19:42 gklug - * chg: INIT Level checking - * - * Revision 1.23 1998/09/08 07:37:20 gklug - * fix: log error if PCI_IO voltage sensor could not be initialized - * - * Revision 1.22 1998/09/04 08:30:03 malthoff - * Bugfixes during SK_DIAG testing: - * - correct NS2BCLK() macro - * - correct SkI2cSndDev() - * - correct SkI2cWait() loop waiting for an event - * - * Revision 1.21 1998/08/27 14:46:01 gklug - * chg: if-then-else replaced by switch - * - * Revision 1.20 1998/08/27 14:40:07 gklug - * test: integral types - * - * Revision 1.19 1998/08/25 07:51:54 gklug - * fix: typos for compiling - * - * Revision 1.18 1998/08/25 06:12:24 gklug - * add: count errors and warnings - * fix: check not the sensor state but the ErrFlag! - * - * Revision 1.17 1998/08/25 05:56:48 gklug - * add: CheckSensor function - * - * Revision 1.16 1998/08/20 11:41:10 gklug - * chg: omit STRCPY macro by using char * as Sensor Description - * - * Revision 1.15 1998/08/20 11:37:35 gklug - * chg: change Ioc to IoC - * - * Revision 1.14 1998/08/20 11:32:52 gklug - * fix: Para compile error - * - * Revision 1.13 1998/08/20 11:27:41 gklug - * fix: Compile bugs with new awrning constants - * - * Revision 1.12 1998/08/20 08:53:05 gklug - * fix: compiler errors - * add: Threshold values - * - * Revision 1.11 1998/08/19 12:39:22 malthoff - * Compiler Fix: Some names have changed. - * - * Revision 1.10 1998/08/19 12:20:56 gklug - * fix: remove struct from C files (see CCC) - * - * Revision 1.9 1998/08/19 06:28:46 malthoff - * SkOsGetTime returns SK_U64 now. - * - * Revision 1.8 1998/08/17 13:53:33 gklug - * fix: Parameter of event function and its result - * - * Revision 1.7 1998/08/17 07:02:15 malthoff - * Modify the functions for accessing the I2C SW Registers. - * Modify SkI2cWait(). - * Put Lm80RcvReg into sklm80.c - * Remove Compiler Errors. - * - * Revision 1.6 1998/08/14 07:13:20 malthoff - * remove pAc with pAC - * remove smc with pAC - * change names to new convention - * - * Revision 1.5 1998/08/14 06:24:49 gklug - * add: init level 1 and 2 - * - * Revision 1.4 1998/08/12 14:31:12 gklug - * add: error log for unknown event - * - * Revision 1.3 1998/08/12 13:37:04 gklug - * add: Init 0 function - * - * Revision 1.2 1998/08/11 07:27:15 gklug - * add: functions of the interface - * adapt rest of source to C coding Conventions - * rmv: unnecessary code taken from Mona Lisa - * - * Revision 1.1 1998/06/19 14:28:43 malthoff - * Created. Sources taken from ML Projekt. - * Sources have to be reworked for GE. - * - * - ******************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -/* - * I2C Protocol - */ -static const char SysKonnectFileId[] = - "$Id: ski2c.c,v 1.57 2003/01/28 09:17:38 rschmidt Exp $"; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - I2C protocol implementation. - - General Description: - - The I2C protocol is used for the temperature sensors and for - the serial EEPROM which hold the configuration. - - This file covers functions that allow to read write and do - some bulk requests a specified I2C address. - - The Genesis has 2 I2C buses. One for the EEPROM which holds - the VPD Data and one for temperature and voltage sensor. - The following picture shows the I2C buses, I2C devices and - their control registers. - - Note: The VPD functions are in skvpd.c -. -. PCI Config I2C Bus for VPD Data: -. -. +------------+ -. | VPD EEPROM | -. +------------+ -. | -. | <-- I2C -. | -. +-----------+-----------+ -. | | -. +-----------------+ +-----------------+ -. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | -. +-----------------+ +-----------------+ -. -. -. I2C Bus for LM80 sensor: -. -. +-----------------+ -. | Temperature and | -. | Voltage Sensor | -. | LM80 | -. +-----------------+ -. | -. | -. I2C --> | -. | -. +----+ -. +-------------->| OR |<--+ -. | +----+ | -. +------+------+ | -. | | | -. +--------+ +--------+ +----------+ -. | B2_I2C | | B2_I2C | | B2_I2C | -. | _CTRL | | _DATA | | _SW | -. +--------+ +--------+ +----------+ -. - The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL - and B2_I2C_DATA registers. - For driver software it is recommended to use the I2C control and - data register, because I2C bus timing is done by the ASIC and - an interrupt may be received when the I2C request is completed. - - Clock Rate Timing: MIN MAX generated by - VPD EEPROM: 50 kHz 100 kHz HW - LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW - LM80 over B2_I2C_SW register 0 400 kHz SW - - Note: The clock generated by the hardware is dependend on the - PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD - clock is 50 kHz. - */ -intro() -{} -#endif - -#ifdef SK_DIAG -/* - * I2C Fast Mode timing values used by the LM80. - * If new devices are added to the I2C bus the timing values have to be checked. - */ -#ifndef I2C_SLOW_TIMING -#define T_CLK_LOW 1300L /* clock low time in ns */ -#define T_CLK_HIGH 600L /* clock high time in ns */ -#define T_DATA_IN_SETUP 100L /* data in Set-up Time */ -#define T_START_HOLD 600L /* start condition hold time */ -#define T_START_SETUP 600L /* start condition Set-up time */ -#define T_STOP_SETUP 600L /* stop condition Set-up time */ -#define T_BUS_IDLE 1300L /* time the bus must free after Tx */ -#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ -#else /* I2C_SLOW_TIMING */ -/* I2C Standard Mode Timing */ -#define T_CLK_LOW 4700L /* clock low time in ns */ -#define T_CLK_HIGH 4000L /* clock high time in ns */ -#define T_DATA_IN_SETUP 250L /* data in Set-up Time */ -#define T_START_HOLD 4000L /* start condition hold time */ -#define T_START_SETUP 4700L /* start condition Set-up time */ -#define T_STOP_SETUP 4000L /* stop condition Set-up time */ -#define T_BUS_IDLE 4700L /* time the bus must free after Tx */ -#endif /* !I2C_SLOW_TIMING */ - -#define NS2BCLK(x) (((x)*125)/10000) - -/* - * I2C Wire Operations - * - * About I2C_CLK_LOW(): - * - * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting - * clock to low, to prevent the ASIC and the I2C data client from driving the - * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client - * send an 'ACK'). See also Concentrator Bugreport No. 10192. - */ -#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) -#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) -#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) -#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) -#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) -#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) -#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) - -#define NS2CLKT(x) ((x*125L)/10000) - -/*--------------- I2C Interface Register Functions --------------- */ - -/* - * sending one bit - */ -void SkI2cSndBit( -SK_IOC IoC, /* I/O Context */ -SK_U8 Bit) /* Bit to send */ -{ - I2C_DATA_OUT(IoC); - if (Bit) { - I2C_DATA_HIGH(IoC); - } - else { - I2C_DATA_LOW(IoC); - } - SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); - I2C_CLK_HIGH(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - I2C_CLK_LOW(IoC); -} /* SkI2cSndBit*/ - - -/* - * Signal a start to the I2C Bus. - * - * A start is signaled when data goes to low in a high clock cycle. - * - * Ends with Clock Low. - * - * Status: not tested - */ -void SkI2cStart( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data high */ - I2C_DATA_OUT(IoC); - I2C_DATA_HIGH(IoC); - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); - - /* Set Data Low */ - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); - - /* Clock low without Data to Input */ - I2C_START_COND(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); -} /* SkI2cStart */ - - -void SkI2cStop( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data low */ - I2C_DATA_OUT(IoC); - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); - - /* - * Set Data High: Do it by setting the Data Line to Input. - * Because of a pull up resistor the Data Line - * floods to high. - */ - I2C_DATA_IN(IoC); - - /* - * When I2C activity is stopped - * o DATA should be set to input and - * o CLOCK should be set to high! - */ - SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); -} /* SkI2cStop */ - - -/* - * Receive just one bit via the I2C bus. - * - * Note: Clock must be set to LOW before calling this function. - * - * Returns The received bit. - */ -int SkI2cRcvBit( -SK_IOC IoC) /* I/O Context */ -{ - int Bit; - SK_U8 I2cSwCtrl; - - /* Init data as input line */ - I2C_DATA_IN(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; - - I2C_CLK_LOW(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); - - return(Bit); -} /* SkI2cRcvBit */ - - -/* - * Receive an ACK. - * - * returns 0 If acknowledged - * 1 in case of an error - */ -int SkI2cRcvAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - return(SkI2cRcvBit(IoC) != 0); -} /* SkI2cRcvAck */ - - -/* - * Send an NACK. - */ -void SkI2cSndNAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - SkI2cSndBit(IoC, 1); -} /* SkI2cSndNAck */ - - -/* - * Send an ACK. - */ -void SkI2cSndAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - * - */ - SkI2cSndBit(IoC, 0); -} /* SkI2cSndAck */ - - -/* - * Send one byte to the I2C device and wait for ACK. - * - * Return acknowleged status. - */ -int SkI2cSndByte( -SK_IOC IoC, /* I/O Context */ -int Byte) /* byte to send */ -{ - int i; - - for (i = 0; i < 8; i++) { - if (Byte & (1<<(7-i))) { - SkI2cSndBit(IoC, 1); - } - else { - SkI2cSndBit(IoC, 0); - } - } - - return(SkI2cRcvAck(IoC)); -} /* SkI2cSndByte */ - - -/* - * Receive one byte and ack it. - * - * Return byte. - */ -int SkI2cRcvByte( -SK_IOC IoC, /* I/O Context */ -int Last) /* Last Byte Flag */ -{ - int i; - int Byte = 0; - - for (i = 0; i < 8; i++) { - Byte <<= 1; - Byte |= SkI2cRcvBit(IoC); - } - - if (Last) { - SkI2cSndNAck(IoC); - } - else { - SkI2cSndAck(IoC); - } - - return(Byte); -} /* SkI2cRcvByte */ - - -/* - * Start dialog and send device address - * - * Return 0 if acknowleged, 1 in case of an error - */ -int SkI2cSndDev( -SK_IOC IoC, /* I/O Context */ -int Addr, /* Device Address */ -int Rw) /* Read / Write Flag */ -{ - SkI2cStart(IoC); - Rw = ~Rw; - Rw &= I2C_WRITE; - return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); -} /* SkI2cSndDev */ - -#endif /* SK_DIAG */ - -/*----------------- I2C CTRL Register Functions ----------*/ - -/* - * waits for a completion of an I2C transfer - * - * returns 0: success, transfer completes - * 1: error, transfer does not complete, I2C transfer - * killed, wait loop terminated. - */ -int SkI2cWait( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ -{ - SK_U64 StartTime; - SK_U64 CurrentTime; - SK_U32 I2cCtrl; - - StartTime = SkOsGetTime(pAC); - - do { - CurrentTime = SkOsGetTime(pAC); - - if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { - - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); -#endif /* !SK_DIAG */ - return(1); - } - - SK_I2C_GET_CTL(IoC, &I2cCtrl); - -#ifdef xYUKON_DBG - printf("StartTime=%lu, CurrentTime=%lu\n", - StartTime, CurrentTime); - if (kbhit()) { - return(1); - } -#endif /* YUKON_DBG */ - - } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); - - return(0); -} /* SkI2cWait */ - - -/* - * waits for a completion of an I2C transfer - * - * Returns - * Nothing - */ -void SkI2cWaitIrq( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_SENSOR *pSen; - SK_U64 StartTime; - SK_U32 IrqSrc; - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - - if (pSen->SenState == SK_SEN_IDLE) { - return; - } - - StartTime = SkOsGetTime(pAC); - do { - if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); -#endif /* !SK_DIAG */ - return; - } - SK_IN32(IoC, B0_ISRC, &IrqSrc); - } while ((IrqSrc & IS_I2C_READY) == 0); - - pSen->SenState = SK_SEN_IDLE; - return; -} /* SkI2cWaitIrq */ - -/* - * writes a single byte or 4 bytes into the I2C device - * - * returns 0: success - * 1: error - */ -int SkI2cWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 I2cData, /* I2C Data to write */ -int I2cDev, /* I2C Device Address */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_OUT32(IoC, B2_I2C_DATA, I2cData); - SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cReg, I2cBurst); - - return(SkI2cWait(pAC, IoC, I2C_WRITE)); -} /* SkI2cWrite*/ - - -#ifdef SK_DIAG - -/* - * reads a single byte or 4 bytes from the I2C device - * - * returns the word read - */ -SK_U32 SkI2cRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int I2cDev, /* I2C Device Address */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_U32 Data; - - SK_OUT32(IoC, B2_I2C_DATA, 0); - SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cReg, I2cBurst); - - if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { - w_print("%s\n", SKERR_I2C_E002MSG); - } - - SK_IN32(IoC, B2_I2C_DATA, &Data); - return(Data); -} /* SkI2cRead */ - -#endif /* SK_DIAG */ - - -/* - * read a sensor's value - * - * This function reads a sensor's value from the I2C sensor chip. The sensor - * is defined by its index into the sensors database in the struct pAC points - * to. - * Returns - * 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -int SkI2cReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - if (pSen->SenRead != NULL) { - return((*pSen->SenRead)(pAC, IoC, pSen)); - } - else - return(0); /* no success */ -} /* SkI2cReadSensor*/ - -/* - * Do the Init state 0 initialization - */ -static int SkI2cInit0( -SK_AC *pAC) /* Adapter Context */ -{ - int i; - - /* Begin with first sensor */ - pAC->I2c.CurrSens = 0; - - /* Begin with timeout control for state machine */ - pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; - - /* Set sensor number to zero */ - pAC->I2c.MaxSens = 0; - -#ifndef SK_DIAG - /* Initialize Number of Dummy Reads */ - pAC->I2c.DummyReads = SK_MAX_SENSORS; -#endif - - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenDesc = "unknown"; - pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN; - pAC->I2c.SenTable[i].SenThreErrHigh = 0; - pAC->I2c.SenTable[i].SenThreErrLow = 0; - pAC->I2c.SenTable[i].SenThreWarnHigh = 0; - pAC->I2c.SenTable[i].SenThreWarnLow = 0; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE; - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = NULL; - pAC->I2c.SenTable[i].SenDev = 0; - } - - /* Now we are "INIT data"ed */ - pAC->I2c.InitLevel = SK_INIT_DATA; - return(0); -} /* SkI2cInit0*/ - - -/* - * Do the init state 1 initialization - * - * initialize the following register of the LM80: - * Configuration register: - * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT - * - * Interrupt Mask Register 1: - * - all interrupts are Disabled (0xff) - * - * Interrupt Mask Register 2: - * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. - * - * Fan Divisor/RST_OUT register: - * - Divisors set to 1 (bits 00), all others 0s. - * - * OS# Configuration/Temperature resolution Register: - * - all 0s - * - */ -static int SkI2cInit1( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int i; - SK_U8 I2cSwCtrl; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - if (pAC->I2c.InitLevel != SK_INIT_DATA) { - /* ReInit not needed in I2C module */ - return(0); - } - - /* Set the Direction of I2C-Data Pin to IN */ - SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); - /* Check for 32-Bit Yukon with Low at I2C-Data Pin */ - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - if ((I2cSwCtrl & I2C_DATA) == 0) { - /* this is a 32-Bit board */ - pAC->GIni.GIYukon32Bit = SK_TRUE; - return(0); - } - - /* Check for 64 Bit Yukon without sensors */ - if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_CFG, 0) != 0) { - return(0); - } - - (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_1, 0); - - (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_2, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_FAN_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_TEMP_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, LM80_CFG_START, LM80_ADDR, LM80_CFG, 0); - - /* - * MaxSens has to be updated here, because PhyType is not - * set when performing Init Level 0 - */ - pAC->I2c.MaxSens = 5; - - pPrt = &pAC->GIni.GP[0]; - - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - if (pAC->GIni.GIMacsFound == 1) { - pAC->I2c.MaxSens += 1; - } - else { - pAC->I2c.MaxSens += 3; - } - } - } - else { - pAC->I2c.MaxSens += 3; - } - - for (i = 0; i < pAC->I2c.MaxSens; i++) { - switch (i) { - case 0: - pAC->I2c.SenTable[i].SenDesc = "Temperature"; - pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN; - break; - case 1: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN; - break; - case 2: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO; - break; - case 3: - pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN; - break; - case 4: - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PMA"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; - if (pAC->GIni.GIVauxAvail) { - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR; - } - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN; - break; - case 5: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC-Co 1V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN; - break; - case 6: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL"; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3"; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN; - break; - case 7: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Speed Fan"; - pAC->I2c.SenTable[i].SenType = SK_SEN_FAN; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, - SKERR_I2C_E001, SKERR_I2C_E001MSG); - break; - } - - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor; - pAC->I2c.SenTable[i].SenDev = LM80_ADDR; - } - -#ifndef SK_DIAG - pAC->I2c.DummyReads = pAC->I2c.MaxSens; -#endif /* !SK_DIAG */ - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - /* Now we are I/O initialized */ - pAC->I2c.InitLevel = SK_INIT_IO; - return(0); -} /* SkI2cInit1 */ - - -/* - * Init level 2: Start first sensor read. - */ -static int SkI2cInit2( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int ReadComplete; - SK_SENSOR *pSen; - - if (pAC->I2c.InitLevel != SK_INIT_IO) { - /* ReInit not needed in I2C module */ - /* Init0 and Init2 not permitted */ - return(0); - } - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); - } - - /* Now we are correctly initialized */ - pAC->I2c.InitLevel = SK_INIT_RUN; - - return(0); -} /* SkI2cInit2*/ - - -/* - * Initialize I2C devices - * - * Get the first voltage value and discard it. - * Go into temperature read mode. A default pointer is not set. - * - * The things to be done depend on the init level in the parameter list: - * Level 0: - * Initialize only the data structures. Do NOT access hardware. - * Level 1: - * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. - * Level 2: - * Everything is possible. Interrupts may be used from now on. - * - * return: - * 0 = success - * other = error. - */ -int SkI2cInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ -int Level) /* Init Level */ -{ - - switch (Level) { - case SK_INIT_DATA: - return(SkI2cInit0(pAC)); - case SK_INIT_IO: - return(SkI2cInit1(pAC, IoC)); - case SK_INIT_RUN: - return(SkI2cInit2(pAC, IoC)); - default: - break; - } - - return(0); -} /* SkI2cInit */ - - -#ifndef SK_DIAG - -/* - * Interrupt service function for the I2C Interface - * - * Clears the Interrupt source - * - * Reads the register and check it for sending a trap. - * - * Starts the timer if necessary. - */ -void SkI2cIsr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_EVPARA Para; - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); -} /* SkI2cIsr */ - - -/* - * Check this sensors Value against the threshold and send events. - */ -static void SkI2cCheckSensor( -SK_AC *pAC, /* Adapter Context */ -SK_SENSOR *pSen) -{ - SK_EVPARA ParaLocal; - SK_BOOL TooHigh; /* Is sensor too high? */ - SK_BOOL TooLow; /* Is sensor too low? */ - SK_U64 CurrTime; /* Current Time */ - SK_BOOL DoTrapSend; /* We need to send a trap */ - SK_BOOL DoErrLog; /* We need to log the error */ - SK_BOOL IsError; /* We need to log the error */ - - /* Check Dummy Reads first */ - if (pAC->I2c.DummyReads > 0) { - pAC->I2c.DummyReads--; - return; - } - - /* Get the current time */ - CurrTime = SkOsGetTime(pAC); - - /* Set para to the most useful setting: The current sensor. */ - ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; - - /* Check the Value against the thresholds. First: Error Thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreErrHigh); - TooLow = (pSen->SenValue < pSen->SenThreErrLow); - - IsError = SK_FALSE; - if (TooHigh || TooLow) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - /* Now error condition is satisfied */ - IsError = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > - CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > - CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegErrTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_ERR; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastErrTrapTS = CurrTime; - pSen->SenErrCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_ERR_UPP : - SK_PNMI_EVT_SEN_ERR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastErrLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, - SKERR_I2C_E011MSG); - } else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, - SKERR_I2C_E012MSG); - } else - { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, - SKERR_I2C_E015MSG); - } - } - } - - /* Check the Value against the thresholds */ - /* 2nd: Warning thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh); - TooLow = (pSen->SenValue < pSen->SenThreWarnLow); - - if (!IsError && (TooHigh || TooLow)) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > - CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > - CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegWarnTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_WARN; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastWarnTrapTS = CurrTime; - pSen->SenWarnCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_WAR_UPP : - SK_PNMI_EVT_SEN_WAR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastWarnLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, - SKERR_I2C_E009MSG); - } else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, - SKERR_I2C_E010MSG); - } else - { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, - SKERR_I2C_E014MSG); - } - } - } - - /* Check for NO error at all */ - if (!IsError && !TooHigh && !TooLow) { - /* Set o.k. Status if no error and no warning condition */ - pSen->SenErrFlag = SK_SEN_ERR_OK; - } - - /* End of check against the thresholds */ - - /* Bug fix AF: 16.Aug.2001: Correct the init base - * of LM80 sensor. - */ - if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { - /* 5V PCI-IO Voltage */ - pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; - } - else { - /* 3.3V PCI-IO Voltage */ - pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; - pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; - } - } - -#if 0 - /* Dynamic thresholds also for VAUX of LM80 sensor */ - if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - /* 3.3V VAUX Voltage */ - if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { - pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - /* 0V VAUX Voltage */ - else { - pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; - pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; - } - } - - /* - * Check initialization state: - * The VIO Thresholds need adaption - */ - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2C && - pSen->SenValue < SK_SEN_WARNHIGH2) { - pSen->SenThreErrLow = SK_SEN_ERRLOW2C; - pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; - pSen->SenInit = SK_TRUE; - } - - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2 && - pSen->SenValue < SK_SEN_WARNHIGH2C) { - pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; - pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; - pSen->SenInit = SK_TRUE; - } -#endif - - if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); - } -} /* SkI2cCheckSensor*/ - - -/* - * The only Event to be served is the timeout event - * - */ -int SkI2cEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - int ReadComplete; - SK_SENSOR *pSen; - SK_U32 Time; - SK_EVPARA ParaLocal; - int i; - - /* New case: no sensors */ - if (pAC->I2c.MaxSens == 0) { - return(0); - } - - switch (Event) { - case SK_I2CEV_IRQ: - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor (pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - else { - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_TIM: - if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { - - ParaLocal.Para64 = (SK_U64)0; - SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor (pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - } - else { - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - pSen->SenErrFlag = SK_SEN_ERR_FAULTY; - SK_I2C_STOP(IoC); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_CLEAR: - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenWarnCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenBegWarnTS = 0; - pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); - } - - return(0); -} /* SkI2cEvent*/ - -#endif /* !SK_DIAG */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/sklm80.c b/drivers/sk98lin/sklm80.c deleted file mode 100644 index 687572b1d2..0000000000 --- a/drivers/sk98lin/sklm80.c +++ /dev/null @@ -1,292 +0,0 @@ -/****************************************************************************** - * - * Name: sklm80.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.20 $ - * Date: $Date: 2002/08/13 09:16:27 $ - * Purpose: Funktions to access Voltage and Temperature Sensor (LM80) - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: sklm80.c,v $ - * Revision 1.20 2002/08/13 09:16:27 rschmidt - * Changed return value for SkLm80ReadSensor() back to 'int' - * Editorial changes - * - * Revision 1.19 2002/08/06 09:43:31 jschmalz - * Extensions and changes for Yukon - * - * Revision 1.18 2002/08/02 12:26:57 rschmidt - * Editorial changes - * - * Revision 1.17 1999/11/22 13:35:51 cgoos - * Changed license header to GPL. - * - * Revision 1.16 1999/05/27 14:05:47 malthoff - * Fans: Set SenVal to 0 if the fan value is 0 or 0xff. Both values - * are outside the limits (0: div zero error, 0xff: value not in - * range, assume 0). - * - * Revision 1.15 1999/05/27 13:38:51 malthoff - * Pervent from Division by zero errors. - * - * Revision 1.14 1999/05/20 09:20:01 cgoos - * Changes for 1000Base-T (Fan sensors). - * - * Revision 1.13 1998/10/22 09:48:14 gklug - * fix: SysKonnectFileId typo - * - * Revision 1.12 1998/10/09 06:12:06 malthoff - * Remove ID_sccs by SysKonnectFileId. - * - * Revision 1.11 1998/09/04 08:33:48 malthoff - * bug fix: SenState = SK_SEN_IDLE when - * leaving SK_SEN_VALEXT state - * - * Revision 1.10 1998/08/20 12:02:10 gklug - * fix: compiler warnings type mismatch - * - * Revision 1.9 1998/08/20 11:37:38 gklug - * chg: change Ioc to IoC - * - * Revision 1.8 1998/08/19 12:20:58 gklug - * fix: remove struct from C files (see CCC) - * - * Revision 1.7 1998/08/17 07:04:57 malthoff - * Take SkLm80RcvReg() function from ski2c.c. - * Add IoC parameter to BREAK_OR_WAIT() macro. - * - * Revision 1.6 1998/08/14 07:11:28 malthoff - * remove pAc with pAC. - * - * Revision 1.5 1998/08/14 06:46:55 gklug - * fix: temperature can get negative - * - * Revision 1.4 1998/08/13 08:27:04 gklug - * add: temperature reading now o.k. - * fix: pSen declaration, SK_ERR_LOG call, ADDR macro - * - * Revision 1.3 1998/08/13 07:28:21 gklug - * fix: pSen was wrong initialized - * add: correct conversion for voltage readings - * - * Revision 1.2 1998/08/11 07:52:14 gklug - * add: Lm80 read sensor function - * - * Revision 1.1 1998/07/17 09:57:12 gklug - * initial version - * - * - * - ******************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -/* - LM80 functions -*/ -static const char SysKonnectFileId[] = - "$Id: sklm80.c,v 1.20 2002/08/13 09:16:27 rschmidt Exp $" ; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef SK_DIAG -#define BREAK_OR_WAIT(pAC,IoC,Event) SkI2cWait(pAC,IoC,Event) -#else /* nSK_DIAG */ -#define BREAK_OR_WAIT(pAC,IoC,Event) break -#endif /* nSK_DIAG */ - -#ifdef SK_DIAG -/* - * read the register 'Reg' from the device 'Dev' - * - * return read error -1 - * success the read value - */ -int SkLm80RcvReg( -SK_IOC IoC, /* Adapter Context */ -int Dev, /* I2C device address */ -int Reg) /* register to read */ -{ - int Val = 0; - int TempExt; - - /* Signal device number */ - if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) { - return(-1); - } - - if (SkI2cSndByte(IoC, Reg)) { - return(-1); - } - - /* repeat start */ - if (SkI2cSndDev(IoC, Dev, I2C_READ)) { - return(-1); - } - - switch (Reg) { - case LM80_TEMP_IN: - Val = (int)SkI2cRcvByte(IoC, 1); - - /* First: correct the value: it might be negative */ - if ((Val & 0x80) != 0) { - /* Value is negative */ - Val = Val - 256; - } - Val = Val * SK_LM80_TEMP_LSB; - SkI2cStop(IoC); - - TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL); - - if (Val > 0) { - Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); - } - else { - Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); - } - return(Val); - break; - case LM80_VT0_IN: - case LM80_VT1_IN: - case LM80_VT2_IN: - case LM80_VT3_IN: - Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB; - break; - - default: - Val = (int)SkI2cRcvByte(IoC, 1); - break; - } - - SkI2cStop(IoC); - return(Val); -} -#endif /* SK_DIAG */ - -/* - * read a sensors value (LM80 specific) - * - * This function reads a sensors value from the I2C sensor chip LM80. - * The sensor is defined by its index into the sensors database in the struct - * pAC points to. - * - * Returns 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -int SkLm80ReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in level 1 and 2 */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - SK_I32 Value; - - switch (pSen->SenState) { - case SK_SEN_IDLE: - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, pSen->SenReg, 0); - - pSen->SenState = SK_SEN_VALUE ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALUE: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - - Value &= 0xff; /* only least significant byte is valid */ - - /* Do NOT check the Value against the thresholds */ - /* Checking is done in the calling instance */ - - if (pSen->SenType == SK_SEN_VOLT) { - /* Voltage sensor */ - pSen->SenValue = Value * SK_LM80_VT_LSB; - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - if (pSen->SenType == SK_SEN_FAN) { - if (Value != 0 && Value != 0xff) { - /* Fan speed counter */ - pSen->SenValue = SK_LM80_FAN_FAKTOR/Value; - } - else { - /* Indicate Fan error */ - pSen->SenValue = 0; - } - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - /* First: correct the value: it might be negative */ - if ((Value & 0x80) != 0) { - /* Value is negative */ - Value = Value - 256; - } - - /* We have a temperature sensor and need to get the signed extension. - * For now we get the extension from the last reading, so in the normal - * case we won't see flickering temperatures. - */ - pSen->SenValue = (Value * SK_LM80_TEMP_LSB) + - (pSen->SenValue % SK_LM80_TEMP_LSB); - - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, LM80_TEMP_CTRL, 0); - - pSen->SenState = SK_SEN_VALEXT ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALEXT: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */ - - /* cut the LSB bit */ - pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) * - SK_LM80_TEMP_LSB); - - if (pSen->SenValue < 0) { - /* Value negative: The bit value must be subtracted */ - pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - else { - /* Value positive: The bit value must be added */ - pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - - pSen->SenState = SK_SEN_IDLE ; - return(1); - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); - return(1); - } - - /* Not completed */ - return(0); -} - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skproc.c b/drivers/sk98lin/skproc.c deleted file mode 100644 index 4e340730e5..0000000000 --- a/drivers/sk98lin/skproc.c +++ /dev/null @@ -1,515 +0,0 @@ -/****************************************************************************** - * - * Name: skproc.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/02/25 14:16:37 $ - * Purpose: Funktions to display statictic data - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Created 22-Nov-2000 - * Author: Mirko Lindner (mlindner@syskonnect.de) - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skproc.c,v $ - * Revision 1.4 2003/02/25 14:16:37 mlindner - * Fix: Copyright statement - * - * Revision 1.3 2002/10/02 12:59:51 mlindner - * Add: Support for Yukon - * Add: Speed check and setup - * Add: Merge source for kernel 2.2.x and 2.4.x - * Add: Read sensor names directly from VPD - * Fix: Volt values - * - * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner - * Fix: Editorial changes - * - * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner - * Fix: Return value of proc_read - * - * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner - * New ProcFs entries - * - * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner - * Add: New ProcFs entries - * Fix: Counter Errors (Jumbo == to long errors) - * Fix: Kernel error compilation - * Fix: too short counters - * - * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner - * Add: More error messages - * - * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner - * fix: ProcFS owner protection - * - * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner - * chg: 2.4 requirements for procfs - * - * Revision 1.1 2001/01/22 14:15:31 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#include - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIALX 32 /* 0x */ -#define LARGE 64 - -extern SK_AC *pACList; -extern struct net_device *SkGeRootDev; - -extern char * SkNumber( - char * str, - long long num, - int base, - int size, - int precision, - int type); - - -/***************************************************************************** - * - * proc_read - print "summaries" entry - * - * Description: - * This function fills the proc entry with statistic data about - * the ethernet device. - * - * - * Returns: buffer with statistic data - * - */ -int proc_read(char *buffer, -char **buffer_location, -off_t offset, -int buffer_length, -int *eof, -void *data) -{ - int len = 0; - int t; - int i; - DEV_NET *pNet; - SK_AC *pAC; - char test_buf[100]; - char sens_msg[50]; - unsigned long Flags; - unsigned int Size; - struct SK_NET_DEVICE *next; - struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; - - SK_PNMI_STRUCT_DATA *pPnmiStruct; - SK_PNMI_STAT *pPnmiStat; - struct proc_dir_entry *file = (struct proc_dir_entry*) data; - - while (SkgeProcDev) { - pNet = (DEV_NET*) SkgeProcDev->priv; - pAC = pNet->pAC; - next = pAC->Next; - pPnmiStruct = &pAC->PnmiStruct; - /* NetIndex in GetStruct is now required, zero is only dummy */ - - for (t=pAC->GIni.GIMacsFound; t > 0; t--) { - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1) - t--; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, - pPnmiStruct, &Size, t-1); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - if (strcmp(pAC->dev[t-1]->name, file->name) == 0) { - pPnmiStat = &pPnmiStruct->Stat[0]; - len = sprintf(buffer, - "\nDetailed statistic for device %s\n", - pAC->dev[t-1]->name); - len += sprintf(buffer + len, - "=======================================\n"); - - /* Board statistics */ - len += sprintf(buffer + len, - "\nBoard statistics\n\n"); - len += sprintf(buffer + len, - "Active Port %c\n", - 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. - Net[t-1].PrefPort]->PortNumber); - len += sprintf(buffer + len, - "Preferred Port %c\n", - 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. - Net[t-1].PrefPort]->PortNumber); - - len += sprintf(buffer + len, - "Bus speed (MHz) %d\n", - pPnmiStruct->BusSpeed); - - len += sprintf(buffer + len, - "Bus width (Bit) %d\n", - pPnmiStruct->BusWidth); - len += sprintf(buffer + len, - "Hardware revision v%d.%d\n", - (pAC->GIni.GIPciHwRev >> 4) & 0x0F, - pAC->GIni.GIPciHwRev & 0x0F); - - /* Print sensor informations */ - for (i=0; i < pAC->I2c.MaxSens; i ++) { - /* Check type */ - switch (pAC->I2c.SenTable[i].SenType) { - case 1: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (C)"); - len += sprintf(buffer + len, - "%-25s %d.%02d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue / 10, - pAC->I2c.SenTable[i].SenValue % 10); - - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (F)"); - len += sprintf(buffer + len, - "%-25s %d.%02d\n", - sens_msg, - ((((pAC->I2c.SenTable[i].SenValue) - *10)*9)/5 + 3200)/100, - ((((pAC->I2c.SenTable[i].SenValue) - *10)*9)/5 + 3200) % 10); - break; - case 2: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (V)"); - len += sprintf(buffer + len, - "%-25s %d.%03d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue / 1000, - pAC->I2c.SenTable[i].SenValue % 1000); - break; - case 3: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (rpm)"); - len += sprintf(buffer + len, - "%-25s %d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue); - break; - default: - break; - } - } - - /*Receive statistics */ - len += sprintf(buffer + len, - "\nReceive statistics\n\n"); - - len += sprintf(buffer + len, - "Received bytes %s\n", - SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Received packets %s\n", - SkNumber(test_buf, pPnmiStat->StatRxOkCts, - 10,0,-1,0)); -#if 0 - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && - pAC->HWRevision < 12) { - pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxShortsCts; - pPnmiStat->StatRxShortsCts = 0; - } -#endif - if (pNet->Mtu > 1500) - pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts; - - len += sprintf(buffer + len, - "Receive errors %s\n", - SkNumber(test_buf, pPnmiStruct->InErrorsCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Receive drops %s\n", - SkNumber(test_buf, pPnmiStruct->RxNoBufCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Received multicast %s\n", - SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Receive error types\n"); - len += sprintf(buffer + len, - " length %s\n", - SkNumber(test_buf, pPnmiStat->StatRxRuntCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " buffer overflow %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " bad crc %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFcsCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " framing %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFramingCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " missed frames %s\n", - SkNumber(test_buf, pPnmiStat->StatRxMissedCts, - 10, 0, -1, 0)); - - if (pNet->Mtu > 1500) - pPnmiStat->StatRxTooLongCts = 0; - - len += sprintf(buffer + len, - " too long %s\n", - SkNumber(test_buf, pPnmiStat->StatRxTooLongCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " carrier extension %s\n", - SkNumber(test_buf, pPnmiStat->StatRxCextCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " too short %s\n", - SkNumber(test_buf, pPnmiStat->StatRxShortsCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " symbol %s\n", - SkNumber(test_buf, pPnmiStat->StatRxSymbolCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " LLC MAC size %s\n", - SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " carrier event %s\n", - SkNumber(test_buf, pPnmiStat->StatRxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " jabber %s\n", - SkNumber(test_buf, pPnmiStat->StatRxJabberCts, - 10, 0, -1, 0)); - - - /*Transmit statistics */ - len += sprintf(buffer + len, - "\nTransmit statistics\n\n"); - - len += sprintf(buffer + len, - "Transmited bytes %s\n", - SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmited packets %s\n", - SkNumber(test_buf, pPnmiStat->StatTxOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit errors %s\n", - SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit dropped %s\n", - SkNumber(test_buf, pPnmiStruct->TxNoBufCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit collisions %s\n", - SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit errors types\n"); - len += sprintf(buffer + len, - " excessive collision %ld\n", - pAC->stats.tx_aborted_errors); - len += sprintf(buffer + len, - " carrier %s\n", - SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " fifo underrun %s\n", - SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " heartbeat %s\n", - SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " window %ld\n", - pAC->stats.tx_window_errors); - - } - } - SkgeProcDev = next; - } - if (offset >= len) { - *eof = 1; - return 0; - } - - *buffer_location = buffer + offset; - if (buffer_length >= len - offset) { - *eof = 1; - } - return (min_t(int, buffer_length, len - offset)); -} - - -/***************************************************************************** - * - * SkDoDiv - convert 64bit number - * - * Description: - * This function "converts" a long long number. - * - * Returns: - * remainder of division - */ -static long SkDoDiv (long long Dividend, int Divisor, long long *pErg) -{ - long Rest; - long long Ergebnis; - long Akku; - - - Akku = Dividend >> 32; - - Ergebnis = ((long long) (Akku / Divisor)) << 32; - Rest = Akku % Divisor ; - - Akku = Rest << 16; - Akku |= ((Dividend & 0xFFFF0000) >> 16); - - - Ergebnis += ((long long) (Akku / Divisor)) << 16; - Rest = Akku % Divisor ; - - Akku = Rest << 16; - Akku |= (Dividend & 0xFFFF); - - Ergebnis += (Akku / Divisor); - Rest = Akku % Divisor ; - - *pErg = Ergebnis; - return (Rest); -} - - -#if 0 -#define do_div(n,base) ({ \ -long long __res; \ -__res = ((unsigned long long) n) % (unsigned) base; \ -n = ((unsigned long long) n) / (unsigned) base; \ -__res; }) - -#endif - - -/***************************************************************************** - * - * SkNumber - Print results - * - * Description: - * This function converts a long long number into a string. - * - * Returns: - * number as string - */ -char * SkNumber(char * str, long long num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[66], *strorg = str; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIALX) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[SkDoDiv(num,base, &num)]; - - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIALX) { - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; - } - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - - str[0] = '\0'; - - return strorg; -} - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skqueue.c b/drivers/sk98lin/skqueue.c deleted file mode 100644 index c49baed4f0..0000000000 --- a/drivers/sk98lin/skqueue.c +++ /dev/null @@ -1,242 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.18 $ - * Date: $Date: 2002/05/07 14:11:11 $ - * Purpose: Management of an event queue. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skqueue.c,v $ - * Revision 1.18 2002/05/07 14:11:11 rwahl - * Fixed Watcom Precompiler error. - * - * Revision 1.17 2002/03/25 10:06:41 mkunz - * SkIgnoreEvent deleted - * - * Revision 1.16 2002/03/15 10:51:59 mkunz - * Added event classes for link aggregation - * - * Revision 1.15 1999/11/22 13:36:29 cgoos - * Changed license header to GPL. - * - * Revision 1.14 1998/10/15 15:11:35 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.13 1998/09/08 08:47:52 gklug - * add: init level handling - * - * Revision 1.12 1998/09/08 07:43:20 gklug - * fix: Sirq Event function name - * - * Revision 1.11 1998/09/08 05:54:34 gklug - * chg: define SK_CSUM is replaced by SK_USE_CSUM - * - * Revision 1.10 1998/09/03 14:14:49 gklug - * add: CSUM and HWAC Eventclass and function. - * - * Revision 1.9 1998/08/19 09:50:50 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.8 1998/08/17 13:43:11 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.7 1998/08/14 07:09:11 gklug - * fix: chg pAc -> pAC - * - * Revision 1.6 1998/08/11 12:13:14 gklug - * add: return code feature of Event service routines - * add: correct Error log calls - * - * Revision 1.5 1998/08/07 12:53:45 gklug - * fix: first compiled version - * - * Revision 1.4 1998/08/07 09:20:48 gklug - * adapt functions to C coding conventions. - * - * Revision 1.3 1998/08/05 11:29:32 gklug - * rmv: Timer event entry. Timer will queue event directly - * - * Revision 1.2 1998/07/31 11:22:40 gklug - * Initial version - * - * Revision 1.1 1998/07/30 15:14:01 gklug - * Initial version. Adapted from SMT - * - * - * - ******************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -/* - Event queue and dispatcher -*/ -static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skqueue.c,v 1.18 2002/05/07 14:11:11 rwahl Exp $" ; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skqueue.h" /* Queue Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - -#define PRINTF(a,b,c) - -/* - * init event queue management - * - * Must be called during init level 0. - */ -void SkEventInit( -SK_AC *pAC, /* Adapter context */ -SK_IOC Ioc, /* IO context */ -int Level) /* Init level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue ; - break; - default: - break; - } -} - -/* - * add event to queue - */ -void SkEventQueue( -SK_AC *pAC, /* Adapters context */ -SK_U32 Class, /* Event Class */ -SK_U32 Event, /* Event to be queued */ -SK_EVPARA Para) /* Event parameter */ -{ - pAC->Event.EvPut->Class = Class ; - pAC->Event.EvPut->Event = Event ; - pAC->Event.EvPut->Para = Para ; - if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pAC->Event.EvPut = pAC->Event.EvQueue ; - - if (pAC->Event.EvPut == pAC->Event.EvGet) { - SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG) ; - } -} - -/* - * event dispatcher - * while event queue is not empty - * get event from queue - * send command to state machine - * end - * return error reported by individual Event function - * 0 if no error occured. - */ -int SkEventDispatcher( -SK_AC *pAC, /* Adapters Context */ -SK_IOC Ioc) /* Io context */ -{ - SK_EVENTELEM *pEv ; /* pointer into queue */ - SK_U32 Class ; - int Rtv ; - - pEv = pAC->Event.EvGet ; - PRINTF("dispatch get %x put %x\n",pEv,pAC->Event.ev_put) ; - while (pEv != pAC->Event.EvPut) { - PRINTF("dispatch Class %d Event %d\n",pEv->Class,pEv->Event) ; - switch(Class = pEv->Class) { -#ifndef SK_USE_LAC_EV - case SKGE_RLMT : /* RLMT Event */ - Rtv = SkRlmtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_I2C : /* I2C Event */ - Rtv = SkI2cEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_PNMI : - Rtv = SkPnmiEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#endif /* SK_USE_LAC_EV */ - case SKGE_DRV : /* Driver Event */ - Rtv = SkDrvEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#ifndef SK_USE_SW_TIMER - case SKGE_HWAC : - Rtv = SkGeSirqEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#else /* !SK_USE_SW_TIMER */ - case SKGE_SWT : - Rtv = SkSwtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#endif /* !SK_USE_SW_TIMER */ -#ifdef SK_USE_LAC_EV - case SKGE_LACP : - Rtv = SkLacpEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_RSF : - Rtv = SkRsfEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_MARKER : - Rtv = SkMarkerEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_FD : - Rtv = SkFdEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#endif /* SK_USE_LAC_EV */ -#ifdef SK_USE_CSUM - case SKGE_CSUM : - Rtv = SkCsEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#endif /* SK_USE_CSUM */ - default : - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, - SKERR_Q_E002MSG) ; - Rtv = 0; - } - - if (Rtv != 0) { - return(Rtv) ; - } - - if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pEv = pAC->Event.EvQueue ; - - /* Renew get: it is used in queue_events to detect overruns */ - pAC->Event.EvGet = pEv; - } - - return(0) ; -} - -#endif /* CONFIG_SK98 */ - -/* End of file */ diff --git a/drivers/sk98lin/skrlmt.c b/drivers/sk98lin/skrlmt.c deleted file mode 100644 index f8a3b41f0f..0000000000 --- a/drivers/sk98lin/skrlmt.c +++ /dev/null @@ -1,3508 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.68 $ - * Date: $Date: 2003/01/31 15:26:56 $ - * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skrlmt.c,v $ - * Revision 1.68 2003/01/31 15:26:56 rschmidt - * Added init for local variables in RlmtInit(). - * - * Revision 1.67 2003/01/31 14:12:41 mkunz - * single port adapter runs now with two identical MAC addresses - * - * Revision 1.66 2002/09/23 15:14:19 rwahl - * - Reset broadcast timestamp on link down. - * - Editorial corrections. - * - * Revision 1.65 2002/07/22 14:29:48 rwahl - * - Removed BRK statement from debug check. - * - * Revision 1.64 2001/11/28 19:36:14 rwahl - * - RLMT Packets sent to an invalid MAC address in CLP/CLPSS mode - * (#10650). - * - Reworked fix for port switching in CLS mode (#10639) - * (no dependency to RLMT module). - * - Enabled dbg output for entry/exit of event functions. - * - Editorial changes. - * - * Revision 1.63 2001/10/26 07:53:18 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.62 2001/07/03 12:16:30 mkunz - * New Flag ChgBcPrio (Change priority of last broadcast received) - * - * Revision 1.61 2001/03/14 12:52:08 rassmann - * Fixed reporting of active port up/down to PNMI. - * - * Revision 1.60 2001/02/21 16:02:25 gklug - * fix: when RLMT starts set Active Port for PNMI - * - * Revision 1.59 2001/02/16 14:38:19 rassmann - * Initializing some pointers earlier in the init phase. - * Rx Mbufs are freed if the net which they belong to is stopped. - * - * Revision 1.58 2001/02/14 14:06:31 rassmann - * Editorial changes. - * - * Revision 1.57 2001/02/05 14:25:26 rassmann - * Prepared RLMT for transparent operation. - * - * Revision 1.56 2001/01/30 10:29:09 rassmann - * Not checking switching befor RlmtStart. - * Editorial changes. - * - * Revision 1.55 2001/01/22 13:41:38 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.54 2000/11/30 13:25:07 rassmann - * Setting SK_TICK_INCR to 1 by default. - * - * Revision 1.53 2000/11/30 10:48:07 cgoos - * Changed definition of SK_RLMT_BC_DELTA. - * - * Revision 1.52 2000/11/27 12:50:03 rassmann - * Checking ports after receiving broadcasts. - * - * Revision 1.51 2000/11/17 08:58:00 rassmann - * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. - * - * Revision 1.50 2000/11/09 12:24:34 rassmann - * Indicating that segmentation check is not running anymore after - * SkRlmtCheckSeg(). - * Restarting segmentation timer after segmentation log. - * Editorial changes. - * - * Revision 1.49 1999/11/22 13:38:02 cgoos - * Changed license header to GPL. - * Added initialization to some variables to avoid compiler warnings. - * - * Revision 1.48 1999/10/04 14:01:17 rassmann - * Corrected reaction to reception of BPDU frames (#10441). - * - * Revision 1.47 1999/07/20 12:53:36 rassmann - * Fixed documentation errors for lookahead macros. - * - * Revision 1.46 1999/05/28 13:29:16 rassmann - * Replaced C++-style comment. - * - * Revision 1.45 1999/05/28 13:28:08 rassmann - * Corrected syntax error (xxx). - * - * Revision 1.44 1999/05/28 11:15:54 rassmann - * Changed behaviour to reflect Design Spec v1.2. - * Controlling Link LED(s). - * Introduced RLMT Packet Version field in RLMT Packet. - * Newstyle lookahead macros (checking meta-information before looking at - * the packet). - * - * Revision 1.43 1999/01/28 13:12:43 rassmann - * Corrected Lookahead (bug introduced in previous Rev.). - * - * Revision 1.42 1999/01/28 12:50:41 rassmann - * Not using broadcast time stamps in CheckLinkState mode. - * - * Revision 1.41 1999/01/27 14:13:02 rassmann - * Monitoring broadcast traffic. - * Switching more reliably and not too early if switch is - * configured for spanning tree. - * - * Revision 1.40 1999/01/22 13:17:30 rassmann - * Informing PNMI of NET_UP. - * Clearing RLMT multicast addresses before setting them for the first time. - * Reporting segmentation earlier, setting a "quiet time" - * after a report. - * - * Revision 1.39 1998/12/10 15:29:53 rassmann - * Corrected SuspectStatus in SkRlmtBuildCheckChain(). - * Corrected CHECK_SEG mode. - * - * Revision 1.38 1998/12/08 13:11:23 rassmann - * Stopping SegTimer at RlmtStop. - * - * Revision 1.37 1998/12/07 16:51:42 rassmann - * Corrected comments. - * - * Revision 1.36 1998/12/04 10:58:56 rassmann - * Setting next pointer to NULL when receiving. - * - * Revision 1.35 1998/12/03 16:12:42 rassmann - * Ignoring/correcting illegal PrefPort values. - * - * Revision 1.34 1998/12/01 11:45:35 rassmann - * Code cleanup. - * - * Revision 1.33 1998/12/01 10:29:32 rassmann - * Starting standby ports before getting the net up. - * Checking if a port is started when the link comes up. - * - * Revision 1.32 1998/11/30 16:19:50 rassmann - * New default for PortNoRx. - * - * Revision 1.31 1998/11/27 19:17:13 rassmann - * Corrected handling of LINK_DOWN coming shortly after LINK_UP. - * - * Revision 1.30 1998/11/24 12:37:31 rassmann - * Implemented segmentation check. - * - * Revision 1.29 1998/11/18 13:04:32 rassmann - * Secured PortUpTimer event. - * Waiting longer before starting standby port(s). - * - * Revision 1.28 1998/11/17 13:43:04 rassmann - * Handling (logical) tx failure. - * Sending packet on logical address after PORT_SWITCH. - * - * Revision 1.27 1998/11/13 17:09:50 rassmann - * Secured some events against being called in wrong state. - * - * Revision 1.26 1998/11/13 16:56:54 rassmann - * Added macro version of SkRlmtLookaheadPacket. - * - * Revision 1.25 1998/11/06 18:06:04 rassmann - * Corrected timing when RLMT checks fail. - * Clearing tx counter earlier in periodical checks. - * - * Revision 1.24 1998/11/05 10:37:27 rassmann - * Checking destination address in Lookahead. - * - * Revision 1.23 1998/11/03 13:53:49 rassmann - * RLMT should switch now (at least in mode 3). - * - * Revision 1.22 1998/10/29 14:34:49 rassmann - * Clearing SK_RLMT struct at startup. - * Initializing PortsUp during SK_RLMT_START. - * - * Revision 1.21 1998/10/28 11:30:17 rassmann - * Default mode is now SK_RLMT_CHECK_LOC_LINK. - * - * Revision 1.20 1998/10/26 16:02:03 rassmann - * Ignoring LINK_DOWN for links that are down. - * - * Revision 1.19 1998/10/22 15:54:01 rassmann - * Corrected EtherLen. - * Starting Link Check when second port comes up. - * - * Revision 1.18 1998/10/22 11:39:50 rassmann - * Corrected signed/unsigned mismatches. - * Corrected receive list handling and address recognition. - * - * Revision 1.17 1998/10/19 17:01:20 rassmann - * More detailed checking of received packets. - * - * Revision 1.16 1998/10/15 15:16:34 rassmann - * Finished Spanning Tree checking. - * Checked with lint. - * - * Revision 1.15 1998/09/24 19:16:07 rassmann - * Code cleanup. - * Introduced Timer for PORT_DOWN due to no RX. - * - * Revision 1.14 1998/09/18 20:27:14 rassmann - * Added address override. - * - * Revision 1.13 1998/09/16 11:31:48 rassmann - * Including skdrv1st.h again. :( - * - * Revision 1.12 1998/09/16 11:09:50 rassmann - * Syntax corrections. - * - * Revision 1.11 1998/09/15 12:32:03 rassmann - * Syntax correction. - * - * Revision 1.10 1998/09/15 11:28:49 rassmann - * Syntax corrections. - * - * Revision 1.9 1998/09/14 17:07:37 rassmann - * Added code for port checking via LAN. - * Changed Mbuf definition. - * - * Revision 1.8 1998/09/07 11:14:14 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/07 09:06:07 rassmann - * Syntax corrections. - * - * Revision 1.6 1998/09/04 19:41:33 rassmann - * Syntax corrections. - * Started entering code for checking local links. - * - * Revision 1.5 1998/09/04 12:14:27 rassmann - * Interface cleanup. - * - * Revision 1.4 1998/09/02 16:55:28 rassmann - * Updated to reflect new DRV/HWAC/RLMT interface. - * - * Revision 1.3 1998/08/27 14:29:03 rassmann - * Code cleanup. - * - * Revision 1.2 1998/08/27 14:26:24 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:26:49 rassmann - * First public version. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters. - * It is mainly intended for adapters with more than one link. - * For such adapters, this module realizes Redundant Link ManagemenT (RLMT). - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skrlmt.c,v 1.68 2003/01/31 15:26:56 rschmidt Exp $ (C) SysKonnect."; -#endif /* !defined(lint) */ - -#define __SKRLMT_C - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - -#ifndef SK_HWAC_LINK_LED -#define SK_HWAC_LINK_LED(a,b,c,d) -#endif /* !defined(SK_HWAC_LINK_LED) */ - -#ifndef DEBUG -#define RLMT_STATIC static -#else /* DEBUG */ -#define RLMT_STATIC - -#ifndef SK_LITTLE_ENDIAN -/* First 32 bits */ -#define OFFS_LO32 1 - -/* Second 32 bits */ -#define OFFS_HI32 0 -#else /* SK_LITTLE_ENDIAN */ -/* First 32 bits */ -#define OFFS_LO32 0 - -/* Second 32 bits */ -#define OFFS_HI32 1 -#endif /* SK_LITTLE_ENDIAN */ - -#endif /* DEBUG */ - -/* ----- Private timeout values ----- */ - -#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */ -#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */ -#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */ -#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */ -#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */ -#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */ - -/* Assume tick counter increment is 1 - may be set OS-dependent. */ -#ifndef SK_TICK_INCR -#define SK_TICK_INCR SK_CONSTU64(1) -#endif /* !defined(SK_TICK_INCR) */ - -/* - * Amount that a time stamp must be later to be recognized as "substantially - * later". This is about 1/128 sec, but above 1 tick counter increment. - */ -#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \ - (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR)) - -/* ----- Private RLMT defaults ----- */ - -#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */ -#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */ - -/* ----- Private RLMT checking states ----- */ - -#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */ -#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */ -#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */ -#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */ - -/* ----- Private PORT checking states ----- */ - -#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */ -#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */ - -/* ----- Private PORT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */ -#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */ -#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */ -#define SK_RLMT_PORTDOWN 1103 /* Port went down. */ -#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */ - -/* ----- Private RLMT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_TIM 2100 /* RLMT timeout. */ -#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */ - -#define TO_SHORTEN(tim) ((tim) / 2) - -/* Error numbers and messages. */ -#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0) -#define SKERR_RLMT_E001_MSG "No Packet." -#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1) -#define SKERR_RLMT_E002_MSG "Short Packet." -#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1) -#define SKERR_RLMT_E003_MSG "Unknown RLMT event." -#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1) -#define SKERR_RLMT_E004_MSG "PortsUp incorrect." -#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1) -#define SKERR_RLMT_E005_MSG \ - "Net seems to be segmented (different root bridges are reported on the ports)." -#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1) -#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected." -#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1) -#define SKERR_RLMT_E007_MSG "LinksUp incorrect." -#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1) -#define SKERR_RLMT_E008_MSG "Port not started but link came up." -#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1) -#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port." -#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1) -#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port." - -/* LLC field values. */ -#define LLC_COMMAND_RESPONSE_BIT 1 -#define LLC_TEST_COMMAND 0xE3 -#define LLC_UI 0x03 - -/* RLMT Packet fields. */ -#define SK_RLMT_DSAP 0 -#define SK_RLMT_SSAP 0 -#define SK_RLMT_CTRL (LLC_TEST_COMMAND) -#define SK_RLMT_INDICATOR0 0x53 /* S */ -#define SK_RLMT_INDICATOR1 0x4B /* K */ -#define SK_RLMT_INDICATOR2 0x2D /* - */ -#define SK_RLMT_INDICATOR3 0x52 /* R */ -#define SK_RLMT_INDICATOR4 0x4C /* L */ -#define SK_RLMT_INDICATOR5 0x4D /* M */ -#define SK_RLMT_INDICATOR6 0x54 /* T */ -#define SK_RLMT_PACKET_VERSION 0 - -/* RLMT SPT Flag values. */ -#define SK_RLMT_SPT_FLAG_CHANGE 0x01 -#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80 - -/* RLMT SPT Packet fields. */ -#define SK_RLMT_SPT_DSAP 0x42 -#define SK_RLMT_SPT_SSAP 0x42 -#define SK_RLMT_SPT_CTRL (LLC_UI) -#define SK_RLMT_SPT_PROTOCOL_ID0 0x00 -#define SK_RLMT_SPT_PROTOCOL_ID1 0x00 -#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00 -#define SK_RLMT_SPT_BPDU_TYPE 0x00 -#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */ -#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00 -#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_MSG_AGE0 0x00 -#define SK_RLMT_SPT_MSG_AGE1 0x00 -#define SK_RLMT_SPT_MAX_AGE0 0x00 -#define SK_RLMT_SPT_MAX_AGE1 0xFF -#define SK_RLMT_SPT_HELLO_TIME0 0x00 -#define SK_RLMT_SPT_HELLO_TIME1 0xFF -#define SK_RLMT_SPT_FWD_DELAY0 0x00 -#define SK_RLMT_SPT_FWD_DELAY1 0x40 - -/* Size defines. */ -#define SK_RLMT_MIN_PACKET_SIZE 34 -#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE) -#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ - SK_RLMT_MIN_PACKET_SIZE) - -/* ----- RLMT packet types ----- */ -#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */ -#define SK_PACKET_ALIVE 2 /* Alive packet to port. */ -#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */ -#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */ - -#ifdef SK_LITTLE_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ - SK_U8 *_Addr = (SK_U8*)(Addr); \ - SK_U16 _Val = (SK_U16)(Val); \ - *_Addr++ = (SK_U8)(_Val >> 8); \ - *_Addr = (SK_U8)(_Val & 0xFF); \ -} -#endif /* SK_LITTLE_ENDIAN */ - -#ifdef SK_BIG_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val)) -#endif /* SK_BIG_ENDIAN */ - -#define AUTONEG_FAILED SK_FALSE -#define AUTONEG_SUCCESS SK_TRUE - - -/* typedefs *******************************************************************/ - -/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */ -typedef struct s_RlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 Indicator[7]; - SK_U8 RlmtPacketType[2]; - SK_U8 Align1[2]; - SK_U8 Random[4]; /* Random value of requesting(!) station. */ - SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ - SK_U8 Data[SK_PACKET_DATA_LEN]; -} SK_RLMT_PACKET; - -typedef struct s_SpTreeRlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 ProtocolId[2]; - SK_U8 ProtocolVersionId; - SK_U8 BpduType; - SK_U8 Flags; - SK_U8 RootId[8]; - SK_U8 RootPathCost[4]; - SK_U8 BridgeId[8]; - SK_U8 PortId[2]; - SK_U8 MessageAge[2]; - SK_U8 MaxAge[2]; - SK_U8 HelloTime[2]; - SK_U8 ForwardDelay[2]; -} SK_SPTREE_PACKET; - -/* global variables ***********************************************************/ - -SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; -SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; -SK_MAC_ADDR BcAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - -/* local variables ************************************************************/ - -/* None. */ - -/* functions ******************************************************************/ - -RLMT_STATIC void SkRlmtCheckSwitch( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtCheckSeg( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtEvtSetNets( - SK_AC *pAC, - SK_IOC IoC, - SK_EVPARA Para); - -/****************************************************************************** - * - * SkRlmtInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine initializes all RLMT-related variables to a known state. - * The initial state is SK_RLMT_RS_INIT. - * All ports are initialized to SK_RLMT_PS_INIT. - * - * - * SK_INIT_IO - * ========== - * - * Nothing. - * - * - * SK_INIT_RUN - * =========== - * - * Determine the adapter's random value. - * Set the hw registers, the "logical MAC address", the - * RLMT multicast address, and eventually the BPDU multicast address. - * - * Context: - * init, pageable - * - * Returns: - * Nothing. - */ -void SkRlmtInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Level) /* Initialization Level */ -{ - SK_U32 i, j; - SK_U64 Random; - SK_EVPARA Para; - SK_MAC_ADDR VirtualMacAddress; - SK_MAC_ADDR PhysicalAMacAddress; - SK_BOOL VirtualMacAddressSet; - SK_BOOL PhysicalAMacAddressSet; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT Init level %d.\n", Level)) - - switch (Level) { - case SK_INIT_DATA: /* Initialize data structures. */ - SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[i].LinkDown = SK_TRUE; - pAC->Rlmt.Port[i].PortDown = SK_TRUE; - pAC->Rlmt.Port[i].PortStarted = SK_FALSE; - pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; - pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[i].PortNumber = i; - pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; - pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; - } - - pAC->Rlmt.NumNets = 1; - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; - pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1]; -#if SK_MAX_NETS > 1 - pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1]; -#endif /* SK_MAX_NETS > 1 */ - break; - - case SK_INIT_IO: /* GIMacsFound first available here. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) - - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - /* Initialize HW registers? */ - if (pAC->GIni.GIMacsFound == 1) { - Para.Para32[0] = SK_RLMT_MODE_CLS; - Para.Para32[1] = 0; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); - } - break; - - case SK_INIT_RUN: - /* Ensure RLMT is set to one net. */ - if (pAC->Rlmt.NumNets > 1) { - Para.Para32[0] = 1; - Para.Para32[1] = -1; - SkRlmtEvtSetNets(pAC, IoC, Para); - } - - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - Random = SkOsGetTime(pAC); - *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random; - - for (j = 0; j < 4; j++) { - pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort-> - CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j]; - } - - (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT); - } - - (void)SkAddrMcUpdate(pAC, IoC, i); - } - - VirtualMacAddressSet = SK_FALSE; - /* Read virtual MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); - VirtualMacAddressSet |= VirtualMacAddress.a[j]; - } - - PhysicalAMacAddressSet = SK_FALSE; - /* Read physical MAC address for MAC A from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); - PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; - } - - /* check if the two mac addresses contain reasonable values */ - if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - - /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD - and the RLMT_LOOKAHEAD macros */ - else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - else { - pAC->Rlmt.RlmtOff = SK_FALSE; - } - break; - - default: /* error */ - break; - } - return; -} /* SkRlmtInit */ - - -/****************************************************************************** - * - * SkRlmtBuildCheckChain - build the check chain - * - * Description: - * This routine builds the local check chain: - * - Each port that is up checks the next port. - * - The last port that is up checks the first port that is up. - * - * Notes: - * - Currently only local ports are considered when building the chain. - * - Currently the SuspectState is just reset; - * it would be better to save it ... - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtBuildCheckChain( -SK_AC *pAC, /* Adapter Context */ -SK_U32 NetIdx) /* Net Number */ -{ - SK_U32 i; - SK_U32 NumMacsUp; - SK_RLMT_PORT * FirstMacUp; - SK_RLMT_PORT * PrevMacUp; - - FirstMacUp = NULL; - PrevMacUp = NULL; - - if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - } - return; /* Done. */ - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtBuildCheckChain.\n")) - - NumMacsUp = 0; - - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &= - ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX); - - /* - * If more than two links are detected we should consider - * checking at least two other ports: - * 1. the next port that is not LinkDown and - * 2. the next port that is not PortDown. - */ - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (NumMacsUp == 0) { - FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - } - else { - PrevMacUp->PortCheck[ - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = - pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[ - PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; - PrevMacUp->PortsChecked++; - } - PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - NumMacsUp++; - } - } - - if (NumMacsUp > 1) { - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = - FirstMacUp->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = - SK_FALSE; - PrevMacUp->PortsChecked++; - } - -#ifdef DEBUG - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d checks %d other ports: %2X.\n", i, - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, - pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) - } -#endif /* DEBUG */ - - return; -} /* SkRlmtBuildCheckChain */ - - -/****************************************************************************** - * - * SkRlmtBuildPacket - build an RLMT packet - * - * Description: - * This routine sets up an RLMT packet. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildPacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber, /* Sending port */ -SK_U16 PacketType, /* RLMT packet type */ -SK_MAC_ADDR *SrcAddr, /* Source address */ -SK_MAC_ADDR *DestAddr) /* Destination address */ -{ - int i; - SK_U16 Length; - SK_MBUF *pMb; - SK_RLMT_PACKET *pPacket; - -#ifdef DEBUG - SK_U8 CheckSrc = 0; - SK_U8 CheckDest = 0; - - for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { - CheckSrc |= SrcAddr->a[i]; - CheckDest |= DestAddr->a[i]; - } - - if ((CheckSrc == 0) || (CheckDest == 0)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, - ("SkRlmtBuildPacket: Invalid %s%saddr.\n", - (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) - } -#endif - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) { - pPacket = (SK_RLMT_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pPacket->DstAddr[i] = DestAddr->a[i]; - pPacket->SrcAddr[i] = SrcAddr->a[i]; - } - pPacket->DSap = SK_RLMT_DSAP; - pPacket->SSap = SK_RLMT_SSAP; - pPacket->Ctrl = SK_RLMT_CTRL; - pPacket->Indicator[0] = SK_RLMT_INDICATOR0; - pPacket->Indicator[1] = SK_RLMT_INDICATOR1; - pPacket->Indicator[2] = SK_RLMT_INDICATOR2; - pPacket->Indicator[3] = SK_RLMT_INDICATOR3; - pPacket->Indicator[4] = SK_RLMT_INDICATOR4; - pPacket->Indicator[5] = SK_RLMT_INDICATOR5; - pPacket->Indicator[6] = SK_RLMT_INDICATOR6; - - SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]); - - for (i = 0; i < 4; i++) { - pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; - } - - SK_U16_TO_NETWORK_ORDER( - SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); - - for (i = 0; i < SK_PACKET_DATA_LEN; i++) { - pPacket->Data[i] = 0x00; - } - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); - - if (PacketType == SK_PACKET_ALIVE) { - pAC->Rlmt.Port[PortNumber].TxHelloCts++; - } - } - - return (pMb); -} /* SkRlmtBuildPacket */ - - -/****************************************************************************** - * - * SkRlmtBuildSpanningTreePacket - build spanning tree check packet - * - * Description: - * This routine sets up a BPDU packet for spanning tree check. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned i; - SK_U16 Length; - SK_MBUF *pMb; - SK_SPTREE_PACKET *pSPacket; - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != - NULL) { - pSPacket = (SK_SPTREE_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->DstAddr[i] = BridgeMcAddr.a[i]; - pSPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pSPacket->DSap = SK_RLMT_SPT_DSAP; - pSPacket->SSap = SK_RLMT_SPT_SSAP; - pSPacket->Ctrl = SK_RLMT_SPT_CTRL; - - pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0; - pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1; - pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID; - pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE; - pSPacket->Flags = SK_RLMT_SPT_FLAGS; - pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0; - pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1; - pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0; - pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1; - pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2; - pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3; - pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0; - pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1; - - /* - * Use logical MAC address as bridge ID and filter these packets - * on receive. - */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] = - pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. - CurrentMacAddress.a[i]; - } - pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0; - pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1; - pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0; - pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1; - pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0; - pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1; - pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0; - pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1; - pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0; - pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1; - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); - - pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++; - } - - return (pMb); -} /* SkRlmtBuildSpanningTreePacket */ - - -/****************************************************************************** - * - * SkRlmtSend - build and send check packets - * - * Description: - * Depending on the RLMT state and the checking state, several packets - * are sent through the indicated port. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtSend( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned j; - SK_EVPARA Para; - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) { - /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */ - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - /* - * Send a directed RLMT packet to all ports that are - * checked by the indicated port. - */ - for (j = 0; j < pRPort->PortsChecked; j++) { - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[j].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - - if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) { - /* - * Send a BPDU packet to make a connected switch tell us - * the correct root bridge. - */ - if ((Para.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG; - pRPort->RootIdSet = SK_FALSE; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, - ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) - } - } - return; -} /* SkRlmtSend */ - - -/****************************************************************************** - * - * SkRlmtPortReceives - check if port is (going) down and bring it up - * - * Description: - * This routine checks if a port who received a non-BPDU packet - * needs to go up or needs to be stopped going down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPortReceives( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - pRPort->PortNoRx = SK_FALSE; - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { - /* - * Port is marked down (rx), but received a non-BPDU packet. - * Bring it up. - */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Received on PortDown.\n")) - - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortDown && !SuspectTx */ - else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Stop bringing port down.\n")) - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortGoingDown */ - - return; -} /* SkRlmtPortReceives */ - - -/****************************************************************************** - * - * SkRlmtPacketReceive - receive a packet for closer examination - * - * Description: - * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPacketReceive( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_MBUF *pMb) /* Received packet */ -{ -#ifdef xDEBUG - extern void DumpData(char *p, int size); -#endif /* DEBUG */ - int i; - unsigned j; - SK_U16 PacketType; - SK_U32 PortNumber; - SK_ADDR_PORT *pAPort; - SK_RLMT_PORT *pRPort; - SK_RLMT_PACKET *pRPacket; - SK_SPTREE_PACKET *pSPacket; - SK_EVPARA Para; - - PortNumber = pMb->PortIdx; - pAPort = &pAC->Addr.Port[PortNumber]; - pRPort = &pAC->Rlmt.Port[PortNumber]; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) - - pRPacket = (SK_RLMT_PACKET*)pMb->pData; - pSPacket = (SK_SPTREE_PACKET*)pRPacket; - -#ifdef xDEBUG - DumpData((char *)pRPacket, 32); -#endif /* DEBUG */ - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { - SkRlmtPortReceives(pAC, IoC, PortNumber); - } - - /* Check destination address. */ - - if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { - - /* Not sent to current MAC or registered MC address => Trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Not for me.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { - - /* - * Was sent by same port (may happen during port switching - * or in case of duplicate MAC addresses). - */ - - /* - * Check for duplicate address here: - * If Packet.Random != My.Random => DupAddr. - */ - for (i = 3; i >= 0; i--) { - if (pRPort->Random[i] != pRPacket->Random[i]) { - break; - } - } - - /* - * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply - * packets (they have the LLC_COMMAND_RESPONSE_BIT set in - * pRPacket->SSap). - */ - if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - pRPacket->SSap == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) - - /* Error Log entry. */ - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); - } - else { - /* Simply trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Sent by me.\n")) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - - /* Check SuspectTx entries. */ - if (pRPort->PortsSuspect > 0) { - for (j = 0; j < pRPort->PortsChecked; j++) { - if (pRPort->PortCheck[j].SuspectTx && - SK_ADDR_EQUAL( - pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { - pRPort->PortCheck[j].SuspectTx = SK_FALSE; - pRPort->PortsSuspect--; - break; - } - } - } - - /* Determine type of packet. */ - if (pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - - /* It's an RLMT packet. */ - PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | - pRPacket->RlmtPacketType[1]); - - switch (PacketType) { - case SK_PACKET_ANNOUNCE: /* Not yet used. */ -#if 0 - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC); -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Announce.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - case SK_PACKET_ALIVE: - if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Reply.\n")) - - if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || - SK_ADDR_EQUAL( - pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { - /* Obviously we could send something. */ - if (pRPort->CheckingState & SK_RLMT_PCS_TX) { - pRPort->CheckingState &= ~SK_RLMT_PCS_TX; - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - } - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, - SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTUP_TIM, Para); - } - } - - /* Mark sending port as alive? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { /* Alive Request Packet. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Request.\n")) - - pRPort->RxHelloCts++; - - /* Answer. */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; - pRPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; - - Para.pParaPtr = pMb; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_CHECK_TX: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Check your tx line.\n")) - - /* A port checking us requests us to check our tx line. */ - pRPort->CheckingState |= SK_RLMT_PCS_TX; - - /* Start PortDownTx timer. */ - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_TX_TIM, Para); - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_ADDR_CHANGED: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Address Change.\n")) - - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) - - /* RA;:;: ??? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - } - else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && - pSPacket->Ctrl == SK_RLMT_SPT_CTRL && - (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: BPDU Packet.\n")) - - /* Spanning Tree packet. */ - pRPort->RxSpHelloCts++; - - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. - Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { - /* - * Check segmentation if a new root bridge is set and - * the segmentation check is not currently running. - */ - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && - (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) - != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_SEG) == 0) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - /* Store tree view of this port. */ - for (i = 0; i < 8; i++) { - pRPort->Root.Id[i] = pSPacket->RootId[i]; - } - pRPort->RootIdSet = SK_TRUE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", - PortNumber, - pRPort->Root.Id[0], pRPort->Root.Id[1], - pRPort->Root.Id[2], pRPort->Root.Id[3], - pRPort->Root.Id[4], pRPort->Root.Id[5], - pRPort->Root.Id[6], pRPort->Root.Id[7])) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_REPORT_SEG) != 0) { - SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown Packet Type.\n")) - - /* Unknown packet. */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - return; -} /* SkRlmtPacketReceive */ - - -/****************************************************************************** - * - * SkRlmtCheckPort - check if a port works - * - * Description: - * This routine checks if a port whose link is up received something - * and if it seems to transmit successfully. - * - * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp - * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg - * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg - * - * if (Rx - RxBpdu == 0) { # No rx. - * if (state == PsUp) { - * PortCheckingState |= ChkRx - * } - * if (ModeCheckSeg && (Timeout == - * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { - * RlmtCheckingState |= ChkSeg) - * PortCheckingState |= ChkSeg - * } - * NewTimeout = TO_SHORTEN(Timeout) - * if (NewTimeout < RLMT_MIN_TIMEOUT) { - * NewTimeout = RLMT_MIN_TIMEOUT - * PortState = PsDown - * ... - * } - * } - * else { # something was received - * # Set counter to 0 at LinkDown? - * # No - rx may be reported after LinkDown ??? - * PortCheckingState &= ~ChkRx - * NewTimeout = RLMT_DEFAULT_TIMEOUT - * if (RxAck == 0) { - * possible reasons: - * is my tx line bad? -- - * send RLMT multicast and report - * back internally? (only possible - * between ports on same adapter) - * } - * if (RxChk == 0) { - * possible reasons: - * - tx line of port set to check me - * maybe bad - * - no other port/adapter available or set - * to check me - * - adapter checking me has a longer - * timeout - * ??? anything that can be done here? - * } - * } - * - * Context: - * runtime, pageable? - * - * Returns: - * New timeout value. - */ -RLMT_STATIC SK_U32 SkRlmtCheckPort( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - unsigned i; - SK_U32 NewTimeout; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", - PortNumber, pRPort->PacketsPerTimeSlot)) - - /* - * Check segmentation if there was no receive at least twice - * in a row (PortNoRx is already set) and the segmentation - * check is not currently running. - */ - - if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", - pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) - - if (pRPort->PortState != SK_RLMT_PS_DOWN) { - NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); - if (NewTimeout < SK_RLMT_MIN_TO_VAL) { - NewTimeout = SK_RLMT_MIN_TO_VAL; - } - - if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - Para.Para32[0] = PortNumber; - pRPort->CheckingState |= SK_RLMT_PCS_RX; - - /* - * What shall we do if the port checked by this one receives - * our request frames? What's bad - our rx line or his tx line? - */ - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownRxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_RX_TIM, Para); - - for (i = 0; i < pRPort->PortsChecked; i++) { - if (pRPort->PortCheck[i].SuspectTx) { - continue; - } - pRPort->PortCheck[i].SuspectTx = SK_TRUE; - pRPort->PortsSuspect++; - if ((Para.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX, - &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[i].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - else { /* PortDown -- or all partners suspect. */ - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - pRPort->PortNoRx = SK_TRUE; - } - else { /* A non-BPDU packet was received. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", - PortNumber, - pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, - pRPort->PacketsPerTimeSlot)) - - SkRlmtPortReceives(pAC, IoC, PortNumber); - if (pAC->Rlmt.CheckSwitch) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - - return (NewTimeout); -} /* SkRlmtCheckPort */ - - -/****************************************************************************** - * - * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) - * - * Description: - * This routine selects the port that received a broadcast frame - * substantially later than all other ports. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectBcRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U64 BcTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ - PortFound = SK_FALSE; - - /* Select port with the latest TimeStamp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", - i, - pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) - - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { - if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { - BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - } - } - } - - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received the last broadcast.\n", *pSelect)) - - /* Look if another port's time stamp is similar. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (i == *pSelect) { - continue; - } - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && - (pAC->Rlmt.Port[i].BcTimeStamp > - BcTimeStamp - SK_RLMT_BC_DELTA || - pAC->Rlmt.Port[i].BcTimeStamp + - SK_RLMT_BC_DELTA > BcTimeStamp)) { - PortFound = SK_FALSE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received a broadcast at a similar time.\n", i)) - break; - } - } - } - -#ifdef DEBUG - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " - "latest broadcast (%u).\n", - *pSelect, - BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) - } -#endif /* DEBUG */ - - return (PortFound); -} /* SkRlmtSelectBcRx */ - - -/****************************************************************************** - * - * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) - * - * Description: - * This routine selects a good port (it is PortUp && !SuspectRx). - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp && !SuspectRx. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (!pAC->Rlmt.Port[i].PortDown && - !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = i; - if (!pAC->Rlmt.Port[Active].PortDown && - !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = Active; - } - if (!pAC->Rlmt.Port[PrefPort].PortDown && - !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", - *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectNotSuspect */ - - -/****************************************************************************** - * - * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) - * - * Description: - * This routine selects a port that is up. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectUp */ - - -/****************************************************************************** - * - * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) - * - * Description: - * This routine selects the port that is going up for the longest time. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U64 GuTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - GuTimeStamp = 0; - PortFound = SK_FALSE; - - /* Select port that is PortGoingUp for the longest time. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - break; - } - } - - if (!PortFound) { - return (SK_FALSE); - } - - for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) - return (SK_TRUE); -} /* SkRlmtSelectGoingUp */ - - -/****************************************************************************** - * - * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) - * - * Description: - * This routine selects a port that is down. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortDown. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectDown */ - - -/****************************************************************************** - * - * SkRlmtCheckSwitch - select new active port and switch to it - * - * Description: - * This routine decides which port should be the active one and queues - * port switching if necessary. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSwitch( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net index */ -{ - SK_EVPARA Para; - SK_U32 Active; - SK_U32 PrefPort; - SK_U32 i; - SK_BOOL PortFound; - - Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ - PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ - PortFound = SK_FALSE; - pAC->Rlmt.CheckSwitch = SK_FALSE; - -#if 0 /* RW 2001/10/18 - active port becomes always prefered one */ - if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ - /* disable auto-fail back */ - PrefPort = Active; - } -#endif - - if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { - /* Last link went down - shut down the net. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; - Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); - - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - return; - } /* pAC->Rlmt.LinksUp == 0 */ - else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && - pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { - /* First link came up - get the net up. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; - - /* - * If pAC->Rlmt.ActivePort != Para.Para32[0], - * the DRV switches to the port that came up. - */ - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { - i = Active; - } - if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { - i = PrefPort; - } - PortFound = SK_TRUE; - break; - } - } - - if (PortFound) { - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - - pAC->Rlmt.Net[NetIdx].ActivePort = i; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); - - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, - pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. - CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); - } - - return; - } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ - else { /* Cannot be reached in dual-net mode. */ - Para.Para32[0] = Active; - - /* - * Preselection: - * If RLMT Mode != CheckLinkState - * select port that received a broadcast frame substantially later - * than all other ports - * else select first port that is not SuspectRx - * else select first port that is PortUp - * else select port that is PortGoingUp for the longest time - * else select first port that is PortDown - * else stop. - * - * For the preselected port: - * If ActivePort is equal in quality, select ActivePort. - * - * If PrefPort is equal in quality, select PrefPort. - * - * If ActivePort != SelectedPort, - * If old ActivePort is LinkDown, - * SwitchHard - * else - * SwitchSoft - */ - /* check of ChgBcPrio flag added */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (!pAC->Rlmt.Net[0].ChgBcPrio)) { - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - /* with changed priority for last broadcast received */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (pAC->Rlmt.Net[0].ChgBcPrio)) { - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (PortFound) { - - if (Para.Para32[1] != Active) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) - pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[0]]->PortNumber; - Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[1]]->PortNumber; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); - if (pAC->Rlmt.Port[Active].LinkDown) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); - } - Para.Para32[1] = NetIdx; - Para.Para32[0] = - pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical - * MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ - } /* Para.Para32[1] != Active */ - } /* PortFound */ - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); - } - } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ - return; -} /* SkRlmtCheckSwitch */ - - -/****************************************************************************** - * - * SkRlmtCheckSeg - Report if segmentation is detected - * - * Description: - * This routine checks if the ports see different root bridges and reports - * segmentation in such a case. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSeg( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net number */ -{ - SK_EVPARA Para; - SK_RLMT_NET *pNet; - SK_U32 i, j; - SK_BOOL Equal; - - pNet = &pAC->Rlmt.Net[NetIdx]; - pNet->RootIdSet = SK_FALSE; - Equal = SK_TRUE; - - for (i = 0; i < pNet->NumPorts; i++) { - if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { - continue; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, - pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], - pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], - pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], - pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) - - if (!pNet->RootIdSet) { - pNet->Root = pNet->Port[i]->Root; - pNet->RootIdSet = SK_TRUE; - continue; - } - - for (j = 0; j < 8; j ++) { - Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; - if (!Equal) { - break; - } - } - - if (!Equal) { - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); - - pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; - - /* 2000-03-06 RA: New. */ - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, - SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - break; - } - } /* for (i = 0; i < pNet->NumPorts; i++) */ - - /* 2000-03-06 RA: Moved here. */ - /* Segmentation check not running anymore. */ - pNet->CheckingState &= ~SK_RLMT_RCS_SEG; - -} /* SkRlmtCheckSeg */ - - -/****************************************************************************** - * - * SkRlmtPortStart - initialize port variables and start port - * - * Description: - * This routine initializes a port's variables and issues a PORT_START - * to the HWAC module. This handles retries if the start fails or the - * link eventually goes down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtPortStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port number */ -{ - SK_EVPARA Para; - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; - pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].CheckingState = 0; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); -} /* SkRlmtPortStart */ - - -/****************************************************************************** - * - * SkRlmtEvtPortStartTim - PORT_START_TIM - * - * Description: - * This routine handles PORT_START_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortStartTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) - return; - } - - /* - * Used to start non-preferred ports if the preferred one - * does not come up. - * This timeout needs only be set when starting the first - * (preferred) port. - */ - if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - /* PORT_START failed. */ - for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) { - if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, - pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber); - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) -} /* SkRlmtEvtPortStartTim */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkUp - LINK_UP - * - * Description: - * This routine handles LLINK_UP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para2; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - if (!pRPort->LinkDown) { - /* RA;:;: Any better solution? */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - /* Do something if timer already fired? */ - - pRPort->LinkDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - pRPort->BcTimeStamp = 0; - pRPort->Net->LinksUp++; - if (pRPort->Net->LinksUp == 1) { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - } - - for (i = 0; i < pRPort->Net->NumPorts; i++) { - if (!pRPort->Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber); - } - } - - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - - if (pRPort->Net->LinksUp >= 2) { - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - } - - /* If the first link comes up, start the periodical RLMT timeout. */ - if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) { - Para2.Para32[0] = pRPort->Net->NetNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer, - pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2); - } - - Para2 = Para; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); - - /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ - if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && - (Para2.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, - &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) - ) != NULL) { - /* Send "new" packet to RLMT multicast address. */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { - if ((Para2.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) { - pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; - pRPort->Net->CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event END.\n")) -} /* SkRlmtEvtLinkUp */ - - -/****************************************************************************** - * - * SkRlmtEvtPortUpTim - PORT_UP_TIM - * - * Description: - * This routine handles PORT_UP_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortUpTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) - return; - } - - pRPort->PortDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_UP; - pRPort->Net->PortsUp++; - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (pAC->Rlmt.NumNets <= 1) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event END.\n")) -} /* SkRlmtEvtPortUpTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPortDownTim - PORT_DOWN_* - * - * Description: - * This routine handles PORT_DOWN_* events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortDownX( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", - Para.Para32[0], Event)) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && - !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) - return; - } - - /* Stop port's timers. */ - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) { - pRPort->PortState = SK_RLMT_PS_DOWN; - } - - if (!pRPort->PortDown) { - pRPort->Net->PortsUp--; - pRPort->PortDown = SK_TRUE; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para); - } - - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - pRPort->BcTimeStamp = 0; - - /* - * RA;:;: To be checked: - * - actions at RLMT_STOP: We should not switch anymore. - */ - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (Para.Para32[0] == - pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) { - /* Active Port went down. */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) -} /* SkRlmtEvtPortDownX */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkDown - LINK_DOWN - * - * Description: - * This routine handles LINK_DOWN events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) - - if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - pRPort->Net->LinksUp--; - pRPort->LinkDown = SK_TRUE; - pRPort->PortState = SK_RLMT_PS_LINK_DOWN; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF); - - if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - - /* Ensure that port is marked down. */ - Para.Para32[1] = -1; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Event END.\n")) -} /* SkRlmtEvtLinkDown */ - - -/****************************************************************************** - * - * SkRlmtEvtPortAddr - PORT_ADDR - * - * Description: - * This routine handles PORT_ADDR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortAddr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i, j; - SK_RLMT_PORT *pRPort; - SK_MAC_ADDR *pOldMacAddr; - SK_MAC_ADDR *pNewMacAddr; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) - return; - } - - /* Port's physical MAC address changed. */ - pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress; - pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress; - - /* - * NOTE: This is not scalable for solutions where ports are - * checked remotely. There, we need to send an RLMT - * address change packet - and how do we ensure delivery? - */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - pRPort = &pAC->Rlmt.Port[i]; - for (j = 0; j < pRPort->PortsChecked; j++) { - if (SK_ADDR_EQUAL( - pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) { - pRPort->PortCheck[j].CheckAddr = *pNewMacAddr; - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event END.\n")) -} /* SkRlmtEvtPortAddr */ - - -/****************************************************************************** - * - * SkRlmtEvtStart - START - * - * Description: - * This routine handles START events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortIdx; - SK_U32 PortNumber; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets should have been started.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >= - pAC->Rlmt.Net[Para.Para32[0]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG); - - /* Change PrefPort to internal default. */ - Para2.Para32[0] = 0xFFFFFFFF; - Para2.Para32[1] = Para.Para32[0]; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2); - } - - PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort; - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber; - - pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0; - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN; - - /* Start preferred port. */ - SkRlmtPortStart(pAC, IoC, PortNumber); - - /* Start Timer (for first port only). */ - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer, - SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2); - - pAC->Rlmt.NetsStarted++; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event END.\n")) -} /* SkRlmtEvtStart */ - - -/****************************************************************************** - * - * SkRlmtEvtStop - STOP - * - * Description: - * This routine handles STOP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStop( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - /* Stop RLMT timers. */ - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer); - - /* Stop net. */ - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE; - Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL; - Para2.Para32[1] = Para.Para32[0]; /* Net# */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2); - - /* Stop ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) { - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer); - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE; - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2); - } - } - - pAC->Rlmt.NetsStarted--; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event END.\n")) -} /* SkRlmtEvtStop */ - - -/****************************************************************************** - * - * SkRlmtEvtTim - TIM - * - * Description: - * This routine handles TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - SK_U32 Timeout; - SK_U32 NewTimeout; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event EMPTY.\n")) - return; - } - - if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 || - pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) { - /* Mode changed or all links down: No more link checking. */ - return; - } - -#if 0 - pAC->Rlmt.SwitchCheckCounter--; - if (pAC->Rlmt.SwitchCheckCounter == 0) { - pAC->Rlmt.SwitchCheckCounter; - } -#endif /* 0 */ - - NewTimeout = SK_RLMT_DEF_TO_VAL; - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (!pRPort->LinkDown) { - Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber); - if (Timeout < NewTimeout) { - NewTimeout = Timeout; - } - - /* - * These counters should be set to 0 for all ports before the - * first frame is sent in the next loop. - */ - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - } - } - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout; - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) { - /* - * If checking remote ports, also send packets if - * (LinksUp == 1) && - * this port checks at least one (remote) port. - */ - - /* - * Must be new loop, as SkRlmtCheckPort can request to - * check segmentation when e.g. checking the last port. - */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) { - SkRlmtSend(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber); - } - } - } - - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer, - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, - Para); - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 && - (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) { - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event END.\n")) -} /* SkRlmtEvtTim */ - - -/****************************************************************************** - * - * SkRlmtEvtSegTim - SEG_TIM - * - * Description: - * This routine handles SEG_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSegTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ -#ifdef xDEBUG - int j; -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event EMPTY.\n")) - return; - } - -#ifdef xDEBUG - for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) { - SK_ADDR_PORT *pAPort; - SK_U32 k; - SK_U16 *InAddr; - SK_U8 InAddr8[6]; - - InAddr = (SK_U16 *)&InAddr8[0]; - pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort; - for (k = 0; k < pAPort->NextExactMatchRlmt; k++) { - /* Get exact match address k from port j. */ - XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - XM_EXM(k), InAddr); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n", - k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - InAddr8[0], InAddr8[1], InAddr8[2], - InAddr8[3], InAddr8[4], InAddr8[5], - pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], - pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], - pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) - } - } -#endif /* xDEBUG */ - - SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event END.\n")) -} /* SkRlmtEvtSegTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPacketRx - PACKET_RECEIVED - * - * Description: - * This routine handles PACKET_RECEIVED events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPacketRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_MBUF *pMb */ -{ - SK_MBUF *pMb; - SK_MBUF *pNextMb; - SK_U32 NetNumber; - - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) - - /* Should we ignore frames during port switching? */ - -#ifdef DEBUG - pMb = Para.pParaPtr; - if (pMb == NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) - } - else if (pMb->pNext != NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("More than one mbuf or pMb->pNext not set.\n")) - } -#endif /* DEBUG */ - - for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) { - pNextMb = pMb->pNext; - pMb->pNext = NULL; - - NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber; - if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) { - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { - SkRlmtPacketReceive(pAC, IoC, pMb); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event END.\n")) -} /* SkRlmtEvtPacketRx */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsClear - STATS_CLEAR - * - * Description: - * This routine handles STATS_CLEAR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsClear( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - /* Clear statistics for logical and physical ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - pRPort = - &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber]; - pRPort->TxHelloCts = 0; - pRPort->RxHelloCts = 0; - pRPort->TxSpHelloReqCts = 0; - pRPort->RxSpHelloCts = 0; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event END.\n")) -} /* SkRlmtEvtStatsClear */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsUpdate - STATS_UPDATE - * - * Description: - * This routine handles STATS_UPDATE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsUpdate( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - /* Update statistics - currently always up-to-date. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event END.\n")) -} /* SkRlmtEvtStatsUpdate */ - - -/****************************************************************************** - * - * SkRlmtEvtPrefportChange - PREFPORT_CHANGE - * - * Description: - * This routine handles PREFPORT_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPrefportChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - /* 0xFFFFFFFF == auto-mode. */ - if (Para.Para32[0] == 0xFFFFFFFF) { - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT; - } - else { - if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0]; - } - - pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0]; - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) -} /* SkRlmtEvtPrefportChange */ - - -/****************************************************************************** - * - * SkRlmtEvtSetNets - SET_NETS - * - * Description: - * This routine handles SET_NETS events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSetNets( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ -{ - int i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || - Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad number of nets: %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - /* Entering and leaving dual mode only allowed while nets are stopped. */ - if (pAC->Rlmt.NetsStarted > 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Changing dual mode only allowed while all nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 1) { - if (pAC->Rlmt.NumNets > 1) { - /* Clear logical MAC addr from second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL); - pAC->Rlmt.Net[1].NumPorts = 0; - } - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0]; - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to one net with two ports.\n")) - } - else if (Para.Para32[0] == 2) { - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; - pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; - pAC->Rlmt.Net[0].NumPorts = - pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - - pAC->Rlmt.Net[i].NetNumber = i; - } - - /* Set logical MAC addr on second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL); - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to two nets with one port each.\n")) - } - else { - /* Not implemented for more than two nets. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SetNets not implemented for more than two nets.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event END.\n")) -} /* SkRlmtSetNets */ - - -/****************************************************************************** - * - * SkRlmtEvtModeChange - MODE_CHANGE - * - * Description: - * This routine handles MODE_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtModeChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ -{ - SK_EVPARA Para2; - SK_U32 i; - SK_U32 PrevRlmtMode; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - Para.Para32[0] |= SK_RLMT_CHECK_LINK; - - if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) && - Para.Para32[0] != SK_RLMT_MODE_CLS) { - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Forced RLMT mode to CLS on single port net.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - /* Update RLMT mode. */ - PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode; - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0]; - - if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - /* SK_RLMT_CHECK_LOC_LINK bit changed. */ - if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 && - pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 && - pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) { - /* 20001207 RA: Was "PortsUp == 1". */ - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer, - pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue, - SKGE_RLMT, SK_RLMT_TIM, Para2); - } - } - - if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) { - /* SK_RLMT_CHECK_SEG bit changed. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) { - (void)SkAddrMcClear(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & - SK_RLMT_CHECK_SEG) != 0) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &BridgeMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown && - (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( - pAC, IoC, i)) != NULL) { - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet = - SK_FALSE; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - } - } - (void)SkAddrMcUpdate(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber); - } /* for ... */ - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) { - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2); - } - } /* SK_RLMT_CHECK_SEG bit changed. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event END.\n")) -} /* SkRlmtEvtModeChange */ - - -/****************************************************************************** - * - * SkRlmtEvent - a PORT- or an RLMT-specific event happened - * - * Description: - * This routine calls subroutines to handle PORT- and RLMT-specific events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * 0 - */ -int SkRlmtEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* Event-specific parameter */ -{ - switch (Event) { - - /* ----- PORT events ----- */ - - case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortStartTim(pAC, IoC, Para); - break; - case SK_RLMT_LINK_UP: /* From SIRQ. */ - SkRlmtEvtLinkUp(pAC, IoC, Para); - break; - case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortUpTim(pAC, IoC, Para); - break; - case SK_RLMT_PORTDOWN: /* From RLMT. */ - case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */ - case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortDownX(pAC, IoC, Event, Para); - break; - case SK_RLMT_LINK_DOWN: /* From SIRQ. */ - SkRlmtEvtLinkDown(pAC, IoC, Para); - break; - case SK_RLMT_PORT_ADDR: /* From ADDR. */ - SkRlmtEvtPortAddr(pAC, IoC, Para); - break; - - /* ----- RLMT events ----- */ - - case SK_RLMT_START: /* From DRV. */ - SkRlmtEvtStart(pAC, IoC, Para); - break; - case SK_RLMT_STOP: /* From DRV. */ - SkRlmtEvtStop(pAC, IoC, Para); - break; - case SK_RLMT_TIM: /* From RLMT via TIME. */ - SkRlmtEvtTim(pAC, IoC, Para); - break; - case SK_RLMT_SEG_TIM: - SkRlmtEvtSegTim(pAC, IoC, Para); - break; - case SK_RLMT_PACKET_RECEIVED: /* From DRV. */ - SkRlmtEvtPacketRx(pAC, IoC, Para); - break; - case SK_RLMT_STATS_CLEAR: /* From PNMI. */ - SkRlmtEvtStatsClear(pAC, IoC, Para); - break; - case SK_RLMT_STATS_UPDATE: /* From PNMI. */ - SkRlmtEvtStatsUpdate(pAC, IoC, Para); - break; - case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */ - SkRlmtEvtPrefportChange(pAC, IoC, Para); - break; - case SK_RLMT_MODE_CHANGE: /* From PNMI. */ - SkRlmtEvtModeChange(pAC, IoC, Para); - break; - case SK_RLMT_SET_NETS: /* From DRV. */ - SkRlmtEvtSetNets(pAC, IoC, Para); - break; - - /* ----- Unknown events ----- */ - - default: /* Create error log entry. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Unknown RLMT Event %d.\n", Event)) - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); - break; - } /* switch() */ - - return (0); -} /* SkRlmtEvent */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/sktimer.c b/drivers/sk98lin/sktimer.c deleted file mode 100644 index 37cd4c9fe1..0000000000 --- a/drivers/sk98lin/sktimer.c +++ /dev/null @@ -1,297 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.12 $ - * Date: $Date: 1999/11/22 13:38:51 $ - * Purpose: High level timer functions. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: sktimer.c,v $ - * Revision 1.12 1999/11/22 13:38:51 cgoos - * Changed license header to GPL. - * - * Revision 1.11 1998/12/17 13:24:13 gklug - * fix: restart problem: do NOT destroy timer queue if init 1 is done - * - * Revision 1.10 1998/10/15 15:11:36 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.9 1998/09/15 15:15:04 cgoos - * Changed TRUE/FALSE to SK_TRUE/SK_FALSE - * - * Revision 1.8 1998/09/08 08:47:55 gklug - * add: init level handling - * - * Revision 1.7 1998/08/19 09:50:53 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.6 1998/08/17 13:43:13 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.5 1998/08/14 07:09:14 gklug - * fix: chg pAc -> pAC - * - * Revision 1.4 1998/08/07 12:53:46 gklug - * fix: first compiled version - * - * Revision 1.3 1998/08/07 09:31:53 gklug - * fix: delta spelling - * - * Revision 1.2 1998/08/07 09:31:02 gklug - * adapt functions to new c coding conventions - * rmv: "fast" handling - * chg: inserting of new timer in queue. - * chg: event queue generation when timer runs out - * - * Revision 1.1 1998/08/05 11:27:55 gklug - * first version: adapted from SMT - * - * - * - * - ******************************************************************************/ - - -#include - -#ifdef CONFIG_SK98 - -/* - Event queue and dispatcher -*/ -static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ; - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - - -/* Forward declaration */ -static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); - - -/* - * Inits the software timer - * - * needs to be called during Init level 1. - */ -void SkTimerInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Level) /* Init Level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Tim.StQueue = 0 ; - break; - case SK_INIT_IO: - SkHwtInit(pAC,Ioc) ; - SkTimerDone(pAC, Ioc); - break; - default: - break; - } -} - -/* - * Stops a high level timer - * - If a timer is not in the queue the function returns normally, too. - */ -void SkTimerStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer) /* Timer Pointer to be started */ -{ - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; - - /* - * remove timer from queue - */ - pTimer->TmActive = SK_FALSE ; - if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { - SkHwtStop(pAC,Ioc) ; - } - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; - ppTimPrev = &pTm->TmNext ) { - if (pTm == pTimer) { - /* - * Timer found in queue - * - dequeue it and - * - correct delta of the next timer - */ - *ppTimPrev = pTm->TmNext ; - - if (pTm->TmNext) { - /* correct delta of next timer in queue */ - pTm->TmNext->TmDelta += pTm->TmDelta ; - } - return ; - } - } -} - -/* - * Start a high level software timer - */ -void SkTimerStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer, /* Timer Pointer to be started */ -SK_U32 Time, /* Time value */ -SK_U32 Class, /* Event Class for this timer */ -SK_U32 Event, /* Event Value for this timer */ -SK_EVPARA Para) /* Event Parameter for this timer */ -{ - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; - SK_U32 Delta ; - - Time /= 16 ; /* input is uS, clock ticks are 16uS */ - if (!Time) - Time = 1 ; - - SkTimerStop(pAC,Ioc,pTimer) ; - - pTimer->TmClass = Class ; - pTimer->TmEvent = Event ; - pTimer->TmPara = Para ; - pTimer->TmActive = SK_TRUE ; - - if (!pAC->Tim.StQueue) { - /* First Timer to be started */ - pAC->Tim.StQueue = pTimer ; - pTimer->TmNext = 0 ; - pTimer->TmDelta = Time ; - SkHwtStart(pAC,Ioc,Time) ; - return ; - } - - /* - * timer correction - */ - timer_done(pAC,Ioc,0) ; - - /* - * find position in queue - */ - Delta = 0 ; - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; - ppTimPrev = &pTm->TmNext ) { - if (Delta + pTm->TmDelta > Time) { - /* Position found */ - /* Here the timer needs to be inserted. */ - break ; - } - Delta += pTm->TmDelta ; - } - - /* insert in queue */ - *ppTimPrev = pTimer ; - pTimer->TmNext = pTm ; - pTimer->TmDelta = Time - Delta ; - - if (pTm) { - /* There is a next timer - * -> correct its Delta value. - */ - pTm->TmDelta -= pTimer->TmDelta ; - } - - /* - * start new with first - */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; -} - - -void SkTimerDone( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - timer_done(pAC,Ioc,1) ; -} - - -static void timer_done( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Restart) /* Do we need to restart the Hardware timer ? */ -{ - SK_U32 Delta ; - SK_TIMER *pTm ; - SK_TIMER *pTComp ; /* Timer completed now now */ - SK_TIMER **ppLast ; /* Next field of Last timer to be deq */ - int Done = 0 ; - - Delta = SkHwtRead(pAC,Ioc) ; - ppLast = &pAC->Tim.StQueue ; - pTm = pAC->Tim.StQueue ; - while (pTm && !Done) { - if (Delta >= pTm->TmDelta) { - /* Timer ran out */ - pTm->TmActive = SK_FALSE ; - Delta -= pTm->TmDelta ; - ppLast = &pTm->TmNext ; - pTm = pTm->TmNext ; - } else { - /* We found the first timer that did not run out */ - pTm->TmDelta -= Delta ; - Delta = 0 ; - Done = 1 ; - } - } - *ppLast = 0 ; - /* - * pTm points to the first Timer that did not run out. - * StQueue points to the first Timer that run out. - */ - - for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) { - SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, - pTComp->TmPara) ; - } - - /* Set head of timer queue to the first timer that did not run out */ - pAC->Tim.StQueue = pTm ; - - if (Restart && pAC->Tim.StQueue) { - /* Restart HW timer */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; - } -} - -#endif /* CONFIG_SK98 */ - -/* End of file */ diff --git a/drivers/sk98lin/skvpd.c b/drivers/sk98lin/skvpd.c deleted file mode 100644 index 3b81e67df8..0000000000 --- a/drivers/sk98lin/skvpd.c +++ /dev/null @@ -1,1329 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/01/13 10:42:45 $ - * Purpose: Shared software to read and write VPD data - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skvpd.c,v $ - * Revision 1.37 2003/01/13 10:42:45 rschmidt - * Replaced check for PCI device Id from YUKON with GENESIS - * to set the VPD size in VpdInit() - * Editorial changes - * - * Revision 1.36 2002/11/14 15:16:56 gheinig - * Added const specifier to key and buf parameters for VpdPara, VpdRead - * and VpdWrite for Diag 7 GUI - * - * Revision 1.35 2002/10/21 14:31:59 gheinig - * Took out CVS web garbage at head of file - * - * Revision 1.34 2002/10/21 11:47:24 gheinig - * Reverted to version 1.32 due to unwanted commit - * - * Revision 1.32 2002/10/14 16:04:29 rschmidt - * Added saving of VPD ROM Size from PCI_OUR_REG_2 - * Avoid reading of PCI_OUR_REG_2 in VpdTransferBlock() - * Editorial changes - * - * Revision 1.31 2002/09/10 09:21:32 mkarl - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis - * - * Revision 1.30 2002/09/09 14:43:03 mkarl - * changes for diagnostics in order to read VPD data before the adapter - * has been initialized - * editorial changes - * - * Revision 1.29 2002/07/26 13:20:43 mkarl - * added Yukon support - * save size of VPD in pAC->vpd.vpd_size - * - * Revision 1.28 2002/04/02 15:31:47 afischer - * Bug fix in VpdWait() - * - * Revision 1.27 2000/08/10 11:29:06 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * Removed unused function VpdWriteDword() (#if 0). - * Made VpdReadKeyword() available for SKDIAG only. - * - * Revision 1.26 2000/06/13 08:00:01 mkarl - * additional cast to avoid compile problems in 64 bit environment - * - * Revision 1.25 1999/11/22 13:39:32 cgoos - * Changed license header to GPL. - * - * Revision 1.24 1999/03/11 14:25:49 malthoff - * Replace __STDC__ with SK_KR_PROTO. - * - * Revision 1.23 1999/01/11 15:13:11 gklug - * fix: syntax error - * - * Revision 1.22 1998/10/30 06:41:15 gklug - * rmv: WARNING - * - * Revision 1.21 1998/10/29 07:15:14 gklug - * fix: Write Stream function needs verify. - * - * Revision 1.20 1998/10/28 18:05:08 gklug - * chg: no DEBUG in VpdMayWrite - * - * Revision 1.19 1998/10/28 15:56:11 gklug - * fix: Return len at end of ReadStream - * fix: Write even less than 4 bytes correctly - * - * Revision 1.18 1998/10/28 09:00:47 gklug - * fix: unreferenced local vars - * - * Revision 1.17 1998/10/28 08:25:45 gklug - * fix: WARNING - * - * Revision 1.16 1998/10/28 08:17:30 gklug - * fix: typo - * - * Revision 1.15 1998/10/28 07:50:32 gklug - * fix: typo - * - * Revision 1.14 1998/10/28 07:20:38 gklug - * chg: Interface functions to use IoC as parameter as well - * fix: VpdRead/WriteDWord now returns SK_U32 - * chg: VPD_IN/OUT names conform to SK_IN/OUT - * add: usage of VPD_IN/OUT8 macros - * add: VpdRead/Write Stream functions to r/w a stream of data - * fix: VpdTransferBlock swapped illegal - * add: VpdMayWrite - * - * Revision 1.13 1998/10/22 10:02:37 gklug - * fix: SysKonnectFileId typo - * - * Revision 1.12 1998/10/20 10:01:01 gklug - * fix: parameter to SkOsGetTime - * - * Revision 1.11 1998/10/15 12:51:48 malthoff - * Remove unrequired parameter p in vpd_setup_para(). - * - * Revision 1.10 1998/10/08 14:52:43 malthoff - * Remove CvsId by SysKonnectFileId. - * - * Revision 1.9 1998/09/16 07:33:52 malthoff - * replace memcmp() by SK_MEMCMP and - * memcpy() by SK_MEMCPY() to be - * independent from the 'C' Standard Library. - * - * Revision 1.8 1998/08/19 12:52:35 malthoff - * compiler fix: use SK_VPD_KEY instead of S_VPD. - * - * Revision 1.7 1998/08/19 08:14:01 gklug - * fix: remove struct keyword as much as possible from the C-code (see CCC) - * - * Revision 1.6 1998/08/18 13:03:58 gklug - * SkOsGetTime now returns SK_U64 - * - * Revision 1.5 1998/08/18 08:17:29 malthoff - * Ensure we issue a VPD read in vpd_read_dword(). - * Discard all VPD keywords other than Vx or Yx, where - * x is '0..9' or 'A..Z'. - * - * Revision 1.4 1998/07/03 14:52:19 malthoff - * Add category SK_DBGCAT_FATAL to some debug macros. - * bug fix: correct the keyword name check in vpd_write(). - * - * Revision 1.3 1998/06/26 11:16:53 malthoff - * Correct the modified File Identifier. - * - * Revision 1.2 1998/06/26 11:13:43 malthoff - * Modify the File Identifier. - * - * Revision 1.1 1998/06/19 14:11:08 malthoff - * Created, Tests with AIX were performed successfully - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -/* - Please refer skvpd.txt for infomation how to include this module - */ -static const char SysKonnectFileId[] = - "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK"; - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/skdebug.h" -#include "h/skdrv2nd.h" - -/* - * Static functions - */ -#ifndef SK_KR_PROTO -static SK_VPD_PARA *vpd_find_para( - SK_AC *pAC, - const char *key, - SK_VPD_PARA *p); -#else /* SK_KR_PROTO */ -static SK_VPD_PARA *vpd_find_para(); -#endif /* SK_KR_PROTO */ - -/* - * waits for a completion of a VPD transfer - * The VPD transfer must complete within SK_TICKS_PER_SEC/16 - * - * returns 0: success, transfer completes - * error exit(9) with a error message - */ -static int VpdWait( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int event) /* event to wait for (VPD_READ / VPD_write) completion*/ -{ - SK_U64 start_time; - SK_U16 state; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD wait for %s\n", event?"Write":"Read")); - start_time = SkOsGetTime(pAC); - do { - if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { - - /* Bug fix AF: Thu Mar 28 2002 - * Do not call: VPD_STOP(pAC, IoC); - * A pending VPD read cycle can not be aborted by writing - * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register). - * Although the write threshold in the OUR-register protects - * VPD read only space from being overwritten this does not - * protect a VPD read from being `converted` into a VPD write - * operation (on the fly). As a consequence the VPD_STOP would - * delete VPD read only data. In case of any problems with the - * I2C bus we exit the loop here. The I2C read operation can - * not be aborted except by a reset (->LR). - */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR, - ("ERROR:VPD wait timeout\n")); - return(1); - } - - VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("state = %x, event %x\n",state,event)); - } while((int)(state & PCI_VPD_FLAG) == event); - - return(0); -} - -#ifdef SKDIAG - -/* - * Read the dword at address 'addr' from the VPD EEPROM. - * - * Needed Time: MIN 1,3 ms MAX 2,6 ms - * - * Note: The DWord is returned in the endianess of the machine the routine - * is running on. - * - * Returns the data read. - */ -SK_U32 VpdReadDWord( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int addr) /* VPD address */ -{ - SK_U32 Rtv; - - /* start VPD read */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword at 0x%x\n",addr)); - addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr); - - /* ignore return code here */ - (void)VpdWait(pAC, IoC, VPD_READ); - - /* Don't swap here, it's a data stream of bytes */ - Rtv = 0; - - VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword data = 0x%x\n",Rtv)); - return(Rtv); -} - -#endif /* SKDIAG */ - -#if 0 - -/* - Write the dword 'data' at address 'addr' into the VPD EEPROM, and - verify that the data is written. - - Needed Time: - -. MIN MAX -. ------------------------------------------------------------------- -. write 1.8 ms 3.6 ms -. internal write cyles 0.7 ms 7.0 ms -. ------------------------------------------------------------------- -. over all program time 2.5 ms 10.6 ms -. read 1.3 ms 2.6 ms -. ------------------------------------------------------------------- -. over all 3.8 ms 13.2 ms -. - - - Returns 0: success - 1: error, I2C transfer does not terminate - 2: error, data verify error - - */ -static int VpdWriteDWord( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -int addr, /* VPD address */ -SK_U32 data) /* VPD data to write */ -{ - /* start VPD write */ - /* Don't swap here, it's a data stream of bytes */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD write dword at addr 0x%x, data = 0x%x\n",addr,data)); - VPD_OUT32(pAC, IoC, PCI_VPD_DAT_REG, (SK_U32)data); - /* But do it here */ - addr |= VPD_WRITE; - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)(addr | VPD_WRITE)); - - /* this may take up to 10,6 ms */ - if (VpdWait(pAC, IoC, VPD_WRITE)) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Write Timed Out\n")); - return(1); - }; - - /* verify data */ - if (VpdReadDWord(pAC, IoC, addr) != data) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Data Verify Error\n")); - return(2); - } - return(0); -} /* VpdWriteDWord */ - -#endif /* 0 */ - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdWriteStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - int j; - SK_U16 AdrReg; - int Rtv; - SK_U8 * pComp; /* Compare pointer */ - SK_U8 Data; /* Input Data for Compare */ - - /* Init Compare Pointer */ - pComp = (SK_U8 *) buf; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* - * At the begin of each cycle read the Data Reg - * So it is initialized even if only a few bytes - * are written. - */ - AdrReg = (SK_U16) Addr; - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - - /* Write current Byte */ - VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - *(SK_U8*)buf); - - if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg |= VPD_WRITE; /* WRITE operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_WRITE); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Write Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - /* - * Now re-read to verify - */ - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Verify Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { - - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); - - if (Data != *pComp) { - /* Verify Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("WriteStream Verify Error\n")); - return(i - (i%sizeof(SK_U32)) + j); - } - } - } - } - - return(Len); -} - - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdReadStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - SK_U16 AdrReg; - int Rtv; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - (SK_U8 *)buf); - } - - return(Len); -} - -/* - * Read ore writes 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdTransferBlock( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int addr, /* VPD start address */ -int len, /* number of bytes to read / to write */ -int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ -{ - int Rtv; /* Return value */ - int vpd_rom_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD %s block, addr = 0x%x, len = %d\n", - dir ? "write" : "read", addr, len)); - - if (len == 0) - return(0); - - vpd_rom_size = pAC->vpd.rom_size; - - if (addr > vpd_rom_size - 4) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Address error: 0x%x, exp. < 0x%x\n", - addr, vpd_rom_size - 4)); - return(0); - } - - if (addr + len > vpd_rom_size) { - len = vpd_rom_size - addr; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Warning: len was cut to %d\n", len)); - } - - if (dir == VPD_READ) { - Rtv = VpdReadStream(pAC, IoC, buf, addr, len); - } - else { - Rtv = VpdWriteStream(pAC, IoC, buf, addr, len); - } - - return(Rtv); -} - -#ifdef SKDIAG - -/* - * Read 'len' bytes of VPD data, starting at 'addr'. - * - * Returns number of bytes read. - */ -int VpdReadBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer were the data should be stored */ -int addr, /* start reading at the VPD address */ -int len) /* number of bytes to read */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); -} - -/* - * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. - * - * Returns number of bytes writes. - */ -int VpdWriteBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer, holds the data to write */ -int addr, /* start writing at the VPD address */ -int len) /* number of bytes to write */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); -} -#endif /* SKDIAG */ - -/* - * (re)initialize the VPD buffer - * - * Reads the VPD data from the EEPROM into the VPD buffer. - * Get the remaining read only and read / write space. - * - * return 0: success - * 1: fatal VPD error - */ -static int VpdInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - SK_VPD_PARA *r, rp; /* RW or RV */ - int i; - unsigned char x; - int vpd_size; - SK_U16 dev_id; - SK_U32 our_reg2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); - - VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); - - VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); - - pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); - - /* - * this function might get used before the hardware is initialized - * therefore we cannot always trust in GIChipId - */ - if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 && - dev_id != VPD_DEV_ID_GENESIS) || - ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 && - !pAC->GIni.GIGenesis)) { - - /* for Yukon the VPD size is always 256 */ - vpd_size = VPD_SIZE_YUKON; - } - else { - /* Genesis uses the maximum ROM size up to 512 for VPD */ - if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) { - vpd_size = VPD_SIZE_GENESIS; - } - else { - vpd_size = pAC->vpd.rom_size; - } - } - - /* read the VPD data into the VPD buffer */ - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ) - != vpd_size) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Block Read Error\n")); - return(1); - } - - pAC->vpd.vpd_size = vpd_size; - - /* find the end tag of the RO area */ - if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_ro = r->p_len - 1; - - /* test the checksum */ - for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - - if (x != 0) { - /* checksum error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("VPD Checksum Error\n")); - return(1); - } - - /* find and check the end tag of the RW area */ - if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_rw = r->p_len; - - /* everything seems to be ok */ - if (pAC->GIni.GIChipId != 0) { - pAC->vpd.v.vpd_status |= VPD_VALID; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, - ("done. Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - return(0); -} - -/* - * find the Keyword 'key' in the VPD buffer and fills the - * parameter struct 'p' with it's values - * - * returns *p success - * 0: parameter was not found or VPD encoding error - */ -static SK_VPD_PARA *vpd_find_para( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to find (e.g. "MN") */ -SK_VPD_PARA *p) /* parameter description struct */ -{ - char *v ; /* points to VPD buffer */ - int max; /* Maximum Number of Iterations */ - - v = pAC->vpd.vpd_buf; - max = 128; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD find para %s .. ",key)); - - /* check mandatory resource type ID string (Product Name) */ - if (*v != (char)RES_ID) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Error: 0x%x missing\n", RES_ID)); - return(0); - } - - if (strcmp(key, VPD_NAME) == 0) { - p->p_len = VPD_GET_RES_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n", p->p_len)); - return(p); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - if (SK_MEMCMP(key,v,2) == 0) { - p->p_len = VPD_GET_VPD_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n",p->p_len)); - return(p); - } - - /* exit when reaching the "RW" Tag or the maximum of itera. */ - max--; - if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - } - else { - v += 3 + VPD_GET_VPD_LEN(v); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])); - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); - if (max == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Key/Len Encoding error\n")); - } -#endif /* DEBUG */ - return(0); -} - -/* - * Move 'n' bytes. Begin with the last byte if 'n' is > 0, - * Start with the last byte if n is < 0. - * - * returns nothing - */ -static void vpd_move_para( -char *start, /* start of memory block */ -char *end, /* end of memory block to move */ -int n) /* number of bytes the memory block has to be moved */ -{ - char *p; - int i; /* number of byte copied */ - - if (n == 0) - return; - - i = (int) (end - start + 1); - if (n < 0) { - p = start + n; - while (i != 0) { - *p++ = *start++; - i--; - } - } - else { - p = end + n; - while (i != 0) { - *p-- = *end--; - i--; - } - } -} - -/* - * setup the VPD keyword 'key' at 'ip'. - * - * returns nothing - */ -static void vpd_insert_key( -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the value string */ -char *ip) /* inseration point */ -{ - SK_VPD_KEY *p; - - p = (SK_VPD_KEY *) ip; - p->p_key[0] = key[0]; - p->p_key[1] = key[1]; - p->p_len = (unsigned char) len; - SK_MEMCPY(&p->p_val,buf,len); -} - -/* - * Setup the VPD end tag "RV" / "RW". - * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. - * - * returns 0: success - * 1: encoding error - */ -static int vpd_mod_endtag( -SK_AC *pAC, /* common data base */ -char *etp) /* end pointer input position */ -{ - SK_VPD_KEY *p; - unsigned char x; - int i; - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1])); - - vpd_size = pAC->vpd.vpd_size; - - p = (SK_VPD_KEY *) etp; - - if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { - /* something wrong here, encoding error */ - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: invalid end tag\n")); - return(1); - } - if (etp > pAC->vpd.vpd_buf + vpd_size/2) { - /* create "RW" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1); - pAC->vpd.v.vpd_free_rw = (int) p->p_len; - i = pAC->vpd.v.vpd_free_rw; - etp += 3; - } - else { - /* create "RV" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3); - pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1; - - /* setup checksum */ - for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - p->p_val = (char) 0 - x; - i = pAC->vpd.v.vpd_free_ro; - etp += 4; - } - while (i) { - *etp++ = 0x00; - i--; - } - - return(0); -} - -/* - * Insert a VPD keyword into the VPD buffer. - * - * The keyword 'key' is inserted at the position 'ip' in the - * VPD buffer. - * The keywords behind the input position will - * be moved. The VPD end tag "RV" or "RW" is generated again. - * - * returns 0: success - * 2: value string was cut - * 4: VPD full, keyword was not written - * 6: fatal VPD error - * - */ -int VpdSetupPara( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the keyword value */ -int type, /* VPD_RO_KEY or VPD_RW_KEY */ -int op) /* operation to do: ADD_KEY or OWR_KEY */ -{ - SK_VPD_PARA vp; - char *etp; /* end tag position */ - int free; /* remaining space in selected area */ - char *ip; /* input position inside the VPD buffer */ - int rtv; /* return code */ - int head; /* additional haeder bytes to move */ - int found; /* additinoal bytes if the keyword was found */ - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD setup para key = %s, val = %s\n",key,buf)); - - vpd_size = pAC->vpd.vpd_size; - - rtv = 0; - ip = 0; - if (type == VPD_RW_KEY) { - /* end tag is "RW" */ - free = pAC->vpd.v.vpd_free_rw; - etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3); - } - else { - /* end tag is "RV" */ - free = pAC->vpd.v.vpd_free_ro; - etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - head = 0; - found = 0; - if (op == OWR_KEY) { - if (vpd_find_para(pAC, key, &vp)) { - found = 3; - ip = vp.p_val - 3; - free += vp.p_len + 3; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Overwrite Key\n")); - } - else { - op = ADD_KEY; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Add Key\n")); - } - } - if (op == ADD_KEY) { - ip = etp; - vp.p_len = 0; - head = 3; - } - - if (len + 3 > free) { - if (free < 7) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Overflow, keyword not written\n")); - return(4); - } - /* cut it again */ - len = free - 3; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Full, Keyword was cut\n")); - } - - vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head); - vpd_insert_key(key, buf, len, ip); - if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Encoding Error\n")); - return(6); - } - - return(rtv); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. - * - * return: A pointer to the vpd_status structure. The structure contains - * this fields. - */ -SK_VPD_STATUS *VpdStat( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - (void)VpdInit(pAC, IoC); - } - return(&pAC->vpd.v); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. - * Scan the VPD buffer for VPD keywords and create the VPD - * keyword list by copying the keywords to 'buf', all after - * each other and terminated with a '\0'. - * - * Exceptions: o The Resource Type ID String (product name) is called "Name" - * o The VPD end tags 'RV' and 'RW' are not listed - * - * The number of copied keywords is counted in 'elements'. - * - * returns 0: success - * 2: buffer overfull, one or more keywords are missing - * 6: fatal VPD error - * - * example values after returning: - * - * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0" - * *len = 30 - * *elements = 9 - */ -int VpdKeys( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer where to copy the keywords */ -int *len, /* buffer length */ -int *elements) /* number of keywords returned */ -{ - char *v; - int n; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. ")); - *elements = 0; - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Init Error, terminated\n")); - return(6); - } - } - - if ((signed)strlen(VPD_NAME) + 1 <= *len) { - v = pAC->vpd.vpd_buf; - strcpy(buf,VPD_NAME); - n = strlen(VPD_NAME) + 1; - buf += n; - *elements = 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = 0; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - /* exit when reaching the "RW" Tag */ - if (SK_MEMCMP(VPD_RW,v,2) == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - continue; - } - - if (n+3 <= *len) { - SK_MEMCPY(buf,v,2); - buf += 2; - *buf++ = '\0'; - n += 3; - v += 3 + VPD_GET_VPD_LEN(v); - *elements += 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = n; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n")); - *len = n; - return(0); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Search for the VPD keyword - * 'key' and copy its value to 'buf'. Add a terminating '\0'. - * If the value does not fit into the buffer cut it after - * 'len' - 1 bytes. - * - * returns 0: success - * 1: keyword not found - * 2: value string was cut - * 3: VPD transfer timeout - * 6: fatal VPD error - */ -int VpdRead( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to read (e.g. "MN") */ -char *buf, /* buffer where to copy the keyword value */ -int *len) /* buffer length */ -{ - SK_VPD_PARA *p, vp; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_len > (*(unsigned *)len)-1) { - p->p_len = *len - 1; - } - SK_MEMCPY(buf, p->p_val, p->p_len); - buf[p->p_len] = '\0'; - *len = p->p_len; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("%c%c%c%c.., len = %d\n", - buf[0],buf[1],buf[2],buf[3],*len)); - } - else { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n")); - return(1); - } - return(0); -} - - -/* - * Check whether a given key may be written - * - * returns - * SK_TRUE Yes it may be written - * SK_FALSE No it may be written - */ -SK_BOOL VpdMayWrite( -char *key) /* keyword to write (allowed values "Yx", "Vx") */ -{ - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - return(SK_FALSE); - } - return(SK_TRUE); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. Insert/overwrite the keyword 'key' - * in the VPD buffer. Cut the keyword value if it does not fit - * into the VPD read / write area. - * - * returns 0: success - * 2: value string was cut - * 3: VPD transfer timeout - * 4: VPD full, keyword was not written - * 5: keyword cannot be written - * 6: fatal VPD error - */ -int VpdWrite( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to write (allowed values "Yx", "Vx") */ -const char *buf) /* buffer where the keyword value can be read from */ -{ - int len; /* length of the keyword to write */ - int rtv; /* return code */ - int rtv2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, - ("VPD write %s = %s\n",key,buf)); - - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("illegal key tag, keyword not written\n")); - return(5); - } - - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - rtv = 0; - len = strlen(buf); - if (len > VPD_MAX_LEN) { - /* cut it */ - len = VPD_MAX_LEN; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); - } - if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD write error\n")); - return(rtv2); - } - - return(rtv); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Remove the VPD keyword - * 'key' from the VPD buffer. - * Only the keywords in the read/write area can be deleted. - * Keywords in the read only area cannot be deleted. - * - * returns 0: success, keyword was removed - * 1: keyword not found - * 5: keyword cannot be deleted - * 6: fatal VPD error - */ -int VpdDelete( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *key) /* keyword to read (e.g. "MN") */ -{ - SK_VPD_PARA *p, vp; - char *etp; - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - /* try to delete read only keyword */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("cannot delete RO keyword\n")); - return(5); - } - - etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3); - - vpd_move_para(vp.p_val+vp.p_len, etp+2, - - ((int)(vp.p_len + 3))); - if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD encoding error\n")); - return(6); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword not found\n")); - return(1); - } - - return(0); -} - -/* - * If the VPD buffer contains valid data write the VPD - * read/write area back to the VPD EEPROM. - * - * returns 0: success - * 3: VPD transfer timeout - */ -int VpdUpdate( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. ")); - if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) { - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2, - vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("transfer timed out\n")); - return(3); - } - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n")); - return(0); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD buffer - * if not already done. If the keyword "VF" is not present it will be - * created and the error log message will be stored to this keyword. - * If "VF" is not present the error log message will be stored to the - * keyword "VL". "VL" will created or overwritten if "VF" is present. - * The VPD read/write area is saved to the VPD EEPROM. - * - * returns nothing, errors will be ignored. - */ -void VpdErrLog( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *msg) /* error log message */ -{ - SK_VPD_PARA *v, vf; /* VF */ - int len; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, - ("VPD error log msg %s\n", msg)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return; - } - } - - len = strlen(msg); - if (len > VPD_MAX_LEN) { - /* cut it */ - len = VPD_MAX_LEN; - } - if ((v = vpd_find_para(pAC, VPD_VF, &vf)) != NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("overwrite VL\n")); - (void)VpdSetupPara(pAC, VPD_VL, msg, len, VPD_RW_KEY, OWR_KEY); - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("write VF\n")); - (void)VpdSetupPara(pAC, VPD_VF, msg, len, VPD_RW_KEY, ADD_KEY); - } - - (void)VpdUpdate(pAC, IoC); -} - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skxmac2.c b/drivers/sk98lin/skxmac2.c deleted file mode 100644 index e6b5a95d4a..0000000000 --- a/drivers/sk98lin/skxmac2.c +++ /dev/null @@ -1,4396 +0,0 @@ -/****************************************************************************** - * - * Name: skxmac2.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.91 $ - * Date: $Date: 2003/02/05 15:09:34 $ - * Purpose: Contains functions to initialize the MACs and PHYs - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skxmac2.c,v $ - * Revision 1.91 2003/02/05 15:09:34 rschmidt - * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv(). - * Disabled auto-update for speed, duplex and flow-control when - * auto-negotiation is not enabled (Bug Id #10766). - * Editorial changes. - * - * Revision 1.90 2003/01/29 13:35:19 rschmidt - * Increment Rx FIFO Overflow counter only in DEBUG-mode. - * Corrected define for blinking active LED. - * - * Revision 1.89 2003/01/28 16:37:45 rschmidt - * Changed init for blinking active LED - * - * Revision 1.88 2003/01/28 10:09:38 rschmidt - * Added debug outputs in SkGmInitMac(). - * Added customized init of LED registers in SkGmInitPhyMarv(), - * for blinking active LED (#ifdef ACT_LED_BLINK) and - * for normal duplex LED (#ifdef DUP_LED_NORMAL). - * Editorial changes. - * - * Revision 1.87 2002/12/10 14:39:05 rschmidt - * Improved initialization of GPHY in SkGmInitPhyMarv(). - * Editorial changes. - * - * Revision 1.86 2002/12/09 15:01:12 rschmidt - * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature). - * - * Revision 1.85 2002/12/05 14:09:16 rschmidt - * Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite(). - * Added additional advertising for 10Base-T when 100Base-T is selected. - * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter. - * Editorial changes. - * - * Revision 1.84 2002/11/15 12:50:09 rschmidt - * Changed SkGmCableDiagStatus() when getting results. - * - * Revision 1.83 2002/11/13 10:28:29 rschmidt - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.82 2002/11/13 09:20:46 rschmidt - * Replaced for(..) with do {} while (...) in SkXmUpdateStats(). - * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic(). - * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT). - * Editorial changes. - * - * Revision 1.81 2002/10/28 14:28:08 rschmidt - * Changed MAC address setup for GMAC in SkGmInitMac(). - * Optimized handling of counter overflow IRQ in SkGmOverflowStatus(). - * Editorial changes. - * - * Revision 1.80 2002/10/14 15:29:44 rschmidt - * Corrected disabling of all PHY IRQs. - * Added WA for deviation #16 (address used for pause packets). - * Set Pause Mode in SkMacRxTxEnable() only for Genesis. - * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode. - * SkXmTimeStamp() replaced by SkMacTimeStamp(). - * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq(). - * Editorial changes. - * - * Revision 1.79 2002/10/10 15:55:36 mkarl - * changes for PLinkSpeedUsed - * - * Revision 1.78 2002/09/12 09:39:51 rwahl - * Removed deactivate code for SIRQ overflow event separate for TX/RX. - * - * Revision 1.77 2002/09/09 12:26:37 mkarl - * added handling for Yukon to SkXmTimeStamp - * - * Revision 1.76 2002/08/21 16:41:16 rschmidt - * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE. - * Added forced speed settings in SkGmInitPhyMarv(). - * Added settings of full/half duplex capabilities for YUKON Fiber. - * Editorial changes. - * - * Revision 1.75 2002/08/16 15:12:01 rschmidt - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Added function SkMacHashing() for ADDR-Module. - * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced - * with macros). - * Removed functions SkGmGetMuxConfig(). - * Added HWCFG_MODE init for YUKON Fiber. - * Changed initialization of GPHY in SkGmInitPhyMarv(). - * Changed check of parameter in SkXmMacStatistic(). - * Editorial changes. - * - * Revision 1.74 2002/08/12 14:00:17 rschmidt - * Replaced usage of Broadcom PHY Ids with defines. - * Corrected error messages in SkGmMacStatistic(). - * Made SkMacPromiscMode() public for ADDR-Modul. - * Editorial changes. - * - * Revision 1.73 2002/08/08 16:26:24 rschmidt - * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac(). - * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM. - * Editorial changes. - * - * Revision 1.72 2002/07/24 15:11:19 rschmidt - * Fixed wrong placement of parenthesis. - * Editorial changes. - * - * Revision 1.71 2002/07/23 16:05:18 rschmidt - * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite(). - * Fixed Tx Counter Overflow IRQ (Bug ID #10730). - * Editorial changes. - * - * Revision 1.70 2002/07/18 14:27:27 rwahl - * Fixed syntax error. - * - * Revision 1.69 2002/07/17 17:08:47 rwahl - * Fixed check in SkXmMacStatistic(). - * - * Revision 1.68 2002/07/16 07:35:24 rwahl - * Removed check for cleared mib counter in SkGmResetCounter(). - * - * Revision 1.67 2002/07/15 18:35:56 rwahl - * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(), - * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(), - * SkXmOverflowStatus(), SkGmOverflowStatus(). - * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both - * RX & TX. - * Changes to SkGmInitMac(): call to SkGmResetCounter(). - * Editorial changes. - * - * Revision 1.66 2002/07/15 15:59:30 rschmidt - * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite(). - * Added MIB Clear Counter in SkGmInitMac(). - * Added Duplex and Flow-Control settings. - * Reset all Multicast filtering Hash reg. in SkGmInitMac(). - * Added new function: SkGmGetMuxConfig(). - * Editorial changes. - * - * Revision 1.65 2002/06/10 09:35:39 rschmidt - * Replaced C++ comments (//). - * Added #define VCPU around VCPUwaitTime. - * Editorial changes. - * - * Revision 1.64 2002/06/05 08:41:10 rschmidt - * Added function for XMAC2: SkXmTimeStamp(). - * Added function for YUKON: SkGmSetRxCmd(). - * Changed SkGmInitMac() resp. SkGmHardRst(). - * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode). - * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). - * Editorial changes. - * - * Revision 1.63 2002/04/25 13:04:44 rschmidt - * Changes for handling YUKON. - * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. - * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced - * by functions SkXmPhyRead(), SkXmPhyWrite(); - * Removed use of PRxCmd to setup XMAC. - * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. - * Added setting of XM_RX_DIS_CEXT in SkXmInitMac(). - * Removed status parameter from MAC IRQ handler SkMacIrq(), - * SkXmIrq() and SkGmIrq(). - * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy(). - * Added SkMac...() functions to handle both XMAC and GMAC. - * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(), - * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(), - * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite(). - * Changes for V-CPU support. - * Editorial changes. - * - * Revision 1.62 2001/08/06 09:50:14 rschmidt - * Workaround BCOM Errata #1 for the C5 type. - * Editorial changes. - * - * Revision 1.61 2001/02/09 15:40:59 rassmann - * Editorial changes. - * - * Revision 1.60 2001/02/07 15:02:01 cgoos - * Added workaround for Fujitsu switch link down. - * - * Revision 1.59 2001/01/10 09:38:06 cgoos - * Fixed Broadcom C0/A1 Id check for workaround. - * - * Revision 1.58 2000/11/29 11:30:38 cgoos - * Changed DEBUG sections with NW output to xDEBUG - * - * Revision 1.57 2000/11/27 12:40:40 rassmann - * Suppressing preamble after first access to BCom, not before (#10556). - * - * Revision 1.56 2000/11/09 12:32:48 rassmann - * Renamed variables. - * - * Revision 1.55 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.54 2000/10/02 14:10:27 rassmann - * Reading BCOM PHY after releasing reset until it returns a valid value. - * - * Revision 1.53 2000/07/27 12:22:11 gklug - * fix: possible endless loop in XmHardRst. - * - * Revision 1.52 2000/05/22 08:48:31 malthoff - * Fix: #10523 errata valid for all BCOM PHYs. - * - * Revision 1.51 2000/05/17 12:52:18 malthoff - * Fixes BCom link errata (#10523). - * - * Revision 1.50 1999/11/22 13:40:14 cgoos - * Changed license header to GPL. - * - * Revision 1.49 1999/11/22 08:12:13 malthoff - * Add workaround for power consumption feature of BCom C0 chip. - * - * Revision 1.48 1999/11/16 08:39:01 malthoff - * Fix: MDIO preamble suppression is port dependent. - * - * Revision 1.47 1999/08/27 08:55:35 malthoff - * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble. - * - * Revision 1.46 1999/08/13 11:01:12 malthoff - * Fix for 1000BT: pFlowCtrlMode was not set correctly. - * - * Revision 1.45 1999/08/12 19:18:28 malthoff - * 1000BT Fixes: Do not owerwrite XM_MMU_CMD. - * Do not execute BCOM A1 workaround for B1 chips. - * Fix pause frame setting. - * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL. - * - * Revision 1.44 1999/08/03 15:23:48 cgoos - * Fixed setting of PHY interrupt mask in half duplex mode. - * - * Revision 1.43 1999/08/03 15:22:17 cgoos - * Added some debug output. - * Disabled XMac GP0 interrupt for external PHYs. - * - * Revision 1.42 1999/08/02 08:39:23 malthoff - * BCOM PHY: TX LED: To get the mono flop behaviour it is required - * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL. - * - * Revision 1.41 1999/07/30 06:54:31 malthoff - * Add temp. workarounds for the BCOM Phy revision A1. - * - * Revision 1.40 1999/06/01 07:43:26 cgoos - * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to - * AUTOFULL/AUTOHALF. - * - * Revision 1.39 1999/05/19 07:29:51 cgoos - * Changes for 1000Base-T. - * - * Revision 1.38 1999/04/08 14:35:10 malthoff - * Add code for enabling signal detect. Enabling signal detect is disabled. - * - * Revision 1.37 1999/03/12 13:42:54 malthoff - * Add: Jumbo Frame Support. - * Add: Receive modes SK_LENERR_OK_ON/OFF and - * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd(). - * - * Revision 1.36 1999/03/08 10:10:55 gklug - * fix: AutoSensing did switch to next mode even if LiPa indicated offline - * - * Revision 1.35 1999/02/22 15:16:41 malthoff - * Remove some compiler warnings. - * - * Revision 1.34 1999/01/22 09:19:59 gklug - * fix: Init DupMode and InitPauseMd are now called in RxTxEnable - * - * Revision 1.33 1998/12/11 15:19:11 gklug - * chg: lipa autoneg stati - * chg: debug messages - * chg: do NOT use spurious XmIrq - * - * Revision 1.32 1998/12/10 11:08:44 malthoff - * bug fix: pAC has been used for IOs in SkXmHardRst(). - * SkXmInitPhy() is also called for the Diag in SkXmInitMac(). - * - * Revision 1.31 1998/12/10 10:39:11 gklug - * fix: do 4 RESETS of the XMAC at the beginning - * fix: dummy read interrupt source register BEFORE initializing the Phy - * add: debug messages - * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt - * - * Revision 1.30 1998/12/07 12:18:32 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.29 1998/12/07 07:12:29 gklug - * fix: if page is received the link is down. - * - * Revision 1.28 1998/12/01 10:12:47 gklug - * chg: if spurious IRQ from XMAC encountered, save it - * - * Revision 1.27 1998/11/26 07:33:38 gklug - * add: InitPhy call is now in XmInit function - * - * Revision 1.26 1998/11/18 13:38:24 malthoff - * 'Imsk' is also unused in SkXmAutoNegDone. - * - * Revision 1.25 1998/11/18 13:28:01 malthoff - * Remove unused variable 'Reg' in SkXmAutoNegDone(). - * - * Revision 1.24 1998/11/18 13:18:45 gklug - * add: workaround for xmac errata #1 - * add: detect Link Down also when Link partner requested config - * chg: XMIrq is only used when link is up - * - * Revision 1.23 1998/11/04 07:07:04 cgoos - * Added function SkXmRxTxEnable. - * - * Revision 1.22 1998/10/30 07:35:54 gklug - * fix: serve LinkDown interrupt when link is already down - * - * Revision 1.21 1998/10/29 15:32:03 gklug - * fix: Link Down signaling - * - * Revision 1.20 1998/10/29 11:17:27 gklug - * fix: AutoNegDone bug - * - * Revision 1.19 1998/10/29 10:14:43 malthoff - * Add endainesss comment for reading/writing MAC addresses. - * - * Revision 1.18 1998/10/28 07:48:55 cgoos - * Fix: ASS somtimes signaled although link is up. - * - * Revision 1.17 1998/10/26 07:55:39 malthoff - * Fix in SkXmInitPauseMd(): Pause Mode - * was disabled and not enabled. - * Fix in SkXmAutoNegDone(): Checking Mode bits - * always failed, becaues of some missing braces. - * - * Revision 1.16 1998/10/22 09:46:52 gklug - * fix SysKonnectFileId typo - * - * Revision 1.15 1998/10/21 05:51:37 gklug - * add: para DoLoop to InitPhy function for loopback set-up - * - * Revision 1.14 1998/10/16 10:59:23 malthoff - * Remove Lint warning for dummy reads. - * - * Revision 1.13 1998/10/15 14:01:20 malthoff - * Fix: SkXmAutoNegDone() is (int) but does not return a value. - * - * Revision 1.12 1998/10/14 14:45:04 malthoff - * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by - * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent - * from the Sirq module. - * - * Revision 1.11 1998/10/14 13:59:01 gklug - * add: InitPhy function - * - * Revision 1.10 1998/10/14 11:20:57 malthoff - * Make SkXmAutoNegDone() public, because it's - * used in diagnostics, too. - * The Link Up event to the RLMT is issued in SkXmIrq(). - * SkXmIrq() is not available in diagnostics. - * Use PHY_READ when reading PHY registers. - * - * Revision 1.9 1998/10/14 05:50:10 cgoos - * Added definition for Para. - * - * Revision 1.8 1998/10/14 05:41:28 gklug - * add: Xmac IRQ - * add: auto-negotiation done function - * - * Revision 1.7 1998/10/09 06:55:20 malthoff - * The configuration of the XMACs Tx Request Threshold - * depends from the drivers port usage now. The port - * usage is configured in GIPortUsage. - * - * Revision 1.6 1998/10/05 07:48:00 malthoff - * minor changes - * - * Revision 1.5 1998/10/01 07:03:54 gklug - * add: dummy function for XMAC ISR - * - * Revision 1.4 1998/09/30 12:37:44 malthoff - * Add SkXmSetRxCmd() and related code. - * - * Revision 1.3 1998/09/28 13:26:40 malthoff - * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd() - * - * Revision 1.2 1998/09/16 14:34:21 malthoff - * Add SkXmClrExactAddr(), SkXmClrSrcCheck(), - * SkXmClrHashAddr(), SkXmFlushTxFifo(), - * SkXmFlushRxFifo(), and SkXmHardRst(). - * Finish Coding of SkXmSoftRst(). - * The sources may be compiled now. - * - * Revision 1.1 1998/09/04 10:05:56 malthoff - * Created. - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* typedefs *******************************************************************/ - -/* BCOM PHY magic pattern list */ -typedef struct s_PhyHack { - int PhyReg; /* Phy register */ - SK_U16 PhyVal; /* Value to write */ -} BCOM_HACK; - -/* local variables ************************************************************/ -static const char SysKonnectFileId[] = - "@(#)$Id: skxmac2.c,v 1.91 2003/02/05 15:09:34 rschmidt Exp $ (C) SK "; - -BCOM_HACK BcomRegA1Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, - { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, - { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, - { 0, 0 } -}; -BCOM_HACK BcomRegC0Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, - { 0x15, 0x0A04 }, { 0x18, 0x0420 }, - { 0, 0 } -}; - -/* function prototypes ********************************************************/ -static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); -static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); -#ifdef OTHER_PHY -static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkXmPhyRead() - Read from XMAC PHY register - * - * Description: reads a 16-bit word from XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Ready' is set */ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - } -} /* SkXmPhyRead */ - - -/****************************************************************************** - * - * SkXmPhyWrite() - Write to XMAC PHY register - * - * Description: writes a 16-bit word to XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* write the PHY register's value */ - XM_OUT16(IoC, Port, XM_PHY_DATA, Val); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } -} /* SkXmPhyWrite */ - - -/****************************************************************************** - * - * SkGmPhyRead() - Read from GPHY register - * - * Description: reads a 16-bit word from GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", - PhyReg, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* set PHY-Register offset and 'Read' OpCode (= 1) */ - *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | - GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - *pVal = 0; - return; - } - - *pVal |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'ReadValid' is set */ - } while (Ctrl == *pVal); - - /* get the PHY register's value */ - GM_IN16(IoC, Port, GM_SMI_DATA, pVal); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ -} /* SkGmPhyRead */ - - -/****************************************************************************** - * - * SkGmPhyWrite() - Write to GPHY register - * - * Description: writes a 16-bit word to GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - SK_U32 DWord; - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", - PhyReg, Val, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's value */ - GM_OUT16(IoC, Port, GM_SMI_DATA, Val); - - /* set PHY-Register offset and 'Write' OpCode (= 0) */ - Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - return; - } - - Val |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - /* read Timer value */ - SK_IN32(IoC, B2_TI_VAL, &DWord); - - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'Busy' is cleared */ - } while (Ctrl == Val); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ -} /* SkGmPhyWrite */ - - -/****************************************************************************** - * - * SkGePhyRead() - Read from PHY register - * - * Description: calls a read PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ -{ - void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); - - if (pAC->GIni.GIGenesis) { - r_func = SkXmPhyRead; - } - else { - r_func = SkGmPhyRead; - } - - r_func(pAC, IoC, Port, PhyReg, pVal); -} /* SkGePhyRead */ - - -/****************************************************************************** - * - * SkGePhyWrite() - Write to PHY register - * - * Description: calls a write PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); - - if (pAC->GIni.GIGenesis) { - w_func = SkXmPhyWrite; - } - else { - w_func = SkGmPhyWrite; - } - - w_func(pAC, IoC, Port, PhyReg, Val); -} /* SkGePhyWrite */ - - -/****************************************************************************** - * - * SkMacPromiscMode() - Enable / Disable Promiscuous Mode - * - * Description: - * enables / disables promiscuous mode by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacPromiscMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U16 RcReg; - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable promiscuous mode */ - if (Enable) { - MdReg |= XM_MD_ENA_PROM; - } - else { - MdReg &= ~XM_MD_ENA_PROM; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } - else { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable unicast and multicast filtering */ - if (Enable) { - RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - else { - RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -} /* SkMacPromiscMode*/ - - -/****************************************************************************** - * - * SkMacHashing() - Enable / Disable Hashing - * - * Description: - * enables / disables hashing by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacHashing( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U16 RcReg; - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable hashing */ - if (Enable) { - MdReg |= XM_MD_ENA_HASH; - } - else { - MdReg &= ~XM_MD_ENA_HASH; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } - else { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable multicast filtering */ - if (Enable) { - RcReg |= GM_RXCR_MCF_ENA; - } - else { - RcReg &= ~GM_RXCR_MCF_ENA; - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -} /* SkMacHashing*/ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register - * - * Description: - * The features - * - FCS stripping, SK_STRIP_FCS_ON/OFF - * - pad byte stripping, SK_STRIP_PAD_ON/OFF - * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF - * for inrange length error frames - * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkXmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd); - - RxCmd = OldRxCmd; - - switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) { - case SK_STRIP_FCS_ON: - RxCmd |= XM_RX_STRIP_FCS; - break; - case SK_STRIP_FCS_OFF: - RxCmd &= ~XM_RX_STRIP_FCS; - break; - } - - switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) { - case SK_STRIP_PAD_ON: - RxCmd |= XM_RX_STRIP_PAD; - break; - case SK_STRIP_PAD_OFF: - RxCmd &= ~XM_RX_STRIP_PAD; - break; - } - - switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) { - case SK_LENERR_OK_ON: - RxCmd |= XM_RX_LENERR_OK; - break; - case SK_LENERR_OK_OFF: - RxCmd &= ~XM_RX_LENERR_OK; - break; - } - - switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) { - case SK_BIG_PK_OK_ON: - RxCmd |= XM_RX_BIG_PK_OK; - break; - case SK_BIG_PK_OK_OFF: - RxCmd &= ~XM_RX_BIG_PK_OK; - break; - } - - switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) { - case SK_SELF_RX_ON: - RxCmd |= XM_RX_SELF_RX; - break; - case SK_SELF_RX_OFF: - RxCmd &= ~XM_RX_SELF_RX; - break; - } - - /* Write the new mode to the Rx command register if required */ - if (OldRxCmd != RxCmd) { - XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd); - } -} /* SkXmSetRxCmd */ - - -/****************************************************************************** - * - * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register - * - * Description: - * The features - * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF - * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkGmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_STRIP_FCS_ON) != 0) { - RxCmd |= GM_RXCR_CRC_DIS; - } - else { - RxCmd &= ~GM_RXCR_CRC_DIS; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); - } - } - - if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_BIG_PK_OK_ON) != 0) { - RxCmd |= GM_SMOD_JUMBO_ENA; - } - else { - RxCmd &= ~GM_SMOD_JUMBO_ENA; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); - } - } -} /* SkGmSetRxCmd */ - - -/****************************************************************************** - * - * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register - * - * Description: modifies the MAC's Rx Control reg. dep. on board type - * - * Returns: - * nothing - */ -void SkMacSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Rx Mode */ -{ - if (pAC->GIni.GIGenesis) { - - SkXmSetRxCmd(pAC, IoC, Port, Mode); - } - else { - - SkGmSetRxCmd(pAC, IoC, Port, Mode); - } -} /* SkMacSetRxCmd */ - - -/****************************************************************************** - * - * SkMacCrcGener() - Enable / Disable CRC Generation - * - * Description: enables / disables CRC generation dep. on board type - * - * Returns: - * nothing - */ -void SkMacCrcGener( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U16 Word; - - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_TX_CMD, &Word); - - if (Enable) { - Word &= ~XM_TX_NO_CRC; - } - else { - Word |= XM_TX_NO_CRC; - } - /* setup Tx Command Register */ - XM_OUT16(pAC, Port, XM_TX_CMD, Word); - } - else { - - GM_IN16(IoC, Port, GM_TX_CTRL, &Word); - - if (Enable) { - Word &= ~GM_TXCR_CRC_DIS; - } - else { - Word |= GM_TXCR_CRC_DIS; - } - /* setup Tx Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, Word); - } -} /* SkMacCrcGener*/ - -#endif /* SK_DIAG */ - - -/****************************************************************************** - * - * SkXmClrExactAddr() - Clear Exact Match Address Registers - * - * Description: - * All Exact Match Address registers of the XMAC 'Port' will be - * cleared starting with 'StartNum' up to (and including) the - * Exact Match address number of 'StopNum'. - * - * Returns: - * nothing - */ -void SkXmClrExactAddr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int StartNum, /* Begin with this Address Register Index (0..15) */ -int StopNum) /* Stop after finished with this Register Idx (0..15) */ -{ - int i; - SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; - - if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || - StartNum > StopNum) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG); - return; - } - - for (i = StartNum; i <= StopNum; i++) { - XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); - } -} /* SkXmClrExactAddr */ - - -/****************************************************************************** - * - * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO - * - * Description: - * Flush the transmit FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -void SkMacFlushTxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); - } - else { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -} /* SkMacFlushTxFifo */ - - -/****************************************************************************** - * - * SkMacFlushRxFifo() - Flush the MAC's receive FIFO - * - * Description: - * Flush the receive FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -void SkMacFlushRxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); - } - else { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -} /* SkMacFlushRxFifo */ - - -/****************************************************************************** - * - * SkXmSoftRst() - Do a XMAC software reset - * - * Description: - * The PHY registers should not be destroyed during this - * kind of software reset. Therefore the XMAC Software Reset - * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used! - * - * The software reset is done by - * - disabling the Rx and Tx state machine, - * - resetting the statistics module, - * - clear all other significant XMAC Mode, - * Command, and Control Registers - * - clearing the Hash Register and the - * Exact Match Address registers, and - * - flushing the XMAC's Rx and Tx FIFOs. - * - * Note: - * Another requirement when stopping the XMAC is to - * avoid sending corrupted frames on the network. - * Disabling the Tx state machine will NOT interrupt - * the currently transmitted frame. But we must take care - * that the Tx FIFO is cleared AFTER the current frame - * is complete sent to the network. - * - * It takes about 12ns to send a frame with 1538 bytes. - * One PCI clock goes at least 15ns (66MHz). Therefore - * after reading XM_GP_PORT back, we are sure that the - * transmitter is disabled AND idle. And this means - * we may flush the transmit FIFO now. - * - * Returns: - * nothing - */ -static void SkXmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - - /* reset the statistics module */ - XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */ - - XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - - /* disable all PHY IRQs */ - switch (pAC->GIni.GP[Port].PhyType) { - case SK_PHY_BCOM: - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - - /* clear the Hash Register */ - XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); - - /* clear the Exact Match Address registers */ - SkXmClrExactAddr(pAC, IoC, Port, 0, 15); - - /* clear the Source Check Address registers */ - XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); - -} /* SkXmSoftRst */ - - -/****************************************************************************** - * - * SkXmHardRst() - Do a XMAC hardware reset - * - * Description: - * The XMAC of the specified 'Port' and all connected devices - * (PHY and SERDES) will receive a reset signal on its *Reset pins. - * External PHYs must be reset be clearing a bit in the GPIO register - * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). - * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * - * Returns: - * nothing - */ -static void SkXmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 Reg; - int i; - int TOut; - SK_U16 Word; - - for (i = 0; i < 4; i++) { - /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - TOut = 0; - do { - if (TOut++ > 10000) { - /* - * Adapter seems to be in RESET state. - * Registers cannot be written. - */ - return; - } - - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST); - - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word); - - } while ((Word & MFF_SET_MAC_RST) == 0); - } - - /* For external PHYs there must be special handling */ - if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - /* reset external PHY */ - SK_IN32(IoC, B2_GP_IO, &Reg); - if (Port == 0) { - Reg |= GP_DIR_0; /* set to output */ - Reg &= ~GP_IO_0; - } - else { - Reg |= GP_DIR_2; /* set to output */ - Reg &= ~GP_IO_2; - } - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* short delay */ - SK_IN32(IoC, B2_GP_IO, &Reg); - } - -} /* SkXmHardRst */ - - -/****************************************************************************** - * - * SkGmSoftRst() - Do a GMAC software reset - * - * Description: - * The GPHY registers should not be destroyed during this - * kind of software reset. - * - * Returns: - * nothing - */ -static void SkGmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - SK_U16 RxCtrl; - - /* reset the statistics module */ - - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - - /* disable all PHY IRQs */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); - - /* clear the Hash Register */ - GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); - - /* Enable Unicast and Multicast filtering */ - GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); - - GM_OUT16(IoC, Port, GM_RX_CTRL, - RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - -} /* SkGmSoftRst */ - - -/****************************************************************************** - * - * SkGmHardRst() - Do a GMAC hardware reset - * - * Description: - * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * - * Returns: - * nothing - */ -static void SkGmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - -} /* SkGmHardRst */ - - -/****************************************************************************** - * - * SkMacSoftRst() - Do a MAC software reset - * - * Description: calls a MAC software reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - if (pAC->GIni.GIGenesis) { - - SkXmSoftRst(pAC, IoC, Port); - } - else { - - SkGmSoftRst(pAC, IoC, Port); - } - - /* flush the MAC's Rx and Tx FIFOs */ - SkMacFlushTxFifo(pAC, IoC, Port); - - SkMacFlushRxFifo(pAC, IoC, Port); - - pPrt->PState = SK_PRT_STOP; - -} /* SkMacSoftRst */ - - -/****************************************************************************** - * - * SkMacHardRst() - Do a MAC hardware reset - * - * Description: calls a MAC hardware reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - - if (pAC->GIni.GIGenesis) { - - SkXmHardRst(pAC, IoC, Port); - } - else { - - SkGmHardRst(pAC, IoC, Port); - } - - pAC->GIni.GP[Port].PState = SK_PRT_RESET; - -} /* SkMacHardRst */ - - -/****************************************************************************** - * - * SkXmInitMac() - Initialize the XMAC II - * - * Description: - * Initialize the XMAC of the specified port. - * The XMAC must be reset or stopped before calling this function. - * - * Note: - * The XMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkXmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 Reg; - int i; - SK_U16 SWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); - - if ((SWord & MFF_SET_MAC_RST) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - /* - * clear HW reset - * Note: The SW reset is self clearing, therefore there is - * nothing to do here. - */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - /* Ensure that XMAC reset release is done (errata from LReinbold?) */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); - - /* Clear PHY reset */ - if (pPrt->PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &Reg); - - if (Port == 0) { - Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */ - } - else { - Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */ - } - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* Enable GMII interface */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); - - /* read Id from external PHY (all have the same address) */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); - - /* - * Optimize MDIO transfer by suppressing preamble. - * Must be done AFTER first access to BCOM chip. - */ - XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); - - XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); - - if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegC0Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, - BcomRegC0Hack[i].PhyVal); - i++; - } - } - else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegA1Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, - BcomRegA1Hack[i].PhyVal); - i++; - } - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord | PHY_B_AC_DIS_PM)); - - /* PHY LED initialization is done in SkGeXmitLED() */ - } - - /* Dummy read the Interrupt source register */ - XM_IN16(IoC, Port, XM_ISRC, &SWord); - - /* - * The auto-negotiation process starts immediately after - * clearing the reset. The auto-negotiation process should be - * started by the SIRQ, therefore stop it here immediately. - */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - -#if 0 - /* temp. code: enable signal detect */ - /* WARNING: do not override GMII setting above */ - XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG); -#endif - } - - /* - * configure the XMACs Station Address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B - */ - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - - XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); - } - - /* Tx Inter Packet Gap (XM_TX_IPG): use default */ - /* Tx High Water Mark (XM_TX_HI_WM): use default */ - /* Tx Low Water Mark (XM_TX_LO_WM): use default */ - /* Host Request Threshold (XM_HT_THR): use default */ - /* Rx Request Threshold (XM_RX_THR): use default */ - /* Rx Low Water Mark (XM_RX_LO_WM): use default */ - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); - - /* Configure Tx Request Threshold */ - SWord = SK_XM_THR_SL; /* for single port */ - - if (pAC->GIni.GIMacsFound > 1) { - switch (pAC->GIni.GIPortUsage) { - case SK_RED_LINK: - SWord = SK_XM_THR_REDL; /* redundant link */ - break; - case SK_MUL_LINK: - SWord = SK_XM_THR_MULL; /* load balancing */ - break; - case SK_JUMBO_LINK: - SWord = SK_XM_THR_JUMBO; /* jumbo frames */ - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); - break; - } - } - XM_OUT16(IoC, Port, XM_TX_THR, SWord); - - /* setup register defaults for the Tx Command Register */ - XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); - - /* setup register defaults for the Rx Command Register */ - SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SWord |= XM_RX_BIG_PK_OK; - } - - if (pPrt->PLinkModeConf == SK_LMODE_HALF) { - /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received - */ - SWord |= XM_RX_DIS_CEXT; - } - - XM_OUT16(IoC, Port, XM_RX_CMD, SWord); - - /* - * setup register defaults for the Mode Register - * - Don't strip error frames to avoid Store & Forward - * on the Rx side. - * - Enable 'Check Station Address' bit - * - Enable 'Check Address Array' bit - */ - XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); - - /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); - - /* - * Do NOT init XMAC interrupt mask here. - * All interrupts remain disable until link comes up! - */ - - /* - * Any additional configuration changes may be done now. - * The last action is to enable the Rx and Tx state machine. - * This should be done after the auto-negotiation process - * has been completed successfully. - */ -} /* SkXmInitMac */ - -/****************************************************************************** - * - * SkGmInitMac() - Initialize the GMAC - * - * Description: - * Initialize the GMAC of the specified port. - * The GMAC must be reset or stopped before calling this function. - * - * Note: - * The GMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkGmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int i; - SK_U16 SWord; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); - - if ((DWord & GMC_RST_SET) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - - /* set HWCFG_MODE */ - DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | - (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : - GPC_HWCFG_GMII_FIB); - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); - - /* release GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); - - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - - /* Dummy read the Interrupt source register */ - SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); - -#ifndef VCPU - /* read Id from PHY */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); - - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); -#endif /* VCPU */ - } - - (void)SkGmResetCounter(pAC, IoC, Port); - - SWord = 0; - - /* speed settings */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; - break; - case SK_LSPEED_100MBPS: - SWord |= GM_GPCR_SPEED_100; - break; - case SK_LSPEED_10MBPS: - break; - } - - /* duplex settings */ - if (pPrt->PLinkMode != SK_LMODE_HALF) { - /* set full duplex */ - SWord |= GM_GPCR_DUP_FULL; - } - - /* flow control settings */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* disable auto-negotiation for flow-control */ - SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS; - break; - case SK_FLOW_MODE_LOC_SEND: - SWord |= GM_GPCR_FC_RX_DIS; - break; - case SK_FLOW_MODE_SYMMETRIC: - /* TBD */ - case SK_FLOW_MODE_SYM_OR_REM: - /* enable auto-negotiation for flow-control and */ - /* enable Rx and Tx of pause frames */ - break; - } - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* disable auto-update for speed, duplex and flow-control */ - SWord |= GM_GPCR_AU_ALL_DIS; - } - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - - /* setup Transmit Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR); - - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | - GM_RXCR_CRC_DIS); - - /* setup Transmit Flow Control Register */ - GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); - - /* setup Transmit Parameter Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); -#endif /* VCPU */ - - SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26); - - GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); - - /* configure the Serial Mode Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); -#endif /* VCPU */ - - SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH; - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* enable jumbo mode (Max. Frame Length = 9018) */ - SWord |= GM_SMOD_JUMBO_ENA; - } - - GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); - - /* - * configure the GMACs Station Addresses - * in PROM you can find our addresses at: - * B2_MAC_1 = xx xx xx xx xx x0 virtual address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort - */ - - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - /* physical address: will be used for pause frames */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - -#ifdef WA_DEV_16 - /* WA for deviation #16 */ - if (pAC->GIni.GIChipRev == 0) { - /* swap the address bytes */ - SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); - - /* write to register in reversed order */ - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); - } - else { - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); - } -#else - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); -#endif /* WA_DEV_16 */ - - /* virtual address: will be used for data */ - SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); - - GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); - - /* reset Multicast filtering Hash registers 1-3 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); - } - - /* reset Multicast filtering Hash register 4 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); - - /* enable interrupt mask for counter overflows */ - GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); - - /* read General Purpose Status */ - GM_IN16(IoC, Port, GM_GP_STAT, &SWord); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("MAC Stat Reg=0x%04X\n", SWord)); - -#ifdef SK_DIAG - c_print("MAC Stat Reg=0x%04X\n", SWord); -#endif /* SK_DIAG */ - -} /* SkGmInitMac */ - - -/****************************************************************************** - * - * SkXmInitDupMd() - Initialize the XMACs Duplex Mode - * - * Description: - * This function initializes the XMACs Duplex Mode. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -void SkXmInitDupMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - switch (pAC->GIni.GP[Port].PLinkModeStatus) { - case SK_LMODE_STAT_AUTOHALF: - case SK_LMODE_STAT_HALF: - /* Configuration Actions for Half Duplex Mode */ - /* - * XM_BURST = default value. We are probable not quick - * enough at the 'XMAC' bus to burst 8kB. - * The XMAC stops bursting if no transmit frames - * are available or the burst limit is exceeded. - */ - /* XM_TX_RT_LIM = default value (15) */ - /* XM_TX_STIME = default value (0xff = 4096 bit times) */ - break; - case SK_LMODE_STAT_AUTOFULL: - case SK_LMODE_STAT_FULL: - /* Configuration Actions for Full Duplex Mode */ - /* - * The duplex mode is configured by the PHY, - * therefore it seems to be that there is nothing - * to do here. - */ - break; - case SK_LMODE_STAT_UNKNOWN: - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); - break; - } -} /* SkXmInitDupMd */ - - -/****************************************************************************** - * - * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port - * - * Description: - * This function initializes the Pause Mode which should - * be used for this port. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -void SkXmInitPauseMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* Disable Pause Frame Reception */ - Word |= XM_MMU_IGN_PF; - } - else { - /* - * enabling pause frame reception is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Enable Pause Frame Reception */ - Word &= ~XM_MMU_IGN_PF; - } - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word); - - XM_IN32(IoC, Port, XM_MODE, &DWord); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* - * Configure Pause Frame Generation - * Use internal and external Pause Frame Generation. - * Sending pause frames is edge triggered. - * Send a Pause frame with the maximum pause time if - * internal oder external FIFO full condition occurs. - * Send a zero pause time frame to re-start transmission. - */ - - /* XM_PAUSE_DA = '010000C28001' (default) */ - - /* XM_MAC_PTIME = 0xffff (maximum) */ - /* remember this value is defined in big endian (!) */ - XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); - - /* Set Pause Mode in Mode Register */ - DWord |= XM_PAUSE_MODE; - - /* Set Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); - } - else { - /* - * disable pause frame generation is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Disable Pause Mode in Mode Register */ - DWord &= ~XM_PAUSE_MODE; - - /* Disable Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); - } - - XM_OUT32(IoC, Port, XM_MODE, DWord); -} /* SkXmInitPauseMd*/ - - -/****************************************************************************** - * - * SkXmInitPhyXmac() - Initialize the XMAC Phy registers - * - * Description: initializes all the XMACs Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl; - - pPrt = &pAC->GIni.GP[Port]; - Ctrl = 0; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl |= PHY_CT_DUP_MD; - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLEs are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl |= PHY_X_AN_HD; - break; - case SK_LMODE_AUTOFULL: - Ctrl |= PHY_X_AN_FD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl |= PHY_X_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl |= PHY_X_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl |= PHY_X_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl |= PHY_X_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl); - - /* Restart Auto-negotiation */ - Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; - } - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); -} /* SkXmInitPhyXmac */ - - -/****************************************************************************** - * - * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers - * - * Description: initializes all the Broadcom Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - SK_U16 Ctrl4; - SK_U16 Ctrl5; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - Ctrl4 = PHY_B_PEC_EN_LTR; - Ctrl5 = PHY_B_AC_TX_TST; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_B_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - Ctrl2 |= PHY_B_1000C_RD; - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_B_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_B_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; - } - - /* Initialize LED register here? */ - /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* configure FIFO to high latency for transmission of ext. packets */ - Ctrl4 |= PHY_B_PEC_HIGH_LA; - - /* configure reception of extended packets */ - Ctrl5 |= PHY_B_AC_LONG_PACK; - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5); - } - - /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyBcom */ - - -/****************************************************************************** - * - * SkGmInitPhyMarv() - Initialize the Marvell Phy registers - * - * Description: initializes all the Marvell Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkGmInitPhyMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 PhyCtrl; - SK_U16 C1000BaseT; - SK_U16 AutoNegAdv; - SK_U16 ExtPhyCtrl; - SK_U16 PhyStat; - SK_U16 PhyStat1; - SK_U16 PhySpecStat; - SK_U16 LedCtrl; - SK_BOOL AutoNeg; - -#ifdef VCPU - VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", - Port, DoLoop); -#else /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - if (!DoLoop) { - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - - ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); - - ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) | - PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl)); - - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - - /* Assert software reset */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, - (SK_U16)(PhyCtrl | PHY_CT_RESET)); - } -#endif /* VCPU */ - - PhyCtrl = 0 /* PHY_CT_COL_TST */; - C1000BaseT = 0; - AutoNegAdv = PHY_SEL_TYPE; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - /* enable Manual Master/Slave */ - C1000BaseT |= PHY_M_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ - } - } - - /* Auto-negotiation ? */ - if (!AutoNeg) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: no auto-negotiation Port %d\n", Port)); - - if (pPrt->PLinkMode == SK_LMODE_FULL) { - /* Set Full Duplex Mode */ - PhyCtrl |= PHY_CT_DUP_MD; - } - - /* Set Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ - } - - /* Set Speed */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - PhyCtrl |= PHY_CT_SP1000; - break; - case SK_LSPEED_100MBPS: - PhyCtrl |= PHY_CT_SP100; - break; - case SK_LSPEED_10MBPS: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - if (!DoLoop) { - PhyCtrl |= PHY_CT_RESET; - } - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: with auto-negotiation Port %d\n", Port)); - - PhyCtrl |= PHY_CT_ANE; - - if (pAC->GIni.GICopperType) { - /* Set Speed capabilities */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_1000MBPS: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - break; - case SK_LSPEED_100MBPS: - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_10MBPS: - AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - C1000BaseT &= ~PHY_M_1000C_AFD; - AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD); - break; - case SK_LMODE_AUTOFULL: - C1000BaseT &= ~PHY_M_1000C_AHD; - AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD); - break; - case SK_LMODE_AUTOBOTH: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Auto-negotiation advertisement */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - else { /* special defines for FIBER (88E1011S only) */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - AutoNegAdv |= PHY_M_AN_1000X_AHD; - break; - case SK_LMODE_AUTOFULL: - AutoNegAdv |= PHY_M_AN_1000X_AFD; - break; - case SK_LMODE_AUTOBOTH: - AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Auto-negotiation advertisement */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_M_P_NO_PAUSE_X; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_M_P_ASYM_MD_X; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_M_P_SYM_MD_X; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_M_P_BOTH_MD_X; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - - if (!DoLoop) { - /* Restart Auto-negotiation */ - PhyCtrl |= PHY_CT_RE_CFG; - } - } - -#ifdef VCPU - /* - * E-mail from Gu Lin (08-03-2002): - */ - - /* Program PHY register 30 as 16'h0708 for simulation speed up */ - SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708); - - VCpuWait(2000); - -#else /* VCPU */ - - /* Write 1000Base-T Control Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl=0x%04X\n", C1000BaseT)); - - /* Write AutoNeg Advertisement Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv)); -#endif /* VCPU */ - - if (DoLoop) { - /* Set the PHY Loopback bit */ - PhyCtrl |= PHY_CT_LOOP; - - /* Program PHY register 16 as 16'h0400 to force link good */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); - -#if 0 - if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { - /* Write Ext. PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, - (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); - } - } - else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { - /* Write PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK); - } -#endif /* 0 */ - } - - /* Write to the PHY Control register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); - -#ifdef VCPU - VCpuWait(2000); -#else - - LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); - -#ifdef ACT_LED_BLINK - LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; -#endif /* ACT_LED_BLINK */ - -#ifdef DUP_LED_NORMAL - LedCtrl |= PHY_M_LEDC_DP_CTRL; -#endif /* DUP_LED_NORMAL */ - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); - -#endif /* VCPU */ - -#ifdef SK_DIAG - c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); - c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); - c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); - c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); -#endif /* SK_DIAG */ - -#ifndef xDEBUG - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - - /* Read 1000Base-T Control Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); - - /* Read AutoNeg Advertisement Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv)); - - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl)); - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat)); - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat1)); - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Spec Stat=0x%04X\n", PhySpecStat)); -#endif /* DEBUG */ - -#ifdef SK_DIAG - c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); - c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); - c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); - c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); - c_print("PHY Stat Reg=0x%04X\n", PhyStat); - c_print("PHY Stat Reg=0x%04X\n", PhyStat1); - c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); -#endif /* SK_DIAG */ - -} /* SkGmInitPhyMarv */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmInitPhyLone() - Initialize the Level One Phy registers - * - * Description: initializes all the Level One Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_L_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* - * level one spec say: "1000Mbps: manual mode not allowed" - * but lets see what happens... - */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_L_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_L_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_L_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_L_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_L_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_L_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; - - } - - /* Initialize LED register here ? */ - /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); - - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyLone */ - - -/****************************************************************************** - * - * SkXmInitPhyNat() - Initialize the National Phy registers - * - * Description: initializes all the National Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ -/* todo: National */ -} /* SkXmInitPhyNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacInitPhy() - Initialize the PHY registers - * - * Description: calls the Init PHY routines dep. on board type - * - * Note: - * - * Returns: - * nothing - */ -void SkMacInitPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_BCOM: - SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmInitPhyLone(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_NAT: - SkXmInitPhyNat(pAC, IoC, Port, DoLoop); - break; -#endif /* OTHER_PHY */ - } -} /* SkMacInitPhy */ - - -#ifndef SK_DIAG -/****************************************************************************** - * - * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg - * - * This function analyses the Interrupt status word. If any of the - * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkXmAutoNegLipaXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus) /* Interrupt Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n", - Port, IStatus)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkXmAutoNegLipaXmac */ - - -/****************************************************************************** - * - * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg - * - * This function analyses the PHY status word. - * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkMacAutoNegLipaPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 PhyStat) /* PHY Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (PhyStat & PHY_ST_AN_OVER) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n", - Port, PhyStat)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkMacAutoNegLipaPhy */ -#endif /* SK_DIAG */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneXmac() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneXmac, Port %d\n",Port)); - - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - - if ((LPAb & PHY_X_AN_RFB) != 0) { - /* At least one of the remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; - } - else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - - /* Check PAUSE mismatch */ - /* We are NOT using chapter 4.23 of the Xaqti manual */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || - pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && - (LPAb & PHY_X_P_SYM_MD) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneXmac */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneBcom() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - -#if 0 -01-Sep-2000 RA;:;: - SK_U16 ResAb; /* Resolved Ability */ -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneBcom, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); -#if 0 -01-Sep-2000 RA;:;: - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); -#endif /* 0 */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); - - if ((LPAb & PHY_B_AN_RF) != 0) { - /* Remote fault bit is set: Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; - } - else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - -#if 0 -01-Sep-2000 RA;:;: - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; -#endif /* 0 */ - - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneBcom */ - - -/****************************************************************************** - * - * SkGmAutoNegDoneMarv() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkGmAutoNegDoneMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneMarv, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); - - if ((LPAb & PHY_M_AN_RF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); - - /* Check Speed & Duplex resolved */ - if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - return(SK_AND_DUP_CAP); - } - - if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; - } - - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - - /* set used link speed */ - switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { - case (unsigned)PHY_M_PS_SPEED_1000: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; - break; - case PHY_M_PS_SPEED_100: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; - break; - default: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; - } - - return(SK_AND_OK); -} /* SkGmAutoNegDoneMarv */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmAutoNegDoneLone() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 QuickStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneLone, Port %d\n",Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); - - if ((LPAb & PHY_L_AN_RF) != 0) { - /* Remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; - } - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_L_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - else if (ResAb & PHY_L_1000S_MSR) { - pPrt->PMSStatus = SK_MS_STAT_MASTER; - } - else { - pPrt->PMSStatus = SK_MS_STAT_SLAVE; - } - - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - /* we must manually resolve the abilities here */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* default */ - break; - case SK_FLOW_MODE_LOC_SEND: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - break; - case SK_FLOW_MODE_SYMMETRIC: - if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - case SK_FLOW_MODE_SYM_OR_REM: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - PHY_L_QS_AS_PAUSE) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - return(SK_AND_OK); -} /* SkXmAutoNegDoneLone */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneNat() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -/* todo: National */ - return(SK_AND_OK); -} /* SkXmAutoNegDoneNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacAutoNegDone() - Auto-negotiation handling - * - * Description: calls the auto-negotiation done routines dep. on board type - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -int SkMacAutoNegDone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int Rtv; - - pPrt = &pAC->GIni.GP[Port]; - - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); - break; - case SK_PHY_BCOM: - Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); - break; - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); - break; - case SK_PHY_NAT: - Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); - break; -#endif /* OTHER_PHY */ - default: - return(SK_AND_OTHER); - } - - if (Rtv != SK_AND_OK) { - return(Rtv); - } - - /* We checked everything and may now enable the link */ - pPrt->PAutoNegFail = SK_FALSE; - - SkMacRxTxEnable(pAC, IoC, Port); - - return(SK_AND_OK); -} /* SkMacAutoNegDone */ - - -/****************************************************************************** - * - * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC - * - * Description: - * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg. - * enables Rx/Tx - * - * Returns: N/A - */ -static void SkXmSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ -{ - SK_U16 Word; - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { - case SK_MAC_LOOPB_ON: - Word |= XM_MMU_MAC_LB; - break; - case SK_MAC_LOOPB_OFF: - Word &= ~XM_MMU_MAC_LB; - break; - } - - switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) { - case SK_PHY_LOOPB_ON: - Word |= XM_MMU_GMII_LOOP; - break; - case SK_PHY_LOOPB_OFF: - Word &= ~XM_MMU_GMII_LOOP; - break; - } - - switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { - case SK_PHY_FULLD_ON: - Word |= XM_MMU_GMII_FD; - break; - case SK_PHY_FULLD_OFF: - Word &= ~XM_MMU_GMII_FD; - break; - } - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - - /* dummy read to ensure writing */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - -} /* SkXmSetRxTxEn */ - - -/****************************************************************************** - * - * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC - * - * Description: - * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg. - * enables Rx/Tx - * - * Returns: N/A - */ -static void SkGmSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ -{ - SK_U16 Ctrl; - - GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); - - switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) { - case SK_MAC_LOOPB_ON: - Ctrl |= GM_GPCR_LOOP_ENA; - break; - case SK_MAC_LOOPB_OFF: - Ctrl &= ~GM_GPCR_LOOP_ENA; - break; - } - - switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) { - case SK_PHY_FULLD_ON: - Ctrl |= GM_GPCR_DUP_FULL; - break; - case SK_PHY_FULLD_OFF: - Ctrl &= ~GM_GPCR_DUP_FULL; - break; - } - - GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); - -} /* SkGmSetRxTxEn */ - - -/****************************************************************************** - * - * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters - * - * Description: calls the Special Set Rx/Tx Enable routines dep. on board type - * - * Returns: N/A - */ -void SkMacSetRxTxEn( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Para) -{ - if (pAC->GIni.GIGenesis) { - - SkXmSetRxTxEn(pAC, IoC, Port, Para); - } - else { - - SkGmSetRxTxEn(pAC, IoC, Port, Para); - } - -} /* SkMacSetRxTxEn */ - - -/****************************************************************************** - * - * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up - * - * Description: enables Rx/Tx dep. on board type - * - * Returns: - * 0 o.k. - * != 0 Error happened - */ -int SkMacRxTxEnable( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 Reg; /* 16-bit register value */ - SK_U16 IntMask; /* MAC interrupt mask */ - SK_U16 SWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (!pPrt->PHWLinkUp) { - /* The Hardware link is NOT up */ - return(0); - } - - if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || - pPrt->PLinkMode == SK_LMODE_AUTOFULL || - pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && - pPrt->PAutoNegFail) { - /* Auto-negotiation is not done or failed */ - return(0); - } - - if (pAC->GIni.GIGenesis) { - /* set Duplex Mode and Pause Mode */ - SkXmInitDupMd(pAC, IoC, Port); - - SkXmInitPauseMd(pAC, IoC, Port); - - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Link Asynchronous Event - * - Link Partner requests config - * - Auto Negotiation Done - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = XM_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overflow */ - IntMask &= ~XM_IS_RXF_OV; -#endif /* DEBUG */ - - if (pPrt->PhyType != SK_PHY_XMAC) { - /* disable GP0 interrupt bit */ - IntMask |= XM_IS_INP_ASS; - } - XM_OUT16(IoC, Port, XM_IMSK, IntMask); - - /* get MMU Command Reg. */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Reg); - - if (pPrt->PhyType != SK_PHY_XMAC && - (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) { - /* set to Full Duplex */ - Reg |= XM_MMU_GMII_FD; - } - - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK); - break; - case SK_PHY_NAT: - /* todo National: - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */ - /* no interrupts possible from National ??? */ - break; -#endif /* OTHER_PHY */ - } - - /* enable Rx/Tx */ - XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - } - else { - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = GMAC_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overrun */ - IntMask |= GM_IS_RX_FF_OR; -#endif /* DEBUG */ - - SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); - - /* get General Purpose Control */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); - - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { - /* set to Full Duplex */ - Reg |= GM_GPCR_DUP_FULL; - } - - /* enable Rx/Tx */ - GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - -#ifndef VCPU - /* Enable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); -#endif /* VCPU */ - } - - return(0); - -} /* SkMacRxTxEnable */ - - -/****************************************************************************** - * - * SkMacRxTxDisable() - Disable Receiver and Transmitter - * - * Description: disables Rx/Tx dep. on board type - * - * Returns: N/A - */ -void SkMacRxTxDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; - - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - - /* dummy read to ensure writing */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - } - else { - - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - - GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); - - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - } -} /* SkMacRxTxDisable */ - - -/****************************************************************************** - * - * SkMacIrqDisable() - Disable IRQ from MAC - * - * Description: sets the IRQ-mask to disable IRQ dep. on board type - * - * Returns: N/A - */ -void SkMacIrqDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - if (pAC->GIni.GIGenesis) { - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - /* Disable all PHY interrupts */ - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* Make sure that PHY is initialized */ - if (pPrt->PState != SK_PRT_RESET) { - /* NOT allowed if BCOM is in RESET state */ - /* Workaround BCOM Errata (#10523) all BCom */ - /* Disable Power Management if link is down */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(Word | PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - } - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - } - else { - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - -#ifndef VCPU - /* Disable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); -#endif /* VCPU */ - } -} /* SkMacIrqDisable */ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSendCont() - Enable / Disable Send Continuous Mode - * - * Description: enable / disable Send Continuous Mode on XMAC - * - * Returns: - * nothing - */ -void SkXmSendCont( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_TX_CONT; - } - else { - MdReg &= ~XM_MD_TX_CONT; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - -} /* SkXmSendCont*/ - -/****************************************************************************** - * - * SkMacTimeStamp() - Enable / Disable Time Stamp - * - * Description: enable / disable Time Stamp generation for Rx packets - * - * Returns: - * nothing - */ -void SkMacTimeStamp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - SK_U8 TimeCtrl; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_ATS; - } - else { - MdReg &= ~XM_MD_ATS; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } - else { - if (Enable) { - TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ; - } - else { - TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; - } - /* Start/Stop Time Stamp Timer */ - SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl); - } -} /* SkMacTimeStamp*/ - -#else /* SK_DIAG */ - -/****************************************************************************** - * - * SkXmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the XMAC - * - * Note: - * With an external PHY, some interrupt bits are not meaningfull any more: - * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE - * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC - * - Page Received (bit #9) XM_IS_RX_PAGE - * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE - * - AutoNegDone (bit #7) XM_IS_AND - * Also probably not valid any more is the GP0 input bit: - * - GPRegisterBit0set XM_IS_INP_ASS - * - * Returns: - * nothing - */ -void SkXmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_EVPARA Para; - SK_U16 IStatus; /* Interrupt status read from the XMAC */ - SK_U16 IStatus2; - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_ISRC, &IStatus); - - /* LinkPartner Auto-negable? */ - if (pPrt->PhyType == SK_PHY_XMAC) { - SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus); - } - else { - /* mask bits that are not used with ext. PHY */ - IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC | - XM_IS_RX_PAGE | XM_IS_TX_PAGE | - XM_IS_AND | XM_IS_INP_ASS); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); - - if (!pPrt->PHWLinkUp) { - /* Spurious XMAC interrupt */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: spurious interrupt on Port %d\n", Port)); - return; - } - - if ((IStatus & XM_IS_INP_ASS) != 0) { - /* Reread ISR Register if link is not in sync */ - XM_IN16(IoC, Port, XM_ISRC, &IStatus2); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n", - Port, IStatus, IStatus2)); - IStatus &= ~XM_IS_INP_ASS; - IStatus |= IStatus2; - } - - if ((IStatus & XM_IS_LNK_AE) != 0) { - /* not used, GP0 is used instead */ - } - - if ((IStatus & XM_IS_TX_ABORT) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_FRC_INT) != 0) { - /* not used, use ASIC IRQ instead if needed */ - } - - if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) { - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - Para.Para32[0] = (SK_U32)Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - - if ((IStatus & XM_IS_RX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_TX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: AND on link that is up Port %d\n", Port)); - } - - if ((IStatus & XM_IS_TSC_OV) != 0) { - /* not used */ - } - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); - } - - if ((IStatus & XM_IS_RXF_OV) != 0) { - /* normal situation -> no effect */ -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if ((IStatus & XM_IS_TXF_UR) != 0) { - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if ((IStatus & XM_IS_TX_COMP) != 0) { - /* not served here */ - } - - if ((IStatus & XM_IS_RX_COMP) != 0) { - /* not served here */ - } -} /* SkXmIrq */ - - -/****************************************************************************** - * - * SkGmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the GMAC - * - * Note: - * - * Returns: - * nothing - */ -void SkGmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_EVPARA Para; - SK_U8 IStatus; /* Interrupt status */ - - pPrt = &pAC->GIni.GP[Port]; - - SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); - - /* LinkPartner Auto-negable? */ - SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { - /* these IRQs will be cleared by reading GMACs register */ - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); - } - - if (IStatus & GM_IS_RX_FF_OR) { - /* clear GMAC Rx FIFO Overrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if (IStatus & GM_IS_TX_FF_UR) { - /* clear GMAC Tx FIFO Underrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU); - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if (IStatus & GM_IS_TX_COMPL) { - /* not served here */ - } - - if (IStatus & GM_IS_RX_COMPL) { - /* not served here */ - } -} /* SkGmIrq */ - -/****************************************************************************** - * - * SkMacIrq() - Interrupt Service Routine for MAC - * - * Description: calls the Interrupt Service Routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - - if (pAC->GIni.GIGenesis) { - /* IRQ from XMAC */ - SkXmIrq(pAC, IoC, Port); - } - else { - /* IRQ from GMAC */ - SkGmIrq(pAC, IoC, Port); - } -} /* SkMacIrq */ - -#endif /* !SK_DIAG */ - -/****************************************************************************** - * - * SkXmUpdateStats() - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values a command must be sent so that the statistic data will - * be written to a predefined memory area on the adapter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 StatReg; - int WaitIndex; - - pPrt = &pAC->GIni.GP[Port]; - WaitIndex = 0; - - /* Send an update command to XMAC specified */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); - - /* - * It is an auto-clearing register. If the command bits - * went to zero again, the statistics are transferred. - * Normally the command should be executed immediately. - * But just to be sure we execute a loop. - */ - do { - - XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg); - - if (++WaitIndex > 10) { - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG); - - return(1); - } - } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0); - - return(0); -} /* SkXmUpdateStats */ - -/****************************************************************************** - * - * SkGmUpdateStats() - Force the GMAC to output the current statistic - * - * Description: - * Empty function for GMAC. Statistic data is accessible in direct way. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - return(0); -} - -/****************************************************************************** - * - * SkXmMacStatistic() - Get XMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 *pVal) /* ptr to return statistic value */ -{ - if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - return(1); - } - - XM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkXmMacStatistic */ - -/****************************************************************************** - * - * SkGmMacStatistic() - Get GMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 *pVal) /* ptr to return statistic value */ -{ - - if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); - return(1); - } - - GM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkGmMacStatistic */ - -/****************************************************************************** - * - * SkXmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force the XMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - - return(0); -} /* SkXmResetCounter */ - -/****************************************************************************** - * - * SkGmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force GMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Reg; /* Phy Address Register */ - SK_U16 Word; - int i; - - GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); - -#ifndef VCPU - /* set MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); - - /* read all MIB Counters with Clear Mode set */ - for (i = 0; i < GM_MIB_CNT_SIZE; i++) { - /* the reset is performed only when the lower 16 bits are read */ - GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); - } - - /* clear MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); -#endif /* !VCPU */ - - return(0); -} /* SkGmResetCounter */ - -/****************************************************************************** - * - * SkXmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to , whereas the - * upper dword stores the XMAC ReceiveCounterEvent register and the lower - * dword the XMAC TransmitCounterEvent register. - * - * Note: - * For XMAC the interrupt source is a self-clearing register, so the source - * must be checked only once. SIRQ module does another check to be sure - * that no interrupt get lost during process time. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U32 RegVal; - - Status = 0; - - if ((IStatus & XM_IS_RXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & XM_IS_TXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal; - } - - *pStatus = Status; - - return(0); -} /* SkXmOverflowStatus */ - - -/****************************************************************************** - * - * SkGmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to , whereas the - * the following bit coding is used: - * 63:56 - unused - * 55:48 - TxRx interrupt register bit7:0 - * 32:47 - Rx interrupt register - * 31:24 - unused - * 23:16 - TxRx interrupt register bit15:8 - * 15:0 - Tx interrupt register - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U16 RegVal; - - Status = 0; - - if ((IStatus & GM_IS_RX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & GM_IS_TX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal; - } - - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); - /* Rx overflow interrupt register bits (LoByte)*/ - Status |= (SK_U64)((SK_U8)RegVal) << 48; - /* Tx overflow interrupt register bits (HiByte)*/ - Status |= (SK_U64)(RegVal >> 8) << 16; - - *pStatus = Status; - - return(0); -} /* SkGmOverflowStatus */ - -/****************************************************************************** - * - * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test - * - * Description: - * starts the cable diagnostic test if 'StartTest' is true - * gets the results if 'StartTest' is true - * - * NOTE: this test is meaningful only when link is down - * - * Returns: - * 0: success - * 1: no YUKON copper - * 2: test in progress - */ -int SkGmCableDiagStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL StartTest) /* flag for start / get result */ -{ - int i; - SK_U16 RegVal; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - - return(1); - } - - if (StartTest) { - /* only start the cable test */ - if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { - /* apply TDR workaround from Marvell */ - SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); - - SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); - } - - /* set address to 0 for MDI[0] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - /* start Cable Diagnostic Test */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, - (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); - - return(0); - } - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Cable Diag.=0x%04X\n", RegVal)); - - if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { - /* test is running */ - return(2); - } - - /* get the test results */ - for (i = 0; i < 4; i++) { - /* set address to i for MDI[i] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); - - /* get Cable Diagnostic values */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); - - pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); - } - - return(0); -} /* SkGmCableDiagStatus */ - -#endif /* CONFIG_SK98 */ - -/* End of file */ diff --git a/drivers/sk98lin/u-boot_compat.h b/drivers/sk98lin/u-boot_compat.h deleted file mode 100644 index 1e385f8ef5..0000000000 --- a/drivers/sk98lin/u-boot_compat.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _UBOOT_COMPAT_H__ -#define _UBOOT_COMPAT_H__ - - -#include -#include -#include -#include -#include - -#define __initdata -#define __init -#define __exit - -#define netif_stop_queue(x) -#define netif_wake_queue(x) -#define netif_running(x) 0 -#define unregister_netdev(x) -#define remove_proc_entry(x,y) - -#define dev_addr enetaddr - -#define spin_lock_irqsave(x,y) y = 0; -#define spin_lock_init(x) -#define spin_lock(x) -#define spin_unlock_irqrestore(x,y) -#define spin_unlock(x) - - -#define ENODEV 1 -#define EAGAIN 2 -#define EBUSY 3 - -#define HZ CFG_HZ - - -#define printk printf -#define KERN_ERR -#define KERN_WARNING -#define KERN_INFO - -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT - - -#define kmalloc(x,y) malloc(x) -#define kfree(x) free(x) -#define GFP_ATOMIC 0 - -#define pci_alloc_consistent(x,y,z) (void *)(*(dma_addr_t *)(z) = (dma_addr_t)malloc(y)) -#define pci_free_consistent(x,y,z,d) free(z) -#define pci_dma_sync_single(x,y,z,d) -#define pci_unmap_page(x,y,z,d) -#define pci_unmap_single(x,y,z,d) -#define pci_present() 1 - -struct sk_buff -{ - u8 * data; - u32 len; - u8 * data_unaligned; -}; - -struct sk_buff * alloc_skb(u32 size, int dummy); -void dev_kfree_skb_any(struct sk_buff *skb); -void skb_reserve(struct sk_buff *skb, unsigned int len); -void skb_put(struct sk_buff *skb, unsigned int len); - -#define dev_kfree_skb dev_kfree_skb_any -#define dev_kfree_skb_irq dev_kfree_skb_any - -#define eth_copy_and_sum(dest,src,len,base) memcpy(dest->data,src,len); - - -#endif /* _UBOOT_COMPAT_H__ */ diff --git a/drivers/sk98lin/uboot_drv.c b/drivers/sk98lin/uboot_drv.c deleted file mode 100644 index d02cd1be24..0000000000 --- a/drivers/sk98lin/uboot_drv.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Driver for SysKonnect Gigabit Ethernet Server Adapters. - * - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_SK98) - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" -#include "u-boot_compat.h" - - -#define SKGE_MAX_CARDS 2 - - -extern int skge_probe(struct eth_device **); -extern void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -extern void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); -extern int SkGeOpen(struct eth_device *); -extern int SkGeClose(struct eth_device *); -extern int SkGeXmit(struct sk_buff *skb, struct eth_device *dev); -extern void ReceiveIrq(SK_AC *pAC, RX_PORT *pRxPort, SK_BOOL SlowPathLock); - -static int skge_init(struct eth_device *dev, bd_t * bis); -static int skge_send(struct eth_device *dev, volatile void *packet, int length); -static int skge_recv(struct eth_device *dev); -static void skge_halt(struct eth_device *dev); - -int skge_initialize(bd_t * bis) -{ - int numdev, i; - struct eth_device *dev[SKGE_MAX_CARDS]; - - numdev = skge_probe(&dev[0]); - - if (numdev > SKGE_MAX_CARDS) - { - printf("ERROR: numdev > SKGE_MAX_CARDS\n"); - } - - for (i = 0; i < numdev; i++) - { - sprintf (dev[i]->name, "SK98#%d", i); - - dev[i]->init = skge_init; - dev[i]->halt = skge_halt; - dev[i]->send = skge_send; - dev[i]->recv = skge_recv; - - eth_register(dev[i]); - } - - return numdev; -} - - -static int skge_init(struct eth_device *dev, bd_t * bis) -{ - int ret; - SK_AC * pAC = ((DEV_NET*)dev->priv)->pAC; - int i; - - ret = SkGeOpen(dev); - - while (pAC->Rlmt.Port[0].PortState != SK_RLMT_PS_GOING_UP) - { - SkGeIsrOnePort (0, pAC->dev[0], 0); - } - - for (i = 0; i < 100; i ++) - { - udelay(1000); - } - - return ret; -} - - -static void skge_halt(struct eth_device *dev) -{ - SkGeClose(dev); -} - - -static int skge_send(struct eth_device *dev, volatile void *packet, - int length) -{ - int ret = -1; - struct sk_buff * skb = alloc_skb(length, 0); - - if (! skb) - { - printf("skge_send: failed to alloc skb\n"); - goto Done; - } - - memcpy(skb->data, (void*)packet, length); - ret = SkGeXmit(skb, dev); - -Done: - return ret; -} - - -static int skge_recv(struct eth_device *dev) -{ - DEV_NET *pNet; - SK_AC *pAC; - int FromPort = 0; - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); - - return 0; -} - - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/uboot_skb.c b/drivers/sk98lin/uboot_skb.c deleted file mode 100644 index 3a487a8e3d..0000000000 --- a/drivers/sk98lin/uboot_skb.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Definitions for the 'struct sk_buff' memory handlers in U-Boot. - * - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -#ifdef CONFIG_SK98 - -#include -#include "u-boot_compat.h" - -#define MAX_SKB 50 - -static struct sk_buff *sk_table[MAX_SKB]; - - -struct sk_buff * alloc_skb(u32 size, int dummy) -{ - int i; - struct sk_buff * ret = NULL; - - for (i = 0; i < MAX_SKB; i++) - { - if (sk_table[i]) - { - /* Already allocated. - */ - continue; - } - - sk_table[i] = malloc(sizeof(struct sk_buff)); - if (! sk_table[i]) - { - printf("alloc_skb: malloc failed\n"); - break; - } - - memset(sk_table[i], 0, sizeof(struct sk_buff)); - sk_table[i]->data = sk_table[i]->data_unaligned = - malloc(size + 16); - if (! sk_table[i]->data) - { - printf("alloc_skb: malloc failed\n"); - free(sk_table[i]); - sk_table[i] = NULL; - break; - } - - sk_table[i]->data += 16 - ((u32)sk_table[i]->data & 15); - sk_table[i]->len = size; - - break; - } - - if (i < MAX_SKB) - { - ret = sk_table[i]; - } - - if (! ret) - { - printf("Unable to allocate skb!\n"); - } - - return ret; -} - -void dev_kfree_skb_any(struct sk_buff *skb) -{ - int i; - - for (i = 0; i < MAX_SKB; i++) - { - if (sk_table[i] != skb) - { - continue; - } - - free(skb->data_unaligned); - free(skb); - sk_table[i] = NULL; - break; - } - - if (i == MAX_SKB) - { - printf("SKB allocation error!\n"); - } -} - -void skb_reserve(struct sk_buff *skb, unsigned int len) -{ - skb->data+=len; -} - -void skb_put(struct sk_buff *skb, unsigned int len) -{ - skb->len+=len; -} - -#endif /* CONFIG_SK98 */ diff --git a/drivers/smc91111.c b/drivers/smc91111.c deleted file mode 100644 index 8061f12979..0000000000 --- a/drivers/smc91111.c +++ /dev/null @@ -1,1623 +0,0 @@ -/*------------------------------------------------------------------------ - . smc91111.c - . This is a driver for SMSC's 91C111 single-chip Ethernet device. - . - . (C) Copyright 2002 - . Sysgo Real-Time Solutions, GmbH - . Rolf Offermanns - . - . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - . Developed by Simple Network Magic Corporation (SNMC) - . Copyright (C) 1996 by Erik Stahlman (ES) - . - . This program is free software; you can redistribute it and/or modify - . it under the terms of the GNU General Public License as published by - . the Free Software Foundation; either version 2 of the License, or - . (at your option) any later version. - . - . This program is distributed in the hope that it will be useful, - . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - . GNU General Public License for more details. - . - . You should have received a copy of the GNU General Public License - . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - . Information contained in this file was obtained from the LAN91C111 - . manual from SMC. To get a copy, if you really want one, you can find - . information under www.smsc.com. - . - . - . "Features" of the SMC chip: - . Integrated PHY/MAC for 10/100BaseT Operation - . Supports internal and external MII - . Integrated 8K packet memory - . EEPROM interface for configuration - . - . Arguments: - . io = for the base address - . irq = for the IRQ - . - . author: - . Erik Stahlman ( erik@vt.edu ) - . Daris A Nevil ( dnevil@snmc.com ) - . - . - . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) - . - . Sources: - . o SMSC LAN91C111 databook (www.smsc.com) - . o smc9194.c by Erik Stahlman - . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) - . - . History: - . 06/19/03 Richard Woodruff Made u-boot environment aware and added mac addr checks. - . 10/17/01 Marco Hasewinkel Modify for DNP/1110 - . 07/25/01 Woojung Huh Modify for ADS Bitsy - . 04/25/01 Daris A Nevil Initial public release through SMSC - . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111 - ----------------------------------------------------------------------------*/ - -#include -#include -#include -#include "smc91111.h" -#include - -#ifdef CONFIG_DRIVER_SMC91111 - -/* Use power-down feature of the chip */ -#define POWER_DOWN 0 - -#define NO_AUTOPROBE - -#define SMC_DEBUG 0 - -#if SMC_DEBUG > 1 -static const char version[] = - "smc91111.c:v1.0 04/25/01 by Daris A Nevil (dnevil@snmc.com)\n"; -#endif - -/* Autonegotiation timeout in seconds */ -#ifndef CONFIG_SMC_AUTONEG_TIMEOUT -#define CONFIG_SMC_AUTONEG_TIMEOUT 10 -#endif - -/*------------------------------------------------------------------------ - . - . Configuration options, for the experienced user to change. - . - -------------------------------------------------------------------------*/ - -/* - . Wait time for memory to be free. This probably shouldn't be - . tuned that much, as waiting for this means nothing else happens - . in the system -*/ -#define MEMORY_WAIT_TIME 16 - - -#if (SMC_DEBUG > 2 ) -#define PRINTK3(args...) printf(args) -#else -#define PRINTK3(args...) -#endif - -#if SMC_DEBUG > 1 -#define PRINTK2(args...) printf(args) -#else -#define PRINTK2(args...) -#endif - -#ifdef SMC_DEBUG -#define PRINTK(args...) printf(args) -#else -#define PRINTK(args...) -#endif - - -/*------------------------------------------------------------------------ - . - . The internal workings of the driver. If you are changing anything - . here with the SMC stuff, you should have the datasheet and know - . what you are doing. - . - -------------------------------------------------------------------------*/ -#define CARDNAME "LAN91C111" - -/* Memory sizing constant */ -#define LAN91C111_MEMORY_MULTIPLIER (1024*2) - -#ifndef CONFIG_SMC91111_BASE -#define CONFIG_SMC91111_BASE 0x20000300 -#endif - -#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE - -#define SMC_DEV_NAME "SMC91111" -#define SMC_PHY_ADDR 0x0000 -#define SMC_ALLOC_MAX_TRY 5 -#define SMC_TX_TIMEOUT 30 - -#define SMC_PHY_CLOCK_DELAY 1000 - -#define ETH_ZLEN 60 - -#ifdef CONFIG_SMC_USE_32_BIT -#define USE_32_BIT 1 -#else -#undef USE_32_BIT -#endif -/*----------------------------------------------------------------- - . - . The driver can be entered at any of the following entry points. - . - .------------------------------------------------------------------ */ - -extern int eth_init(bd_t *bd); -extern void eth_halt(void); -extern int eth_rx(void); -extern int eth_send(volatile void *packet, int length); - -#ifdef SHARED_RESOURCES - extern void swap_to(int device_id); -#endif - -/* - . This is called by register_netdev(). It is responsible for - . checking the portlist for the SMC9000 series chipset. If it finds - . one, then it will initialize the device, find the hardware information, - . and sets up the appropriate device parameters. - . NOTE: Interrupts are *OFF* when this procedure is called. - . - . NB:This shouldn't be static since it is referred to externally. -*/ -int smc_init(void); - -/* - . This is called by unregister_netdev(). It is responsible for - . cleaning up before the driver is finally unregistered and discarded. -*/ -void smc_destructor(void); - -/* - . The kernel calls this function when someone wants to use the device, - . typically 'ifconfig ethX up'. -*/ -static int smc_open(bd_t *bd); - - -/* - . This is called by the kernel in response to 'ifconfig ethX down'. It - . is responsible for cleaning up everything that the open routine - . does, and maybe putting the card into a powerdown state. -*/ -static int smc_close(void); - -/* - . Configures the PHY through the MII Management interface -*/ -#ifndef CONFIG_SMC91111_EXT_PHY -static void smc_phy_configure(void); -#endif /* !CONFIG_SMC91111_EXT_PHY */ - -/* - . This is a separate procedure to handle the receipt of a packet, to - . leave the interrupt code looking slightly cleaner -*/ -static int smc_rcv(void); - -/* See if a MAC address is defined in the current environment. If so use it. If not - . print a warning and set the environment and other globals with the default. - . If an EEPROM is present it really should be consulted. -*/ -int smc_get_ethaddr(bd_t *bd); -int get_rom_mac(uchar *v_rom_mac); - -/* - ------------------------------------------------------------ - . - . Internal routines - . - ------------------------------------------------------------ -*/ - -#ifdef CONFIG_SMC_USE_IOFUNCS -/* - * input and output functions - * - * Implemented due to inx,outx macros accessing the device improperly - * and putting the device into an unkown state. - * - * For instance, on Sharp LPD7A400 SDK, affects were chip memory - * could not be free'd (hence the alloc failures), duplicate packets, - * packets being corrupt (shifted) on the wire, etc. Switching to the - * inx,outx functions fixed this problem. - */ -static inline word SMC_inw(dword offset); -static inline void SMC_outw(word value, dword offset); -static inline byte SMC_inb(dword offset); -static inline void SMC_outb(byte value, dword offset); -static inline void SMC_insw(dword offset, volatile uchar* buf, dword len); -static inline void SMC_outsw(dword offset, uchar* buf, dword len); - -#define barrier() __asm__ __volatile__("": : :"memory") - -static inline word SMC_inw(dword offset) -{ - word v; - v = *((volatile word*)(SMC_BASE_ADDRESS+offset)); - barrier(); *(volatile u32*)(0xc0000000); - return v; -} - -static inline void SMC_outw(word value, dword offset) -{ - *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value; - barrier(); *(volatile u32*)(0xc0000000); -} - -static inline byte SMC_inb(dword offset) -{ - word _w; - - _w = SMC_inw(offset & ~((dword)1)); - return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w); -} - -static inline void SMC_outb(byte value, dword offset) -{ - word _w; - - _w = SMC_inw(offset & ~((dword)1)); - if (offset & 1) - *((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff); - else - *((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00); -} - -static inline void SMC_insw(dword offset, volatile uchar* buf, dword len) -{ - volatile word *p = (volatile word *)buf; - - while (len-- > 0) { - *p++ = SMC_inw(offset); - barrier(); - *((volatile u32*)(0xc0000000)); - } -} - -static inline void SMC_outsw(dword offset, uchar* buf, dword len) -{ - volatile word *p = (volatile word *)buf; - - while (len-- > 0) { - SMC_outw(*p++, offset); - barrier(); - *(volatile u32*)(0xc0000000); - } -} -#endif /* CONFIG_SMC_USE_IOFUNCS */ - -static char unsigned smc_mac_addr[6] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8}; - -/* - * This function must be called before smc_open() if you want to override - * the default mac address. - */ - -void smc_set_mac_addr(const unsigned char *addr) { - int i; - - for (i=0; i < sizeof(smc_mac_addr); i++){ - smc_mac_addr[i] = addr[i]; - } -} - -/* - * smc_get_macaddr is no longer used. If you want to override the default - * mac address, call smc_get_mac_addr as a part of the board initialization. - */ - -#if 0 -void smc_get_macaddr( byte *addr ) { - /* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */ - unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010); - int i; - - - for (i=0; i<6; i++) { - addr[0] = *(dnp1110_mac+0); - addr[1] = *(dnp1110_mac+1); - addr[2] = *(dnp1110_mac+2); - addr[3] = *(dnp1110_mac+3); - addr[4] = *(dnp1110_mac+4); - addr[5] = *(dnp1110_mac+5); - } -} -#endif /* 0 */ - -/*********************************************** - * Show available memory * - ***********************************************/ -void dump_memory_info(void) -{ - word mem_info; - word old_bank; - - old_bank = SMC_inw(BANK_SELECT)&0xF; - - SMC_SELECT_BANK(0); - mem_info = SMC_inw( MIR_REG ); - PRINTK2("Memory: %4d available\n", (mem_info >> 8)*2048); - - SMC_SELECT_BANK(old_bank); -} -/* - . A rather simple routine to print out a packet for debugging purposes. -*/ -#if SMC_DEBUG > 2 -static void print_packet( byte *, int ); -#endif - -#define tx_done(dev) 1 - - -/* this does a soft reset on the device */ -static void smc_reset( void ); - -/* Enable Interrupts, Receive, and Transmit */ -static void smc_enable( void ); - -/* this puts the device in an inactive state */ -static void smc_shutdown( void ); - -/* Routines to Read and Write the PHY Registers across the - MII Management Interface -*/ - -#ifndef CONFIG_SMC91111_EXT_PHY -static word smc_read_phy_register(byte phyreg); -static void smc_write_phy_register(byte phyreg, word phydata); -#endif /* !CONFIG_SMC91111_EXT_PHY */ - - -static int poll4int (byte mask, int timeout) -{ - int tmo = get_timer (0) + timeout * CFG_HZ; - int is_timeout = 0; - word old_bank = SMC_inw (BSR_REG); - - PRINTK2 ("Polling...\n"); - SMC_SELECT_BANK (2); - while ((SMC_inw (SMC91111_INT_REG) & mask) == 0) { - if (get_timer (0) >= tmo) { - is_timeout = 1; - break; - } - } - - /* restore old bank selection */ - SMC_SELECT_BANK (old_bank); - - if (is_timeout) - return 1; - else - return 0; -} - -/* Only one release command at a time, please */ -static inline void smc_wait_mmu_release_complete (void) -{ - int count = 0; - - /* assume bank 2 selected */ - while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { - udelay (1); /* Wait until not busy */ - if (++count > 200) - break; - } -} - -/* - . Function: smc_reset( void ) - . Purpose: - . This sets the SMC91111 chip to its normal state, hopefully from whatever - . mess that any other DOS driver has put it in. - . - . Maybe I should reset more registers to defaults in here? SOFTRST should - . do that for me. - . - . Method: - . 1. send a SOFT RESET - . 2. wait for it to finish - . 3. enable autorelease mode - . 4. reset the memory management unit - . 5. clear all interrupts - . -*/ -static void smc_reset (void) -{ - PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME); - - /* This resets the registers mostly to defaults, but doesn't - affect EEPROM. That seems unnecessary */ - SMC_SELECT_BANK (0); - SMC_outw (RCR_SOFTRST, RCR_REG); - - /* Setup the Configuration Register */ - /* This is necessary because the CONFIG_REG is not affected */ - /* by a soft reset */ - - SMC_SELECT_BANK (1); -#if defined(CONFIG_SMC91111_EXT_PHY) - SMC_outw (CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG); -#else - SMC_outw (CONFIG_DEFAULT, CONFIG_REG); -#endif - - - /* Release from possible power-down state */ - /* Configuration register is not affected by Soft Reset */ - SMC_outw (SMC_inw (CONFIG_REG) | CONFIG_EPH_POWER_EN, CONFIG_REG); - - SMC_SELECT_BANK (0); - - /* this should pause enough for the chip to be happy */ - udelay (10); - - /* Disable transmit and receive functionality */ - SMC_outw (RCR_CLEAR, RCR_REG); - SMC_outw (TCR_CLEAR, TCR_REG); - - /* set the control register */ - SMC_SELECT_BANK (1); - SMC_outw (CTL_DEFAULT, CTL_REG); - - /* Reset the MMU */ - SMC_SELECT_BANK (2); - smc_wait_mmu_release_complete (); - SMC_outw (MC_RESET, MMU_CMD_REG); - while (SMC_inw (MMU_CMD_REG) & MC_BUSY) - udelay (1); /* Wait until not busy */ - - /* Note: It doesn't seem that waiting for the MMU busy is needed here, - but this is a place where future chipsets _COULD_ break. Be wary - of issuing another MMU command right after this */ - - /* Disable all interrupts */ - SMC_outb (0, IM_REG); -} - -/* - . Function: smc_enable - . Purpose: let the chip talk to the outside work - . Method: - . 1. Enable the transmitter - . 2. Enable the receiver - . 3. Enable interrupts -*/ -static void smc_enable() -{ - PRINTK2("%s: smc_enable\n", SMC_DEV_NAME); - SMC_SELECT_BANK( 0 ); - /* see the header file for options in TCR/RCR DEFAULT*/ - SMC_outw( TCR_DEFAULT, TCR_REG ); - SMC_outw( RCR_DEFAULT, RCR_REG ); - - /* clear MII_DIS */ -/* smc_write_phy_register(PHY_CNTL_REG, 0x0000); */ -} - -/* - . Function: smc_shutdown - . Purpose: closes down the SMC91xxx chip. - . Method: - . 1. zero the interrupt mask - . 2. clear the enable receive flag - . 3. clear the enable xmit flags - . - . TODO: - . (1) maybe utilize power down mode. - . Why not yet? Because while the chip will go into power down mode, - . the manual says that it will wake up in response to any I/O requests - . in the register space. Empirical results do not show this working. -*/ -static void smc_shutdown() -{ - PRINTK2(CARDNAME ": smc_shutdown\n"); - - /* no more interrupts for me */ - SMC_SELECT_BANK( 2 ); - SMC_outb( 0, IM_REG ); - - /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK( 0 ); - SMC_outb( RCR_CLEAR, RCR_REG ); - SMC_outb( TCR_CLEAR, TCR_REG ); -#ifdef SHARED_RESOURCES - swap_to(FLASH); -#endif -} - - -/* - . Function: smc_hardware_send_packet(struct net_device * ) - . Purpose: - . This sends the actual packet to the SMC9xxx chip. - . - . Algorithm: - . First, see if a saved_skb is available. - . ( this should NOT be called if there is no 'saved_skb' - . Now, find the packet number that the chip allocated - . Point the data pointers at it in memory - . Set the length word in the chip's memory - . Dump the packet to chip memory - . Check if a last byte is needed ( odd length packet ) - . if so, set the control flag right - . Tell the card to send it - . Enable the transmit interrupt, so I know if it failed - . Free the kernel data if I actually sent it. -*/ -static int smc_send_packet (volatile void *packet, int packet_length) -{ - byte packet_no; - unsigned long ioaddr; - byte *buf; - int length; - int numPages; - int try = 0; - int time_out; - byte status; - byte saved_pnr; - word saved_ptr; - - /* save PTR and PNR registers before manipulation */ - SMC_SELECT_BANK (2); - saved_pnr = SMC_inb( PN_REG ); - saved_ptr = SMC_inw( PTR_REG ); - - PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME); - - length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; - - /* allocate memory - ** The MMU wants the number of pages to be the number of 256 bytes - ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) - ** - ** The 91C111 ignores the size bits, but the code is left intact - ** for backwards and future compatibility. - ** - ** Pkt size for allocating is data length +6 (for additional status - ** words, length and ctl!) - ** - ** If odd size then last byte is included in this header. - */ - numPages = ((length & 0xfffe) + 6); - numPages >>= 8; /* Divide by 256 */ - - if (numPages > 7) { - printf ("%s: Far too big packet error. \n", SMC_DEV_NAME); - return 0; - } - - /* now, try to allocate the memory */ - SMC_SELECT_BANK (2); - SMC_outw (MC_ALLOC | numPages, MMU_CMD_REG); - - /* FIXME: the ALLOC_INT bit never gets set * - * so the following will always give a * - * memory allocation error. * - * same code works in armboot though * - * -ro - */ - -again: - try++; - time_out = MEMORY_WAIT_TIME; - do { - status = SMC_inb (SMC91111_INT_REG); - if (status & IM_ALLOC_INT) { - /* acknowledge the interrupt */ - SMC_outb (IM_ALLOC_INT, SMC91111_INT_REG); - break; - } - } while (--time_out); - - if (!time_out) { - PRINTK2 ("%s: memory allocation, try %d failed ...\n", - SMC_DEV_NAME, try); - if (try < SMC_ALLOC_MAX_TRY) - goto again; - else - return 0; - } - - PRINTK2 ("%s: memory allocation, try %d succeeded ...\n", - SMC_DEV_NAME, try); - - /* I can send the packet now.. */ - - ioaddr = SMC_BASE_ADDRESS; - - buf = (byte *) packet; - - /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = SMC_inb (AR_REG); - if (packet_no & AR_FAILED) { - /* or isn't there? BAD CHIP! */ - printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME); - return 0; - } - - /* we have a packet address, so tell the card to use it */ -#ifndef CONFIG_XAENIAX - SMC_outb (packet_no, PN_REG); -#else - /* On Xaeniax board, we can't use SMC_outb here because that way - * the Allocate MMU command will end up written to the command register - * as well, which will lead to a problem. - */ - SMC_outl (packet_no << 16, 0); -#endif - /* do not write new ptr value if Write data fifo not empty */ - while ( saved_ptr & PTR_NOTEMPTY ) - printf ("Write data fifo not empty!\n"); - - /* point to the beginning of the packet */ - SMC_outw (PTR_AUTOINC, PTR_REG); - - PRINTK3 ("%s: Trying to xmit packet of length %x\n", - SMC_DEV_NAME, length); - -#if SMC_DEBUG > 2 - printf ("Transmitting Packet\n"); - print_packet (buf, length); -#endif - - /* send the packet length ( +6 for status, length and ctl byte ) - and the status word ( set to zeros ) */ -#ifdef USE_32_BIT - SMC_outl ((length + 6) << 16, SMC91111_DATA_REG); -#else - SMC_outw (0, SMC91111_DATA_REG); - /* send the packet length ( +6 for status words, length, and ctl */ - SMC_outw ((length + 6), SMC91111_DATA_REG); -#endif - - /* send the actual data - . I _think_ it's faster to send the longs first, and then - . mop up by sending the last word. It depends heavily - . on alignment, at least on the 486. Maybe it would be - . a good idea to check which is optimal? But that could take - . almost as much time as is saved? - */ -#ifdef USE_32_BIT - SMC_outsl (SMC91111_DATA_REG, buf, length >> 2); -#ifndef CONFIG_XAENIAX - if (length & 0x2) - SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))), - SMC91111_DATA_REG); -#else - /* On XANEIAX, we can only use 32-bit writes, so we need to handle - * unaligned tail part specially. The standard code doesn't work. - */ - if ((length & 3) == 3) { - u16 * ptr = (u16*) &buf[length-3]; - SMC_outl((*ptr) | ((0x2000 | buf[length-1]) << 16), - SMC91111_DATA_REG); - } else if ((length & 2) == 2) { - u16 * ptr = (u16*) &buf[length-2]; - SMC_outl(*ptr, SMC91111_DATA_REG); - } else if (length & 1) { - SMC_outl((0x2000 | buf[length-1]), SMC91111_DATA_REG); - } else { - SMC_outl(0, SMC91111_DATA_REG); - } -#endif -#else - SMC_outsw (SMC91111_DATA_REG, buf, (length) >> 1); -#endif /* USE_32_BIT */ - -#ifndef CONFIG_XAENIAX - /* Send the last byte, if there is one. */ - if ((length & 1) == 0) { - SMC_outw (0, SMC91111_DATA_REG); - } else { - SMC_outw (buf[length - 1] | 0x2000, SMC91111_DATA_REG); - } -#endif - - /* and let the chipset deal with it */ - SMC_outw (MC_ENQUEUE, MMU_CMD_REG); - - /* poll for TX INT */ - /* if (poll4int (IM_TX_INT, SMC_TX_TIMEOUT)) { */ - /* poll for TX_EMPTY INT - autorelease enabled */ - if (poll4int(IM_TX_EMPTY_INT, SMC_TX_TIMEOUT)) { - /* sending failed */ - PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME); - - /* release packet */ - /* no need to release, MMU does that now */ -#ifdef CONFIG_XAENIAX - SMC_outw (MC_FREEPKT, MMU_CMD_REG); -#endif - - /* wait for MMU getting ready (low) */ - while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { - udelay (10); - } - - PRINTK2 ("MMU ready\n"); - - - return 0; - } else { - /* ack. int */ - SMC_outb (IM_TX_EMPTY_INT, SMC91111_INT_REG); - /* SMC_outb (IM_TX_INT, SMC91111_INT_REG); */ - PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME, - length); - - /* release packet */ - /* no need to release, MMU does that now */ -#ifdef CONFIG_XAENIAX - SMC_outw (MC_FREEPKT, MMU_CMD_REG); -#endif - - /* wait for MMU getting ready (low) */ - while (SMC_inw (MMU_CMD_REG) & MC_BUSY) { - udelay (10); - } - - PRINTK2 ("MMU ready\n"); - - - } - - /* restore previously saved registers */ -#ifndef CONFIG_XAENIAX - SMC_outb( saved_pnr, PN_REG ); -#else - /* On Xaeniax board, we can't use SMC_outb here because that way - * the Allocate MMU command will end up written to the command register - * as well, which will lead to a problem. - */ - SMC_outl(saved_pnr << 16, 0); -#endif - SMC_outw( saved_ptr, PTR_REG ); - - return length; -} - -/*------------------------------------------------------------------------- - | - | smc_destructor( struct net_device * dev ) - | Input parameters: - | dev, pointer to the device structure - | - | Output: - | None. - | - --------------------------------------------------------------------------- -*/ -void smc_destructor() -{ - PRINTK2(CARDNAME ": smc_destructor\n"); -} - - -/* - * Open and Initialize the board - * - * Set up everything, reset the card, etc .. - * - */ -static int smc_open (bd_t * bd) -{ - int i, err; - - PRINTK2 ("%s: smc_open\n", SMC_DEV_NAME); - - /* reset the hardware */ - smc_reset (); - smc_enable (); - - /* Configure the PHY */ -#ifndef CONFIG_SMC91111_EXT_PHY - smc_phy_configure (); -#endif - - /* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */ -/* SMC_SELECT_BANK(0); */ -/* SMC_outw(0, RPC_REG); */ - SMC_SELECT_BANK (1); - - err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ - if (err < 0) { - memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ - return (-1); /* upper code ignores this, but NOT bi_enetaddr */ - } -#ifdef USE_32_BIT - for (i = 0; i < 6; i += 2) { - word address; - - address = smc_mac_addr[i + 1] << 8; - address |= smc_mac_addr[i]; - SMC_outw (address, (ADDR0_REG + i)); - } -#else - for (i = 0; i < 6; i++) - SMC_outb (smc_mac_addr[i], (ADDR0_REG + i)); -#endif - - return 0; -} - -/*------------------------------------------------------------- - . - . smc_rcv - receive a packet from the card - . - . There is ( at least ) a packet waiting to be read from - . chip-memory. - . - . o Read the status - . o If an error, record it - . o otherwise, read in the packet - -------------------------------------------------------------- -*/ -static int smc_rcv() -{ - int packet_number; - word status; - word packet_length; - int is_error = 0; -#ifdef USE_32_BIT - dword stat_len; -#endif - byte saved_pnr; - word saved_ptr; - - SMC_SELECT_BANK(2); - /* save PTR and PTR registers */ - saved_pnr = SMC_inb( PN_REG ); - saved_ptr = SMC_inw( PTR_REG ); - - packet_number = SMC_inw( RXFIFO_REG ); - - if ( packet_number & RXFIFO_REMPTY ) { - - return 0; - } - - PRINTK3("%s: smc_rcv\n", SMC_DEV_NAME); - /* start reading from the start of the packet */ - SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG ); - - /* First two words are status and packet_length */ -#ifdef USE_32_BIT - stat_len = SMC_inl(SMC91111_DATA_REG); - status = stat_len & 0xffff; - packet_length = stat_len >> 16; -#else - status = SMC_inw( SMC91111_DATA_REG ); - packet_length = SMC_inw( SMC91111_DATA_REG ); -#endif - - packet_length &= 0x07ff; /* mask off top bits */ - - PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ); - - if ( !(status & RS_ERRORS ) ){ - /* Adjust for having already read the first two words */ - packet_length -= 4; /*4; */ - - - /* set odd length for bug in LAN91C111, */ - /* which never sets RS_ODDFRAME */ - /* TODO ? */ - - -#ifdef USE_32_BIT - PRINTK3(" Reading %d dwords (and %d bytes) \n", - packet_length >> 2, packet_length & 3 ); - /* QUESTION: Like in the TX routine, do I want - to send the DWORDs or the bytes first, or some - mixture. A mixture might improve already slow PIO - performance */ - SMC_insl( SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 2 ); - /* read the left over bytes */ - if (packet_length & 3) { - int i; - - byte *tail = (byte *)(NetRxPackets[0] + (packet_length & ~3)); - dword leftover = SMC_inl(SMC91111_DATA_REG); - for (i=0; i<(packet_length & 3); i++) - *tail++ = (byte) (leftover >> (8*i)) & 0xff; - } -#else - PRINTK3(" Reading %d words and %d byte(s) \n", - (packet_length >> 1 ), packet_length & 1 ); - SMC_insw(SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 1); - -#endif /* USE_32_BIT */ - -#if SMC_DEBUG > 2 - printf("Receiving Packet\n"); - print_packet( NetRxPackets[0], packet_length ); -#endif - } else { - /* error ... */ - /* TODO ? */ - is_error = 1; - } - - while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) - udelay(1); /* Wait until not busy */ - - /* error or good, tell the card to get rid of this packet */ - SMC_outw( MC_RELEASE, MMU_CMD_REG ); - - while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY ) - udelay(1); /* Wait until not busy */ - - /* restore saved registers */ -#ifndef CONFIG_XAENIAX - SMC_outb( saved_pnr, PN_REG ); -#else - /* On Xaeniax board, we can't use SMC_outb here because that way - * the Allocate MMU command will end up written to the command register - * as well, which will lead to a problem. - */ - SMC_outl( saved_pnr << 16, 0); -#endif - SMC_outw( saved_ptr, PTR_REG ); - - if (!is_error) { - /* Pass the packet up to the protocol layers. */ - NetReceive(NetRxPackets[0], packet_length); - return packet_length; - } else { - return 0; - } - -} - - -/*---------------------------------------------------- - . smc_close - . - . this makes the board clean up everything that it can - . and not talk to the outside world. Caused by - . an 'ifconfig ethX down' - . - -----------------------------------------------------*/ -static int smc_close() -{ - PRINTK2("%s: smc_close\n", SMC_DEV_NAME); - - /* clear everything */ - smc_shutdown(); - - return 0; -} - - -#if 0 -/*------------------------------------------------------------ - . Modify a bit in the LAN91C111 register set - .-------------------------------------------------------------*/ -static word smc_modify_regbit(int bank, int ioaddr, int reg, - unsigned int bit, int val) -{ - word regval; - - SMC_SELECT_BANK( bank ); - - regval = SMC_inw( reg ); - if (val) - regval |= bit; - else - regval &= ~bit; - - SMC_outw( regval, 0 ); - return(regval); -} - - -/*------------------------------------------------------------ - . Retrieve a bit in the LAN91C111 register set - .-------------------------------------------------------------*/ -static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit) -{ - SMC_SELECT_BANK( bank ); - if ( SMC_inw( reg ) & bit) - return(1); - else - return(0); -} - - -/*------------------------------------------------------------ - . Modify a LAN91C111 register (word access only) - .-------------------------------------------------------------*/ -static void smc_modify_reg(int bank, int ioaddr, int reg, word val) -{ - SMC_SELECT_BANK( bank ); - SMC_outw( val, reg ); -} - - -/*------------------------------------------------------------ - . Retrieve a LAN91C111 register (word access only) - .-------------------------------------------------------------*/ -static int smc_get_reg(int bank, int ioaddr, int reg) -{ - SMC_SELECT_BANK( bank ); - return(SMC_inw( reg )); -} - -#endif /* 0 */ - -/*---PHY CONTROL AND CONFIGURATION----------------------------------------- */ - -#if (SMC_DEBUG > 2 ) - -/*------------------------------------------------------------ - . Debugging function for viewing MII Management serial bitstream - .-------------------------------------------------------------*/ -static void smc_dump_mii_stream (byte * bits, int size) -{ - int i; - - printf ("BIT#:"); - for (i = 0; i < size; ++i) { - printf ("%d", i % 10); - } - - printf ("\nMDOE:"); - for (i = 0; i < size; ++i) { - if (bits[i] & MII_MDOE) - printf ("1"); - else - printf ("0"); - } - - printf ("\nMDO :"); - for (i = 0; i < size; ++i) { - if (bits[i] & MII_MDO) - printf ("1"); - else - printf ("0"); - } - - printf ("\nMDI :"); - for (i = 0; i < size; ++i) { - if (bits[i] & MII_MDI) - printf ("1"); - else - printf ("0"); - } - - printf ("\n"); -} -#endif - -/*------------------------------------------------------------ - . Reads a register from the MII Management serial interface - .-------------------------------------------------------------*/ -#ifndef CONFIG_SMC91111_EXT_PHY -static word smc_read_phy_register (byte phyreg) -{ - int oldBank; - int i; - byte mask; - word mii_reg; - byte bits[64]; - int clk_idx = 0; - int input_idx; - word phydata; - byte phyaddr = SMC_PHY_ADDR; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) - bits[clk_idx++] = MII_MDOE | MII_MDO; - - /* Start code <01> */ - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - /* Read command <10> */ - bits[clk_idx++] = MII_MDOE | MII_MDO; - bits[clk_idx++] = MII_MDOE; - - /* Output the PHY address, msb first */ - mask = (byte) 0x10; - for (i = 0; i < 5; ++i) { - if (phyaddr & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Output the phy register number, msb first */ - mask = (byte) 0x10; - for (i = 0; i < 5; ++i) { - if (phyreg & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Tristate and turnaround (2 bit times) */ - bits[clk_idx++] = 0; - /*bits[clk_idx++] = 0; */ - - /* Input starts at this bit time */ - input_idx = clk_idx; - - /* Will input 16 bits */ - for (i = 0; i < 16; ++i) - bits[clk_idx++] = 0; - - /* Final clock bit */ - bits[clk_idx++] = 0; - - /* Save the current bank */ - oldBank = SMC_inw (BANK_SELECT); - - /* Select bank 3 */ - SMC_SELECT_BANK (3); - - /* Get the current MII register value */ - mii_reg = SMC_inw (MII_REG); - - /* Turn off all MII Interface bits */ - mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); - - /* Clock all 64 cycles */ - for (i = 0; i < sizeof bits; ++i) { - /* Clock Low - output data */ - SMC_outw (mii_reg | bits[i], MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - - - /* Clock Hi - input data */ - SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - bits[i] |= SMC_inw (MII_REG) & MII_MDI; - } - - /* Return to idle state */ - /* Set clock to low, data to low, and output tristated */ - SMC_outw (mii_reg, MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - - /* Restore original bank select */ - SMC_SELECT_BANK (oldBank); - - /* Recover input data */ - phydata = 0; - for (i = 0; i < 16; ++i) { - phydata <<= 1; - - if (bits[input_idx++] & MII_MDI) - phydata |= 0x0001; - } - -#if (SMC_DEBUG > 2 ) - printf ("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", - phyaddr, phyreg, phydata); - smc_dump_mii_stream (bits, sizeof bits); -#endif - - return (phydata); -} - - -/*------------------------------------------------------------ - . Writes a register to the MII Management serial interface - .-------------------------------------------------------------*/ -static void smc_write_phy_register (byte phyreg, word phydata) -{ - int oldBank; - int i; - word mask; - word mii_reg; - byte bits[65]; - int clk_idx = 0; - byte phyaddr = SMC_PHY_ADDR; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) - bits[clk_idx++] = MII_MDOE | MII_MDO; - - /* Start code <01> */ - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - /* Write command <01> */ - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - /* Output the PHY address, msb first */ - mask = (byte) 0x10; - for (i = 0; i < 5; ++i) { - if (phyaddr & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Output the phy register number, msb first */ - mask = (byte) 0x10; - for (i = 0; i < 5; ++i) { - if (phyreg & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Tristate and turnaround (2 bit times) */ - bits[clk_idx++] = 0; - bits[clk_idx++] = 0; - - /* Write out 16 bits of data, msb first */ - mask = 0x8000; - for (i = 0; i < 16; ++i) { - if (phydata & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Final clock bit (tristate) */ - bits[clk_idx++] = 0; - - /* Save the current bank */ - oldBank = SMC_inw (BANK_SELECT); - - /* Select bank 3 */ - SMC_SELECT_BANK (3); - - /* Get the current MII register value */ - mii_reg = SMC_inw (MII_REG); - - /* Turn off all MII Interface bits */ - mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO); - - /* Clock all cycles */ - for (i = 0; i < sizeof bits; ++i) { - /* Clock Low - output data */ - SMC_outw (mii_reg | bits[i], MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - - - /* Clock Hi - input data */ - SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - bits[i] |= SMC_inw (MII_REG) & MII_MDI; - } - - /* Return to idle state */ - /* Set clock to low, data to low, and output tristated */ - SMC_outw (mii_reg, MII_REG); - udelay (SMC_PHY_CLOCK_DELAY); - - /* Restore original bank select */ - SMC_SELECT_BANK (oldBank); - -#if (SMC_DEBUG > 2 ) - printf ("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", - phyaddr, phyreg, phydata); - smc_dump_mii_stream (bits, sizeof bits); -#endif -} -#endif /* !CONFIG_SMC91111_EXT_PHY */ - - -/*------------------------------------------------------------ - . Waits the specified number of milliseconds - kernel friendly - .-------------------------------------------------------------*/ -#ifndef CONFIG_SMC91111_EXT_PHY -static void smc_wait_ms(unsigned int ms) -{ - udelay(ms*1000); -} -#endif /* !CONFIG_SMC91111_EXT_PHY */ - - -/*------------------------------------------------------------ - . Configures the specified PHY using Autonegotiation. Calls - . smc_phy_fixed() if the user has requested a certain config. - .-------------------------------------------------------------*/ -#ifndef CONFIG_SMC91111_EXT_PHY -static void smc_phy_configure () -{ - int timeout; - byte phyaddr; - word my_phy_caps; /* My PHY capabilities */ - word my_ad_caps; /* My Advertised capabilities */ - word status = 0; /*;my status = 0 */ - int failed = 0; - - PRINTK3 ("%s: smc_program_phy()\n", SMC_DEV_NAME); - - - /* Get the detected phy address */ - phyaddr = SMC_PHY_ADDR; - - /* Reset the PHY, setting all other bits to zero */ - smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_RST); - - /* Wait for the reset to complete, or time out */ - timeout = 6; /* Wait up to 3 seconds */ - while (timeout--) { - if (!(smc_read_phy_register (PHY_CNTL_REG) - & PHY_CNTL_RST)) { - /* reset complete */ - break; - } - - smc_wait_ms (500); /* wait 500 millisecs */ - } - - if (timeout < 1) { - printf ("%s:PHY reset timed out\n", SMC_DEV_NAME); - goto smc_phy_configure_exit; - } - - /* Read PHY Register 18, Status Output */ - /* lp->lastPhy18 = smc_read_phy_register(PHY_INT_REG); */ - - /* Enable PHY Interrupts (for register 18) */ - /* Interrupts listed here are disabled */ - smc_write_phy_register (PHY_MASK_REG, 0xffff); - - /* Configure the Receive/Phy Control register */ - SMC_SELECT_BANK (0); - SMC_outw (RPC_DEFAULT, RPC_REG); - - /* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */ - my_phy_caps = smc_read_phy_register (PHY_STAT_REG); - my_ad_caps = PHY_AD_CSMA; /* I am CSMA capable */ - - if (my_phy_caps & PHY_STAT_CAP_T4) - my_ad_caps |= PHY_AD_T4; - - if (my_phy_caps & PHY_STAT_CAP_TXF) - my_ad_caps |= PHY_AD_TX_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TXH) - my_ad_caps |= PHY_AD_TX_HDX; - - if (my_phy_caps & PHY_STAT_CAP_TF) - my_ad_caps |= PHY_AD_10_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TH) - my_ad_caps |= PHY_AD_10_HDX; - - /* Update our Auto-Neg Advertisement Register */ - smc_write_phy_register (PHY_AD_REG, my_ad_caps); - - /* Read the register back. Without this, it appears that when */ - /* auto-negotiation is restarted, sometimes it isn't ready and */ - /* the link does not come up. */ - smc_read_phy_register(PHY_AD_REG); - - PRINTK2 ("%s: phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); - PRINTK2 ("%s: phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps); - - /* Restart auto-negotiation process in order to advertise my caps */ - smc_write_phy_register (PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST); - - /* Wait for the auto-negotiation to complete. This may take from */ - /* 2 to 3 seconds. */ - /* Wait for the reset to complete, or time out */ - timeout = CONFIG_SMC_AUTONEG_TIMEOUT * 2; - while (timeout--) { - - status = smc_read_phy_register (PHY_STAT_REG); - if (status & PHY_STAT_ANEG_ACK) { - /* auto-negotiate complete */ - break; - } - - smc_wait_ms (500); /* wait 500 millisecs */ - - /* Restart auto-negotiation if remote fault */ - if (status & PHY_STAT_REM_FLT) { - printf ("%s: PHY remote fault detected\n", - SMC_DEV_NAME); - - /* Restart auto-negotiation */ - printf ("%s: PHY restarting auto-negotiation\n", - SMC_DEV_NAME); - smc_write_phy_register (PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | - PHY_CNTL_ANEG_RST | - PHY_CNTL_SPEED | - PHY_CNTL_DPLX); - } - } - - if (timeout < 1) { - printf ("%s: PHY auto-negotiate timed out\n", SMC_DEV_NAME); - failed = 1; - } - - /* Fail if we detected an auto-negotiate remote fault */ - if (status & PHY_STAT_REM_FLT) { - printf ("%s: PHY remote fault detected\n", SMC_DEV_NAME); - failed = 1; - } - - /* Re-Configure the Receive/Phy Control register */ - SMC_outw (RPC_DEFAULT, RPC_REG); - -smc_phy_configure_exit: ; - -} -#endif /* !CONFIG_SMC91111_EXT_PHY */ - - -#if SMC_DEBUG > 2 -static void print_packet( byte * buf, int length ) -{ - int i; - int remainder; - int lines; - - printf("Packet of length %d \n", length ); - -#if SMC_DEBUG > 3 - lines = length / 16; - remainder = length % 16; - - for ( i = 0; i < lines ; i ++ ) { - int cur; - - for ( cur = 0; cur < 8; cur ++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printf("%02x%02x ", a, b ); - } - printf("\n"); - } - for ( i = 0; i < remainder/2 ; i++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printf("%02x%02x ", a, b ); - } - printf("\n"); -#endif -} -#endif - -int eth_init(bd_t *bd) { -#ifdef SHARED_RESOURCES - swap_to(ETHERNET); -#endif - return (smc_open(bd)); -} - -void eth_halt() { - smc_close(); -} - -int eth_rx() { - return smc_rcv(); -} - -int eth_send(volatile void *packet, int length) { - return smc_send_packet(packet, length); -} - -int smc_get_ethaddr (bd_t * bd) -{ - int env_size, rom_valid, env_present = 0, reg; - char *s = NULL, *e, es[] = "11:22:33:44:55:66"; - char s_env_mac[64]; - uchar v_env_mac[6], v_rom_mac[6], *v_mac; - - env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); - if ((env_size > 0) && (env_size < sizeof (es))) { /* exit if env is bad */ - printf ("\n*** ERROR: ethaddr is not set properly!!\n"); - return (-1); - } - - if (env_size > 0) { - env_present = 1; - s = s_env_mac; - } - - for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ - v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; - if (s) - s = (*e) ? e + 1 : e; - } - - rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ - - if (!env_present) { /* if NO env */ - if (rom_valid) { /* but ROM is valid */ - v_mac = v_rom_mac; - sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", - v_mac[0], v_mac[1], v_mac[2], v_mac[3], - v_mac[4], v_mac[5]); - setenv ("ethaddr", s_env_mac); - } else { /* no env, bad ROM */ - printf ("\n*** ERROR: ethaddr is NOT set !!\n"); - return (-1); - } - } else { /* good env, don't care ROM */ - v_mac = v_env_mac; /* always use a good env over a ROM */ - } - - if (env_present && rom_valid) { /* if both env and ROM are good */ - if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { - printf ("\nWarning: MAC addresses don't match:\n"); - printf ("\tHW MAC address: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - v_rom_mac[0], v_rom_mac[1], - v_rom_mac[2], v_rom_mac[3], - v_rom_mac[4], v_rom_mac[5] ); - printf ("\t\"ethaddr\" value: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - v_env_mac[0], v_env_mac[1], - v_env_mac[2], v_env_mac[3], - v_env_mac[4], v_env_mac[5]) ; - debug ("### Set MAC addr from environment\n"); - } - } - memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ - smc_set_mac_addr ((uchar *)v_mac); /* use old function to update smc default */ - PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], - v_mac[2], v_mac[3], v_mac[4], v_mac[5]); - return (0); -} - -int get_rom_mac (uchar *v_rom_mac) -{ -#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ - char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; - - memcpy (v_rom_mac, hw_mac_addr, 6); - return (1); -#else - int i; - int valid_mac = 0; - - SMC_SELECT_BANK (1); - for (i=0; i<6; i++) - { - v_rom_mac[i] = SMC_inb ((ADDR0_REG + i)); - valid_mac |= v_rom_mac[i]; - } - - return (valid_mac ? 1 : 0); -#endif -} -#endif /* CONFIG_DRIVER_SMC91111 */ diff --git a/drivers/smc91111.h b/drivers/smc91111.h deleted file mode 100644 index d03cbc320b..0000000000 --- a/drivers/smc91111.h +++ /dev/null @@ -1,719 +0,0 @@ -/*------------------------------------------------------------------------ - . smc91111.h - macros for the LAN91C111 Ethernet Driver - . - . (C) Copyright 2002 - . Sysgo Real-Time Solutions, GmbH - . Rolf Offermanns - . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - . Developed by Simple Network Magic Corporation (SNMC) - . Copyright (C) 1996 by Erik Stahlman (ES) - . - . This program is free software; you can redistribute it and/or modify - . it under the terms of the GNU General Public License as published by - . the Free Software Foundation; either version 2 of the License, or - . (at your option) any later version. - . - . This program is distributed in the hope that it will be useful, - . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - . GNU General Public License for more details. - . - . You should have received a copy of the GNU General Public License - . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - . This file contains register information and access macros for - . the LAN91C111 single chip ethernet controller. It is a modified - . version of the smc9194.h file. - . - . Information contained in this file was obtained from the LAN91C111 - . manual from SMC. To get a copy, if you really want one, you can find - . information under www.smsc.com. - . - . Authors - . Erik Stahlman ( erik@vt.edu ) - . Daris A Nevil ( dnevil@snmc.com ) - . - . History - . 03/16/01 Daris A Nevil Modified for use with LAN91C111 device - . - ---------------------------------------------------------------------------*/ -#ifndef _SMC91111_H_ -#define _SMC91111_H_ - -#include -#include - -/* - * This function may be called by the board specific initialisation code - * in order to override the default mac address. - */ - -void smc_set_mac_addr (const unsigned char *addr); - - -/* I want some simple types */ - -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long int dword; - -/* - . DEBUGGING LEVELS - . - . 0 for normal operation - . 1 for slightly more details - . >2 for various levels of increasingly useless information - . 2 for interrupt tracking, status flags - . 3 for packet info - . 4 for complete packet dumps -*/ -/*#define SMC_DEBUG 0 */ - -/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ - -#define SMC_IO_EXTENT 16 - -#ifdef CONFIG_PXA250 - -#ifdef CONFIG_XSENGINE -#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1)))) -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r<<1)))) -#define SMC_inb(p) ({ \ - unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p<<1)); \ - unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \ - if (__p & 2) __v >>= 8; \ - else __v &= 0xff; \ - __v; }) -#elif defined(CONFIG_XAENIAX) -#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) -#define SMC_inw(z) ({ \ - unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (z)); \ - unsigned int __v = *(volatile unsigned int *)((__p) & ~3); \ - if (__p & 3) __v >>= 16; \ - else __v &= 0xffff; \ - __v; }) -#define SMC_inb(p) ({ \ - unsigned int ___v = SMC_inw((p) & ~1); \ - if (p & 1) ___v >>= 8; \ - else ___v &= 0xff; \ - ___v; }) -#else -#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) -#define SMC_inb(p) ({ \ - unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p)); \ - unsigned int __v = *(volatile unsigned short *)((__p) & ~1); \ - if (__p & 1) __v >>= 8; \ - else __v &= 0xff; \ - __v; }) -#endif - -#ifdef CONFIG_XSENGINE -#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))) = d) -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r<<1))) = d) -#elif defined (CONFIG_XAENIAX) -#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) -#define SMC_outw(d,p) ({ \ - dword __dwo = SMC_inl((p) & ~3); \ - dword __dwn = (word)(d); \ - __dwo &= ((p) & 3) ? 0x0000ffff : 0xffff0000; \ - __dwo |= ((p) & 3) ? __dwn << 16 : __dwn; \ - SMC_outl(__dwo, (p) & ~3); \ -}) -#else -#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) -#endif - -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ - __w &= ((r)&1) ? 0x00FF : 0xFF00; \ - __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ - }) - -#define SMC_outsl(r,b,l) ({ int __i; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outl( *(__b2 + __i), r); \ - } \ - }) - -#define SMC_outsw(r,b,l) ({ int __i; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r); \ - } \ - }) - -#define SMC_insl(r,b,l) ({ int __i ; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inl(r); \ - SMC_inl(0); \ - }; \ - }) - -#define SMC_insw(r,b,l) ({ int __i ; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ - }; \ - }) - -#define SMC_insb(r,b,l) ({ int __i ; \ - byte *__b2; \ - __b2 = (byte *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inb(r); \ - SMC_inb(0); \ - }; \ - }) - -#else /* if not CONFIG_PXA250 */ - -#ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */ -/* - * We have only 16 Bit PCMCIA access on Socket 0 - */ - -#ifdef CONFIG_ADNPESC1 -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+((r)<<1)))) -#elif CONFIG_BLACKFIN -#define SMC_inw(r) ({ word __v = (*((volatile word *)(SMC_BASE_ADDRESS+(r)))); asm("ssync;"); __v;}) -#else -#define SMC_inw(r) (*((volatile word *)(SMC_BASE_ADDRESS+(r)))) -#endif -#define SMC_inb(r) (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF) - -#ifdef CONFIG_ADNPESC1 -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+((r)<<1))) = d) -#elif CONFIG_BLACKFIN -#define SMC_outw(d,r) {(*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d);asm("ssync;");} -#else -#define SMC_outw(d,r) (*((volatile word *)(SMC_BASE_ADDRESS+(r))) = d) -#endif -#define SMC_outb(d,r) ({ word __d = (byte)(d); \ - word __w = SMC_inw((r)&~1); \ - __w &= ((r)&1) ? 0x00FF : 0xFF00; \ - __w |= ((r)&1) ? __d<<8 : __d; \ - SMC_outw(__w,(r)&~1); \ - }) -#if 0 -#define SMC_outsw(r,b,l) outsw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_outsw(r,b,l) ({ int __i; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outw( *(__b2 + __i), r); \ - } \ - }) -#endif - -#if 0 -#define SMC_insw(r,b,l) insw(SMC_BASE_ADDRESS+(r), (b), (l)) -#else -#define SMC_insw(r,b,l) ({ int __i ; \ - word *__b2; \ - __b2 = (word *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inw(r); \ - SMC_inw(0); \ - }; \ - }) -#endif - -#endif /* CONFIG_SMC_USE_IOFUNCS */ - -#if defined(CONFIG_SMC_USE_32_BIT) - -#ifdef CONFIG_XSENGINE -#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1)))) -#else -#define SMC_inl(r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r)))) -#endif - -#define SMC_insl(r,b,l) ({ int __i ; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - *(__b2 + __i) = SMC_inl(r); \ - SMC_inl(0); \ - }; \ - }) - -#ifdef CONFIG_XSENGINE -#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))) = d) -#else -#define SMC_outl(d,r) (*((volatile dword *)(SMC_BASE_ADDRESS+(r))) = d) -#endif -#define SMC_outsl(r,b,l) ({ int __i; \ - dword *__b2; \ - __b2 = (dword *) b; \ - for (__i = 0; __i < l; __i++) { \ - SMC_outl( *(__b2 + __i), r); \ - } \ - }) - -#endif /* CONFIG_SMC_USE_32_BIT */ - -#endif - -/*--------------------------------------------------------------- - . - . A description of the SMSC registers is probably in order here, - . although for details, the SMC datasheet is invaluable. - . - . Basically, the chip has 4 banks of registers ( 0 to 3 ), which - . are accessed by writing a number into the BANK_SELECT register - . ( I also use a SMC_SELECT_BANK macro for this ). - . - . The banks are configured so that for most purposes, bank 2 is all - . that is needed for simple run time tasks. - -----------------------------------------------------------------------*/ - -/* - . Bank Select Register: - . - . yyyy yyyy 0000 00xx - . xx = bank number - . yyyy yyyy = 0x33, for identification purposes. -*/ -#define BANK_SELECT 14 - -/* Transmit Control Register */ -/* BANK 0 */ -#define TCR_REG 0x0000 /* transmit control register */ -#define TCR_ENABLE 0x0001 /* When 1 we can transmit */ -#define TCR_LOOP 0x0002 /* Controls output pin LBK */ -#define TCR_FORCOL 0x0004 /* When 1 will force a collision */ -#define TCR_PAD_EN 0x0080 /* When 1 will pad tx frames < 64 bytes w/0 */ -#define TCR_NOCRC 0x0100 /* When 1 will not append CRC to tx frames */ -#define TCR_MON_CSN 0x0400 /* When 1 tx monitors carrier */ -#define TCR_FDUPLX 0x0800 /* When 1 enables full duplex operation */ -#define TCR_STP_SQET 0x1000 /* When 1 stops tx if Signal Quality Error */ -#define TCR_EPH_LOOP 0x2000 /* When 1 enables EPH block loopback */ -#define TCR_SWFDUP 0x8000 /* When 1 enables Switched Full Duplex mode */ - -#define TCR_CLEAR 0 /* do NOTHING */ -/* the default settings for the TCR register : */ -/* QUESTION: do I want to enable padding of short packets ? */ -#define TCR_DEFAULT TCR_ENABLE - - -/* EPH Status Register */ -/* BANK 0 */ -#define EPH_STATUS_REG 0x0002 -#define ES_TX_SUC 0x0001 /* Last TX was successful */ -#define ES_SNGL_COL 0x0002 /* Single collision detected for last tx */ -#define ES_MUL_COL 0x0004 /* Multiple collisions detected for last tx */ -#define ES_LTX_MULT 0x0008 /* Last tx was a multicast */ -#define ES_16COL 0x0010 /* 16 Collisions Reached */ -#define ES_SQET 0x0020 /* Signal Quality Error Test */ -#define ES_LTXBRD 0x0040 /* Last tx was a broadcast */ -#define ES_TXDEFR 0x0080 /* Transmit Deferred */ -#define ES_LATCOL 0x0200 /* Late collision detected on last tx */ -#define ES_LOSTCARR 0x0400 /* Lost Carrier Sense */ -#define ES_EXC_DEF 0x0800 /* Excessive Deferral */ -#define ES_CTR_ROL 0x1000 /* Counter Roll Over indication */ -#define ES_LINK_OK 0x4000 /* Driven by inverted value of nLNK pin */ -#define ES_TXUNRN 0x8000 /* Tx Underrun */ - - -/* Receive Control Register */ -/* BANK 0 */ -#define RCR_REG 0x0004 -#define RCR_RX_ABORT 0x0001 /* Set if a rx frame was aborted */ -#define RCR_PRMS 0x0002 /* Enable promiscuous mode */ -#define RCR_ALMUL 0x0004 /* When set accepts all multicast frames */ -#define RCR_RXEN 0x0100 /* IFF this is set, we can receive packets */ -#define RCR_STRIP_CRC 0x0200 /* When set strips CRC from rx packets */ -#define RCR_ABORT_ENB 0x0200 /* When set will abort rx on collision */ -#define RCR_FILT_CAR 0x0400 /* When set filters leading 12 bit s of carrier */ -#define RCR_SOFTRST 0x8000 /* resets the chip */ - -/* the normal settings for the RCR register : */ -#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) -#define RCR_CLEAR 0x0 /* set it to a base state */ - -/* Counter Register */ -/* BANK 0 */ -#define COUNTER_REG 0x0006 - -/* Memory Information Register */ -/* BANK 0 */ -#define MIR_REG 0x0008 - -/* Receive/Phy Control Register */ -/* BANK 0 */ -#define RPC_REG 0x000A -#define RPC_SPEED 0x2000 /* When 1 PHY is in 100Mbps mode. */ -#define RPC_DPLX 0x1000 /* When 1 PHY is in Full-Duplex Mode */ -#define RPC_ANEG 0x0800 /* When 1 PHY is in Auto-Negotiate Mode */ -#define RPC_LSXA_SHFT 5 /* Bits to shift LS2A,LS1A,LS0A to lsb */ -#define RPC_LSXB_SHFT 2 /* Bits to get LS2B,LS1B,LS0B to lsb */ -#define RPC_LED_100_10 (0x00) /* LED = 100Mbps OR's with 10Mbps link detect */ -#define RPC_LED_RES (0x01) /* LED = Reserved */ -#define RPC_LED_10 (0x02) /* LED = 10Mbps link detect */ -#define RPC_LED_FD (0x03) /* LED = Full Duplex Mode */ -#define RPC_LED_TX_RX (0x04) /* LED = TX or RX packet occurred */ -#define RPC_LED_100 (0x05) /* LED = 100Mbps link dectect */ -#define RPC_LED_TX (0x06) /* LED = TX packet occurred */ -#define RPC_LED_RX (0x07) /* LED = RX packet occurred */ -#if defined(CONFIG_DK1C20) || defined(CONFIG_DK1S10) -/* buggy schematic: LEDa -> yellow, LEDb --> green */ -#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ - | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ - | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) -#elif defined(CONFIG_ADNPESC1) -/* SSV ADNP/ESC1 has only one LED: LEDa -> Rx/Tx indicator */ -#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ - | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ - | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) -#else -/* SMSC reference design: LEDa --> green, LEDb --> yellow */ -#define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ - | (RPC_LED_100_10 << RPC_LSXA_SHFT) \ - | (RPC_LED_TX_RX << RPC_LSXB_SHFT) ) -#endif - -/* Bank 0 0x000C is reserved */ - -/* Bank Select Register */ -/* All Banks */ -#define BSR_REG 0x000E - - -/* Configuration Reg */ -/* BANK 1 */ -#define CONFIG_REG 0x0000 -#define CONFIG_EXT_PHY 0x0200 /* 1=external MII, 0=internal Phy */ -#define CONFIG_GPCNTRL 0x0400 /* Inverse value drives pin nCNTRL */ -#define CONFIG_NO_WAIT 0x1000 /* When 1 no extra wait states on ISA bus */ -#define CONFIG_EPH_POWER_EN 0x8000 /* When 0 EPH is placed into low power mode. */ - -/* Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low */ -#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) - - -/* Base Address Register */ -/* BANK 1 */ -#define BASE_REG 0x0002 - - -/* Individual Address Registers */ -/* BANK 1 */ -#define ADDR0_REG 0x0004 -#define ADDR1_REG 0x0006 -#define ADDR2_REG 0x0008 - - -/* General Purpose Register */ -/* BANK 1 */ -#define GP_REG 0x000A - - -/* Control Register */ -/* BANK 1 */ -#define CTL_REG 0x000C -#define CTL_RCV_BAD 0x4000 /* When 1 bad CRC packets are received */ -#define CTL_AUTO_RELEASE 0x0800 /* When 1 tx pages are released automatically */ -#define CTL_LE_ENABLE 0x0080 /* When 1 enables Link Error interrupt */ -#define CTL_CR_ENABLE 0x0040 /* When 1 enables Counter Rollover interrupt */ -#define CTL_TE_ENABLE 0x0020 /* When 1 enables Transmit Error interrupt */ -#define CTL_EEPROM_SELECT 0x0004 /* Controls EEPROM reload & store */ -#define CTL_RELOAD 0x0002 /* When set reads EEPROM into registers */ -#define CTL_STORE 0x0001 /* When set stores registers into EEPROM */ -#define CTL_DEFAULT (0x1A10) /* Autorelease enabled*/ - -/* MMU Command Register */ -/* BANK 2 */ -#define MMU_CMD_REG 0x0000 -#define MC_BUSY 1 /* When 1 the last release has not completed */ -#define MC_NOP (0<<5) /* No Op */ -#define MC_ALLOC (1<<5) /* OR with number of 256 byte packets */ -#define MC_RESET (2<<5) /* Reset MMU to initial state */ -#define MC_REMOVE (3<<5) /* Remove the current rx packet */ -#define MC_RELEASE (4<<5) /* Remove and release the current rx packet */ -#define MC_FREEPKT (5<<5) /* Release packet in PNR register */ -#define MC_ENQUEUE (6<<5) /* Enqueue the packet for transmit */ -#define MC_RSTTXFIFO (7<<5) /* Reset the TX FIFOs */ - - -/* Packet Number Register */ -/* BANK 2 */ -#define PN_REG 0x0002 - - -/* Allocation Result Register */ -/* BANK 2 */ -#define AR_REG 0x0003 -#define AR_FAILED 0x80 /* Alocation Failed */ - - -/* RX FIFO Ports Register */ -/* BANK 2 */ -#define RXFIFO_REG 0x0004 /* Must be read as a word */ -#define RXFIFO_REMPTY 0x8000 /* RX FIFO Empty */ - - -/* TX FIFO Ports Register */ -/* BANK 2 */ -#define TXFIFO_REG RXFIFO_REG /* Must be read as a word */ -#define TXFIFO_TEMPTY 0x80 /* TX FIFO Empty */ - - -/* Pointer Register */ -/* BANK 2 */ -#define PTR_REG 0x0006 -#define PTR_RCV 0x8000 /* 1=Receive area, 0=Transmit area */ -#define PTR_AUTOINC 0x4000 /* Auto increment the pointer on each access */ -#define PTR_READ 0x2000 /* When 1 the operation is a read */ -#define PTR_NOTEMPTY 0x0800 /* When 1 _do not_ write fifo DATA REG */ - - -/* Data Register */ -/* BANK 2 */ -#define SMC91111_DATA_REG 0x0008 - - -/* Interrupt Status/Acknowledge Register */ -/* BANK 2 */ -#define SMC91111_INT_REG 0x000C - - -/* Interrupt Mask Register */ -/* BANK 2 */ -#define IM_REG 0x000D -#define IM_MDINT 0x80 /* PHY MI Register 18 Interrupt */ -#define IM_ERCV_INT 0x40 /* Early Receive Interrupt */ -#define IM_EPH_INT 0x20 /* Set by Etheret Protocol Handler section */ -#define IM_RX_OVRN_INT 0x10 /* Set by Receiver Overruns */ -#define IM_ALLOC_INT 0x08 /* Set when allocation request is completed */ -#define IM_TX_EMPTY_INT 0x04 /* Set if the TX FIFO goes empty */ -#define IM_TX_INT 0x02 /* Transmit Interrrupt */ -#define IM_RCV_INT 0x01 /* Receive Interrupt */ - - -/* Multicast Table Registers */ -/* BANK 3 */ -#define MCAST_REG1 0x0000 -#define MCAST_REG2 0x0002 -#define MCAST_REG3 0x0004 -#define MCAST_REG4 0x0006 - - -/* Management Interface Register (MII) */ -/* BANK 3 */ -#define MII_REG 0x0008 -#define MII_MSK_CRS100 0x4000 /* Disables CRS100 detection during tx half dup */ -#define MII_MDOE 0x0008 /* MII Output Enable */ -#define MII_MCLK 0x0004 /* MII Clock, pin MDCLK */ -#define MII_MDI 0x0002 /* MII Input, pin MDI */ -#define MII_MDO 0x0001 /* MII Output, pin MDO */ - - -/* Revision Register */ -/* BANK 3 */ -#define REV_REG 0x000A /* ( hi: chip id low: rev # ) */ - - -/* Early RCV Register */ -/* BANK 3 */ -/* this is NOT on SMC9192 */ -#define ERCV_REG 0x000C -#define ERCV_RCV_DISCRD 0x0080 /* When 1 discards a packet being received */ -#define ERCV_THRESHOLD 0x001F /* ERCV Threshold Mask */ - -/* External Register */ -/* BANK 7 */ -#define EXT_REG 0x0000 - - -#define CHIP_9192 3 -#define CHIP_9194 4 -#define CHIP_9195 5 -#define CHIP_9196 6 -#define CHIP_91100 7 -#define CHIP_91100FD 8 -#define CHIP_91111FD 9 - -#if 0 -static const char * chip_ids[ 15 ] = { - NULL, NULL, NULL, - /* 3 */ "SMC91C90/91C92", - /* 4 */ "SMC91C94", - /* 5 */ "SMC91C95", - /* 6 */ "SMC91C96", - /* 7 */ "SMC91C100", - /* 8 */ "SMC91C100FD", - /* 9 */ "SMC91C111", - NULL, NULL, - NULL, NULL, NULL}; -#endif - -/* - . Transmit status bits -*/ -#define TS_SUCCESS 0x0001 -#define TS_LOSTCAR 0x0400 -#define TS_LATCOL 0x0200 -#define TS_16COL 0x0010 - -/* - . Receive status bits -*/ -#define RS_ALGNERR 0x8000 -#define RS_BRODCAST 0x4000 -#define RS_BADCRC 0x2000 -#define RS_ODDFRAME 0x1000 /* bug: the LAN91C111 never sets this on receive */ -#define RS_TOOLONG 0x0800 -#define RS_TOOSHORT 0x0400 -#define RS_MULTICAST 0x0001 -#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) - - -/* PHY Types */ -enum { - PHY_LAN83C183 = 1, /* LAN91C111 Internal PHY */ - PHY_LAN83C180 -}; - - -/* PHY Register Addresses (LAN91C111 Internal PHY) */ - -/* PHY Control Register */ -#define PHY_CNTL_REG 0x00 -#define PHY_CNTL_RST 0x8000 /* 1=PHY Reset */ -#define PHY_CNTL_LPBK 0x4000 /* 1=PHY Loopback */ -#define PHY_CNTL_SPEED 0x2000 /* 1=100Mbps, 0=10Mpbs */ -#define PHY_CNTL_ANEG_EN 0x1000 /* 1=Enable Auto negotiation */ -#define PHY_CNTL_PDN 0x0800 /* 1=PHY Power Down mode */ -#define PHY_CNTL_MII_DIS 0x0400 /* 1=MII 4 bit interface disabled */ -#define PHY_CNTL_ANEG_RST 0x0200 /* 1=Reset Auto negotiate */ -#define PHY_CNTL_DPLX 0x0100 /* 1=Full Duplex, 0=Half Duplex */ -#define PHY_CNTL_COLTST 0x0080 /* 1= MII Colision Test */ - -/* PHY Status Register */ -#define PHY_STAT_REG 0x01 -#define PHY_STAT_CAP_T4 0x8000 /* 1=100Base-T4 capable */ -#define PHY_STAT_CAP_TXF 0x4000 /* 1=100Base-X full duplex capable */ -#define PHY_STAT_CAP_TXH 0x2000 /* 1=100Base-X half duplex capable */ -#define PHY_STAT_CAP_TF 0x1000 /* 1=10Mbps full duplex capable */ -#define PHY_STAT_CAP_TH 0x0800 /* 1=10Mbps half duplex capable */ -#define PHY_STAT_CAP_SUPR 0x0040 /* 1=recv mgmt frames with not preamble */ -#define PHY_STAT_ANEG_ACK 0x0020 /* 1=ANEG has completed */ -#define PHY_STAT_REM_FLT 0x0010 /* 1=Remote Fault detected */ -#define PHY_STAT_CAP_ANEG 0x0008 /* 1=Auto negotiate capable */ -#define PHY_STAT_LINK 0x0004 /* 1=valid link */ -#define PHY_STAT_JAB 0x0002 /* 1=10Mbps jabber condition */ -#define PHY_STAT_EXREG 0x0001 /* 1=extended registers implemented */ - -/* PHY Identifier Registers */ -#define PHY_ID1_REG 0x02 /* PHY Identifier 1 */ -#define PHY_ID2_REG 0x03 /* PHY Identifier 2 */ - -/* PHY Auto-Negotiation Advertisement Register */ -#define PHY_AD_REG 0x04 -#define PHY_AD_NP 0x8000 /* 1=PHY requests exchange of Next Page */ -#define PHY_AD_ACK 0x4000 /* 1=got link code word from remote */ -#define PHY_AD_RF 0x2000 /* 1=advertise remote fault */ -#define PHY_AD_T4 0x0200 /* 1=PHY is capable of 100Base-T4 */ -#define PHY_AD_TX_FDX 0x0100 /* 1=PHY is capable of 100Base-TX FDPLX */ -#define PHY_AD_TX_HDX 0x0080 /* 1=PHY is capable of 100Base-TX HDPLX */ -#define PHY_AD_10_FDX 0x0040 /* 1=PHY is capable of 10Base-T FDPLX */ -#define PHY_AD_10_HDX 0x0020 /* 1=PHY is capable of 10Base-T HDPLX */ -#define PHY_AD_CSMA 0x0001 /* 1=PHY is capable of 802.3 CMSA */ - -/* PHY Auto-negotiation Remote End Capability Register */ -#define PHY_RMT_REG 0x05 -/* Uses same bit definitions as PHY_AD_REG */ - -/* PHY Configuration Register 1 */ -#define PHY_CFG1_REG 0x10 -#define PHY_CFG1_LNKDIS 0x8000 /* 1=Rx Link Detect Function disabled */ -#define PHY_CFG1_XMTDIS 0x4000 /* 1=TP Transmitter Disabled */ -#define PHY_CFG1_XMTPDN 0x2000 /* 1=TP Transmitter Powered Down */ -#define PHY_CFG1_BYPSCR 0x0400 /* 1=Bypass scrambler/descrambler */ -#define PHY_CFG1_UNSCDS 0x0200 /* 1=Unscramble Idle Reception Disable */ -#define PHY_CFG1_EQLZR 0x0100 /* 1=Rx Equalizer Disabled */ -#define PHY_CFG1_CABLE 0x0080 /* 1=STP(150ohm), 0=UTP(100ohm) */ -#define PHY_CFG1_RLVL0 0x0040 /* 1=Rx Squelch level reduced by 4.5db */ -#define PHY_CFG1_TLVL_SHIFT 2 /* Transmit Output Level Adjust */ -#define PHY_CFG1_TLVL_MASK 0x003C -#define PHY_CFG1_TRF_MASK 0x0003 /* Transmitter Rise/Fall time */ - - -/* PHY Configuration Register 2 */ -#define PHY_CFG2_REG 0x11 -#define PHY_CFG2_APOLDIS 0x0020 /* 1=Auto Polarity Correction disabled */ -#define PHY_CFG2_JABDIS 0x0010 /* 1=Jabber disabled */ -#define PHY_CFG2_MREG 0x0008 /* 1=Multiple register access (MII mgt) */ -#define PHY_CFG2_INTMDIO 0x0004 /* 1=Interrupt signaled with MDIO pulseo */ - -/* PHY Status Output (and Interrupt status) Register */ -#define PHY_INT_REG 0x12 /* Status Output (Interrupt Status) */ -#define PHY_INT_INT 0x8000 /* 1=bits have changed since last read */ -#define PHY_INT_LNKFAIL 0x4000 /* 1=Link Not detected */ -#define PHY_INT_LOSSSYNC 0x2000 /* 1=Descrambler has lost sync */ -#define PHY_INT_CWRD 0x1000 /* 1=Invalid 4B5B code detected on rx */ -#define PHY_INT_SSD 0x0800 /* 1=No Start Of Stream detected on rx */ -#define PHY_INT_ESD 0x0400 /* 1=No End Of Stream detected on rx */ -#define PHY_INT_RPOL 0x0200 /* 1=Reverse Polarity detected */ -#define PHY_INT_JAB 0x0100 /* 1=Jabber detected */ -#define PHY_INT_SPDDET 0x0080 /* 1=100Base-TX mode, 0=10Base-T mode */ -#define PHY_INT_DPLXDET 0x0040 /* 1=Device in Full Duplex */ - -/* PHY Interrupt/Status Mask Register */ -#define PHY_MASK_REG 0x13 /* Interrupt Mask */ -/* Uses the same bit definitions as PHY_INT_REG */ - - -/*------------------------------------------------------------------------- - . I define some macros to make it easier to do somewhat common - . or slightly complicated, repeated tasks. - --------------------------------------------------------------------------*/ - -/* select a register bank, 0 to 3 */ - -#define SMC_SELECT_BANK(x) { SMC_outw( x, BANK_SELECT ); } - -/* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( IM_REG );\ - mask |= (x);\ - SMC_outb( mask, IM_REG ); \ -} - -/* this disables an interrupt from the interrupt mask register */ - -#define SMC_DISABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = SMC_inb( IM_REG );\ - mask &= ~(x);\ - SMC_outb( mask, IM_REG ); \ -} - -/*---------------------------------------------------------------------- - . Define the interrupts that I want to receive from the card - . - . I want: - . IM_EPH_INT, for nasty errors - . IM_RCV_INT, for happy received packets - . IM_RX_OVRN_INT, because I have to kick the receiver - . IM_MDINT, for PHY Register 18 Status Changes - --------------------------------------------------------------------------*/ -#define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \ - IM_MDINT) - -#endif /* _SMC_91111_H_ */ diff --git a/drivers/tigon3.c b/drivers/tigon3.c deleted file mode 100644 index 5f6a4ecd0a..0000000000 --- a/drivers/tigon3.c +++ /dev/null @@ -1,5699 +0,0 @@ -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/******************************************************************************/ -#include -#include -#if defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_TIGON3) -#ifdef CONFIG_BMW -#include -#endif -#include -#include -#include "bcm570x_mm.h" - -#define EMBEDDED 1 -/******************************************************************************/ -/* Local functions. */ -/******************************************************************************/ - -LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice); -LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice); - -static LM_STATUS LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE - RequestedMediaType, - PLM_MEDIA_TYPE pMediaType, - PLM_LINE_SPEED pLineSpeed, - PLM_DUPLEX_MODE pDuplexMode); - -static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice); - -__inline static LM_VOID LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice); -__inline static LM_VOID LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice); - -static LM_STATUS LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, - LM_REQUESTED_MEDIA_TYPE - RequestedMediaType); -static LM_STATUS LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, - LM_REQUESTED_MEDIA_TYPE RequestedMediaType); -static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice); -STATIC LM_STATUS LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, - LM_UINT32 LocalPhyAd, - LM_UINT32 RemotePhyAd); -#if INCLUDE_TBI_SUPPORT -STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice); -STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice); -#endif -STATIC LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice); -STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, - LM_UINT16 Ssid); -STATIC LM_STATUS LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, - LM_PHYSICAL_ADDRESS BufferPhy, - LM_UINT32 BufferSize); -STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number); -STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice); -STATIC LM_STATUS LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, - PLM_PACKET pPacket, PT3_SND_BD pSendBd); - -/******************************************************************************/ -/* External functions. */ -/******************************************************************************/ - -LM_STATUS LM_LoadRlsFirmware (PLM_DEVICE_BLOCK pDevice); - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register) -{ - LM_UINT32 Value32; - -#if PCIX_TARGET_WORKAROUND - MM_ACQUIRE_UNDI_LOCK (pDevice); -#endif - MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); - MM_ReadConfig32 (pDevice, T3_PCI_REG_DATA_REG, &Value32); -#if PCIX_TARGET_WORKAROUND - MM_RELEASE_UNDI_LOCK (pDevice); -#endif - - return Value32; -} /* LM_RegRdInd */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_VOID -LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, LM_UINT32 Value32) -{ - -#if PCIX_TARGET_WORKAROUND - MM_ACQUIRE_UNDI_LOCK (pDevice); -#endif - MM_WriteConfig32 (pDevice, T3_PCI_REG_ADDR_REG, Register); - MM_WriteConfig32 (pDevice, T3_PCI_REG_DATA_REG, Value32); -#if PCIX_TARGET_WORKAROUND - MM_RELEASE_UNDI_LOCK (pDevice); -#endif -} /* LM_RegWrInd */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr) -{ - LM_UINT32 Value32; - - MM_ACQUIRE_UNDI_LOCK (pDevice); -#ifdef BIG_ENDIAN_HOST - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); - Value32 = REG_RD (pDevice, PciCfg.MemWindowData); - /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */ -#else - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); - MM_ReadConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32); -#endif - MM_RELEASE_UNDI_LOCK (pDevice); - - return Value32; -} /* LM_MemRdInd */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_VOID -LM_MemWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, LM_UINT32 Value32) -{ - MM_ACQUIRE_UNDI_LOCK (pDevice); -#ifdef BIG_ENDIAN_HOST - REG_WR (pDevice, PciCfg.MemWindowBaseAddr, MemAddr); - REG_WR (pDevice, uIntMem.Mbuf[(MemAddr & 0x7fff) / 4], Value32); -#else - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32); -#endif - MM_RELEASE_UNDI_LOCK (pDevice); -} /* LM_MemWrInd */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_QueueRxPackets (PLM_DEVICE_BLOCK pDevice) -{ - LM_STATUS Lmstatus; - PLM_PACKET pPacket; - PT3_RCV_BD pRcvBd; - LM_UINT32 StdBdAdded = 0; -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - LM_UINT32 JumboBdAdded = 0; -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - Lmstatus = LM_STATUS_SUCCESS; - - pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); - while (pPacket) { - switch (pPacket->u.Rx.RcvProdRing) { -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - case T3_JUMBO_RCV_PROD_RING: /* Jumbo Receive Ring. */ - /* Initialize the buffer descriptor. */ - pRcvBd = - &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx]; - pRcvBd->Flags = - RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING; - pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize; - - /* Initialize the receive buffer pointer */ -#if 0 /* Jimmy, deleted in new */ - pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; - pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; -#endif - MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); - - /* The opaque field may point to an offset from a fix addr. */ - pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - - MM_UINT_PTR (pDevice-> - pPacketDescBase)); - - /* Update the producer index. */ - pDevice->RxJumboProdIdx = - (pDevice->RxJumboProdIdx + - 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; - - JumboBdAdded++; - break; -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - case T3_STD_RCV_PROD_RING: /* Standard Receive Ring. */ - /* Initialize the buffer descriptor. */ - pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx]; - pRcvBd->Flags = RCV_BD_FLAG_END; - pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE; - - /* Initialize the receive buffer pointer */ -#if 0 /* Jimmy, deleted in new replaced with MM_MapRxDma */ - pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; - pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; -#endif - MM_MapRxDma (pDevice, pPacket, &pRcvBd->HostAddr); - - /* The opaque field may point to an offset from a fix addr. */ - pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR (pPacket) - - MM_UINT_PTR (pDevice-> - pPacketDescBase)); - - /* Update the producer index. */ - pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & - T3_STD_RCV_RCB_ENTRY_COUNT_MASK; - - StdBdAdded++; - break; - - case T3_UNKNOWN_RCV_PROD_RING: - default: - Lmstatus = LM_STATUS_FAILURE; - break; - } /* switch */ - - /* Bail out if there is any error. */ - if (Lmstatus != LM_STATUS_SUCCESS) { - break; - } - - pPacket = - (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); - } /* while */ - - wmb (); - /* Update the procedure index. */ - if (StdBdAdded) { - MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, - pDevice->RxStdProdIdx); - } -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - if (JumboBdAdded) { - MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, - pDevice->RxJumboProdIdx); - } -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - return Lmstatus; -} /* LM_QueueRxPackets */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -STATIC LM_VOID LM_NvramInit (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - LM_UINT32 j; - - /* Intialize clock period and state machine. */ - Value32 = SEEPROM_ADDR_CLK_PERD (SEEPROM_CLOCK_PERIOD) | - SEEPROM_ADDR_FSM_RESET; - REG_WR (pDevice, Grc.EepromAddr, Value32); - - for (j = 0; j < 100; j++) { - MM_Wait (10); - } - - /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */ - Value32 = REG_RD (pDevice, Grc.LocalCtrl); - REG_WR (pDevice, Grc.LocalCtrl, - Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM); - - /* Set the 5701 compatibility mode if we are using EEPROM. */ - if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && - T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { - Value32 = REG_RD (pDevice, Nvram.Config1); - if ((Value32 & FLASH_INTERFACE_ENABLE) == 0) { - /* Use the new interface to read EEPROM. */ - Value32 &= ~FLASH_COMPAT_BYPASS; - - REG_WR (pDevice, Nvram.Config1, Value32); - } - } -} /* LM_NvRamInit */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -STATIC LM_STATUS -LM_EepromRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) -{ - LM_UINT32 Value32; - LM_UINT32 Addr; - LM_UINT32 Dev; - LM_UINT32 j; - - if (Offset > SEEPROM_CHIP_SIZE) { - return LM_STATUS_FAILURE; - } - - Dev = Offset / SEEPROM_CHIP_SIZE; - Addr = Offset % SEEPROM_CHIP_SIZE; - - Value32 = REG_RD (pDevice, Grc.EepromAddr); - Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK | - SEEPROM_ADDR_RW_MASK); - REG_WR (pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID (Dev) | - SEEPROM_ADDR_ADDRESS (Addr) | SEEPROM_ADDR_START | - SEEPROM_ADDR_READ); - - for (j = 0; j < 1000; j++) { - Value32 = REG_RD (pDevice, Grc.EepromAddr); - if (Value32 & SEEPROM_ADDR_COMPLETE) { - break; - } - MM_Wait (10); - } - - if (Value32 & SEEPROM_ADDR_COMPLETE) { - Value32 = REG_RD (pDevice, Grc.EepromData); - *pData = Value32; - - return LM_STATUS_SUCCESS; - } - - return LM_STATUS_FAILURE; -} /* LM_EepromRead */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -STATIC LM_STATUS -LM_NvramRead (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, LM_UINT32 * pData) -{ - LM_UINT32 Value32; - LM_STATUS Status; - LM_UINT32 j; - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Status = LM_EepromRead (pDevice, Offset, pData); - } else { - /* Determine if we have flash or EEPROM. */ - Value32 = REG_RD (pDevice, Nvram.Config1); - if (Value32 & FLASH_INTERFACE_ENABLE) { - if (Value32 & FLASH_SSRAM_BUFFERRED_MODE) { - Offset = ((Offset / BUFFERED_FLASH_PAGE_SIZE) << - BUFFERED_FLASH_PAGE_POS) + - (Offset % BUFFERED_FLASH_PAGE_SIZE); - } - } - - REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); - for (j = 0; j < 1000; j++) { - if (REG_RD (pDevice, Nvram.SwArb) & SW_ARB_GNT1) { - break; - } - MM_Wait (20); - } - if (j == 1000) { - return LM_STATUS_FAILURE; - } - - /* Read from flash or EEPROM with the new 5703/02 interface. */ - REG_WR (pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK); - - REG_WR (pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT | - NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); - - /* Wait for the done bit to clear. */ - for (j = 0; j < 500; j++) { - MM_Wait (10); - - Value32 = REG_RD (pDevice, Nvram.Cmd); - if (!(Value32 & NVRAM_CMD_DONE)) { - break; - } - } - - /* Wait for the done bit. */ - if (!(Value32 & NVRAM_CMD_DONE)) { - for (j = 0; j < 500; j++) { - MM_Wait (10); - - Value32 = REG_RD (pDevice, Nvram.Cmd); - if (Value32 & NVRAM_CMD_DONE) { - MM_Wait (10); - - *pData = - REG_RD (pDevice, Nvram.ReadData); - - /* Change the endianess. */ - *pData = - ((*pData & 0xff) << 24) | - ((*pData & 0xff00) << 8) | - ((*pData & 0xff0000) >> 8) | - ((*pData >> 24) & 0xff); - - break; - } - } - } - - REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1); - if (Value32 & NVRAM_CMD_DONE) { - Status = LM_STATUS_SUCCESS; - } else { - Status = LM_STATUS_FAILURE; - } - } - - return Status; -} /* LM_NvramRead */ - -STATIC void LM_ReadVPD (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Vpd_arr[256 / 4]; - LM_UINT8 *Vpd = (LM_UINT8 *) & Vpd_arr[0]; - LM_UINT32 *Vpd_dptr = &Vpd_arr[0]; - LM_UINT32 Value32; - unsigned int j; - - /* Read PN from VPD */ - for (j = 0; j < 256; j += 4, Vpd_dptr++) { - if (LM_NvramRead (pDevice, 0x100 + j, &Value32) != - LM_STATUS_SUCCESS) { - printf ("BCM570x: LM_ReadVPD: VPD read failed" - " (no EEPROM onboard)\n"); - return; - } - *Vpd_dptr = cpu_to_le32 (Value32); - } - for (j = 0; j < 256;) { - unsigned int Vpd_r_len; - unsigned int Vpd_r_end; - - if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91)) { - j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8); - } else if (Vpd[j] == 0x90) { - Vpd_r_len = Vpd[j + 1] + (Vpd[j + 2] << 8); - j += 3; - Vpd_r_end = Vpd_r_len + j; - while (j < Vpd_r_end) { - if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N')) { - unsigned int len = Vpd[j + 2]; - - if (len <= 24) { - memcpy (pDevice->PartNo, - &Vpd[j + 3], len); - } - break; - } else { - if (Vpd[j + 2] == 0) { - break; - } - j = j + Vpd[j + 2]; - } - } - break; - } else { - break; - } - } -} - -STATIC void LM_ReadBootCodeVersion (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32, offset, ver_offset; - int i; - - if (LM_NvramRead (pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS) - return; - if (Value32 != 0xaa559966) - return; - if (LM_NvramRead (pDevice, 0xc, &offset) != LM_STATUS_SUCCESS) - return; - - offset = ((offset & 0xff) << 24) | ((offset & 0xff00) << 8) | - ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff); - if (LM_NvramRead (pDevice, offset, &Value32) != LM_STATUS_SUCCESS) - return; - if ((Value32 == 0x0300000e) && - (LM_NvramRead (pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) - && (Value32 == 0)) { - - if (LM_NvramRead (pDevice, offset + 8, &ver_offset) != - LM_STATUS_SUCCESS) - return; - ver_offset = ((ver_offset & 0xff0000) >> 8) | - ((ver_offset >> 24) & 0xff); - for (i = 0; i < 16; i += 4) { - if (LM_NvramRead - (pDevice, offset + ver_offset + i, - &Value32) != LM_STATUS_SUCCESS) { - return; - } - *((LM_UINT32 *) & pDevice->BootCodeVer[i]) = - cpu_to_le32 (Value32); - } - } else { - char c; - - if (LM_NvramRead (pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS) - return; - - i = 0; - c = ((Value32 & 0xff0000) >> 16); - - if (c < 10) { - pDevice->BootCodeVer[i++] = c + '0'; - } else { - pDevice->BootCodeVer[i++] = (c / 10) + '0'; - pDevice->BootCodeVer[i++] = (c % 10) + '0'; - } - pDevice->BootCodeVer[i++] = '.'; - c = (Value32 & 0xff000000) >> 24; - if (c < 10) { - pDevice->BootCodeVer[i++] = c + '0'; - } else { - pDevice->BootCodeVer[i++] = (c / 10) + '0'; - pDevice->BootCodeVer[i++] = (c % 10) + '0'; - } - pDevice->BootCodeVer[i] = 0; - } -} - -STATIC void LM_GetBusSpeed (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 PciState = pDevice->PciState; - LM_UINT32 ClockCtrl; - char *SpeedStr = ""; - - if (PciState & T3_PCI_STATE_32BIT_PCI_BUS) { - strcpy (pDevice->BusSpeedStr, "32-bit "); - } else { - strcpy (pDevice->BusSpeedStr, "64-bit "); - } - if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) { - strcat (pDevice->BusSpeedStr, "PCI "); - if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) { - SpeedStr = "66MHz"; - } else { - SpeedStr = "33MHz"; - } - } else { - strcat (pDevice->BusSpeedStr, "PCIX "); - if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE) { - SpeedStr = "133MHz"; - } else { - ClockCtrl = REG_RD (pDevice, PciCfg.ClockCtrl) & 0x1f; - switch (ClockCtrl) { - case 0: - SpeedStr = "33MHz"; - break; - - case 2: - SpeedStr = "50MHz"; - break; - - case 4: - SpeedStr = "66MHz"; - break; - - case 6: - SpeedStr = "100MHz"; - break; - - case 7: - SpeedStr = "133MHz"; - break; - } - } - } - strcat (pDevice->BusSpeedStr, SpeedStr); -} - -/******************************************************************************/ -/* Description: */ -/* This routine initializes default parameters and reads the PCI */ -/* configurations. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_GetAdapterInfo (PLM_DEVICE_BLOCK pDevice) -{ - PLM_ADAPTER_INFO pAdapterInfo; - LM_UINT32 Value32; - LM_STATUS Status; - LM_UINT32 j; - LM_UINT32 EeSigFound; - LM_UINT32 EePhyTypeSerdes = 0; - LM_UINT32 EePhyLedMode = 0; - LM_UINT32 EePhyId = 0; - - /* Get Device Id and Vendor Id */ - Status = MM_ReadConfig32 (pDevice, PCI_VENDOR_ID_REG, &Value32); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - pDevice->PciVendorId = (LM_UINT16) Value32; - pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16); - - /* If we are not getting the write adapter, exit. */ - if ((Value32 != T3_PCI_ID_BCM5700) && - (Value32 != T3_PCI_ID_BCM5701) && - (Value32 != T3_PCI_ID_BCM5702) && - (Value32 != T3_PCI_ID_BCM5702x) && - (Value32 != T3_PCI_ID_BCM5702FE) && - (Value32 != T3_PCI_ID_BCM5703) && - (Value32 != T3_PCI_ID_BCM5703x) && (Value32 != T3_PCI_ID_BCM5704)) { - return LM_STATUS_FAILURE; - } - - Status = MM_ReadConfig32 (pDevice, PCI_REV_ID_REG, &Value32); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - pDevice->PciRevId = (LM_UINT8) Value32; - - /* Get IRQ. */ - Status = MM_ReadConfig32 (pDevice, PCI_INT_LINE_REG, &Value32); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - pDevice->Irq = (LM_UINT8) Value32; - - /* Get interrupt pin. */ - pDevice->IntPin = (LM_UINT8) (Value32 >> 8); - - /* Get chip revision id. */ - Status = MM_ReadConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32); - pDevice->ChipRevId = Value32 >> 16; - - /* Get subsystem vendor. */ - Status = - MM_ReadConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - pDevice->SubsystemVendorId = (LM_UINT16) Value32; - - /* Get PCI subsystem id. */ - pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16); - - /* Get the cache line size. */ - MM_ReadConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32); - pDevice->CacheLineSize = (LM_UINT8) Value32; - pDevice->SavedCacheLineReg = Value32; - - if (pDevice->ChipRevId != T3_CHIP_ID_5703_A1 && - pDevice->ChipRevId != T3_CHIP_ID_5703_A2 && - pDevice->ChipRevId != T3_CHIP_ID_5704_A0) { - pDevice->UndiFix = FALSE; - } -#if !PCIX_TARGET_WORKAROUND - pDevice->UndiFix = FALSE; -#endif - /* Map the memory base to system address space. */ - if (!pDevice->UndiFix) { - Status = MM_MapMemBase (pDevice); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - /* Initialize the memory view pointer. */ - pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase; - } -#if PCIX_TARGET_WORKAROUND - /* store whether we are in PCI are PCI-X mode */ - pDevice->EnablePciXFix = FALSE; - - MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); - if ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0) { - /* Enable PCI-X workaround only if we are running on 5700 BX. */ - if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { - pDevice->EnablePciXFix = TRUE; - } - } - if (pDevice->UndiFix) { - pDevice->EnablePciXFix = TRUE; - } -#endif - /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */ - /* management register may be clobbered which may cause the */ - /* BCM5700 to go into D3 state. While in this state, we will */ - /* not have memory mapped register access. As a workaround, we */ - /* need to restore the device to D0 state. */ - MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32); - Value32 |= T3_PM_PME_ASSERTED; - Value32 &= ~T3_PM_POWER_STATE_MASK; - Value32 |= T3_PM_POWER_STATE_D0; - MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32); - - /* read the current PCI command word */ - MM_ReadConfig32 (pDevice, PCI_COMMAND_REG, &Value32); - - /* Make sure bus-mastering is enabled. */ - Value32 |= PCI_BUSMASTER_ENABLE; - -#if PCIX_TARGET_WORKAROUND - /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR# - are enabled */ - if (pDevice->EnablePciXFix == TRUE) { - Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | - PCI_PARITY_ERROR_ENABLE); - } - if (pDevice->UndiFix) { - Value32 &= ~PCI_MEM_SPACE_ENABLE; - } -#endif - - if (pDevice->EnableMWI) { - Value32 |= PCI_MEMORY_WRITE_INVALIDATE; - } else { - Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE); - } - - /* Error out if mem-mapping is NOT enabled for PCI systems */ - if (!(Value32 | PCI_MEM_SPACE_ENABLE)) { - return LM_STATUS_FAILURE; - } - - /* save the value we are going to write into the PCI command word */ - pDevice->PciCommandStatusWords = Value32; - - Status = MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, Value32); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - - /* Set power state to D0. */ - LM_SetPowerState (pDevice, LM_POWER_STATE_D0); - -#ifdef BIG_ENDIAN_PCI - pDevice->MiscHostCtrl = - MISC_HOST_CTRL_MASK_PCI_INT | - MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | - MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | - MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; -#else /* No CPU Swap modes for PCI IO */ - - /* Setup the mode registers. */ - pDevice->MiscHostCtrl = - MISC_HOST_CTRL_MASK_PCI_INT | - MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | -#ifdef BIG_ENDIAN_HOST - MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP | -#endif /* BIG_ENDIAN_HOST */ - MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | - MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; -#endif /* !BIG_ENDIAN_PCI */ - - /* write to PCI misc host ctr first in order to enable indirect accesses */ - MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, - pDevice->MiscHostCtrl); - - REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl); - -#ifdef BIG_ENDIAN_PCI - Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; -#else -/* No CPU Swap modes for PCI IO */ -#ifdef BIG_ENDIAN_HOST - Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | - GRC_MODE_WORD_SWAP_NON_FRAME_DATA; -#else - Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; -#endif -#endif /* !BIG_ENDIAN_PCI */ - - REG_WR (pDevice, Grc.Mode, Value32); - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - REG_WR (pDevice, Grc.LocalCtrl, - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | - GRC_MISC_LOCAL_CTRL_GPIO_OE1); - } - MM_Wait (40); - - /* Enable indirect memory access */ - REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); - - if (REG_RD (pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK) { - REG_WR (pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK | - T3_PCI_SELECT_ALTERNATE_CLOCK); - REG_WR (pDevice, PciCfg.ClockCtrl, - T3_PCI_SELECT_ALTERNATE_CLOCK); - MM_Wait (40); /* required delay is 27usec */ - } - REG_WR (pDevice, PciCfg.ClockCtrl, 0); - REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); - -#if PCIX_TARGET_WORKAROUND - MM_ReadConfig32 (pDevice, T3_PCI_STATE_REG, &Value32); - if ((pDevice->EnablePciXFix == FALSE) && - ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)) { - if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B2 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B5) { - __raw_writel (0, - &(pDevice->pMemView->uIntMem. - MemBlock32K[0x300])); - __raw_writel (0, - &(pDevice->pMemView->uIntMem. - MemBlock32K[0x301])); - __raw_writel (0xffffffff, - &(pDevice->pMemView->uIntMem. - MemBlock32K[0x301])); - if (__raw_readl - (&(pDevice->pMemView->uIntMem.MemBlock32K[0x300]))) - { - pDevice->EnablePciXFix = TRUE; - } - } - } -#endif -#if 1 - /* - * This code was at the beginning of else block below, but that's - * a bug if node address in shared memory. - */ - MM_Wait (50); - LM_NvramInit (pDevice); -#endif - /* Get the node address. First try to get in from the shared memory. */ - /* If the signature is not present, then get it from the NVRAM. */ - Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_HIGH_MAILBOX); - if ((Value32 >> 16) == 0x484b) { - - pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8); - pDevice->NodeAddress[1] = (LM_UINT8) Value32; - - Value32 = MEM_RD_OFFSET (pDevice, T3_MAC_ADDR_LOW_MAILBOX); - - pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24); - pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16); - pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8); - pDevice->NodeAddress[5] = (LM_UINT8) Value32; - - Status = LM_STATUS_SUCCESS; - } else { - Status = LM_NvramRead (pDevice, 0x7c, &Value32); - if (Status == LM_STATUS_SUCCESS) { - pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16); - pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24); - - Status = LM_NvramRead (pDevice, 0x80, &Value32); - - pDevice->NodeAddress[2] = (LM_UINT8) Value32; - pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8); - pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16); - pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24); - } - } - - /* Assign a default address. */ - if (Status != LM_STATUS_SUCCESS) { -#ifndef EMBEDDED - printk (KERN_ERR - "Cannot get MAC addr from NVRAM. Using default.\n"); -#endif - pDevice->NodeAddress[0] = 0x00; - pDevice->NodeAddress[1] = 0x10; - pDevice->NodeAddress[2] = 0x18; - pDevice->NodeAddress[3] = 0x68; - pDevice->NodeAddress[4] = 0x61; - pDevice->NodeAddress[5] = 0x76; - } - - pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0]; - pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1]; - pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2]; - pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3]; - pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4]; - pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5]; - - /* Initialize the default values. */ - pDevice->NoTxPseudoHdrChksum = FALSE; - pDevice->NoRxPseudoHdrChksum = FALSE; - pDevice->NicSendBd = FALSE; - pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT; - pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT; - pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS; - pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS; - pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES; - pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES; - pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; - pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; - pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; - pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; - pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS; - pDevice->EnableMWI = FALSE; - pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; - pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; - pDevice->DisableAutoNeg = FALSE; - pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO; - pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO; - pDevice->LedMode = LED_MODE_AUTO; - pDevice->ResetPhyOnInit = TRUE; - pDevice->DelayPciGrant = TRUE; - pDevice->UseTaggedStatus = FALSE; - pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE; - - pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO; - pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO; - pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO; - - pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; - pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE; - pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE; - pDevice->EnableTbi = FALSE; -#if INCLUDE_TBI_SUPPORT - pDevice->PollTbiLink = BAD_DEFAULT_VALUE; -#endif - - switch (T3_ASIC_REV (pDevice->ChipRevId)) { - case T3_ASIC_REV_5704: - pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; - pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64; - break; - default: - pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; - pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96; - break; - } - - pDevice->LinkStatus = LM_STATUS_LINK_DOWN; - pDevice->QueueRxPackets = TRUE; - - pDevice->EnableWireSpeed = TRUE; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - /* Make this is a known adapter. */ - pAdapterInfo = LM_GetAdapterInfoBySsid (pDevice->SubsystemVendorId, - pDevice->SubsystemId); - - pDevice->BondId = REG_RD (pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK; - if (pDevice->BondId != GRC_MISC_BD_ID_5700 && - pDevice->BondId != GRC_MISC_BD_ID_5701 && - pDevice->BondId != GRC_MISC_BD_ID_5702FE && - pDevice->BondId != GRC_MISC_BD_ID_5703 && - pDevice->BondId != GRC_MISC_BD_ID_5703S && - pDevice->BondId != GRC_MISC_BD_ID_5704 && - pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE) { - return LM_STATUS_UNKNOWN_ADAPTER; - } - - pDevice->SplitModeEnable = SPLIT_MODE_DISABLE; - if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) && - (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)) { - pDevice->SplitModeEnable = SPLIT_MODE_ENABLE; - pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ; - } - - /* Get Eeprom info. */ - Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_SIG_ADDR); - if (Value32 == T3_NIC_DATA_SIG) { - EeSigFound = TRUE; - Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_NIC_CFG_ADDR); - - /* Determine PHY type. */ - switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK) { - case T3_NIC_CFG_PHY_TYPE_COPPER: - EePhyTypeSerdes = FALSE; - break; - - case T3_NIC_CFG_PHY_TYPE_FIBER: - EePhyTypeSerdes = TRUE; - break; - - default: - EePhyTypeSerdes = FALSE; - break; - } - - /* Determine PHY led mode. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { - case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED: - EePhyLedMode = LED_MODE_THREE_LINK; - break; - - case T3_NIC_CFG_LED_MODE_LINK_SPEED: - EePhyLedMode = LED_MODE_LINK10; - break; - - default: - EePhyLedMode = LED_MODE_AUTO; - break; - } - } else { - switch (Value32 & T3_NIC_CFG_LED_MODE_MASK) { - case T3_NIC_CFG_LED_MODE_OPEN_DRAIN: - EePhyLedMode = LED_MODE_OPEN_DRAIN; - break; - - case T3_NIC_CFG_LED_MODE_OUTPUT: - EePhyLedMode = LED_MODE_OUTPUT; - break; - - default: - EePhyLedMode = LED_MODE_AUTO; - break; - } - } - if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || - pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { - /* Enable EEPROM write protection. */ - if (Value32 & T3_NIC_EEPROM_WP) { - pDevice->EepromWp = TRUE; - } - } - - /* Get the PHY Id. */ - Value32 = MEM_RD_OFFSET (pDevice, T3_NIC_DATA_PHY_ID_ADDR); - if (Value32) { - EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) & - PHY_ID1_OUI_MASK) << 10; - - Value32 = Value32 & T3_NIC_PHY_ID2_MASK; - - EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | - (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & - PHY_ID2_REV_MASK); - } else { - EePhyId = 0; - } - } else { - EeSigFound = FALSE; - } - - /* Set the PHY address. */ - pDevice->PhyAddr = PHY_DEVICE_ID; - - /* Disable auto polling. */ - pDevice->MiMode = 0xc0000; - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - MM_Wait (40); - - /* Get the PHY id. */ - LM_ReadPhy (pDevice, PHY_ID1_REG, &Value32); - pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10; - - LM_ReadPhy (pDevice, PHY_ID2_REG, &Value32); - pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | - (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK); - - /* Set the EnableTbi flag to false if we have a copper PHY. */ - switch (pDevice->PhyId & PHY_ID_MASK) { - case PHY_BCM5400_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM5401_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM5411_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM5701_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM5703_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM5704_PHY_ID: - pDevice->EnableTbi = FALSE; - break; - - case PHY_BCM8002_PHY_ID: - pDevice->EnableTbi = TRUE; - break; - - default: - - if (pAdapterInfo) { - pDevice->PhyId = pAdapterInfo->PhyId; - pDevice->EnableTbi = pAdapterInfo->Serdes; - } else if (EeSigFound) { - pDevice->PhyId = EePhyId; - pDevice->EnableTbi = EePhyTypeSerdes; - } - break; - } - - /* Bail out if we don't know the copper PHY id. */ - if (UNKNOWN_PHY_ID (pDevice->PhyId) && !pDevice->EnableTbi) { - return LM_STATUS_FAILURE; - } - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { - if ((pDevice->SavedCacheLineReg & 0xff00) < 0x4000) { - pDevice->SavedCacheLineReg &= 0xffff00ff; - pDevice->SavedCacheLineReg |= 0x4000; - } - } - /* Change driver parameters. */ - Status = MM_GetConfig (pDevice); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } -#if INCLUDE_5701_AX_FIX - if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { - pDevice->ResetPhyOnInit = TRUE; - } -#endif - - /* Save the current phy link status. */ - if (!pDevice->EnableTbi) { - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - - /* If we don't have link reset the PHY. */ - if (!(Value32 & PHY_STATUS_LINK_PASS) - || pDevice->ResetPhyOnInit) { - - LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); - - for (j = 0; j < 100; j++) { - MM_Wait (10); - - LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); - if (Value32 && !(Value32 & PHY_CTRL_PHY_RESET)) { - MM_Wait (40); - break; - } - } - -#if INCLUDE_5701_AX_FIX - /* 5701_AX_BX bug: only advertises 10mb speed. */ - if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { - - Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | - PHY_AN_AD_10BASET_HALF | - PHY_AN_AD_10BASET_FULL | - PHY_AN_AD_100BASETX_FULL | - PHY_AN_AD_100BASETX_HALF; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - - Value32 = BCM540X_AN_AD_1000BASET_HALF | - BCM540X_AN_AD_1000BASET_FULL | - BCM540X_CONFIG_AS_MASTER | - BCM540X_ENABLE_CONFIG_AS_MASTER; - LM_WritePhy (pDevice, - BCM540X_1000BASET_CTRL_REG, - Value32); - pDevice->advertising1000 = Value32; - - LM_WritePhy (pDevice, PHY_CTRL_REG, - PHY_CTRL_AUTO_NEG_ENABLE | - PHY_CTRL_RESTART_AUTO_NEG); - } -#endif - if (T3_ASIC_REV (pDevice->ChipRevId) == - T3_ASIC_REV_5703) { - LM_WritePhy (pDevice, 0x18, 0x0c00); - LM_WritePhy (pDevice, 0x17, 0x201f); - LM_WritePhy (pDevice, 0x15, 0x2aaa); - } - if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { - LM_WritePhy (pDevice, 0x1c, 0x8d68); - LM_WritePhy (pDevice, 0x1c, 0x8d68); - } - /* Enable Ethernet@WireSpeed. */ - if (pDevice->EnableWireSpeed) { - LM_WritePhy (pDevice, 0x18, 0x7007); - LM_ReadPhy (pDevice, 0x18, &Value32); - LM_WritePhy (pDevice, 0x18, - Value32 | BIT_15 | BIT_4); - } - } - } - - /* Turn off tap power management. */ - if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); - - MM_Wait (40); - } -#if INCLUDE_TBI_SUPPORT - pDevice->IgnoreTbiLinkChange = FALSE; - - if (pDevice->EnableTbi) { - pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; - pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; - if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) || - pDevice->DisableAutoNeg) { - pDevice->PollTbiLink = FALSE; - } - } else { - pDevice->PollTbiLink = FALSE; - } -#endif /* INCLUDE_TBI_SUPPORT */ - - /* UseTaggedStatus is only valid for 5701 and later. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->UseTaggedStatus = FALSE; - - pDevice->CoalesceMode = 0; - } else { - pDevice->CoalesceMode = - HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT | - HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT; - } - - /* Set the status block size. */ - if (T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_AX && - T3_CHIP_REV (pDevice->ChipRevId) != T3_CHIP_REV_5700_BX) { - pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE; - } - - /* Check the DURING_INT coalescing ticks parameters. */ - if (pDevice->UseTaggedStatus) { - if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { - pDevice->RxCoalescingTicksDuringInt = - DEFAULT_RX_COALESCING_TICKS_DURING_INT; - } - - if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { - pDevice->TxCoalescingTicksDuringInt = - DEFAULT_TX_COALESCING_TICKS_DURING_INT; - } - - if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { - pDevice->RxMaxCoalescedFramesDuringInt = - DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT; - } - - if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { - pDevice->TxMaxCoalescedFramesDuringInt = - DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT; - } - } else { - if (pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { - pDevice->RxCoalescingTicksDuringInt = 0; - } - - if (pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) { - pDevice->TxCoalescingTicksDuringInt = 0; - } - - if (pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { - pDevice->RxMaxCoalescedFramesDuringInt = 0; - } - - if (pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) { - pDevice->TxMaxCoalescedFramesDuringInt = 0; - } - } - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - if (pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */ )) { - pDevice->RxJumboDescCnt = 0; - if (pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC) { - pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; - } - } else { - pDevice->RxJumboBufferSize = - (pDevice->RxMtu + 8 /* CRC + VLAN */ + - COMMON_CACHE_LINE_SIZE - 1) & ~COMMON_CACHE_LINE_MASK; - - if (pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE) { - pDevice->RxJumboBufferSize = - DEFAULT_JUMBO_RCV_BUFFER_SIZE; - pDevice->RxMtu = - pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */ ; - } - pDevice->TxMtu = pDevice->RxMtu; - - } -#else - pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - pDevice->RxPacketDescCnt = -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - pDevice->RxJumboDescCnt + -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - pDevice->RxStdDescCnt; - - if (pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC) { - pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; - } - - if (pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE) { - pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE; - } - - /* Configure the proper ways to get link change interrupt. */ - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO) { - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; - } else { - pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; - } - } else if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - /* Auto-polling does not work on 5700_AX and 5700_BX. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; - } - } - - /* Determine the method to get link change status. */ - if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO) { - /* The link status bit in the status block does not work on 5700_AX */ - /* and 5700_BX chips. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->LinkChngMode = - T3_LINK_CHNG_MODE_USE_STATUS_REG; - } else { - pDevice->LinkChngMode = - T3_LINK_CHNG_MODE_USE_STATUS_BLOCK; - } - } - - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; - } - - /* Configure PHY led mode. */ - if (pDevice->LedMode == LED_MODE_AUTO) { - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - if (pDevice->SubsystemVendorId == T3_SVID_DELL) { - pDevice->LedMode = LED_MODE_LINK10; - } else { - pDevice->LedMode = LED_MODE_THREE_LINK; - - if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { - pDevice->LedMode = EePhyLedMode; - } - } - - /* bug? 5701 in LINK10 mode does not seem to work when */ - /* PhyIntMode is LINK_READY. */ - if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 - && -#if INCLUDE_TBI_SUPPORT - pDevice->EnableTbi == FALSE && -#endif - pDevice->LedMode == LED_MODE_LINK10) { - pDevice->PhyIntMode = - T3_PHY_INT_MODE_MI_INTERRUPT; - pDevice->LinkChngMode = - T3_LINK_CHNG_MODE_USE_STATUS_REG; - } - - if (pDevice->EnableTbi) { - pDevice->LedMode = LED_MODE_THREE_LINK; - } - } else { - if (EeSigFound && EePhyLedMode != LED_MODE_AUTO) { - pDevice->LedMode = EePhyLedMode; - } else { - pDevice->LedMode = LED_MODE_OPEN_DRAIN; - } - } - } - - /* Enable OneDmaAtOnce. */ - if (pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE) { - pDevice->OneDmaAtOnce = FALSE; - } - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B2) { - pDevice->WolSpeed = WOL_SPEED_10MB; - } else { - pDevice->WolSpeed = WOL_SPEED_100MB; - } - - /* Offloadings. */ - pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; - - /* Turn off task offloading on Ax. */ - if (pDevice->ChipRevId == T3_CHIP_ID_5700_B0) { - pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | - LM_TASK_OFFLOAD_TX_UDP_CHECKSUM); - } - pDevice->PciState = REG_RD (pDevice, PciCfg.PciState); - LM_ReadVPD (pDevice); - LM_ReadBootCodeVersion (pDevice); - LM_GetBusSpeed (pDevice); - - return LM_STATUS_SUCCESS; -} /* LM_GetAdapterInfo */ - -STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid (LM_UINT16 Svid, LM_UINT16 Ssid) -{ - static LM_ADAPTER_INFO AdapterArr[] = { - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, - PHY_BCM5401_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, - PHY_BCM8002_PHY_ID, 1}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, - PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, - PHY_BCM5701_PHY_ID, 0}, - - {T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0}, - {T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1}, - {T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0}, - - {T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0}, - {T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0}, - {T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0}, - {T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0}, - - {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, - 0}, - {T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1}, - {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0}, - {T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, - 0}, - - }; - LM_UINT32 j; - - for (j = 0; j < sizeof (AdapterArr) / sizeof (LM_ADAPTER_INFO); j++) { - if (AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid) { - return &AdapterArr[j]; - } - } - - return NULL; -} - -/******************************************************************************/ -/* Description: */ -/* This routine sets up receive/transmit buffer descriptions queues. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_InitializeAdapter (PLM_DEVICE_BLOCK pDevice) -{ - LM_PHYSICAL_ADDRESS MemPhy; - PLM_UINT8 pMemVirt; - PLM_PACKET pPacket; - LM_STATUS Status; - LM_UINT32 Size; - LM_UINT32 j; - - /* Set power state to D0. */ - LM_SetPowerState (pDevice, LM_POWER_STATE_D0); - - /* Intialize the queues. */ - QQ_InitQueue (&pDevice->RxPacketReceivedQ.Container, - MAX_RX_PACKET_DESC_COUNT); - QQ_InitQueue (&pDevice->RxPacketFreeQ.Container, - MAX_RX_PACKET_DESC_COUNT); - - QQ_InitQueue (&pDevice->TxPacketFreeQ.Container, - MAX_TX_PACKET_DESC_COUNT); - QQ_InitQueue (&pDevice->TxPacketActiveQ.Container, - MAX_TX_PACKET_DESC_COUNT); - QQ_InitQueue (&pDevice->TxPacketXmittedQ.Container, - MAX_TX_PACKET_DESC_COUNT); - - /* Allocate shared memory for: status block, the buffers for receive */ - /* rings -- standard, mini, jumbo, and return rings. */ - Size = T3_STATUS_BLOCK_SIZE + sizeof (T3_STATS_BLOCK) + - T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD) + -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); - - /* Memory for host based Send BD. */ - if (pDevice->NicSendBd == FALSE) { - Size += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; - } - - /* Allocate the memory block. */ - Status = - MM_AllocateSharedMemory (pDevice, Size, (PLM_VOID) & pMemVirt, - &MemPhy, FALSE); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - - /* Program DMA Read/Write */ - if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) { - pDevice->DmaReadWriteCtrl = 0x763f000f; - } else { - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5704) { - pDevice->DmaReadWriteCtrl = 0x761f0000; - } else { - pDevice->DmaReadWriteCtrl = 0x761b000f; - } - if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || - pDevice->ChipRevId == T3_CHIP_ID_5703_A2) { - pDevice->OneDmaAtOnce = TRUE; - } - } - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5703) { - pDevice->DmaReadWriteCtrl &= 0xfffffff0; - } - - if (pDevice->OneDmaAtOnce) { - pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE; - } - REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); - - if (LM_DmaTest (pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS) { - return LM_STATUS_FAILURE; - } - - /* Status block. */ - pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt; - pDevice->StatusBlkPhy = MemPhy; - pMemVirt += T3_STATUS_BLOCK_SIZE; - LM_INC_PHYSICAL_ADDRESS (&MemPhy, T3_STATUS_BLOCK_SIZE); - - /* Statistics block. */ - pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt; - pDevice->StatsBlkPhy = MemPhy; - pMemVirt += sizeof (T3_STATS_BLOCK); - LM_INC_PHYSICAL_ADDRESS (&MemPhy, sizeof (T3_STATS_BLOCK)); - - /* Receive standard BD buffer. */ - pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt; - pDevice->RxStdBdPhy = MemPhy; - - pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); - LM_INC_PHYSICAL_ADDRESS (&MemPhy, - T3_STD_RCV_RCB_ENTRY_COUNT * - sizeof (T3_RCV_BD)); - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - /* Receive jumbo BD buffer. */ - pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt; - pDevice->RxJumboBdPhy = MemPhy; - - pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); - LM_INC_PHYSICAL_ADDRESS (&MemPhy, - T3_JUMBO_RCV_RCB_ENTRY_COUNT * - sizeof (T3_RCV_BD)); -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - /* Receive return BD buffer. */ - pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt; - pDevice->RcvRetBdPhy = MemPhy; - - pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof (T3_RCV_BD); - LM_INC_PHYSICAL_ADDRESS (&MemPhy, - T3_RCV_RETURN_RCB_ENTRY_COUNT * - sizeof (T3_RCV_BD)); - - /* Set up Send BD. */ - if (pDevice->NicSendBd == FALSE) { - pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt; - pDevice->SendBdPhy = MemPhy; - - pMemVirt += sizeof (T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; - LM_INC_PHYSICAL_ADDRESS (&MemPhy, - sizeof (T3_SND_BD) * - T3_SEND_RCB_ENTRY_COUNT); - } else { - pDevice->pSendBdVirt = (PT3_SND_BD) - pDevice->pMemView->uIntMem.First32k.BufferDesc; - pDevice->SendBdPhy.High = 0; - pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR; - } - - /* Allocate memory for packet descriptors. */ - Size = (pDevice->RxPacketDescCnt + - pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE; - Status = MM_AllocateMemory (pDevice, Size, (PLM_VOID *) & pPacket); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - pDevice->pPacketDescBase = (PLM_VOID) pPacket; - - /* Create transmit packet descriptors from the memory block and add them */ - /* to the TxPacketFreeQ for each send ring. */ - for (j = 0; j < pDevice->TxPacketDescCnt; j++) { - /* Ring index. */ - pPacket->Flags = 0; - - /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */ - QQ_PushTail (&pDevice->TxPacketFreeQ.Container, pPacket); - - /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ - /* is the total size of the packet descriptor including the */ - /* os-specific extensions in the UM_PACKET structure. */ - pPacket = - (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); - } /* for(j.. */ - - /* Create receive packet descriptors from the memory block and add them */ - /* to the RxPacketFreeQ. Create the Standard packet descriptors. */ - for (j = 0; j < pDevice->RxStdDescCnt; j++) { - /* Receive producer ring. */ - pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING; - - /* Receive buffer size. */ - pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE; - - /* Add the descriptor to RxPacketFreeQ. */ - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - - /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ - /* is the total size of the packet descriptor including the */ - /* os-specific extensions in the UM_PACKET structure. */ - pPacket = - (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); - } /* for */ - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - /* Create the Jumbo packet descriptors. */ - for (j = 0; j < pDevice->RxJumboDescCnt; j++) { - /* Receive producer ring. */ - pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING; - - /* Receive buffer size. */ - pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize; - - /* Add the descriptor to RxPacketFreeQ. */ - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - - /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ - /* is the total size of the packet descriptor including the */ - /* os-specific extensions in the UM_PACKET structure. */ - pPacket = - (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); - } /* for */ -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - /* Initialize the rest of the packet descriptors. */ - Status = MM_InitializeUmPackets (pDevice); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - - /* if */ - /* Default receive mask. */ - pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST | - LM_ACCEPT_UNICAST; - - /* Make sure we are in the first 32k memory window or NicSendBd. */ - REG_WR (pDevice, PciCfg.MemWindowBaseAddr, 0); - - /* Initialize the hardware. */ - Status = LM_ResetAdapter (pDevice); - if (Status != LM_STATUS_SUCCESS) { - return Status; - } - - /* We are done with initialization. */ - pDevice->InitDone = TRUE; - - return LM_STATUS_SUCCESS; -} /* LM_InitializeAdapter */ - -/******************************************************************************/ -/* Description: */ -/* This function Enables/Disables a given block. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS -LM_CntrlBlock (PLM_DEVICE_BLOCK pDevice, LM_UINT32 mask, LM_UINT32 cntrl) -{ - LM_UINT32 j, i, data; - LM_UINT32 MaxWaitCnt; - - MaxWaitCnt = 2; - j = 0; - - for (i = 0; i < 32; i++) { - if (!(mask & (1 << i))) - continue; - - switch (1 << i) { - case T3_BLOCK_DMA_RD: - data = REG_RD (pDevice, DmaRead.Mode); - if (cntrl == LM_DISABLE) { - data &= ~DMA_READ_MODE_ENABLE; - REG_WR (pDevice, DmaRead.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, DmaRead.Mode) & - DMA_READ_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, DmaRead.Mode, - data | DMA_READ_MODE_ENABLE); - break; - - case T3_BLOCK_DMA_COMP: - data = REG_RD (pDevice, DmaComp.Mode); - if (cntrl == LM_DISABLE) { - data &= ~DMA_COMP_MODE_ENABLE; - REG_WR (pDevice, DmaComp.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, DmaComp.Mode) & - DMA_COMP_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, DmaComp.Mode, - data | DMA_COMP_MODE_ENABLE); - break; - - case T3_BLOCK_RX_BD_INITIATOR: - data = REG_RD (pDevice, RcvBdIn.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_BD_IN_MODE_ENABLE; - REG_WR (pDevice, RcvBdIn.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvBdIn.Mode) & - RCV_BD_IN_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvBdIn.Mode, - data | RCV_BD_IN_MODE_ENABLE); - break; - - case T3_BLOCK_RX_BD_COMP: - data = REG_RD (pDevice, RcvBdComp.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_BD_COMP_MODE_ENABLE; - REG_WR (pDevice, RcvBdComp.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvBdComp.Mode) & - RCV_BD_COMP_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvBdComp.Mode, - data | RCV_BD_COMP_MODE_ENABLE); - break; - - case T3_BLOCK_DMA_WR: - data = REG_RD (pDevice, DmaWrite.Mode); - if (cntrl == LM_DISABLE) { - data &= ~DMA_WRITE_MODE_ENABLE; - REG_WR (pDevice, DmaWrite.Mode, data); - - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, DmaWrite.Mode) & - DMA_WRITE_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, DmaWrite.Mode, - data | DMA_WRITE_MODE_ENABLE); - break; - - case T3_BLOCK_MSI_HANDLER: - data = REG_RD (pDevice, Msi.Mode); - if (cntrl == LM_DISABLE) { - data &= ~MSI_MODE_ENABLE; - REG_WR (pDevice, Msi.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, Msi.Mode) & - MSI_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, Msi.Mode, - data | MSI_MODE_ENABLE); - break; - - case T3_BLOCK_RX_LIST_PLMT: - data = REG_RD (pDevice, RcvListPlmt.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_LIST_PLMT_MODE_ENABLE; - REG_WR (pDevice, RcvListPlmt.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvListPlmt.Mode) - & RCV_LIST_PLMT_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvListPlmt.Mode, - data | RCV_LIST_PLMT_MODE_ENABLE); - break; - - case T3_BLOCK_RX_LIST_SELECTOR: - data = REG_RD (pDevice, RcvListSel.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_LIST_SEL_MODE_ENABLE; - REG_WR (pDevice, RcvListSel.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvListSel.Mode) & - RCV_LIST_SEL_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvListSel.Mode, - data | RCV_LIST_SEL_MODE_ENABLE); - break; - - case T3_BLOCK_RX_DATA_INITIATOR: - data = REG_RD (pDevice, RcvDataBdIn.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_DATA_BD_IN_MODE_ENABLE; - REG_WR (pDevice, RcvDataBdIn.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvDataBdIn.Mode) - & RCV_DATA_BD_IN_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvDataBdIn.Mode, - data | RCV_DATA_BD_IN_MODE_ENABLE); - break; - - case T3_BLOCK_RX_DATA_COMP: - data = REG_RD (pDevice, RcvDataComp.Mode); - if (cntrl == LM_DISABLE) { - data &= ~RCV_DATA_COMP_MODE_ENABLE; - REG_WR (pDevice, RcvDataComp.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, RcvDataBdIn.Mode) - & RCV_DATA_COMP_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, RcvDataComp.Mode, - data | RCV_DATA_COMP_MODE_ENABLE); - break; - - case T3_BLOCK_HOST_COALESING: - data = REG_RD (pDevice, HostCoalesce.Mode); - if (cntrl == LM_DISABLE) { - data &= ~HOST_COALESCE_ENABLE; - REG_WR (pDevice, HostCoalesce.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndBdIn.Mode) & - HOST_COALESCE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, HostCoalesce.Mode, - data | HOST_COALESCE_ENABLE); - break; - - case T3_BLOCK_MAC_RX_ENGINE: - if (cntrl == LM_DISABLE) { - pDevice->RxMode &= ~RX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.RxMode, - pDevice->RxMode); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, MacCtrl.RxMode) & - RX_MODE_ENABLE)) { - break; - } - MM_Wait (10); - } - } else { - pDevice->RxMode |= RX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.RxMode, - pDevice->RxMode); - } - break; - - case T3_BLOCK_MBUF_CLUSTER_FREE: - data = REG_RD (pDevice, MbufClusterFree.Mode); - if (cntrl == LM_DISABLE) { - data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE; - REG_WR (pDevice, MbufClusterFree.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD - (pDevice, - MbufClusterFree. - Mode) & - MBUF_CLUSTER_FREE_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, MbufClusterFree.Mode, - data | MBUF_CLUSTER_FREE_MODE_ENABLE); - break; - - case T3_BLOCK_SEND_BD_INITIATOR: - data = REG_RD (pDevice, SndBdIn.Mode); - if (cntrl == LM_DISABLE) { - data &= ~SND_BD_IN_MODE_ENABLE; - REG_WR (pDevice, SndBdIn.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndBdIn.Mode) & - SND_BD_IN_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, SndBdIn.Mode, - data | SND_BD_IN_MODE_ENABLE); - break; - - case T3_BLOCK_SEND_BD_COMP: - data = REG_RD (pDevice, SndBdComp.Mode); - if (cntrl == LM_DISABLE) { - data &= ~SND_BD_COMP_MODE_ENABLE; - REG_WR (pDevice, SndBdComp.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndBdComp.Mode) & - SND_BD_COMP_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, SndBdComp.Mode, - data | SND_BD_COMP_MODE_ENABLE); - break; - - case T3_BLOCK_SEND_BD_SELECTOR: - data = REG_RD (pDevice, SndBdSel.Mode); - if (cntrl == LM_DISABLE) { - data &= ~SND_BD_SEL_MODE_ENABLE; - REG_WR (pDevice, SndBdSel.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndBdSel.Mode) & - SND_BD_SEL_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, SndBdSel.Mode, - data | SND_BD_SEL_MODE_ENABLE); - break; - - case T3_BLOCK_SEND_DATA_INITIATOR: - data = REG_RD (pDevice, SndDataIn.Mode); - if (cntrl == LM_DISABLE) { - data &= ~T3_SND_DATA_IN_MODE_ENABLE; - REG_WR (pDevice, SndDataIn.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndDataIn.Mode) & - T3_SND_DATA_IN_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, SndDataIn.Mode, - data | T3_SND_DATA_IN_MODE_ENABLE); - break; - - case T3_BLOCK_SEND_DATA_COMP: - data = REG_RD (pDevice, SndDataComp.Mode); - if (cntrl == LM_DISABLE) { - data &= ~SND_DATA_COMP_MODE_ENABLE; - REG_WR (pDevice, SndDataComp.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, SndDataComp.Mode) - & SND_DATA_COMP_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, SndDataComp.Mode, - data | SND_DATA_COMP_MODE_ENABLE); - break; - - case T3_BLOCK_MAC_TX_ENGINE: - if (cntrl == LM_DISABLE) { - pDevice->TxMode &= ~TX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.TxMode, - pDevice->TxMode); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, MacCtrl.TxMode) & - TX_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else { - pDevice->TxMode |= TX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.TxMode, - pDevice->TxMode); - } - break; - - case T3_BLOCK_MEM_ARBITOR: - data = REG_RD (pDevice, MemArbiter.Mode); - if (cntrl == LM_DISABLE) { - data &= ~T3_MEM_ARBITER_MODE_ENABLE; - REG_WR (pDevice, MemArbiter.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, MemArbiter.Mode) & - T3_MEM_ARBITER_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, MemArbiter.Mode, - data | T3_MEM_ARBITER_MODE_ENABLE); - break; - - case T3_BLOCK_MBUF_MANAGER: - data = REG_RD (pDevice, BufMgr.Mode); - if (cntrl == LM_DISABLE) { - data &= ~BUFMGR_MODE_ENABLE; - REG_WR (pDevice, BufMgr.Mode, data); - for (j = 0; j < MaxWaitCnt; j++) { - if (! - (REG_RD (pDevice, BufMgr.Mode) & - BUFMGR_MODE_ENABLE)) - break; - MM_Wait (10); - } - } else - REG_WR (pDevice, BufMgr.Mode, - data | BUFMGR_MODE_ENABLE); - break; - - case T3_BLOCK_MAC_GLOBAL: - if (cntrl == LM_DISABLE) { - pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE | - MAC_MODE_ENABLE_RDE | - MAC_MODE_ENABLE_FHDE); - } else { - pDevice->MacMode |= (MAC_MODE_ENABLE_TDE | - MAC_MODE_ENABLE_RDE | - MAC_MODE_ENABLE_FHDE); - } - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - break; - - default: - return LM_STATUS_FAILURE; - } /* switch */ - - if (j >= MaxWaitCnt) { - return LM_STATUS_FAILURE; - } - } - - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* This function reinitializes the adapter. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_ResetAdapter (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - LM_UINT16 Value16; - LM_UINT32 j, k; - - /* Disable interrupt. */ - LM_DisableInterrupt (pDevice); - - /* May get a spurious interrupt */ - pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED; - - /* Disable transmit and receive DMA engines. Abort all pending requests. */ - if (pDevice->InitDone) { - LM_Abort (pDevice); - } - - pDevice->ShuttingDown = FALSE; - - LM_ResetChip (pDevice); - - /* Bug: Athlon fix for B3 silicon only. This bit does not do anything */ - /* in other chip revisions. */ - if (pDevice->DelayPciGrant) { - Value32 = REG_RD (pDevice, PciCfg.ClockCtrl); - REG_WR (pDevice, PciCfg.ClockCtrl, Value32 | BIT_31); - } - - if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { - if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { - Value32 = REG_RD (pDevice, PciCfg.PciState); - Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; - REG_WR (pDevice, PciCfg.PciState, Value32); - } - } - - /* Enable TaggedStatus mode. */ - if (pDevice->UseTaggedStatus) { - pDevice->MiscHostCtrl |= - MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE; - } - - /* Restore PCI configuration registers. */ - MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, - pDevice->SavedCacheLineReg); - MM_WriteConfig32 (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, - (pDevice->SubsystemId << 16) | pDevice-> - SubsystemVendorId); - - /* Clear the statistics block. */ - for (j = 0x0300; j < 0x0b00; j++) { - MEM_WR_OFFSET (pDevice, j, 0); - } - - /* Initialize the statistis Block */ - pDevice->pStatusBlkVirt->Status = 0; - pDevice->pStatusBlkVirt->RcvStdConIdx = 0; - pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; - pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; - - for (j = 0; j < 16; j++) { - pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0; - pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0; - } - - for (k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT; k++) { - pDevice->pRxStdBdVirt[k].HostAddr.High = 0; - pDevice->pRxStdBdVirt[k].HostAddr.Low = 0; - } - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - /* Receive jumbo BD buffer. */ - for (k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++) { - pDevice->pRxJumboBdVirt[k].HostAddr.High = 0; - pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0; - } -#endif - - REG_WR (pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); - - /* GRC mode control register. */ -#ifdef BIG_ENDIAN_PCI /* Jimmy, this ifdef block deleted in new code! */ - Value32 = - GRC_MODE_WORD_SWAP_DATA | - GRC_MODE_WORD_SWAP_NON_FRAME_DATA | - GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; -#else - /* No CPU Swap modes for PCI IO */ - Value32 = -#ifdef BIG_ENDIAN_HOST - GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | - GRC_MODE_WORD_SWAP_NON_FRAME_DATA | - GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | -#else - GRC_MODE_WORD_SWAP_NON_FRAME_DATA | - GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA | -#endif - GRC_MODE_INT_ON_MAC_ATTN | GRC_MODE_HOST_STACK_UP; -#endif /* !BIG_ENDIAN_PCI */ - - /* Configure send BD mode. */ - if (pDevice->NicSendBd == FALSE) { - Value32 |= GRC_MODE_HOST_SEND_BDS; - } else { - Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS; - } - - /* Configure pseudo checksum mode. */ - if (pDevice->NoTxPseudoHdrChksum) { - Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM; - } - - if (pDevice->NoRxPseudoHdrChksum) { - Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM; - } - - REG_WR (pDevice, Grc.Mode, Value32); - - /* Setup the timer prescalar register. */ - REG_WR (pDevice, Grc.MiscCfg, 65 << 1); /* Clock is alwasy 66Mhz. */ - - /* Set up the MBUF pool base address and size. */ - REG_WR (pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase); - REG_WR (pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize); - - /* Set up the DMA descriptor pool base address and size. */ - REG_WR (pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR); - REG_WR (pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE); - - /* Configure MBUF and Threshold watermarks */ - /* Configure the DMA read MBUF low water mark. */ - if (pDevice->DmaMbufLowMark) { - REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, - pDevice->DmaMbufLowMark); - } else { - if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { - REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, - T3_DEF_DMA_MBUF_LOW_WMARK); - } else { - REG_WR (pDevice, BufMgr.MbufReadDmaLowWaterMark, - T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO); - } - } - - /* Configure the MAC Rx MBUF low water mark. */ - if (pDevice->RxMacMbufLowMark) { - REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, - pDevice->RxMacMbufLowMark); - } else { - if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { - REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, - T3_DEF_RX_MAC_MBUF_LOW_WMARK); - } else { - REG_WR (pDevice, BufMgr.MbufMacRxLowWaterMark, - T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO); - } - } - - /* Configure the MBUF high water mark. */ - if (pDevice->MbufHighMark) { - REG_WR (pDevice, BufMgr.MbufHighWaterMark, - pDevice->MbufHighMark); - } else { - if (pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) { - REG_WR (pDevice, BufMgr.MbufHighWaterMark, - T3_DEF_MBUF_HIGH_WMARK); - } else { - REG_WR (pDevice, BufMgr.MbufHighWaterMark, - T3_DEF_MBUF_HIGH_WMARK_JUMBO); - } - } - - REG_WR (pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK); - REG_WR (pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK); - - /* Enable buffer manager. */ - REG_WR (pDevice, BufMgr.Mode, - BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); - - for (j = 0; j < 2000; j++) { - if (REG_RD (pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE) - break; - MM_Wait (10); - } - - if (j >= 2000) { - return LM_STATUS_FAILURE; - } - - /* Enable the FTQs. */ - REG_WR (pDevice, Ftq.Reset, 0xffffffff); - REG_WR (pDevice, Ftq.Reset, 0); - - /* Wait until FTQ is ready */ - for (j = 0; j < 2000; j++) { - if (REG_RD (pDevice, Ftq.Reset) == 0) - break; - MM_Wait (10); - } - - if (j >= 2000) { - return LM_STATUS_FAILURE; - } - - /* Initialize the Standard Receive RCB. */ - REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High, - pDevice->RxStdBdPhy.High); - REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low, - pDevice->RxStdBdPhy.Low); - REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags, - MAX_STD_RCV_BUFFER_SIZE << 16); - - /* Initialize the Jumbo Receive RCB. */ - REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, - T3_RCB_FLAG_RING_DISABLED); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High, - pDevice->RxJumboBdPhy.High); - REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low, - pDevice->RxJumboBdPhy.Low); - - REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0); - -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - /* Initialize the Mini Receive RCB. */ - REG_WR (pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags, - T3_RCB_FLAG_RING_DISABLED); - - { - REG_WR (pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr, - (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR); - REG_WR (pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr, - (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR); - } - - /* Receive BD Ring replenish threshold. */ - REG_WR (pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt / 8); -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - REG_WR (pDevice, RcvBdIn.JumboRcvThreshold, - pDevice->RxJumboDescCnt / 8); -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - /* Disable all the unused rings. */ - for (j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) { - MEM_WR (pDevice, SendRcb[j].u.MaxLen_Flags, - T3_RCB_FLAG_RING_DISABLED); - } /* for */ - - /* Initialize the indices. */ - pDevice->SendProdIdx = 0; - pDevice->SendConIdx = 0; - - MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, 0); - MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, 0); - - /* Set up host or NIC based send RCB. */ - if (pDevice->NicSendBd == FALSE) { - MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, - pDevice->SendBdPhy.High); - MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, - pDevice->SendBdPhy.Low); - - /* Set up the NIC ring address in the RCB. */ - MEM_WR (pDevice, SendRcb[0].NicRingAddr, - T3_NIC_SND_BUFFER_DESC_ADDR); - - /* Setup the RCB. */ - MEM_WR (pDevice, SendRcb[0].u.MaxLen_Flags, - T3_SEND_RCB_ENTRY_COUNT << 16); - - for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { - pDevice->pSendBdVirt[k].HostAddr.High = 0; - pDevice->pSendBdVirt[k].HostAddr.Low = 0; - } - } else { - MEM_WR (pDevice, SendRcb[0].HostRingAddr.High, 0); - MEM_WR (pDevice, SendRcb[0].HostRingAddr.Low, 0); - MEM_WR (pDevice, SendRcb[0].NicRingAddr, - pDevice->SendBdPhy.Low); - - for (k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) { - __raw_writel (0, - &(pDevice->pSendBdVirt[k].HostAddr.High)); - __raw_writel (0, - &(pDevice->pSendBdVirt[k].HostAddr.Low)); - __raw_writel (0, - &(pDevice->pSendBdVirt[k].u1.Len_Flags)); - pDevice->ShadowSendBd[k].HostAddr.High = 0; - pDevice->ShadowSendBd[k].u1.Len_Flags = 0; - } - } - atomic_set (&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT - 1); - - /* Configure the receive return rings. */ - for (j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++) { - MEM_WR (pDevice, RcvRetRcb[j].u.MaxLen_Flags, - T3_RCB_FLAG_RING_DISABLED); - } - - pDevice->RcvRetConIdx = 0; - - MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.High, - pDevice->RcvRetBdPhy.High); - MEM_WR (pDevice, RcvRetRcb[0].HostRingAddr.Low, - pDevice->RcvRetBdPhy.Low); - - /* Set up the NIC ring address in the RCB. */ - /* Not very clear from the spec. I am guessing that for Receive */ - /* Return Ring, NicRingAddr is not used. */ - MEM_WR (pDevice, RcvRetRcb[0].NicRingAddr, 0); - - /* Setup the RCB. */ - MEM_WR (pDevice, RcvRetRcb[0].u.MaxLen_Flags, - T3_RCV_RETURN_RCB_ENTRY_COUNT << 16); - - /* Reinitialize RX ring producer index */ - MB_REG_WR (pDevice, Mailbox.RcvStdProdIdx.Low, 0); - MB_REG_WR (pDevice, Mailbox.RcvJumboProdIdx.Low, 0); - MB_REG_WR (pDevice, Mailbox.RcvMiniProdIdx.Low, 0); - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - pDevice->RxJumboProdIdx = 0; - pDevice->RxJumboQueuedCnt = 0; -#endif - - /* Reinitialize our copy of the indices. */ - pDevice->RxStdProdIdx = 0; - pDevice->RxStdQueuedCnt = 0; - -#if T3_JUMBO_RCV_ENTRY_COUNT - pDevice->RxJumboProdIdx = 0; -#endif /* T3_JUMBO_RCV_ENTRY_COUNT */ - - /* Configure the MAC address. */ - LM_SetMacAddress (pDevice, pDevice->NodeAddress); - - /* Initialize the transmit random backoff seed. */ - Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + - pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + - pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & - MAC_TX_BACKOFF_SEED_MASK; - REG_WR (pDevice, MacCtrl.TxBackoffSeed, Value32); - - /* Receive MTU. Frames larger than the MTU is marked as oversized. */ - REG_WR (pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8); /* CRC + VLAN. */ - - /* Configure Time slot/IPG per 802.3 */ - REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); - - /* - * Configure Receive Rules so that packets don't match - * Programmble rule will be queued to Return Ring 1 - */ - REG_WR (pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS); - - /* - * Configure to have 16 Classes of Services (COS) and one - * queue per class. Bad frames are queued to RRR#1. - * And frames don't match rules are also queued to COS#1. - */ - REG_WR (pDevice, RcvListPlmt.Config, 0x181); - - /* Enable Receive Placement Statistics */ - REG_WR (pDevice, RcvListPlmt.StatsEnableMask, 0xffffff); - REG_WR (pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE); - - /* Enable Send Data Initator Statistics */ - REG_WR (pDevice, SndDataIn.StatsEnableMask, 0xffffff); - REG_WR (pDevice, SndDataIn.StatsCtrl, - T3_SND_DATA_IN_STATS_CTRL_ENABLE | - T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE); - - /* Disable the host coalescing state machine before configuring it's */ - /* parameters. */ - REG_WR (pDevice, HostCoalesce.Mode, 0); - for (j = 0; j < 2000; j++) { - Value32 = REG_RD (pDevice, HostCoalesce.Mode); - if (!(Value32 & HOST_COALESCE_ENABLE)) { - break; - } - MM_Wait (10); - } - - /* Host coalescing configurations. */ - REG_WR (pDevice, HostCoalesce.RxCoalescingTicks, - pDevice->RxCoalescingTicks); - REG_WR (pDevice, HostCoalesce.TxCoalescingTicks, - pDevice->TxCoalescingTicks); - REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFrames, - pDevice->RxMaxCoalescedFrames); - REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFrames, - pDevice->TxMaxCoalescedFrames); - REG_WR (pDevice, HostCoalesce.RxCoalescedTickDuringInt, - pDevice->RxCoalescingTicksDuringInt); - REG_WR (pDevice, HostCoalesce.TxCoalescedTickDuringInt, - pDevice->TxCoalescingTicksDuringInt); - REG_WR (pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt, - pDevice->RxMaxCoalescedFramesDuringInt); - REG_WR (pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt, - pDevice->TxMaxCoalescedFramesDuringInt); - - /* Initialize the address of the status block. The NIC will DMA */ - /* the status block to this memory which resides on the host. */ - REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.High, - pDevice->StatusBlkPhy.High); - REG_WR (pDevice, HostCoalesce.StatusBlkHostAddr.Low, - pDevice->StatusBlkPhy.Low); - - /* Initialize the address of the statistics block. The NIC will DMA */ - /* the statistics to this block of memory. */ - REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.High, - pDevice->StatsBlkPhy.High); - REG_WR (pDevice, HostCoalesce.StatsBlkHostAddr.Low, - pDevice->StatsBlkPhy.Low); - - REG_WR (pDevice, HostCoalesce.StatsCoalescingTicks, - pDevice->StatsCoalescingTicks); - - REG_WR (pDevice, HostCoalesce.StatsBlkNicAddr, 0x300); - REG_WR (pDevice, HostCoalesce.StatusBlkNicAddr, 0xb00); - - /* Enable Host Coalesing state machine */ - REG_WR (pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE | - pDevice->CoalesceMode); - - /* Enable the Receive BD Completion state machine. */ - REG_WR (pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE | - RCV_BD_COMP_MODE_ATTN_ENABLE); - - /* Enable the Receive List Placement state machine. */ - REG_WR (pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE); - - /* Enable the Receive List Selector state machine. */ - REG_WR (pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE | - RCV_LIST_SEL_MODE_ATTN_ENABLE); - - /* Enable transmit DMA, clear statistics. */ - pDevice->MacMode = MAC_MODE_ENABLE_TX_STATISTICS | - MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE | - MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE; - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | - MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS); - - /* GRC miscellaneous local control register. */ - pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN | - GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM; - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1; - } - - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); - MM_Wait (40); - - /* Reset RX counters. */ - for (j = 0; j < sizeof (LM_RX_COUNTERS); j++) { - ((PLM_UINT8) & pDevice->RxCounters)[j] = 0; - } - - /* Reset TX counters. */ - for (j = 0; j < sizeof (LM_TX_COUNTERS); j++) { - ((PLM_UINT8) & pDevice->TxCounters)[j] = 0; - } - - MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); - - /* Enable the DMA Completion state machine. */ - REG_WR (pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE); - - /* Enable the DMA Write state machine. */ - Value32 = DMA_WRITE_MODE_ENABLE | - DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE | - DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE | - DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE | - DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE | - DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE | - DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE | - DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE | - DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE; - REG_WR (pDevice, DmaWrite.Mode, Value32); - - if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { - if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { - Value16 = REG_RD (pDevice, PciCfg.PciXCommand); - Value16 &= - ~(PCIX_CMD_MAX_SPLIT_MASK | - PCIX_CMD_MAX_BURST_MASK); - Value16 |= - ((PCIX_CMD_MAX_BURST_CPIOB << - PCIX_CMD_MAX_BURST_SHL) & - PCIX_CMD_MAX_BURST_MASK); - if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { - Value16 |= - (pDevice-> - SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL) - & PCIX_CMD_MAX_SPLIT_MASK; - } - REG_WR (pDevice, PciCfg.PciXCommand, Value16); - } - } - - /* Enable the Read DMA state machine. */ - Value32 = DMA_READ_MODE_ENABLE | - DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE | - DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE | - DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE | - DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE | - DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE | - DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE | - DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE | - DMA_READ_MODE_LONG_READ_ATTN_ENABLE; - - if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) { - Value32 |= DMA_READ_MODE_SPLIT_ENABLE; - } - REG_WR (pDevice, DmaRead.Mode, Value32); - - /* Enable the Receive Data Completion state machine. */ - REG_WR (pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE | - RCV_DATA_COMP_MODE_ATTN_ENABLE); - - /* Enable the Mbuf Cluster Free state machine. */ - REG_WR (pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE); - - /* Enable the Send Data Completion state machine. */ - REG_WR (pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE); - - /* Enable the Send BD Completion state machine. */ - REG_WR (pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE | - SND_BD_COMP_MODE_ATTN_ENABLE); - - /* Enable the Receive BD Initiator state machine. */ - REG_WR (pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE | - RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE); - - /* Enable the Receive Data and Receive BD Initiator state machine. */ - REG_WR (pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE | - RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE); - - /* Enable the Send Data Initiator state machine. */ - REG_WR (pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE); - - /* Enable the Send BD Initiator state machine. */ - REG_WR (pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE | - SND_BD_IN_MODE_ATTN_ENABLE); - - /* Enable the Send BD Selector state machine. */ - REG_WR (pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE | - SND_BD_SEL_MODE_ATTN_ENABLE); - -#if INCLUDE_5701_AX_FIX - /* Load the firmware for the 5701_A0 workaround. */ - if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0) { - LM_LoadRlsFirmware (pDevice); - } -#endif - - /* Enable the transmitter. */ - pDevice->TxMode = TX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); - - /* Enable the receiver. */ - pDevice->RxMode = RX_MODE_ENABLE; - REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); - - if (pDevice->RestoreOnWakeUp) { - pDevice->RestoreOnWakeUp = FALSE; - pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg; - pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType; - } - - /* Disable auto polling. */ - pDevice->MiMode = 0xc0000; - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = LED_CTRL_PHY_MODE_1; - } else { - if (pDevice->LedMode == LED_MODE_OUTPUT) { - Value32 = LED_CTRL_PHY_MODE_2; - } else { - Value32 = LED_CTRL_PHY_MODE_1; - } - } - REG_WR (pDevice, MacCtrl.LedCtrl, Value32); - - /* Activate Link to enable MAC state machine */ - REG_WR (pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN); - - if (pDevice->EnableTbi) { - REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_RESET); - MM_Wait (10); - REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); - if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1) { - REG_WR (pDevice, MacCtrl.SerdesCfg, 0x616000); - } - } - /* Setup the phy chip. */ - LM_SetupPhy (pDevice); - - if (!pDevice->EnableTbi) { - /* Clear CRC stats */ - LM_ReadPhy (pDevice, 0x1e, &Value32); - LM_WritePhy (pDevice, 0x1e, Value32 | 0x8000); - LM_ReadPhy (pDevice, 0x14, &Value32); - } - - /* Set up the receive mask. */ - LM_SetReceiveMask (pDevice, pDevice->ReceiveMask); - - /* Queue Rx packet buffers. */ - if (pDevice->QueueRxPackets) { - LM_QueueRxPackets (pDevice); - } - - /* Enable interrupt to the host. */ - if (pDevice->InitDone) { - LM_EnableInterrupt (pDevice); - } - - return LM_STATUS_SUCCESS; -} /* LM_ResetAdapter */ - -/******************************************************************************/ -/* Description: */ -/* This routine disables the adapter from generating interrupts. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_DisableInterrupt (PLM_DEVICE_BLOCK pDevice) -{ - REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl | - MISC_HOST_CTRL_MASK_PCI_INT); - MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 1); - - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* This routine enables the adapter to generate interrupts. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_EnableInterrupt (PLM_DEVICE_BLOCK pDevice) -{ - REG_WR (pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl & - ~MISC_HOST_CTRL_MASK_PCI_INT); - MB_REG_WR (pDevice, Mailbox.Interrupt[0].Low, 0); - - if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_SET_INT); - } - - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* This routine puts a packet on the wire if there is a transmit DMA */ -/* descriptor available; otherwise the packet is queued for later */ -/* transmission. If the second argue is NULL, this routine will put */ -/* the queued packet on the wire if possible. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -#if 0 -LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - LM_UINT32 FragCount; - PT3_SND_BD pSendBd; - PT3_SND_BD pShadowSendBd; - LM_UINT32 Value32, Len; - LM_UINT32 Idx; - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - return LM_5700SendPacket (pDevice, pPacket); - } - - /* Update the SendBdLeft count. */ - atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); - - /* Initalize the send buffer descriptors. */ - Idx = pDevice->SendProdIdx; - - pSendBd = &pDevice->pSendBdVirt[Idx]; - - /* Next producer index. */ - if (pDevice->NicSendBd == TRUE) { - T3_64BIT_HOST_ADDR paddr; - - pShadowSendBd = &pDevice->ShadowSendBd[Idx]; - for (FragCount = 0;;) { - MM_MapTxDma (pDevice, pPacket, &paddr, &Len, FragCount); - /* Initialize the pointer to the send buffer fragment. */ - if (paddr.High != pShadowSendBd->HostAddr.High) { - __raw_writel (paddr.High, - &(pSendBd->HostAddr.High)); - pShadowSendBd->HostAddr.High = paddr.High; - } - __raw_writel (paddr.Low, &(pSendBd->HostAddr.Low)); - - /* Setup the control flags and send buffer size. */ - Value32 = (Len << 16) | pPacket->Flags; - - Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; - - FragCount++; - if (FragCount >= pPacket->u.Tx.FragCount) { - Value32 |= SND_BD_FLAG_END; - if (Value32 != pShadowSendBd->u1.Len_Flags) { - __raw_writel (Value32, - &(pSendBd->u1.Len_Flags)); - pShadowSendBd->u1.Len_Flags = Value32; - } - if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { - __raw_writel (pPacket->VlanTag, - &(pSendBd->u2.VlanTag)); - } - break; - } else { - if (Value32 != pShadowSendBd->u1.Len_Flags) { - __raw_writel (Value32, - &(pSendBd->u1.Len_Flags)); - pShadowSendBd->u1.Len_Flags = Value32; - } - if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { - __raw_writel (pPacket->VlanTag, - &(pSendBd->u2.VlanTag)); - } - } - - pSendBd++; - pShadowSendBd++; - if (Idx == 0) { - pSendBd = &pDevice->pSendBdVirt[0]; - pShadowSendBd = &pDevice->ShadowSendBd[0]; - } - } /* for */ - - /* Put the packet descriptor in the ActiveQ. */ - QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); - - wmb (); - MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); - - } else { - for (FragCount = 0;;) { - /* Initialize the pointer to the send buffer fragment. */ - MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, - FragCount); - - pSendBd->u2.VlanTag = pPacket->VlanTag; - - /* Setup the control flags and send buffer size. */ - Value32 = (Len << 16) | pPacket->Flags; - - Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; - - FragCount++; - if (FragCount >= pPacket->u.Tx.FragCount) { - pSendBd->u1.Len_Flags = - Value32 | SND_BD_FLAG_END; - break; - } else { - pSendBd->u1.Len_Flags = Value32; - } - pSendBd++; - if (Idx == 0) { - pSendBd = &pDevice->pSendBdVirt[0]; - } - } /* for */ - - /* Put the packet descriptor in the ActiveQ. */ - QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); - - wmb (); - MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); - - } - - /* Update the producer index. */ - pDevice->SendProdIdx = Idx; - - return LM_STATUS_SUCCESS; -} -#endif - -LM_STATUS LM_SendPacket (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) -{ - LM_UINT32 FragCount; - PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd; - T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT]; - LM_UINT32 StartIdx, Idx; - - while (1) { - /* Initalize the send buffer descriptors. */ - StartIdx = Idx = pDevice->SendProdIdx; - - if (pDevice->NicSendBd) { - pTmpSendBd = pSendBd = &NicSendBdArr[0]; - } else { - pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx]; - } - - /* Next producer index. */ - for (FragCount = 0;;) { - LM_UINT32 Value32, Len; - - /* Initialize the pointer to the send buffer fragment. */ - MM_MapTxDma (pDevice, pPacket, &pSendBd->HostAddr, &Len, - FragCount); - - pSendBd->u2.VlanTag = pPacket->VlanTag; - - /* Setup the control flags and send buffer size. */ - Value32 = (Len << 16) | pPacket->Flags; - - Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; - - FragCount++; - if (FragCount >= pPacket->u.Tx.FragCount) { - pSendBd->u1.Len_Flags = - Value32 | SND_BD_FLAG_END; - break; - } else { - pSendBd->u1.Len_Flags = Value32; - } - pSendBd++; - if ((Idx == 0) && !pDevice->NicSendBd) { - pSendBd = &pDevice->pSendBdVirt[0]; - } - } /* for */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - if (LM_Test4GBoundary (pDevice, pPacket, pTmpSendBd) == - LM_STATUS_SUCCESS) { - if (MM_CoalesceTxBuffer (pDevice, pPacket) != - LM_STATUS_SUCCESS) { - QQ_PushHead (&pDevice->TxPacketFreeQ. - Container, pPacket); - return LM_STATUS_FAILURE; - } - continue; - } - } - break; - } - /* Put the packet descriptor in the ActiveQ. */ - QQ_PushTail (&pDevice->TxPacketActiveQ.Container, pPacket); - - if (pDevice->NicSendBd) { - pSendBd = &pDevice->pSendBdVirt[StartIdx]; - pShadowSendBd = &pDevice->ShadowSendBd[StartIdx]; - - while (StartIdx != Idx) { - LM_UINT32 Value32; - - if ((Value32 = pTmpSendBd->HostAddr.High) != - pShadowSendBd->HostAddr.High) { - __raw_writel (Value32, - &(pSendBd->HostAddr.High)); - pShadowSendBd->HostAddr.High = Value32; - } - - __raw_writel (pTmpSendBd->HostAddr.Low, - &(pSendBd->HostAddr.Low)); - - if ((Value32 = pTmpSendBd->u1.Len_Flags) != - pShadowSendBd->u1.Len_Flags) { - __raw_writel (Value32, - &(pSendBd->u1.Len_Flags)); - pShadowSendBd->u1.Len_Flags = Value32; - } - - if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { - __raw_writel (pTmpSendBd->u2.VlanTag, - &(pSendBd->u2.VlanTag)); - } - - StartIdx = - (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; - if (StartIdx == 0) - pSendBd = &pDevice->pSendBdVirt[0]; - else - pSendBd++; - pTmpSendBd++; - } - wmb (); - MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); - - if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { - MB_REG_WR (pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); - } - } else { - wmb (); - MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); - - if (T3_CHIP_REV (pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) { - MB_REG_WR (pDevice, Mailbox.SendHostProdIdx[0].Low, - Idx); - } - } - - /* Update the SendBdLeft count. */ - atomic_sub (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); - - /* Update the producer index. */ - pDevice->SendProdIdx = Idx; - - return LM_STATUS_SUCCESS; -} - -STATIC LM_STATUS -LM_Test4GBoundary (PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket, - PT3_SND_BD pSendBd) -{ - int FragCount; - LM_UINT32 Idx, Base, Len; - - Idx = pDevice->SendProdIdx; - for (FragCount = 0;;) { - Len = pSendBd->u1.Len_Flags >> 16; - if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) && - (pSendBd->HostAddr.High == 0) && - ((Base + 8 + Len) < Base)) { - return LM_STATUS_SUCCESS; - } - FragCount++; - if (FragCount >= pPacket->u.Tx.FragCount) { - break; - } - pSendBd++; - if (!pDevice->NicSendBd) { - Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; - if (Idx == 0) { - pSendBd = &pDevice->pSendBdVirt[0]; - } - } - } - return LM_STATUS_FAILURE; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -__inline static unsigned long -ComputeCrc32 (unsigned char *pBuffer, unsigned long BufferSize) -{ - unsigned long Reg; - unsigned long Tmp; - unsigned long j, k; - - Reg = 0xffffffff; - - for (j = 0; j < BufferSize; j++) { - Reg ^= pBuffer[j]; - - for (k = 0; k < 8; k++) { - Tmp = Reg & 0x01; - - Reg >>= 1; - - if (Tmp) { - Reg ^= 0xedb88320; - } - } - } - - return ~Reg; -} /* ComputeCrc32 */ - -/******************************************************************************/ -/* Description: */ -/* This routine sets the receive control register according to ReceiveMask */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_SetReceiveMask (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask) -{ - LM_UINT32 ReceiveMask; - LM_UINT32 RxMode; - LM_UINT32 j, k; - - ReceiveMask = Mask; - - RxMode = pDevice->RxMode; - - if (Mask & LM_ACCEPT_UNICAST) { - Mask &= ~LM_ACCEPT_UNICAST; - } - - if (Mask & LM_ACCEPT_MULTICAST) { - Mask &= ~LM_ACCEPT_MULTICAST; - } - - if (Mask & LM_ACCEPT_ALL_MULTICAST) { - Mask &= ~LM_ACCEPT_ALL_MULTICAST; - } - - if (Mask & LM_ACCEPT_BROADCAST) { - Mask &= ~LM_ACCEPT_BROADCAST; - } - - RxMode &= ~RX_MODE_PROMISCUOUS_MODE; - if (Mask & LM_PROMISCUOUS_MODE) { - RxMode |= RX_MODE_PROMISCUOUS_MODE; - Mask &= ~LM_PROMISCUOUS_MODE; - } - - RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED); - if (Mask & LM_ACCEPT_ERROR_PACKET) { - RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED; - Mask &= ~LM_ACCEPT_ERROR_PACKET; - } - - /* Make sure all the bits are valid before committing changes. */ - if (Mask) { - return LM_STATUS_FAILURE; - } - - /* Commit the new filter. */ - pDevice->RxMode = RxMode; - REG_WR (pDevice, MacCtrl.RxMode, RxMode); - - pDevice->ReceiveMask = ReceiveMask; - - /* Set up the MC hash table. */ - if (ReceiveMask & LM_ACCEPT_ALL_MULTICAST) { - for (k = 0; k < 4; k++) { - REG_WR (pDevice, MacCtrl.HashReg[k], 0xffffffff); - } - } else if (ReceiveMask & LM_ACCEPT_MULTICAST) { - LM_UINT32 HashReg[4]; - - HashReg[0] = 0; - HashReg[1] = 0; - HashReg[2] = 0; - HashReg[3] = 0; - for (j = 0; j < pDevice->McEntryCount; j++) { - LM_UINT32 RegIndex; - LM_UINT32 Bitpos; - LM_UINT32 Crc32; - - Crc32 = - ComputeCrc32 (pDevice->McTable[j], - ETHERNET_ADDRESS_SIZE); - - /* The most significant 7 bits of the CRC32 (no inversion), */ - /* are used to index into one of the possible 128 bit positions. */ - Bitpos = ~Crc32 & 0x7f; - - /* Hash register index. */ - RegIndex = (Bitpos & 0x60) >> 5; - - /* Bit to turn on within a hash register. */ - Bitpos &= 0x1f; - - /* Enable the multicast bit. */ - HashReg[RegIndex] |= (1 << Bitpos); - } - - /* REV_AX has problem with multicast filtering where it uses both */ - /* DA and SA to perform hashing. */ - for (k = 0; k < 4; k++) { - REG_WR (pDevice, MacCtrl.HashReg[k], HashReg[k]); - } - } else { - /* Reject all multicast frames. */ - for (j = 0; j < 4; j++) { - REG_WR (pDevice, MacCtrl.HashReg[j], 0); - } - } - - /* By default, Tigon3 will accept broadcast frames. We need to setup */ - if (ReceiveMask & LM_ACCEPT_BROADCAST) { - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, - REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, - REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, - REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, - REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); - } else { - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, - REJECT_BROADCAST_RULE1_RULE); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, - REJECT_BROADCAST_RULE1_VALUE); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, - REJECT_BROADCAST_RULE2_RULE); - REG_WR (pDevice, - MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, - REJECT_BROADCAST_RULE2_VALUE); - } - - /* disable the rest of the rules. */ - for (j = RCV_LAST_RULE_IDX; j < 16; j++) { - REG_WR (pDevice, MacCtrl.RcvRules[j].Rule, 0); - REG_WR (pDevice, MacCtrl.RcvRules[j].Value, 0); - } - - return LM_STATUS_SUCCESS; -} /* LM_SetReceiveMask */ - -/******************************************************************************/ -/* Description: */ -/* Disable the interrupt and put the transmitter and receiver engines in */ -/* an idle state. Also aborts all pending send requests and receive */ -/* buffers. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_Abort (PLM_DEVICE_BLOCK pDevice) -{ - PLM_PACKET pPacket; - LM_UINT Idx; - - LM_DisableInterrupt (pDevice); - - /* Disable all the state machines. */ - LM_CntrlBlock (pDevice, T3_BLOCK_MAC_RX_ENGINE, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_INITIATOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_PLMT, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_LIST_SELECTOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_INITIATOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_DATA_COMP, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_RX_BD_COMP, LM_DISABLE); - - LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_SELECTOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_INITIATOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_INITIATOR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_DMA_RD, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_SEND_DATA_COMP, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_DMA_COMP, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_SEND_BD_COMP, LM_DISABLE); - - /* Clear TDE bit */ - pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE; - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - - LM_CntrlBlock (pDevice, T3_BLOCK_MAC_TX_ENGINE, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_HOST_COALESING, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_DMA_WR, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_CLUSTER_FREE, LM_DISABLE); - - /* Reset all FTQs */ - REG_WR (pDevice, Ftq.Reset, 0xffffffff); - REG_WR (pDevice, Ftq.Reset, 0x0); - - LM_CntrlBlock (pDevice, T3_BLOCK_MBUF_MANAGER, LM_DISABLE); - LM_CntrlBlock (pDevice, T3_BLOCK_MEM_ARBITOR, LM_DISABLE); - - MM_ACQUIRE_INT_LOCK (pDevice); - - /* Abort packets that have already queued to go out. */ - pPacket = (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ.Container); - while (pPacket) { - - pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED; - pDevice->TxCounters.TxPacketAbortedCnt++; - - atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); - - QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); - - pPacket = (PLM_PACKET) - QQ_PopHead (&pDevice->TxPacketActiveQ.Container); - } - - /* Cleanup the receive return rings. */ - LM_ServiceRxInterrupt (pDevice); - - /* Don't want to indicate rx packets in Ndis miniport shutdown context. */ - /* Doing so may cause system crash. */ - if (!pDevice->ShuttingDown) { - /* Indicate packets to the protocol. */ - MM_IndicateTxPackets (pDevice); - - /* Indicate received packets to the protocols. */ - MM_IndicateRxPackets (pDevice); - } else { - /* Move the receive packet descriptors in the ReceivedQ to the */ - /* free queue. */ - for (;;) { - pPacket = - (PLM_PACKET) QQ_PopHead (&pDevice-> - RxPacketReceivedQ. - Container); - if (pPacket == NULL) { - break; - } - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, - pPacket); - } - } - - /* Clean up the Std Receive Producer ring. */ - Idx = pDevice->pStatusBlkVirt->RcvStdConIdx; - - while (Idx != pDevice->RxStdProdIdx) { - pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + - MM_UINT_PTR (pDevice->pRxStdBdVirt[Idx]. - Opaque)); - - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - - Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK; - } /* while */ - - /* Reinitialize our copy of the indices. */ - pDevice->RxStdProdIdx = 0; - -#if T3_JUMBO_RCV_RCB_ENTRY_COUNT - /* Clean up the Jumbo Receive Producer ring. */ - Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx; - - while (Idx != pDevice->RxJumboProdIdx) { - pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + - MM_UINT_PTR (pDevice-> - pRxJumboBdVirt[Idx]. - Opaque)); - - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - - Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; - } /* while */ - - /* Reinitialize our copy of the indices. */ - pDevice->RxJumboProdIdx = 0; -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ - - MM_RELEASE_INT_LOCK (pDevice); - - /* Initialize the statistis Block */ - pDevice->pStatusBlkVirt->Status = 0; - pDevice->pStatusBlkVirt->RcvStdConIdx = 0; - pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; - pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; - - return LM_STATUS_SUCCESS; -} /* LM_Abort */ - -/******************************************************************************/ -/* Description: */ -/* Disable the interrupt and put the transmitter and receiver engines in */ -/* an idle state. Aborts all pending send requests and receive buffers. */ -/* Also free all the receive buffers. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_Halt (PLM_DEVICE_BLOCK pDevice) -{ - PLM_PACKET pPacket; - LM_UINT32 EntryCnt; - - LM_Abort (pDevice); - - /* Get the number of entries in the queue. */ - EntryCnt = QQ_GetEntryCnt (&pDevice->RxPacketFreeQ.Container); - - /* Make sure all the packets have been accounted for. */ - for (EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++) { - pPacket = - (PLM_PACKET) QQ_PopHead (&pDevice->RxPacketFreeQ.Container); - if (pPacket == 0) - break; - - MM_FreeRxBuffer (pDevice, pPacket); - - QQ_PushTail (&pDevice->RxPacketFreeQ.Container, pPacket); - } - - LM_ResetChip (pDevice); - - /* Restore PCI configuration registers. */ - MM_WriteConfig32 (pDevice, PCI_CACHE_LINE_SIZE_REG, - pDevice->SavedCacheLineReg); - LM_RegWrInd (pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, - (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId); - - /* Reprogram the MAC address. */ - LM_SetMacAddress (pDevice, pDevice->NodeAddress); - - return LM_STATUS_SUCCESS; -} /* LM_Halt */ - -STATIC LM_STATUS LM_ResetChip (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - LM_UINT32 j; - - /* Wait for access to the nvram interface before resetting. This is */ - /* a workaround to prevent EEPROM corruption. */ - if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && - T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { - /* Request access to the flash interface. */ - REG_WR (pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); - - for (j = 0; j < 100000; j++) { - Value32 = REG_RD (pDevice, Nvram.SwArb); - if (Value32 & SW_ARB_GNT1) { - break; - } - MM_Wait (10); - } - } - - /* Global reset. */ - REG_WR (pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET); - MM_Wait (40); - MM_Wait (40); - MM_Wait (40); - - /* make sure we re-enable indirect accesses */ - MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, - pDevice->MiscHostCtrl); - - /* Set MAX PCI retry to zero. */ - Value32 = - T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE; - if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { - if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { - Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; - } - } - MM_WriteConfig32 (pDevice, T3_PCI_STATE_REG, Value32); - - /* Restore PCI command register. */ - MM_WriteConfig32 (pDevice, PCI_COMMAND_REG, - pDevice->PciCommandStatusWords); - - /* Disable PCI-X relaxed ordering bit. */ - MM_ReadConfig32 (pDevice, PCIX_CAP_REG, &Value32); - Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING; - MM_WriteConfig32 (pDevice, PCIX_CAP_REG, Value32); - - /* Enable memory arbiter. */ - REG_WR (pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); - -#ifdef BIG_ENDIAN_PCI /* This from jfd */ - Value32 = GRC_MODE_WORD_SWAP_DATA | GRC_MODE_WORD_SWAP_NON_FRAME_DATA; -#else -#ifdef BIG_ENDIAN_HOST - /* Reconfigure the mode register. */ - Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | - GRC_MODE_WORD_SWAP_NON_FRAME_DATA | - GRC_MODE_BYTE_SWAP_DATA | GRC_MODE_WORD_SWAP_DATA; -#else - /* Reconfigure the mode register. */ - Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; -#endif -#endif - REG_WR (pDevice, Grc.Mode, Value32); - - /* Prevent PXE from restarting. */ - MEM_WR_OFFSET (pDevice, 0x0b50, T3_MAGIC_NUM); - - if (pDevice->EnableTbi) { - pDevice->MacMode = MAC_MODE_PORT_MODE_TBI; - REG_WR (pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI); - } else { - REG_WR (pDevice, MacCtrl.Mode, 0); - } - - /* Wait for the firmware to finish initialization. */ - for (j = 0; j < 100000; j++) { - MM_Wait (10); - - Value32 = MEM_RD_OFFSET (pDevice, 0x0b50); - if (Value32 == ~T3_MAGIC_NUM) { - break; - } - } - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -__inline static void LM_ServiceTxInterrupt (PLM_DEVICE_BLOCK pDevice) -{ - PLM_PACKET pPacket; - LM_UINT32 HwConIdx; - LM_UINT32 SwConIdx; - - HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; - - /* Get our copy of the consumer index. The buffer descriptors */ - /* that are in between the consumer indices are freed. */ - SwConIdx = pDevice->SendConIdx; - - /* Move the packets from the TxPacketActiveQ that are sent out to */ - /* the TxPacketXmittedQ. Packets that are sent use the */ - /* descriptors that are between SwConIdx and HwConIdx. */ - while (SwConIdx != HwConIdx) { - /* Get the packet that was sent from the TxPacketActiveQ. */ - pPacket = - (PLM_PACKET) QQ_PopHead (&pDevice->TxPacketActiveQ. - Container); - - /* Set the return status. */ - pPacket->PacketStatus = LM_STATUS_SUCCESS; - - /* Put the packet in the TxPacketXmittedQ for indication later. */ - QQ_PushTail (&pDevice->TxPacketXmittedQ.Container, pPacket); - - /* Move to the next packet's BD. */ - SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & - T3_SEND_RCB_ENTRY_COUNT_MASK; - - /* Update the number of unused BDs. */ - atomic_add (pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); - - /* Get the new updated HwConIdx. */ - HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; - } /* while */ - - /* Save the new SwConIdx. */ - pDevice->SendConIdx = SwConIdx; - -} /* LM_ServiceTxInterrupt */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -__inline static void LM_ServiceRxInterrupt (PLM_DEVICE_BLOCK pDevice) -{ - PLM_PACKET pPacket; - PT3_RCV_BD pRcvBd; - LM_UINT32 HwRcvRetProdIdx; - LM_UINT32 SwRcvRetConIdx; - - /* Loop thru the receive return rings for received packets. */ - HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; - - SwRcvRetConIdx = pDevice->RcvRetConIdx; - while (SwRcvRetConIdx != HwRcvRetProdIdx) { - pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx]; - - /* Get the received packet descriptor. */ - pPacket = (PLM_PACKET) (MM_UINT_PTR (pDevice->pPacketDescBase) + - MM_UINT_PTR (pRcvBd->Opaque)); - - /* Check the error flag. */ - if (pRcvBd->ErrorFlag && - pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { - pPacket->PacketStatus = LM_STATUS_FAILURE; - - pDevice->RxCounters.RxPacketErrCnt++; - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC) { - pDevice->RxCounters.RxErrCrcCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT) { - pDevice->RxCounters.RxErrCollCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT) { - pDevice->RxCounters.RxErrLinkLostCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR) { - pDevice->RxCounters.RxErrPhyDecodeCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) { - pDevice->RxCounters.RxErrOddNibbleCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT) { - pDevice->RxCounters.RxErrMacAbortCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64) { - pDevice->RxCounters.RxErrShortPacketCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES) { - pDevice->RxCounters.RxErrNoResourceCnt++; - } - - if (pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD) { - pDevice->RxCounters.RxErrLargePacketCnt++; - } - } else { - pPacket->PacketStatus = LM_STATUS_SUCCESS; - pPacket->PacketSize = pRcvBd->Len - 4; - - pPacket->Flags = pRcvBd->Flags; - if (pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG) { - pPacket->VlanTag = pRcvBd->VlanTag; - } - - pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum; - } - - /* Put the packet descriptor containing the received packet */ - /* buffer in the RxPacketReceivedQ for indication later. */ - QQ_PushTail (&pDevice->RxPacketReceivedQ.Container, pPacket); - - /* Go to the next buffer descriptor. */ - SwRcvRetConIdx = (SwRcvRetConIdx + 1) & - T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK; - - /* Get the updated HwRcvRetProdIdx. */ - HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; - } /* while */ - - pDevice->RcvRetConIdx = SwRcvRetConIdx; - - /* Update the receive return ring consumer index. */ - MB_REG_WR (pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx); -} /* LM_ServiceRxInterrupt */ - -/******************************************************************************/ -/* Description: */ -/* This is the interrupt event handler routine. It acknowledges all */ -/* pending interrupts and process all pending events. */ -/* */ -/* Return: */ -/* LM_STATUS_SUCCESS */ -/******************************************************************************/ -LM_STATUS LM_ServiceInterrupts (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - int ServicePhyInt = FALSE; - - /* Setup the phy chip whenever the link status changes. */ - if (pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG) { - Value32 = REG_RD (pDevice, MacCtrl.Status); - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { - if (Value32 & MAC_STATUS_MI_INTERRUPT) { - ServicePhyInt = TRUE; - } - } else if (Value32 & MAC_STATUS_LINK_STATE_CHANGED) { - ServicePhyInt = TRUE; - } - } else { - if (pDevice->pStatusBlkVirt-> - Status & STATUS_BLOCK_LINK_CHANGED_STATUS) { - pDevice->pStatusBlkVirt->Status = - STATUS_BLOCK_UPDATED | (pDevice->pStatusBlkVirt-> - Status & - ~STATUS_BLOCK_LINK_CHANGED_STATUS); - ServicePhyInt = TRUE; - } - } -#if INCLUDE_TBI_SUPPORT - if (pDevice->IgnoreTbiLinkChange == TRUE) { - ServicePhyInt = FALSE; - } -#endif - if (ServicePhyInt == TRUE) { - LM_SetupPhy (pDevice); - } - - /* Service receive and transmit interrupts. */ - LM_ServiceRxInterrupt (pDevice); - LM_ServiceTxInterrupt (pDevice); - - /* No spinlock for this queue since this routine is serialized. */ - if (!QQ_Empty (&pDevice->RxPacketReceivedQ.Container)) { - /* Indicate receive packets. */ - MM_IndicateRxPackets (pDevice); - /* LM_QueueRxPackets(pDevice); */ - } - - /* No spinlock for this queue since this routine is serialized. */ - if (!QQ_Empty (&pDevice->TxPacketXmittedQ.Container)) { - MM_IndicateTxPackets (pDevice); - } - - return LM_STATUS_SUCCESS; -} /* LM_ServiceInterrupts */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_MulticastAdd (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) -{ - PLM_UINT8 pEntry; - LM_UINT32 j; - - pEntry = pDevice->McTable[0]; - for (j = 0; j < pDevice->McEntryCount; j++) { - if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { - /* Found a match, increment the instance count. */ - pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1; - - return LM_STATUS_SUCCESS; - } - - pEntry += LM_MC_ENTRY_SIZE; - } - - if (pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) { - return LM_STATUS_FAILURE; - } - - pEntry = pDevice->McTable[pDevice->McEntryCount]; - - COPY_ETH_ADDRESS (pMcAddress, pEntry); - pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1; - - pDevice->McEntryCount++; - - LM_SetReceiveMask (pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST); - - return LM_STATUS_SUCCESS; -} /* LM_MulticastAdd */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_MulticastDel (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress) -{ - PLM_UINT8 pEntry; - LM_UINT32 j; - - pEntry = pDevice->McTable[0]; - for (j = 0; j < pDevice->McEntryCount; j++) { - if (IS_ETH_ADDRESS_EQUAL (pEntry, pMcAddress)) { - /* Found a match, decrement the instance count. */ - pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1; - - /* No more instance left, remove the address from the table. */ - /* Move the last entry in the table to the delete slot. */ - if (pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 && - pDevice->McEntryCount > 1) { - - COPY_ETH_ADDRESS (pDevice-> - McTable[pDevice-> - McEntryCount - 1], - pEntry); - pEntry[LM_MC_INSTANCE_COUNT_INDEX] = - pDevice->McTable[pDevice->McEntryCount - 1] - [LM_MC_INSTANCE_COUNT_INDEX]; - } - pDevice->McEntryCount--; - - /* Update the receive mask if the table is empty. */ - if (pDevice->McEntryCount == 0) { - LM_SetReceiveMask (pDevice, - pDevice-> - ReceiveMask & - ~LM_ACCEPT_MULTICAST); - } - - return LM_STATUS_SUCCESS; - } - - pEntry += LM_MC_ENTRY_SIZE; - } - - return LM_STATUS_FAILURE; -} /* LM_MulticastDel */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_MulticastClear (PLM_DEVICE_BLOCK pDevice) -{ - pDevice->McEntryCount = 0; - - LM_SetReceiveMask (pDevice, - pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); - - return LM_STATUS_SUCCESS; -} /* LM_MulticastClear */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_SetMacAddress (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress) -{ - LM_UINT32 j; - - for (j = 0; j < 4; j++) { - REG_WR (pDevice, MacCtrl.MacAddr[j].High, - (pMacAddress[0] << 8) | pMacAddress[1]); - REG_WR (pDevice, MacCtrl.MacAddr[j].Low, - (pMacAddress[2] << 24) | (pMacAddress[3] << 16) | - (pMacAddress[4] << 8) | pMacAddress[5]); - } - - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* Sets up the default line speed, and duplex modes based on the requested */ -/* media type. */ -/* */ -/* Return: */ -/* None. */ -/******************************************************************************/ -static LM_STATUS -LM_TranslateRequestedMediaType (LM_REQUESTED_MEDIA_TYPE RequestedMediaType, - PLM_MEDIA_TYPE pMediaType, - PLM_LINE_SPEED pLineSpeed, - PLM_DUPLEX_MODE pDuplexMode) -{ - *pMediaType = LM_MEDIA_TYPE_AUTO; - *pLineSpeed = LM_LINE_SPEED_UNKNOWN; - *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN; - - /* determine media type */ - switch (RequestedMediaType) { - case LM_REQUESTED_MEDIA_TYPE_BNC: - *pMediaType = LM_MEDIA_TYPE_BNC; - *pLineSpeed = LM_LINE_SPEED_10MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO: - *pMediaType = LM_MEDIA_TYPE_UTP; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_10MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_10MBPS; - *pDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_100MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_100MBPS; - *pDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_1000MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX: - *pMediaType = LM_MEDIA_TYPE_UTP; - *pLineSpeed = LM_LINE_SPEED_1000MBPS; - *pDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS: - *pMediaType = LM_MEDIA_TYPE_FIBER; - *pLineSpeed = LM_LINE_SPEED_100MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX: - *pMediaType = LM_MEDIA_TYPE_FIBER; - *pLineSpeed = LM_LINE_SPEED_100MBPS; - *pDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS: - *pMediaType = LM_MEDIA_TYPE_FIBER; - *pLineSpeed = LM_LINE_SPEED_1000MBPS; - *pDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX: - *pMediaType = LM_MEDIA_TYPE_FIBER; - *pLineSpeed = LM_LINE_SPEED_1000MBPS; - *pDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - default: - break; - } /* switch */ - - return LM_STATUS_SUCCESS; -} /* LM_TranslateRequestedMediaType */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* LM_STATUS_LINK_ACTIVE */ -/* LM_STATUS_LINK_DOWN */ -/******************************************************************************/ -static LM_STATUS LM_InitBcm540xPhy (PLM_DEVICE_BLOCK pDevice) -{ - LM_LINE_SPEED CurrentLineSpeed; - LM_DUPLEX_MODE CurrentDuplexMode; - LM_STATUS CurrentLinkStatus; - LM_UINT32 Value32; - LM_UINT32 j; - -#if 1 /* jmb: bugfix -- moved here, out of code that sets initial pwr state */ - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x2); -#endif - if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) { - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - - if (!pDevice->InitDone) { - Value32 = 0; - } - - if (!(Value32 & PHY_STATUS_LINK_PASS)) { - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x0c20); - - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1804); - - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x1204); - - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0132); - - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0232); - - LM_WritePhy (pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); - LM_WritePhy (pDevice, BCM540X_DSP_RW_PORT, 0x0a20); - - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - for (j = 0; j < 1000; j++) { - MM_Wait (10); - - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - if (Value32 & PHY_STATUS_LINK_PASS) { - MM_Wait (40); - break; - } - } - - if ((pDevice->PhyId & PHY_ID_REV_MASK) == - PHY_BCM5401_B0_REV) { - if (!(Value32 & PHY_STATUS_LINK_PASS) - && (pDevice->OldLineSpeed == - LM_LINE_SPEED_1000MBPS)) { - LM_WritePhy (pDevice, PHY_CTRL_REG, - PHY_CTRL_PHY_RESET); - for (j = 0; j < 100; j++) { - MM_Wait (10); - - LM_ReadPhy (pDevice, - PHY_CTRL_REG, - &Value32); - if (! - (Value32 & - PHY_CTRL_PHY_RESET)) { - MM_Wait (40); - break; - } - } - - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, - 0x0c20); - - LM_WritePhy (pDevice, - BCM540X_DSP_ADDRESS_REG, - 0x0012); - LM_WritePhy (pDevice, - BCM540X_DSP_RW_PORT, - 0x1804); - - LM_WritePhy (pDevice, - BCM540X_DSP_ADDRESS_REG, - 0x0013); - LM_WritePhy (pDevice, - BCM540X_DSP_RW_PORT, - 0x1204); - - LM_WritePhy (pDevice, - BCM540X_DSP_ADDRESS_REG, - 0x8006); - LM_WritePhy (pDevice, - BCM540X_DSP_RW_PORT, - 0x0132); - - LM_WritePhy (pDevice, - BCM540X_DSP_ADDRESS_REG, - 0x8006); - LM_WritePhy (pDevice, - BCM540X_DSP_RW_PORT, - 0x0232); - - LM_WritePhy (pDevice, - BCM540X_DSP_ADDRESS_REG, - 0x201f); - LM_WritePhy (pDevice, - BCM540X_DSP_RW_PORT, - 0x0a20); - } - } - } - } else if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { - /* Bug: 5701 A0, B0 TX CRC workaround. */ - LM_WritePhy (pDevice, 0x15, 0x0a75); - LM_WritePhy (pDevice, 0x1c, 0x8c68); - LM_WritePhy (pDevice, 0x1c, 0x8d68); - LM_WritePhy (pDevice, 0x1c, 0x8c68); - } - - /* Acknowledge interrupts. */ - LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, BCM540X_INT_STATUS_REG, &Value32); - - /* Configure the interrupt mask. */ - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { - LM_WritePhy (pDevice, BCM540X_INT_MASK_REG, - ~BCM540X_INT_LINK_CHANGE); - } - - /* Configure PHY led mode. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701 || - (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700)) { - if (pDevice->LedMode == LED_MODE_THREE_LINK) { - LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, - BCM540X_EXT_CTRL_LINK3_LED_MODE); - } else { - LM_WritePhy (pDevice, BCM540X_EXT_CTRL_REG, 0); - } - } - - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - - /* Get current link and duplex mode. */ - for (j = 0; j < 100; j++) { - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - - if (Value32 & PHY_STATUS_LINK_PASS) { - break; - } - MM_Wait (40); - } - - if (Value32 & PHY_STATUS_LINK_PASS) { - - /* Determine the current line and duplex settings. */ - LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); - for (j = 0; j < 2000; j++) { - MM_Wait (10); - - LM_ReadPhy (pDevice, BCM540X_AUX_STATUS_REG, &Value32); - if (Value32) { - break; - } - } - - switch (Value32 & BCM540X_AUX_SPEED_MASK) { - case BCM540X_AUX_10BASET_HD: - CurrentLineSpeed = LM_LINE_SPEED_10MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case BCM540X_AUX_10BASET_FD: - CurrentLineSpeed = LM_LINE_SPEED_10MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case BCM540X_AUX_100BASETX_HD: - CurrentLineSpeed = LM_LINE_SPEED_100MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case BCM540X_AUX_100BASETX_FD: - CurrentLineSpeed = LM_LINE_SPEED_100MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - case BCM540X_AUX_100BASET_HD: - CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_HALF; - break; - - case BCM540X_AUX_100BASET_FD: - CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; - CurrentDuplexMode = LM_DUPLEX_MODE_FULL; - break; - - default: - - CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN; - CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN; - break; - } - - /* Make sure we are in auto-neg mode. */ - for (j = 0; j < 200; j++) { - LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); - if (Value32 && Value32 != 0x7fff) { - break; - } - - if (Value32 == 0 && pDevice->RequestedMediaType == - LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS) { - break; - } - - MM_Wait (10); - } - - /* Use the current line settings for "auto" mode. */ - if (pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO - || pDevice->RequestedMediaType == - LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { - if (Value32 & PHY_CTRL_AUTO_NEG_ENABLE) { - CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; - - /* We may be exiting low power mode and the link is in */ - /* 10mb. In this case, we need to restart autoneg. */ - LM_ReadPhy (pDevice, BCM540X_1000BASET_CTRL_REG, - &Value32); - pDevice->advertising1000 = Value32; - /* 5702FE supports 10/100Mb only. */ - if (T3_ASIC_REV (pDevice->ChipRevId) != - T3_ASIC_REV_5703 - || pDevice->BondId != - GRC_MISC_BD_ID_5702FE) { - if (! - (Value32 & - (BCM540X_AN_AD_1000BASET_HALF | - BCM540X_AN_AD_1000BASET_FULL))) { - CurrentLinkStatus = - LM_STATUS_LINK_SETTING_MISMATCH; - } - } - } else { - CurrentLinkStatus = - LM_STATUS_LINK_SETTING_MISMATCH; - } - } else { - /* Force line settings. */ - /* Use the current setting if it matches the user's requested */ - /* setting. */ - LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); - if ((pDevice->LineSpeed == CurrentLineSpeed) && - (pDevice->DuplexMode == CurrentDuplexMode)) { - if ((pDevice->DisableAutoNeg && - !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) || - (!pDevice->DisableAutoNeg && - (Value32 & PHY_CTRL_AUTO_NEG_ENABLE))) { - CurrentLinkStatus = - LM_STATUS_LINK_ACTIVE; - } else { - CurrentLinkStatus = - LM_STATUS_LINK_SETTING_MISMATCH; - } - } else { - CurrentLinkStatus = - LM_STATUS_LINK_SETTING_MISMATCH; - } - } - - /* Save line settings. */ - pDevice->LineSpeed = CurrentLineSpeed; - pDevice->DuplexMode = CurrentDuplexMode; - pDevice->MediaType = LM_MEDIA_TYPE_UTP; - } - - return CurrentLinkStatus; -} /* LM_InitBcm540xPhy */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS -LM_SetFlowControl (PLM_DEVICE_BLOCK pDevice, - LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd) -{ - LM_FLOW_CONTROL FlowCap; - - /* Resolve flow control. */ - FlowCap = LM_FLOW_CONTROL_NONE; - - /* See Table 28B-3 of 802.3ab-1999 spec. */ - if (pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE) { - if (LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE) { - if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { - if (RemotePhyAd & - PHY_LINK_PARTNER_PAUSE_CAPABLE) { - FlowCap = - LM_FLOW_CONTROL_TRANSMIT_PAUSE | - LM_FLOW_CONTROL_RECEIVE_PAUSE; - } else if (RemotePhyAd & - PHY_LINK_PARTNER_ASYM_PAUSE) { - FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - } else { - if (RemotePhyAd & - PHY_LINK_PARTNER_PAUSE_CAPABLE) { - FlowCap = - LM_FLOW_CONTROL_TRANSMIT_PAUSE | - LM_FLOW_CONTROL_RECEIVE_PAUSE; - } - } - } else if (LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) { - if ((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) && - (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)) { - FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE; - } - } - } else { - FlowCap = pDevice->FlowControlCap; - } - - /* Enable/disable rx PAUSE. */ - pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL; - if (FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE && - (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || - pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)) { - pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; - pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL; - - } - REG_WR (pDevice, MacCtrl.RxMode, pDevice->RxMode); - - /* Enable/disable tx PAUSE. */ - pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL; - if (FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE && - (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || - pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) { - pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; - pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL; - - } - REG_WR (pDevice, MacCtrl.TxMode, pDevice->TxMode); - - return LM_STATUS_SUCCESS; -} - -#if INCLUDE_TBI_SUPPORT -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -STATIC LM_STATUS LM_InitBcm800xPhy (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - LM_UINT32 j; - - Value32 = REG_RD (pDevice, MacCtrl.Status); - - /* Reset the SERDES during init and when we have link. */ - if (!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED) { - /* Set PLL lock range. */ - LM_WritePhy (pDevice, 0x16, 0x8007); - - /* Software reset. */ - LM_WritePhy (pDevice, 0x00, 0x8000); - - /* Wait for reset to complete. */ - for (j = 0; j < 500; j++) { - MM_Wait (10); - } - - /* Config mode; seletct PMA/Ch 1 regs. */ - LM_WritePhy (pDevice, 0x10, 0x8411); - - /* Enable auto-lock and comdet, select txclk for tx. */ - LM_WritePhy (pDevice, 0x11, 0x0a10); - - LM_WritePhy (pDevice, 0x18, 0x00a0); - LM_WritePhy (pDevice, 0x16, 0x41ff); - - /* Assert and deassert POR. */ - LM_WritePhy (pDevice, 0x13, 0x0400); - MM_Wait (40); - LM_WritePhy (pDevice, 0x13, 0x0000); - - LM_WritePhy (pDevice, 0x11, 0x0a50); - MM_Wait (40); - LM_WritePhy (pDevice, 0x11, 0x0a10); - - /* Delay for signal to stabilize. */ - for (j = 0; j < 15000; j++) { - MM_Wait (10); - } - - /* Deselect the channel register so we can read the PHY id later. */ - LM_WritePhy (pDevice, 0x10, 0x8011); - } - - return LM_STATUS_SUCCESS; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -STATIC LM_STATUS LM_SetupFiberPhy (PLM_DEVICE_BLOCK pDevice) -{ - LM_STATUS CurrentLinkStatus; - AUTONEG_STATUS AnStatus = 0; - LM_UINT32 Value32; - LM_UINT32 Cnt; - LM_UINT32 j, k; - - pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK); - - /* Initialize the send_config register. */ - REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); - - /* Enable TBI and full duplex mode. */ - pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI; - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - - /* Initialize the BCM8002 SERDES PHY. */ - switch (pDevice->PhyId & PHY_ID_MASK) { - case PHY_BCM8002_PHY_ID: - LM_InitBcm800xPhy (pDevice); - break; - - default: - break; - } - - /* Enable link change interrupt. */ - REG_WR (pDevice, MacCtrl.MacEvent, - MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); - - /* Default to link down. */ - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - - /* Get the link status. */ - Value32 = REG_RD (pDevice, MacCtrl.Status); - if (Value32 & MAC_STATUS_PCS_SYNCED) { - if ((pDevice->RequestedMediaType == - LM_REQUESTED_MEDIA_TYPE_AUTO) - || (pDevice->DisableAutoNeg == FALSE)) { - /* auto-negotiation mode. */ - /* Initialize the autoneg default capaiblities. */ - AutonegInit (&pDevice->AnInfo); - - /* Set the context pointer to point to the main device structure. */ - pDevice->AnInfo.pContext = pDevice; - - /* Setup flow control advertisement register. */ - Value32 = GetPhyAdFlowCntrlSettings (pDevice); - if (Value32 & PHY_AN_AD_PAUSE_CAPABLE) { - pDevice->AnInfo.mr_adv_sym_pause = 1; - } else { - pDevice->AnInfo.mr_adv_sym_pause = 0; - } - - if (Value32 & PHY_AN_AD_ASYM_PAUSE) { - pDevice->AnInfo.mr_adv_asym_pause = 1; - } else { - pDevice->AnInfo.mr_adv_asym_pause = 0; - } - - /* Try to autoneg up to six times. */ - if (pDevice->IgnoreTbiLinkChange) { - Cnt = 1; - } else { - Cnt = 6; - } - for (j = 0; j < Cnt; j++) { - REG_WR (pDevice, MacCtrl.TxAutoNeg, 0); - - Value32 = - pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK; - REG_WR (pDevice, MacCtrl.Mode, Value32); - MM_Wait (20); - - REG_WR (pDevice, MacCtrl.Mode, - pDevice-> - MacMode | MAC_MODE_SEND_CONFIGS); - - MM_Wait (20); - - pDevice->AnInfo.State = AN_STATE_UNKNOWN; - pDevice->AnInfo.CurrentTime_us = 0; - - REG_WR (pDevice, Grc.Timer, 0); - for (k = 0; - (pDevice->AnInfo.CurrentTime_us < 75000) - && (k < 75000); k++) { - AnStatus = - Autoneg8023z (&pDevice->AnInfo); - - if ((AnStatus == AUTONEG_STATUS_DONE) || - (AnStatus == AUTONEG_STATUS_FAILED)) - { - break; - } - - pDevice->AnInfo.CurrentTime_us = - REG_RD (pDevice, Grc.Timer); - - } - if ((AnStatus == AUTONEG_STATUS_DONE) || - (AnStatus == AUTONEG_STATUS_FAILED)) { - break; - } - if (j >= 1) { - if (!(REG_RD (pDevice, MacCtrl.Status) & - MAC_STATUS_PCS_SYNCED)) { - break; - } - } - } - - /* Stop sending configs. */ - MM_AnTxIdle (&pDevice->AnInfo); - - /* Resolve flow control settings. */ - if ((AnStatus == AUTONEG_STATUS_DONE) && - pDevice->AnInfo.mr_an_complete - && pDevice->AnInfo.mr_link_ok - && pDevice->AnInfo.mr_lp_adv_full_duplex) { - LM_UINT32 RemotePhyAd; - LM_UINT32 LocalPhyAd; - - LocalPhyAd = 0; - if (pDevice->AnInfo.mr_adv_sym_pause) { - LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE; - } - - if (pDevice->AnInfo.mr_adv_asym_pause) { - LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE; - } - - RemotePhyAd = 0; - if (pDevice->AnInfo.mr_lp_adv_sym_pause) { - RemotePhyAd |= - PHY_LINK_PARTNER_PAUSE_CAPABLE; - } - - if (pDevice->AnInfo.mr_lp_adv_asym_pause) { - RemotePhyAd |= - PHY_LINK_PARTNER_ASYM_PAUSE; - } - - LM_SetFlowControl (pDevice, LocalPhyAd, - RemotePhyAd); - - CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; - } - for (j = 0; j < 30; j++) { - MM_Wait (20); - REG_WR (pDevice, MacCtrl.Status, - MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED); - MM_Wait (20); - if ((REG_RD (pDevice, MacCtrl.Status) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - if (pDevice->PollTbiLink) { - Value32 = REG_RD (pDevice, MacCtrl.Status); - if (Value32 & MAC_STATUS_RECEIVING_CFG) { - pDevice->IgnoreTbiLinkChange = TRUE; - } else { - pDevice->IgnoreTbiLinkChange = FALSE; - } - } - Value32 = REG_RD (pDevice, MacCtrl.Status); - if (CurrentLinkStatus == LM_STATUS_LINK_DOWN && - (Value32 & MAC_STATUS_PCS_SYNCED) && - ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0)) { - CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; - } - } else { - /* We are forcing line speed. */ - pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE; - LM_SetFlowControl (pDevice, 0, 0); - - CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | - MAC_MODE_SEND_CONFIGS); - } - } - /* Set the link polarity bit. */ - pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - - pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED | - (pDevice->pStatusBlkVirt-> - Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS); - - for (j = 0; j < 100; j++) { - REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED); - MM_Wait (5); - if ((REG_RD (pDevice, MacCtrl.Status) & - (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - - Value32 = REG_RD (pDevice, MacCtrl.Status); - if ((Value32 & MAC_STATUS_PCS_SYNCED) == 0) { - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - if (pDevice->DisableAutoNeg == FALSE) { - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode | - MAC_MODE_SEND_CONFIGS); - MM_Wait (1); - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - } - } - - /* Initialize the current link status. */ - if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { - pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS; - pDevice->DuplexMode = LM_DUPLEX_MODE_FULL; - REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_1000MBPS_LED_ON); - } else { - pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN; - pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN; - REG_WR (pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_OVERRIDE_TRAFFIC_LED); - } - - /* Indicate link status. */ - if (pDevice->LinkStatus != CurrentLinkStatus) { - pDevice->LinkStatus = CurrentLinkStatus; - MM_IndicateStatus (pDevice, CurrentLinkStatus); - } - - return LM_STATUS_SUCCESS; -} -#endif /* INCLUDE_TBI_SUPPORT */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_SetupCopperPhy (PLM_DEVICE_BLOCK pDevice) -{ - LM_STATUS CurrentLinkStatus; - LM_UINT32 Value32; - - /* Assume there is not link first. */ - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - - /* Disable phy link change attention. */ - REG_WR (pDevice, MacCtrl.MacEvent, 0); - - /* Clear link change attention. */ - REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED); - - /* Disable auto-polling for the moment. */ - pDevice->MiMode = 0xc0000; - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - MM_Wait (40); - - /* Determine the requested line speed and duplex. */ - pDevice->OldLineSpeed = pDevice->LineSpeed; - LM_TranslateRequestedMediaType (pDevice->RequestedMediaType, - &pDevice->MediaType, - &pDevice->LineSpeed, - &pDevice->DuplexMode); - - /* Initialize the phy chip. */ - switch (pDevice->PhyId & PHY_ID_MASK) { - case PHY_BCM5400_PHY_ID: - case PHY_BCM5401_PHY_ID: - case PHY_BCM5411_PHY_ID: - case PHY_BCM5701_PHY_ID: - case PHY_BCM5703_PHY_ID: - case PHY_BCM5704_PHY_ID: - CurrentLinkStatus = LM_InitBcm540xPhy (pDevice); - break; - - default: - break; - } - - if (CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH) { - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - } - - /* Setup flow control. */ - pDevice->FlowControl = LM_FLOW_CONTROL_NONE; - if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { - LM_FLOW_CONTROL FlowCap; /* Flow control capability. */ - - FlowCap = LM_FLOW_CONTROL_NONE; - - if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) { - if (pDevice->DisableAutoNeg == FALSE || - pDevice->RequestedMediaType == - LM_REQUESTED_MEDIA_TYPE_AUTO - || pDevice->RequestedMediaType == - LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { - LM_UINT32 ExpectedPhyAd; - LM_UINT32 LocalPhyAd; - LM_UINT32 RemotePhyAd; - - LM_ReadPhy (pDevice, PHY_AN_AD_REG, - &LocalPhyAd); - pDevice->advertising = LocalPhyAd; - LocalPhyAd &= - (PHY_AN_AD_ASYM_PAUSE | - PHY_AN_AD_PAUSE_CAPABLE); - - ExpectedPhyAd = - GetPhyAdFlowCntrlSettings (pDevice); - - if (LocalPhyAd != ExpectedPhyAd) { - CurrentLinkStatus = LM_STATUS_LINK_DOWN; - } else { - LM_ReadPhy (pDevice, - PHY_LINK_PARTNER_ABILITY_REG, - &RemotePhyAd); - - LM_SetFlowControl (pDevice, LocalPhyAd, - RemotePhyAd); - } - } else { - pDevice->FlowControlCap &= - ~LM_FLOW_CONTROL_AUTO_PAUSE; - LM_SetFlowControl (pDevice, 0, 0); - } - } - } - - if (CurrentLinkStatus == LM_STATUS_LINK_DOWN) { - LM_ForceAutoNeg (pDevice, pDevice->RequestedMediaType); - - /* If we force line speed, we make get link right away. */ - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - if (Value32 & PHY_STATUS_LINK_PASS) { - CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; - } - } - - /* GMII interface. */ - pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK; - if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { - if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS || - pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) { - pDevice->MacMode |= MAC_MODE_PORT_MODE_MII; - } else { - pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; - } - } else { - pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; - } - - /* Set the MAC to operate in the appropriate duplex mode. */ - pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX; - if (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF) { - pDevice->MacMode |= MAC_MODE_HALF_DUPLEX; - } - - /* Set the link polarity bit. */ - pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - if ((pDevice->LedMode == LED_MODE_LINK10) || - (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE && - pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)) { - pDevice->MacMode |= MAC_MODE_LINK_POLARITY; - } - } else { - if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) { - pDevice->MacMode |= MAC_MODE_LINK_POLARITY; - } - - /* Set LED mode. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = LED_CTRL_PHY_MODE_1; - } else { - if (pDevice->LedMode == LED_MODE_OUTPUT) { - Value32 = LED_CTRL_PHY_MODE_2; - } else { - Value32 = LED_CTRL_PHY_MODE_1; - } - } - REG_WR (pDevice, MacCtrl.LedCtrl, Value32); - } - - REG_WR (pDevice, MacCtrl.Mode, pDevice->MacMode); - - /* Enable auto polling. */ - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE; - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - } - - /* Enable phy link change attention. */ - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) { - REG_WR (pDevice, MacCtrl.MacEvent, - MAC_EVENT_ENABLE_MI_INTERRUPT); - } else { - REG_WR (pDevice, MacCtrl.MacEvent, - MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); - } - if ((T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) && - (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) && - (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && - (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) && - (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) || - !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))) { - MM_Wait (120); - REG_WR (pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED); - MEM_WR_OFFSET (pDevice, T3_FIRMWARE_MAILBOX, - T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE); - } - - /* Indicate link status. */ - if (pDevice->LinkStatus != CurrentLinkStatus) { - pDevice->LinkStatus = CurrentLinkStatus; - MM_IndicateStatus (pDevice, CurrentLinkStatus); - } - - return LM_STATUS_SUCCESS; -} /* LM_SetupCopperPhy */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_SetupPhy (PLM_DEVICE_BLOCK pDevice) -{ - LM_STATUS LmStatus; - LM_UINT32 Value32; - -#if INCLUDE_TBI_SUPPORT - if (pDevice->EnableTbi) { - LmStatus = LM_SetupFiberPhy (pDevice); - } else -#endif /* INCLUDE_TBI_SUPPORT */ - { - LmStatus = LM_SetupCopperPhy (pDevice); - } - if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) { - if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) { - Value32 = REG_RD (pDevice, PciCfg.PciState); - REG_WR (pDevice, PciCfg.PciState, - Value32 | T3_PCI_STATE_RETRY_SAME_DMA); - } - } - if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && - (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)) { - REG_WR (pDevice, MacCtrl.TxLengths, 0x26ff); - } else { - REG_WR (pDevice, MacCtrl.TxLengths, 0x2620); - } - - return LmStatus; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_VOID -LM_ReadPhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, PLM_UINT32 pData32) -{ - LM_UINT32 Value32; - LM_UINT32 j; - - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & - ~MI_MODE_AUTO_POLLING_ENABLE); - MM_Wait (40); - } - - Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | - ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << - MI_COM_FIRST_PHY_REG_ADDR_BIT) | MI_COM_CMD_READ | MI_COM_START; - - REG_WR (pDevice, MacCtrl.MiCom, Value32); - - for (j = 0; j < 20; j++) { - MM_Wait (25); - - Value32 = REG_RD (pDevice, MacCtrl.MiCom); - - if (!(Value32 & MI_COM_BUSY)) { - MM_Wait (5); - Value32 = REG_RD (pDevice, MacCtrl.MiCom); - Value32 &= MI_COM_PHY_DATA_MASK; - break; - } - } - - if (Value32 & MI_COM_BUSY) { - Value32 = 0; - } - - *pData32 = Value32; - - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - MM_Wait (40); - } -} /* LM_ReadPhy */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_VOID -LM_WritePhy (PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, LM_UINT32 Data32) -{ - LM_UINT32 Value32; - LM_UINT32 j; - - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode & - ~MI_MODE_AUTO_POLLING_ENABLE); - MM_Wait (40); - } - - Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | - ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << - MI_COM_FIRST_PHY_REG_ADDR_BIT) | (Data32 & MI_COM_PHY_DATA_MASK) | - MI_COM_CMD_WRITE | MI_COM_START; - - REG_WR (pDevice, MacCtrl.MiCom, Value32); - - for (j = 0; j < 20; j++) { - MM_Wait (25); - - Value32 = REG_RD (pDevice, MacCtrl.MiCom); - - if (!(Value32 & MI_COM_BUSY)) { - MM_Wait (5); - break; - } - } - - if (pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) { - REG_WR (pDevice, MacCtrl.MiMode, pDevice->MiMode); - MM_Wait (40); - } -} /* LM_WritePhy */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_SetPowerState (PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel) -{ - LM_UINT32 PmeSupport; - LM_UINT32 Value32; - LM_UINT32 PmCtrl; - - /* make sureindirect accesses are enabled */ - MM_WriteConfig32 (pDevice, T3_PCI_MISC_HOST_CTRL_REG, - pDevice->MiscHostCtrl); - - /* Clear the PME_ASSERT bit and the power state bits. Also enable */ - /* the PME bit. */ - MM_ReadConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl); - - PmCtrl |= T3_PM_PME_ASSERTED; - PmCtrl &= ~T3_PM_POWER_STATE_MASK; - - /* Set the appropriate power state. */ - if (PowerLevel == LM_POWER_STATE_D0) { - - /* Bring the card out of low power mode. */ - PmCtrl |= T3_PM_POWER_STATE_D0; - MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); - - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); - MM_Wait (40); -#if 0 /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */ - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x02); -#endif - - return LM_STATUS_SUCCESS; - } else if (PowerLevel == LM_POWER_STATE_D1) { - PmCtrl |= T3_PM_POWER_STATE_D1; - } else if (PowerLevel == LM_POWER_STATE_D2) { - PmCtrl |= T3_PM_POWER_STATE_D2; - } else if (PowerLevel == LM_POWER_STATE_D3) { - PmCtrl |= T3_PM_POWER_STATE_D3; - } else { - return LM_STATUS_FAILURE; - } - PmCtrl |= T3_PM_PME_ENABLE; - - /* Mask out all interrupts so LM_SetupPhy won't be called while we are */ - /* setting new line speed. */ - Value32 = REG_RD (pDevice, PciCfg.MiscHostCtrl); - REG_WR (pDevice, PciCfg.MiscHostCtrl, - Value32 | MISC_HOST_CTRL_MASK_PCI_INT); - - if (!pDevice->RestoreOnWakeUp) { - pDevice->RestoreOnWakeUp = TRUE; - pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg; - pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType; - } - - /* Force auto-negotiation to 10 line speed. */ - pDevice->DisableAutoNeg = FALSE; - pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; - LM_SetupPhy (pDevice); - - /* Put the driver in the initial state, and go through the power down */ - /* sequence. */ - LM_Halt (pDevice); - - MM_ReadConfig32 (pDevice, T3_PCI_PM_CAP_REG, &PmeSupport); - - if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) { - - /* Enable WOL. */ - LM_WritePhy (pDevice, BCM5401_AUX_CTRL, 0x5a); - MM_Wait (40); - - /* Set LED mode. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = LED_CTRL_PHY_MODE_1; - } else { - if (pDevice->LedMode == LED_MODE_OUTPUT) { - Value32 = LED_CTRL_PHY_MODE_2; - } else { - Value32 = LED_CTRL_PHY_MODE_1; - } - } - - Value32 = MAC_MODE_PORT_MODE_MII; - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700) { - if (pDevice->LedMode == LED_MODE_LINK10 || - pDevice->WolSpeed == WOL_SPEED_10MB) { - Value32 |= MAC_MODE_LINK_POLARITY; - } - } else { - Value32 |= MAC_MODE_LINK_POLARITY; - } - REG_WR (pDevice, MacCtrl.Mode, Value32); - MM_Wait (40); - MM_Wait (40); - MM_Wait (40); - - /* Always enable magic packet wake-up if we have vaux. */ - if ((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && - (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET)) { - Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE; - } - - REG_WR (pDevice, MacCtrl.Mode, Value32); - - /* Enable the receiver. */ - REG_WR (pDevice, MacCtrl.RxMode, RX_MODE_ENABLE); - } - - /* Disable tx/rx clocks, and seletect an alternate clock. */ - if (pDevice->WolSpeed == WOL_SPEED_100MB) { - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = - T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | - T3_PCI_SELECT_ALTERNATE_CLOCK; - } else { - Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK; - } - REG_WR (pDevice, PciCfg.ClockCtrl, Value32); - - MM_Wait (40); - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = - T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | - T3_PCI_SELECT_ALTERNATE_CLOCK | - T3_PCI_44MHZ_CORE_CLOCK; - } else { - Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | - T3_PCI_44MHZ_CORE_CLOCK; - } - - REG_WR (pDevice, PciCfg.ClockCtrl, Value32); - - MM_Wait (40); - - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = - T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | - T3_PCI_44MHZ_CORE_CLOCK; - } else { - Value32 = T3_PCI_44MHZ_CORE_CLOCK; - } - - REG_WR (pDevice, PciCfg.ClockCtrl, Value32); - } else { - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - Value32 = - T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | - T3_PCI_SELECT_ALTERNATE_CLOCK | - T3_PCI_POWER_DOWN_PCI_PLL133; - } else { - Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | - T3_PCI_POWER_DOWN_PCI_PLL133; - } - - REG_WR (pDevice, PciCfg.ClockCtrl, Value32); - } - - MM_Wait (40); - - if (!pDevice->EepromWp - && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)) { - /* Switch adapter to auxilliary power. */ - if (T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5700 || - T3_ASIC_REV (pDevice->ChipRevId) == T3_ASIC_REV_5701) { - /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_GPIO_OE0 | - GRC_MISC_LOCAL_CTRL_GPIO_OE1 | - GRC_MISC_LOCAL_CTRL_GPIO_OE2 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); - MM_Wait (40); - } else { - /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */ - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_GPIO_OE0 | - GRC_MISC_LOCAL_CTRL_GPIO_OE1 | - GRC_MISC_LOCAL_CTRL_GPIO_OE2 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); - MM_Wait (40); - - /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */ - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_GPIO_OE0 | - GRC_MISC_LOCAL_CTRL_GPIO_OE1 | - GRC_MISC_LOCAL_CTRL_GPIO_OE2 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); - MM_Wait (40); - - /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ - REG_WR (pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | - GRC_MISC_LOCAL_CTRL_GPIO_OE0 | - GRC_MISC_LOCAL_CTRL_GPIO_OE1 | - GRC_MISC_LOCAL_CTRL_GPIO_OE2 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | - GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); - MM_Wait (40); - } - } - - /* Set the phy to low power mode. */ - /* Put the the hardware in low power mode. */ - MM_WriteConfig32 (pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); - - return LM_STATUS_SUCCESS; -} /* LM_SetPowerState */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -static LM_UINT32 GetPhyAdFlowCntrlSettings (PLM_DEVICE_BLOCK pDevice) -{ - LM_UINT32 Value32; - - Value32 = 0; - - /* Auto negotiation flow control only when autonegotiation is enabled. */ - if (pDevice->DisableAutoNeg == FALSE || - pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || - pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) { - /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */ - if ((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) || - ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) - && (pDevice-> - FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) { - Value32 |= PHY_AN_AD_PAUSE_CAPABLE; - } else if (pDevice-> - FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE) { - Value32 |= PHY_AN_AD_ASYM_PAUSE; - } else if (pDevice-> - FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) { - Value32 |= - PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; - } - } - - return Value32; -} - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/* LM_STATUS_FAILURE */ -/* LM_STATUS_SUCCESS */ -/* */ -/******************************************************************************/ -static LM_STATUS -LM_ForceAutoNegBcm540xPhy (PLM_DEVICE_BLOCK pDevice, - LM_REQUESTED_MEDIA_TYPE RequestedMediaType) -{ - LM_MEDIA_TYPE MediaType; - LM_LINE_SPEED LineSpeed; - LM_DUPLEX_MODE DuplexMode; - LM_UINT32 NewPhyCtrl; - LM_UINT32 Value32; - LM_UINT32 Cnt; - - /* Get the interface type, line speed, and duplex mode. */ - LM_TranslateRequestedMediaType (RequestedMediaType, &MediaType, - &LineSpeed, &DuplexMode); - - if (pDevice->RestoreOnWakeUp) { - LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); - pDevice->advertising1000 = 0; - Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF; - if (pDevice->WolSpeed == WOL_SPEED_100MB) { - Value32 |= - PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; - } - Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - } - /* Setup the auto-negotiation advertisement register. */ - else if (LineSpeed == LM_LINE_SPEED_UNKNOWN) { - /* Setup the 10/100 Mbps auto-negotiation advertisement register. */ - Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | - PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL | - PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - - /* Advertise 1000Mbps */ - Value32 = - BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL; - -#if INCLUDE_5701_AX_FIX - /* Bug: workaround for CRC error in gigabit mode when we are in */ - /* slave mode. This will force the PHY to operate in */ - /* master mode. */ - if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || - pDevice->ChipRevId == T3_CHIP_ID_5701_B0) { - Value32 |= BCM540X_CONFIG_AS_MASTER | - BCM540X_ENABLE_CONFIG_AS_MASTER; - } -#endif - - LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, Value32); - pDevice->advertising1000 = Value32; - } else { - if (LineSpeed == LM_LINE_SPEED_1000MBPS) { - Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - - if (DuplexMode != LM_DUPLEX_MODE_FULL) { - Value32 = BCM540X_AN_AD_1000BASET_HALF; - } else { - Value32 = BCM540X_AN_AD_1000BASET_FULL; - } - - LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, - Value32); - pDevice->advertising1000 = Value32; - } else if (LineSpeed == LM_LINE_SPEED_100MBPS) { - LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); - pDevice->advertising1000 = 0; - - if (DuplexMode != LM_DUPLEX_MODE_FULL) { - Value32 = PHY_AN_AD_100BASETX_HALF; - } else { - Value32 = PHY_AN_AD_100BASETX_FULL; - } - - Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - } else if (LineSpeed == LM_LINE_SPEED_10MBPS) { - LM_WritePhy (pDevice, BCM540X_1000BASET_CTRL_REG, 0); - pDevice->advertising1000 = 0; - - if (DuplexMode != LM_DUPLEX_MODE_FULL) { - Value32 = PHY_AN_AD_10BASET_HALF; - } else { - Value32 = PHY_AN_AD_10BASET_FULL; - } - - Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; - Value32 |= GetPhyAdFlowCntrlSettings (pDevice); - - LM_WritePhy (pDevice, PHY_AN_AD_REG, Value32); - pDevice->advertising = Value32; - } - } - - /* Force line speed if auto-negotiation is disabled. */ - if (pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN) { - /* This code path is executed only when there is link. */ - pDevice->MediaType = MediaType; - pDevice->LineSpeed = LineSpeed; - pDevice->DuplexMode = DuplexMode; - - /* Force line seepd. */ - NewPhyCtrl = 0; - switch (LineSpeed) { - case LM_LINE_SPEED_10MBPS: - NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS; - break; - case LM_LINE_SPEED_100MBPS: - NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS; - break; - case LM_LINE_SPEED_1000MBPS: - NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; - break; - default: - NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; - break; - } - - if (DuplexMode == LM_DUPLEX_MODE_FULL) { - NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE; - } - - /* Don't do anything if the PHY_CTRL is already what we wanted. */ - LM_ReadPhy (pDevice, PHY_CTRL_REG, &Value32); - if (Value32 != NewPhyCtrl) { - /* Temporary bring the link down before forcing line speed. */ - LM_WritePhy (pDevice, PHY_CTRL_REG, - PHY_CTRL_LOOPBACK_MODE); - - /* Wait for link to go down. */ - for (Cnt = 0; Cnt < 15000; Cnt++) { - MM_Wait (10); - - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - LM_ReadPhy (pDevice, PHY_STATUS_REG, &Value32); - - if (!(Value32 & PHY_STATUS_LINK_PASS)) { - MM_Wait (40); - break; - } - } - - LM_WritePhy (pDevice, PHY_CTRL_REG, NewPhyCtrl); - MM_Wait (40); - } - } else { - LM_WritePhy (pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE | - PHY_CTRL_RESTART_AUTO_NEG); - } - - return LM_STATUS_SUCCESS; -} /* LM_ForceAutoNegBcm540xPhy */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -static LM_STATUS -LM_ForceAutoNeg (PLM_DEVICE_BLOCK pDevice, - LM_REQUESTED_MEDIA_TYPE RequestedMediaType) -{ - LM_STATUS LmStatus; - - /* Initialize the phy chip. */ - switch (pDevice->PhyId & PHY_ID_MASK) { - case PHY_BCM5400_PHY_ID: - case PHY_BCM5401_PHY_ID: - case PHY_BCM5411_PHY_ID: - case PHY_BCM5701_PHY_ID: - case PHY_BCM5703_PHY_ID: - case PHY_BCM5704_PHY_ID: - LmStatus = - LM_ForceAutoNegBcm540xPhy (pDevice, RequestedMediaType); - break; - - default: - LmStatus = LM_STATUS_FAILURE; - break; - } - - return LmStatus; -} /* LM_ForceAutoNeg */ - -/******************************************************************************/ -/* Description: */ -/* */ -/* Return: */ -/******************************************************************************/ -LM_STATUS LM_LoadFirmware (PLM_DEVICE_BLOCK pDevice, - PT3_FWIMG_INFO pFwImg, - LM_UINT32 LoadCpu, LM_UINT32 StartCpu) -{ - LM_UINT32 i; - LM_UINT32 address; - - if (LoadCpu & T3_RX_CPU_ID) { - if (LM_HaltCpu (pDevice, T3_RX_CPU_ID) != LM_STATUS_SUCCESS) { - return LM_STATUS_FAILURE; - } - - /* First of all clear scrach pad memory */ - for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i += 4) { - LM_RegWrInd (pDevice, T3_RX_CPU_SPAD_ADDR + i, 0); - } - - /* Copy code first */ - address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); - for (i = 0; i <= pFwImg->Text.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->Text.Buffer)[i / - 4]); - } - - address = - T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); - for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->ROnlyData. - Buffer)[i / 4]); - } - - address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); - for (i = 0; i <= pFwImg->Data.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->Data.Buffer)[i / - 4]); - } - } - - if (LoadCpu & T3_TX_CPU_ID) { - if (LM_HaltCpu (pDevice, T3_TX_CPU_ID) != LM_STATUS_SUCCESS) { - return LM_STATUS_FAILURE; - } - - /* First of all clear scrach pad memory */ - for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i += 4) { - LM_RegWrInd (pDevice, T3_TX_CPU_SPAD_ADDR + i, 0); - } - - /* Copy code first */ - address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); - for (i = 0; i <= pFwImg->Text.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->Text.Buffer)[i / - 4]); - } - - address = - T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); - for (i = 0; i <= pFwImg->ROnlyData.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->ROnlyData. - Buffer)[i / 4]); - } - - address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); - for (i = 0; i <= pFwImg->Data.Length; i += 4) { - LM_RegWrInd (pDevice, address + i, - ((LM_UINT32 *) pFwImg->Data.Buffer)[i / - 4]); - } - } - - if (StartCpu & T3_RX_CPU_ID) { - /* Start Rx CPU */ - REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); - REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); - for (i = 0; i < 5; i++) { - if (pFwImg->StartAddress == - REG_RD (pDevice, rxCpu.reg.PC)) - break; - - REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); - REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); - REG_WR (pDevice, rxCpu.reg.PC, pFwImg->StartAddress); - MM_Wait (1000); - } - - REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); - REG_WR (pDevice, rxCpu.reg.mode, 0); - } - - if (StartCpu & T3_TX_CPU_ID) { - /* Start Tx CPU */ - REG_WR (pDevice, txCpu.reg.state, 0xffffffff); - REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); - for (i = 0; i < 5; i++) { - if (pFwImg->StartAddress == - REG_RD (pDevice, txCpu.reg.PC)) - break; - - REG_WR (pDevice, txCpu.reg.state, 0xffffffff); - REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); - REG_WR (pDevice, txCpu.reg.PC, pFwImg->StartAddress); - MM_Wait (1000); - } - - REG_WR (pDevice, txCpu.reg.state, 0xffffffff); - REG_WR (pDevice, txCpu.reg.mode, 0); - } - - return LM_STATUS_SUCCESS; -} - -STATIC LM_STATUS LM_HaltCpu (PLM_DEVICE_BLOCK pDevice, LM_UINT32 cpu_number) -{ - LM_UINT32 i; - - if (cpu_number == T3_RX_CPU_ID) { - for (i = 0; i < 10000; i++) { - REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); - REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); - - if (REG_RD (pDevice, rxCpu.reg.mode) & CPU_MODE_HALT) - break; - } - - REG_WR (pDevice, rxCpu.reg.state, 0xffffffff); - REG_WR (pDevice, rxCpu.reg.mode, CPU_MODE_HALT); - MM_Wait (10); - } else { - for (i = 0; i < 10000; i++) { - REG_WR (pDevice, txCpu.reg.state, 0xffffffff); - REG_WR (pDevice, txCpu.reg.mode, CPU_MODE_HALT); - - if (REG_RD (pDevice, txCpu.reg.mode) & CPU_MODE_HALT) - break; - } - } - - return ((i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS); -} - -int LM_BlinkLED (PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec) -{ - LM_UINT32 Oldcfg; - int j; - int ret = 0; - - if (BlinkDurationSec == 0) { - return 0; - } - if (BlinkDurationSec > 120) { - BlinkDurationSec = 120; - } - - Oldcfg = REG_RD (pDevice, MacCtrl.LedCtrl); - for (j = 0; j < BlinkDurationSec * 2; j++) { - if (j % 2) { - /* Turn on the LEDs. */ - REG_WR (pDevice, MacCtrl.LedCtrl, - LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_1000MBPS_LED_ON | - LED_CTRL_100MBPS_LED_ON | - LED_CTRL_10MBPS_LED_ON | - LED_CTRL_OVERRIDE_TRAFFIC_LED | - LED_CTRL_BLINK_TRAFFIC_LED | - LED_CTRL_TRAFFIC_LED); - } else { - /* Turn off the LEDs. */ - REG_WR (pDevice, MacCtrl.LedCtrl, - LED_CTRL_OVERRIDE_LINK_LED | - LED_CTRL_OVERRIDE_TRAFFIC_LED); - } - -#ifndef EMBEDDED - current->state = TASK_INTERRUPTIBLE; - if (schedule_timeout (HZ / 2) != 0) { - ret = -EINTR; - break; - } -#else - udelay (100000); /* 1s sleep */ -#endif - } - REG_WR (pDevice, MacCtrl.LedCtrl, Oldcfg); - return ret; -} - -int t3_do_dma (PLM_DEVICE_BLOCK pDevice, - LM_PHYSICAL_ADDRESS host_addr_phy, int length, int dma_read) -{ - T3_DMA_DESC dma_desc; - int i; - LM_UINT32 dma_desc_addr; - LM_UINT32 value32; - - REG_WR (pDevice, BufMgr.Mode, 0); - REG_WR (pDevice, Ftq.Reset, 0); - - dma_desc.host_addr.High = host_addr_phy.High; - dma_desc.host_addr.Low = host_addr_phy.Low; - dma_desc.nic_mbuf = 0x2100; - dma_desc.len = length; - dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */ - - if (dma_read) { - dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) | - T3_QID_DMA_HIGH_PRI_READ; - REG_WR (pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE); - } else { - dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) | - T3_QID_DMA_HIGH_PRI_WRITE; - REG_WR (pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE); - } - - dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR; - - /* Writing this DMA descriptor to DMA memory */ - for (i = 0; i < sizeof (T3_DMA_DESC); i += 4) { - value32 = *((PLM_UINT32) (((PLM_UINT8) & dma_desc) + i)); - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, - dma_desc_addr + i); - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_DATA_REG, - cpu_to_le32 (value32)); - } - MM_WriteConfig32 (pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0); - - if (dma_read) - REG_WR (pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, - dma_desc_addr); - else - REG_WR (pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, - dma_desc_addr); - - for (i = 0; i < 40; i++) { - if (dma_read) - value32 = - REG_RD (pDevice, - Ftq.RcvBdCompFtqFifoEnqueueDequeue); - else - value32 = - REG_RD (pDevice, - Ftq.RcvDataCompFtqFifoEnqueueDequeue); - - if ((value32 & 0xffff) == dma_desc_addr) - break; - - MM_Wait (10); - } - - return LM_STATUS_SUCCESS; -} - -STATIC LM_STATUS -LM_DmaTest (PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, - LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize) -{ - int j; - LM_UINT32 *ptr; - int dma_success = 0; - - if (T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5700 && - T3_ASIC_REV (pDevice->ChipRevId) != T3_ASIC_REV_5701) { - return LM_STATUS_SUCCESS; - } - while (!dma_success) { - /* Fill data with incremental patterns */ - ptr = (LM_UINT32 *) pBufferVirt; - for (j = 0; j < BufferSize / 4; j++) - *ptr++ = j; - - if (t3_do_dma (pDevice, BufferPhy, BufferSize, 1) == - LM_STATUS_FAILURE) { - return LM_STATUS_FAILURE; - } - - MM_Wait (40); - ptr = (LM_UINT32 *) pBufferVirt; - /* Fill data with zero */ - for (j = 0; j < BufferSize / 4; j++) - *ptr++ = 0; - - if (t3_do_dma (pDevice, BufferPhy, BufferSize, 0) == - LM_STATUS_FAILURE) { - return LM_STATUS_FAILURE; - } - - MM_Wait (40); - /* Check for data */ - ptr = (LM_UINT32 *) pBufferVirt; - for (j = 0; j < BufferSize / 4; j++) { - if (*ptr++ != j) { - if ((pDevice-> - DmaReadWriteCtrl & - DMA_CTRL_WRITE_BOUNDARY_MASK) - == DMA_CTRL_WRITE_BOUNDARY_DISABLE) { - pDevice->DmaReadWriteCtrl = - (pDevice-> - DmaReadWriteCtrl & - ~DMA_CTRL_WRITE_BOUNDARY_MASK) | - DMA_CTRL_WRITE_BOUNDARY_16; - REG_WR (pDevice, - PciCfg.DmaReadWriteCtrl, - pDevice->DmaReadWriteCtrl); - break; - } else { - return LM_STATUS_FAILURE; - } - } - } - if (j == (BufferSize / 4)) - dma_success = 1; - } - return LM_STATUS_SUCCESS; -} - -#endif diff --git a/drivers/tigon3.h b/drivers/tigon3.h deleted file mode 100644 index c03347fdc9..0000000000 --- a/drivers/tigon3.h +++ /dev/null @@ -1,3339 +0,0 @@ - -/******************************************************************************/ -/* */ -/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ -/* Corporation. */ -/* All rights reserved. */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, located in the file LICENSE. */ -/* */ -/* History: */ -/* */ -/******************************************************************************/ - -#ifndef TIGON3_H -#define TIGON3_H - -#include "bcm570x_lm.h" -#if INCLUDE_TBI_SUPPORT -#include "bcm570x_autoneg.h" -#endif - -/* io defines */ -#if !defined(BIG_ENDIAN_HOST) -#define readl(addr) \ - (LONGSWAP((*(volatile unsigned int *)(addr)))) -#define writel(b,addr) \ - ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b))) -#else -#if 0 /* !defined(PPC603) */ -#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr))) -#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b)) -#else -#if 1 -#define readl(addr) (*(volatile unsigned int*)(addr)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) -#else -extern int sprintf (char *buf, const char *f, ...); -static __inline unsigned int readl (void *addr) -{ - char buf[128]; - unsigned int tmp = (*(volatile unsigned int *)(addr)); - sprintf (buf, "%s:%s: read 0x%x from 0x%x\n", __FILE__, __LINE__, tmp, - addr, 0, 0); - sysSerialPrintString (buf); - return tmp; -} -static __inline void writel (unsigned int b, unsigned int addr) -{ - char buf[128]; - ((*(volatile unsigned int *)(addr)) = (b)); - sprintf (buf, "%s:%s: write 0x%x to 0x%x\n", __FILE__, __LINE__, b, - addr, 0, 0); - sysSerialPrintString (buf); -} -#endif -#endif /* PPC603 */ -#endif - -/******************************************************************************/ -/* Constants. */ -/******************************************************************************/ - -/* Maxim number of packet descriptors used for sending packets. */ -#define MAX_TX_PACKET_DESC_COUNT 600 -#define DEFAULT_TX_PACKET_DESC_COUNT 2 - -/* Maximum number of packet descriptors used for receiving packets. */ -#if T3_JUMBO_RCB_ENTRY_COUNT -#define MAX_RX_PACKET_DESC_COUNT \ - (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT) -#else -#define MAX_RX_PACKET_DESC_COUNT 800 -#endif -#define DEFAULT_RX_PACKET_DESC_COUNT 2 - -/* Threshhold for double copying small tx packets. 0 will disable double */ -/* copying of small Tx packets. */ -#define DEFAULT_TX_COPY_BUFFER_SIZE 0 -#define MIN_TX_COPY_BUFFER_SIZE 64 -#define MAX_TX_COPY_BUFFER_SIZE 512 - -/* Cache line. */ -#define COMMON_CACHE_LINE_SIZE 0x20 -#define COMMON_CACHE_LINE_MASK (COMMON_CACHE_LINE_SIZE-1) - -/* Maximum number of fragment we can handle. */ -#ifndef MAX_FRAGMENT_COUNT -#define MAX_FRAGMENT_COUNT 32 -#endif - -/* B0 bug. */ -#define BCM5700_BX_MIN_FRAG_SIZE 10 -#define BCM5700_BX_MIN_FRAG_BUF_SIZE 16 /* nice aligned size. */ -#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK (BCM5700_BX_MIN_FRAG_BUF_SIZE-1) -#define BCM5700_BX_TX_COPY_BUF_SIZE (BCM5700_BX_MIN_FRAG_BUF_SIZE * \ - MAX_FRAGMENT_COUNT) - -/* MAGIC number. */ -/* #define T3_MAGIC_NUM 'KevT' */ -#define T3_FIRMWARE_MAILBOX 0x0b50 -#define T3_MAGIC_NUM 0x4B657654 -#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b - -#define T3_NIC_DATA_SIG_ADDR 0x0b54 -#define T3_NIC_DATA_SIG 0x4b657654 - -#define T3_NIC_DATA_NIC_CFG_ADDR 0x0b58 -#define T3_NIC_CFG_LED_MODE_UNKNOWN BIT_NONE -#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED BIT_2 -#define T3_NIC_CFG_LED_MODE_LINK_SPEED BIT_3 -#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN BIT_2 -#define T3_NIC_CFG_LED_MODE_OUTPUT BIT_3 -#define T3_NIC_CFG_LED_MODE_MASK (BIT_2 | BIT_3) -#define T3_NIC_CFG_PHY_TYPE_UNKNOWN BIT_NONE -#define T3_NIC_CFG_PHY_TYPE_COPPER BIT_4 -#define T3_NIC_CFG_PHY_TYPE_FIBER BIT_5 -#define T3_NIC_CFG_PHY_TYPE_MASK (BIT_4 | BIT_5) -#define T3_NIC_CFG_ENABLE_WOL BIT_6 -#define T3_NIC_CFG_ENABLE_ASF BIT_7 -#define T3_NIC_EEPROM_WP BIT_8 - -#define T3_NIC_DATA_PHY_ID_ADDR 0x0b74 -#define T3_NIC_PHY_ID1_MASK 0xffff0000 -#define T3_NIC_PHY_ID2_MASK 0x0000ffff - -#define T3_CMD_MAILBOX 0x0b78 -#define T3_CMD_NICDRV_ALIVE 0x01 -#define T3_CMD_NICDRV_PAUSE_FW 0x02 -#define T3_CMD_NICDRV_IPV4ADDR_CHANGE 0x03 -#define T3_CMD_NICDRV_IPV6ADDR_CHANGE 0x04 -#define T3_CMD_5703A0_FIX_DMAFW_DMAR 0x05 -#define T3_CMD_5703A0_FIX_DMAFW_DMAW 0x06 - -#define T3_CMD_LENGTH_MAILBOX 0x0b7c -#define T3_CMD_DATA_MAILBOX 0x0b80 - -#define T3_ASF_FW_STATUS_MAILBOX 0x0c00 - -#define T3_DRV_STATE_MAILBOX 0x0c04 -#define T3_DRV_STATE_START 0x01 -#define T3_DRV_STATE_UNLOAD 0x02 -#define T3_DRV_STATE_WOL 0x03 -#define T3_DRV_STATE_SUSPEND 0x04 - -#define T3_FW_RESET_TYPE_MAILBOX 0x0c08 - -#define T3_MAC_ADDR_HIGH_MAILBOX 0x0c14 -#define T3_MAC_ADDR_LOW_MAILBOX 0x0c18 - -/******************************************************************************/ -/* Hardware constants. */ -/******************************************************************************/ - -/* Number of entries in the send ring: must be 512. */ -#define T3_SEND_RCB_ENTRY_COUNT 512 -#define T3_SEND_RCB_ENTRY_COUNT_MASK (T3_SEND_RCB_ENTRY_COUNT-1) - -/* Number of send RCBs. May be 1-16 but for now, only support one. */ -#define T3_MAX_SEND_RCB_COUNT 16 - -/* Number of entries in the Standard Receive RCB. Must be 512 entries. */ -#define T3_STD_RCV_RCB_ENTRY_COUNT 512 -#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK (T3_STD_RCV_RCB_ENTRY_COUNT-1) -#define DEFAULT_STD_RCV_DESC_COUNT 200 /* Must be < 512. */ -#define MAX_STD_RCV_BUFFER_SIZE 0x600 - -/* Number of entries in the Mini Receive RCB. This value can either be */ -/* 0, 1024. Currently Mini Receive RCB is disabled. */ -#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT -#define T3_MINI_RCV_RCB_ENTRY_COUNT 0 -#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */ -#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK (T3_MINI_RCV_RCB_ENTRY_COUNT-1) -#define MAX_MINI_RCV_BUFFER_SIZE 512 -#define DEFAULT_MINI_RCV_BUFFER_SIZE 64 -#define DEFAULT_MINI_RCV_DESC_COUNT 100 /* Must be < 1024. */ - -/* Number of entries in the Jumbo Receive RCB. This value must 256 or 0. */ -/* Currently, Jumbo Receive RCB is disabled. */ -#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT -#define T3_JUMBO_RCV_RCB_ENTRY_COUNT 0 -#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ -#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1) - -#define MAX_JUMBO_RCV_BUFFER_SIZE (10 * 1024) /* > 1514 */ -#define DEFAULT_JUMBO_RCV_BUFFER_SIZE (4 * 1024) /* > 1514 */ -#define DEFAULT_JUMBO_RCV_DESC_COUNT 128 /* Must be < 256. */ - -#define MAX_JUMBO_TX_BUFFER_SIZE (8 * 1024) /* > 1514 */ -#define DEFAULT_JUMBO_TX_BUFFER_SIZE (4 * 1024) /* > 1514 */ - -/* Number of receive return RCBs. Maybe 1-16 but for now, only support one. */ -#define T3_MAX_RCV_RETURN_RCB_COUNT 16 - -/* Number of entries in a Receive Return ring. This value is either 1024 */ -/* or 2048. */ -#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT -#define T3_RCV_RETURN_RCB_ENTRY_COUNT 1024 -#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */ -#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK (T3_RCV_RETURN_RCB_ENTRY_COUNT-1) - -/* Default coalescing parameters. */ -#define DEFAULT_RX_COALESCING_TICKS 100 -#define MAX_RX_COALESCING_TICKS 500 -#define DEFAULT_TX_COALESCING_TICKS 400 -#define MAX_TX_COALESCING_TICKS 500 -#define DEFAULT_RX_MAX_COALESCED_FRAMES 10 -#define MAX_RX_MAX_COALESCED_FRAMES 100 -#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES 5 -#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES 42 -#define ADAPTIVE_LO_RX_COALESCING_TICKS 50 -#define ADAPTIVE_HI_RX_COALESCING_TICKS 300 -#define ADAPTIVE_LO_PKT_THRESH 30000 -#define ADAPTIVE_HI_PKT_THRESH 74000 -#define DEFAULT_TX_MAX_COALESCED_FRAMES 40 -#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES 25 -#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES 75 -#define MAX_TX_MAX_COALESCED_FRAMES 100 - -#define DEFAULT_RX_COALESCING_TICKS_DURING_INT 25 -#define DEFAULT_TX_COALESCING_TICKS_DURING_INT 25 -#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT 5 -#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT 5 - -#define BAD_DEFAULT_VALUE 0xffffffff - -#define DEFAULT_STATS_COALESCING_TICKS 1000000 -#define MAX_STATS_COALESCING_TICKS 3600000000U - -/* Receive BD Replenish thresholds. */ -#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD 4 -#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD 4 - -#define SPLIT_MODE_DISABLE 0 -#define SPLIT_MODE_ENABLE 1 - -#define SPLIT_MODE_5704_MAX_REQ 3 - -/* Maximum physical fragment size. */ -#define MAX_FRAGMENT_SIZE (64 * 1024) - -/* Standard view. */ -#define T3_STD_VIEW_SIZE (64 * 1024) -#define T3_FLAT_VIEW_SIZE (32 * 1024 * 1024) - -/* Buffer descriptor base address on the NIC's memory. */ - -#define T3_NIC_SND_BUFFER_DESC_ADDR 0x4000 -#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR 0x6000 -#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR 0x7000 - -#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xc000 -#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xd000 -#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xe000 - -#define T3_NIC_SND_BUFFER_DESC_SIZE (T3_SEND_RCB_ENTRY_COUNT * \ - sizeof(T3_SND_BD) / 4) - -#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE (T3_STD_RCV_RCB_ENTRY_COUNT * \ - sizeof(T3_RCV_BD) / 4) - -#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \ - sizeof(T3_EXT_RCV_BD) / 4) - -/* MBUF pool. */ -#define T3_NIC_MBUF_POOL_ADDR 0x8000 -/* #define T3_NIC_MBUF_POOL_SIZE 0x18000 */ -#define T3_NIC_MBUF_POOL_SIZE96 0x18000 -#define T3_NIC_MBUF_POOL_SIZE64 0x10000 - -#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM 0x20000 - -/* DMA descriptor pool */ -#define T3_NIC_DMA_DESC_POOL_ADDR 0x2000 -#define T3_NIC_DMA_DESC_POOL_SIZE 0x2000 /* 8KB. */ - -#define T3_DEF_DMA_MBUF_LOW_WMARK 0x40 -#define T3_DEF_RX_MAC_MBUF_LOW_WMARK 0x20 -#define T3_DEF_MBUF_HIGH_WMARK 0x60 - -#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO 304 -#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO 152 -#define T3_DEF_MBUF_HIGH_WMARK_JUMBO 380 - -#define T3_DEF_DMA_DESC_LOW_WMARK 5 -#define T3_DEF_DMA_DESC_HIGH_WMARK 10 - -/* Maximum size of giant TCP packet can be sent */ -#define T3_TCP_SEG_MAX_OFFLOAD_SIZE 64*1000 -#define T3_TCP_SEG_MIN_NUM_SEG 20 - -#define T3_RX_CPU_ID 0x1 -#define T3_TX_CPU_ID 0x2 -#define T3_RX_CPU_SPAD_ADDR 0x30000 -#define T3_RX_CPU_SPAD_SIZE 0x4000 -#define T3_TX_CPU_SPAD_ADDR 0x34000 -#define T3_TX_CPU_SPAD_SIZE 0x4000 - -typedef struct T3_DIR_ENTRY { - PLM_UINT8 Buffer; - LM_UINT32 Offset; - LM_UINT32 Length; -} T3_DIR_ENTRY, *PT3_DIR_ENTRY; - -typedef struct T3_FWIMG_INFO { - LM_UINT32 StartAddress; - T3_DIR_ENTRY Text; - T3_DIR_ENTRY ROnlyData; - T3_DIR_ENTRY Data; - T3_DIR_ENTRY Sbss; - T3_DIR_ENTRY Bss; -} T3_FWIMG_INFO, *PT3_FWIMG_INFO; - -/******************************************************************************/ -/* Tigon3 PCI Registers. */ -/******************************************************************************/ -#define T3_PCI_ID_BCM5700 0x164414e4 -#define T3_PCI_ID_BCM5701 0x164514e4 -#define T3_PCI_ID_BCM5702 0x164614e4 -#define T3_PCI_ID_BCM5702x 0x16A614e4 -#define T3_PCI_ID_BCM5703 0x164714e4 -#define T3_PCI_ID_BCM5703x 0x16A714e4 -#define T3_PCI_ID_BCM5702FE 0x164D14e4 -#define T3_PCI_ID_BCM5704 0x164814e4 - -#define T3_PCI_VENDOR_ID (T3_PCI_ID & 0xffff) -#define T3_PCI_DEVICE_ID (T3_PCI_ID >> 16) - -#define T3_PCI_MISC_HOST_CTRL_REG 0x68 - -/* The most significant 16bit of register 0x68. */ -/* ChipId:4, ChipRev:4, MetalRev:8 */ -#define T3_CHIP_ID_5700_A0 0x7000 -#define T3_CHIP_ID_5700_A1 0x7001 -#define T3_CHIP_ID_5700_B0 0x7100 -#define T3_CHIP_ID_5700_B1 0x7101 -#define T3_CHIP_ID_5700_C0 0x7200 - -#define T3_CHIP_ID_5701_A0 0x0000 -#define T3_CHIP_ID_5701_B0 0x0100 -#define T3_CHIP_ID_5701_B2 0x0102 -#define T3_CHIP_ID_5701_B5 0x0105 - -#define T3_CHIP_ID_5703_A0 0x1000 -#define T3_CHIP_ID_5703_A1 0x1001 -#define T3_CHIP_ID_5703_A2 0x1002 - -#define T3_CHIP_ID_5704_A0 0x2000 - -/* Chip Id. */ -#define T3_ASIC_REV(_ChipRevId) ((_ChipRevId) >> 12) -#define T3_ASIC_REV_5700 0x07 -#define T3_ASIC_REV_5701 0x00 -#define T3_ASIC_REV_5703 0x01 -#define T3_ASIC_REV_5704 0x02 - -/* Chip id and revision. */ -#define T3_CHIP_REV(_ChipRevId) ((_ChipRevId) >> 8) -#define T3_CHIP_REV_5700_AX 0x70 -#define T3_CHIP_REV_5700_BX 0x71 -#define T3_CHIP_REV_5700_CX 0x72 -#define T3_CHIP_REV_5701_AX 0x00 - -/* Metal revision. */ -#define T3_METAL_REV(_ChipRevId) ((_ChipRevId) & 0xff) -#define T3_METAL_REV_A0 0x00 -#define T3_METAL_REV_A1 0x01 -#define T3_METAL_REV_B0 0x00 -#define T3_METAL_REV_B1 0x01 -#define T3_METAL_REV_B2 0x02 - -#define T3_PCI_REG_CLOCK_CTRL 0x74 - -#define T3_PCI_DISABLE_RX_CLOCK BIT_10 -#define T3_PCI_DISABLE_TX_CLOCK BIT_11 -#define T3_PCI_SELECT_ALTERNATE_CLOCK BIT_12 -#define T3_PCI_POWER_DOWN_PCI_PLL133 BIT_15 -#define T3_PCI_44MHZ_CORE_CLOCK BIT_18 - -#define T3_PCI_REG_ADDR_REG 0x78 -#define T3_PCI_REG_DATA_REG 0x80 - -#define T3_PCI_MEM_WIN_ADDR_REG 0x7c -#define T3_PCI_MEM_WIN_DATA_REG 0x84 - -#define T3_PCI_PM_CAP_REG 0x48 - -#define T3_PCI_PM_CAP_PME_D3COLD BIT_31 -#define T3_PCI_PM_CAP_PME_D3HOT BIT_30 - -#define T3_PCI_PM_STATUS_CTRL_REG 0x4c - -#define T3_PM_POWER_STATE_MASK (BIT_0 | BIT_1) -#define T3_PM_POWER_STATE_D0 BIT_NONE -#define T3_PM_POWER_STATE_D1 BIT_0 -#define T3_PM_POWER_STATE_D2 BIT_1 -#define T3_PM_POWER_STATE_D3 (BIT_0 | BIT_1) - -#define T3_PM_PME_ENABLE BIT_8 -#define T3_PM_PME_ASSERTED BIT_15 - -/* PCI state register. */ -#define T3_PCI_STATE_REG 0x70 - -#define T3_PCI_STATE_FORCE_RESET BIT_0 -#define T3_PCI_STATE_INT_NOT_ACTIVE BIT_1 -#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE BIT_2 -#define T3_PCI_STATE_BUS_SPEED_HIGH BIT_3 -#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 - -/* Broadcom subsystem/subvendor IDs. */ -#define T3_SVID_BROADCOM 0x14e4 - -#define T3_SSID_BROADCOM_BCM95700A6 0x1644 -#define T3_SSID_BROADCOM_BCM95701A5 0x0001 -#define T3_SSID_BROADCOM_BCM95700T6 0x0002 /* BCM8002 */ -#define T3_SSID_BROADCOM_BCM95700A9 0x0003 /* Agilent */ -#define T3_SSID_BROADCOM_BCM95701T1 0x0005 -#define T3_SSID_BROADCOM_BCM95701T8 0x0006 -#define T3_SSID_BROADCOM_BCM95701A7 0x0007 /* Agilent */ -#define T3_SSID_BROADCOM_BCM95701A10 0x0008 -#define T3_SSID_BROADCOM_BCM95701A12 0x8008 -#define T3_SSID_BROADCOM_BCM95703Ax1 0x0009 -#define T3_SSID_BROADCOM_BCM95703Ax2 0x8009 - -/* 3COM subsystem/subvendor IDs. */ -#define T3_SVID_3COM 0x10b7 - -#define T3_SSID_3COM_3C996T 0x1000 -#define T3_SSID_3COM_3C996BT 0x1006 -#define T3_SSID_3COM_3C996CT 0x1002 -#define T3_SSID_3COM_3C997T 0x1003 -#define T3_SSID_3COM_3C1000T 0x1007 -#define T3_SSID_3COM_3C940BR01 0x1008 - -/* Fiber boards. */ -#define T3_SSID_3COM_3C996SX 0x1004 -#define T3_SSID_3COM_3C997SX 0x1005 - -/* Dell subsystem/subvendor IDs. */ - -#define T3_SVID_DELL 0x1028 - -#define T3_SSID_DELL_VIPER 0x00d1 -#define T3_SSID_DELL_JAGUAR 0x0106 -#define T3_SSID_DELL_MERLOT 0x0109 -#define T3_SSID_DELL_SLIM_MERLOT 0x010a - -/* Compaq subsystem/subvendor IDs */ - -#define T3_SVID_COMPAQ 0x0e11 - -#define T3_SSID_COMPAQ_BANSHEE 0x007c -#define T3_SSID_COMPAQ_BANSHEE_2 0x009a -#define T3_SSID_COMPAQ_CHANGELING 0x007d -#define T3_SSID_COMPAQ_NC7780 0x0085 -#define T3_SSID_COMPAQ_NC7780_2 0x0099 - -/******************************************************************************/ -/* MII registers. */ -/******************************************************************************/ - -/* Control register. */ -#define PHY_CTRL_REG 0x00 - -#define PHY_CTRL_SPEED_MASK (BIT_6 | BIT_13) -#define PHY_CTRL_SPEED_SELECT_10MBPS BIT_NONE -#define PHY_CTRL_SPEED_SELECT_100MBPS BIT_13 -#define PHY_CTRL_SPEED_SELECT_1000MBPS BIT_6 -#define PHY_CTRL_COLLISION_TEST_ENABLE BIT_7 -#define PHY_CTRL_FULL_DUPLEX_MODE BIT_8 -#define PHY_CTRL_RESTART_AUTO_NEG BIT_9 -#define PHY_CTRL_ISOLATE_PHY BIT_10 -#define PHY_CTRL_LOWER_POWER_MODE BIT_11 -#define PHY_CTRL_AUTO_NEG_ENABLE BIT_12 -#define PHY_CTRL_LOOPBACK_MODE BIT_14 -#define PHY_CTRL_PHY_RESET BIT_15 - -/* Status register. */ -#define PHY_STATUS_REG 0x01 - -#define PHY_STATUS_LINK_PASS BIT_2 -#define PHY_STATUS_AUTO_NEG_COMPLETE BIT_5 - -/* Phy Id registers. */ -#define PHY_ID1_REG 0x02 -#define PHY_ID1_OUI_MASK 0xffff - -#define PHY_ID2_REG 0x03 -#define PHY_ID2_REV_MASK 0x000f -#define PHY_ID2_MODEL_MASK 0x03f0 -#define PHY_ID2_OUI_MASK 0xfc00 - -/* Auto-negotiation advertisement register. */ -#define PHY_AN_AD_REG 0x04 - -#define PHY_AN_AD_ASYM_PAUSE BIT_11 -#define PHY_AN_AD_PAUSE_CAPABLE BIT_10 -#define PHY_AN_AD_10BASET_HALF BIT_5 -#define PHY_AN_AD_10BASET_FULL BIT_6 -#define PHY_AN_AD_100BASETX_HALF BIT_7 -#define PHY_AN_AD_100BASETX_FULL BIT_8 -#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD 0x01 - -/* Auto-negotiation Link Partner Ability register. */ -#define PHY_LINK_PARTNER_ABILITY_REG 0x05 - -#define PHY_LINK_PARTNER_ASYM_PAUSE BIT_11 -#define PHY_LINK_PARTNER_PAUSE_CAPABLE BIT_10 - -/* Auto-negotiation expansion register. */ -#define PHY_AN_EXPANSION_REG 0x06 - -/******************************************************************************/ -/* BCM5400 and BCM5401 phy info. */ -/******************************************************************************/ - -#define PHY_DEVICE_ID 1 - -/* OUI: bit 31-10; Model#: bit 9-4; Rev# bit 3-0. */ -#define PHY_UNKNOWN_PHY 0x00000000 -#define PHY_BCM5400_PHY_ID 0x60008040 -#define PHY_BCM5401_PHY_ID 0x60008050 -#define PHY_BCM5411_PHY_ID 0x60008070 -#define PHY_BCM5701_PHY_ID 0x60008110 -#define PHY_BCM5703_PHY_ID 0x60008160 -#define PHY_BCM5704_PHY_ID 0x60008190 -#define PHY_BCM8002_PHY_ID 0x60010140 - -#define PHY_BCM5401_B0_REV 0x1 -#define PHY_BCM5401_B2_REV 0x3 -#define PHY_BCM5401_C0_REV 0x6 - -#define PHY_ID_OUI_MASK 0xfffffc00 -#define PHY_ID_MODEL_MASK 0x000003f0 -#define PHY_ID_REV_MASK 0x0000000f -#define PHY_ID_MASK (PHY_ID_OUI_MASK | \ - PHY_ID_MODEL_MASK) - -#define UNKNOWN_PHY_ID(x) ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \ - (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID)) - -/* 1000Base-T control register. */ -#define BCM540X_1000BASET_CTRL_REG 0x09 - -#define BCM540X_AN_AD_1000BASET_HALF BIT_8 -#define BCM540X_AN_AD_1000BASET_FULL BIT_9 -#define BCM540X_CONFIG_AS_MASTER BIT_11 -#define BCM540X_ENABLE_CONFIG_AS_MASTER BIT_12 - -/* Extended control register. */ -#define BCM540X_EXT_CTRL_REG 0x10 - -#define BCM540X_EXT_CTRL_LINK3_LED_MODE BIT_1 -#define BCM540X_EXT_CTRL_TBI BIT_15 - -/* PHY extended status register. */ -#define BCM540X_EXT_STATUS_REG 0x11 - -#define BCM540X_EXT_STATUS_LINK_PASS BIT_8 - -/* DSP Coefficient Read/Write Port. */ -#define BCM540X_DSP_RW_PORT 0x15 - -/* DSP Coeficient Address Register. */ -#define BCM540X_DSP_ADDRESS_REG 0x17 - -#define BCM540X_DSP_TAP_NUMBER_MASK 0x00 -#define BCM540X_DSP_AGC_A 0x00 -#define BCM540X_DSP_AGC_B 0x01 -#define BCM540X_DSP_MSE_PAIR_STATUS 0x02 -#define BCM540X_DSP_SOFT_DECISION 0x03 -#define BCM540X_DSP_PHASE_REG 0x04 -#define BCM540X_DSP_SKEW 0x05 -#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND 0x06 -#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND 0x07 -#define BCM540X_DSP_LAST_ECHO 0x08 -#define BCM540X_DSP_FREQUENCY 0x09 -#define BCM540X_DSP_PLL_BANDWIDTH 0x0a -#define BCM540X_DSP_PLL_PHASE_OFFSET 0x0b - -#define BCM540X_DSP_FILTER_DCOFFSET (BIT_10 | BIT_11) -#define BCM540X_DSP_FILTER_FEXT3 (BIT_8 | BIT_9 | BIT_11) -#define BCM540X_DSP_FILTER_FEXT2 (BIT_9 | BIT_11) -#define BCM540X_DSP_FILTER_FEXT1 (BIT_8 | BIT_11) -#define BCM540X_DSP_FILTER_FEXT0 BIT_11 -#define BCM540X_DSP_FILTER_NEXT3 (BIT_8 | BIT_9 | BIT_10) -#define BCM540X_DSP_FILTER_NEXT2 (BIT_9 | BIT_10) -#define BCM540X_DSP_FILTER_NEXT1 (BIT_8 | BIT_10) -#define BCM540X_DSP_FILTER_NEXT0 BIT_10 -#define BCM540X_DSP_FILTER_ECHO (BIT_8 | BIT_9) -#define BCM540X_DSP_FILTER_DFE BIT_9 -#define BCM540X_DSP_FILTER_FFE BIT_8 - -#define BCM540X_DSP_CONTROL_ALL_FILTERS BIT_12 - -#define BCM540X_DSP_SEL_CH_0 BIT_NONE -#define BCM540X_DSP_SEL_CH_1 BIT_13 -#define BCM540X_DSP_SEL_CH_2 BIT_14 -#define BCM540X_DSP_SEL_CH_3 (BIT_13 | BIT_14) - -#define BCM540X_CONTROL_ALL_CHANNELS BIT_15 - -/* Auxilliary Control Register (Shadow Register) */ -#define BCM5401_AUX_CTRL 0x18 - -#define BCM5401_SHADOW_SEL_MASK 0x7 -#define BCM5401_SHADOW_SEL_NORMAL 0x00 -#define BCM5401_SHADOW_SEL_10BASET 0x01 -#define BCM5401_SHADOW_SEL_POWER_CONTROL 0x02 -#define BCM5401_SHADOW_SEL_IP_PHONE 0x03 -#define BCM5401_SHADOW_SEL_MISC_TEST1 0x04 -#define BCM5401_SHADOW_SEL_MISC_TEST2 0x05 -#define BCM5401_SHADOW_SEL_IP_PHONE_SEED 0x06 - -/* Shadow register selector == '000' */ -#define BCM5401_SHDW_NORMAL_DIAG_MODE BIT_3 -#define BCM5401_SHDW_NORMAL_DISABLE_MBP BIT_4 -#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR BIT_5 -#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF BIT_6 -#define BCM5401_SHDW_NORMAL_DISABLE_PRF BIT_7 -#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL BIT_NONE -#define BCM5401_SHDW_NORMAL_RX_SLICING_4D BIT_8 -#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D BIT_9 -#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D (BIT_8 | BIT_9) -#define BCM5401_SHDW_NORMAL_TX_6DB_CODING BIT_10 -#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK BIT_11 -#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS BIT_NONE -#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS BIT_12 -#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS BIT_13 -#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS (BIT_12 | BIT_13) -#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH BIT_14 -#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK BIT_15 - -/* Auxilliary status summary. */ -#define BCM540X_AUX_STATUS_REG 0x19 - -#define BCM540X_AUX_LINK_PASS BIT_2 -#define BCM540X_AUX_SPEED_MASK (BIT_8 | BIT_9 | BIT_10) -#define BCM540X_AUX_10BASET_HD BIT_8 -#define BCM540X_AUX_10BASET_FD BIT_9 -#define BCM540X_AUX_100BASETX_HD (BIT_8 | BIT_9) -#define BCM540X_AUX_100BASET4 BIT_10 -#define BCM540X_AUX_100BASETX_FD (BIT_8 | BIT_10) -#define BCM540X_AUX_100BASET_HD (BIT_9 | BIT_10) -#define BCM540X_AUX_100BASET_FD (BIT_8 | BIT_9 | BIT_10) - -/* Interrupt status. */ -#define BCM540X_INT_STATUS_REG 0x1a - -#define BCM540X_INT_LINK_CHANGE BIT_1 -#define BCM540X_INT_SPEED_CHANGE BIT_2 -#define BCM540X_INT_DUPLEX_CHANGE BIT_3 -#define BCM540X_INT_AUTO_NEG_PAGE_RX BIT_10 - -/* Interrupt mask register. */ -#define BCM540X_INT_MASK_REG 0x1b - -/******************************************************************************/ -/* Register definitions. */ -/******************************************************************************/ - -typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER; -typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER; -typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER; - -typedef struct { - /* Big endian format. */ - T3_32BIT_REGISTER High; - T3_32BIT_REGISTER Low; -} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER; - -typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR; - -#define T3_NUM_OF_DMA_DESC 256 -#define T3_NUM_OF_MBUF 768 - -typedef struct { - T3_64BIT_REGISTER host_addr; - T3_32BIT_REGISTER nic_mbuf; - T3_16BIT_REGISTER len; - T3_16BIT_REGISTER cqid_sqid; - T3_32BIT_REGISTER flags; - T3_32BIT_REGISTER opaque1; - T3_32BIT_REGISTER opaque2; - T3_32BIT_REGISTER opaque3; -} T3_DMA_DESC, *PT3_DMA_DESC; - -/******************************************************************************/ -/* Ring control block. */ -/******************************************************************************/ - -typedef struct { - T3_64BIT_REGISTER HostRingAddr; - - union { - struct { -#ifdef BIG_ENDIAN_HOST - T3_16BIT_REGISTER MaxLen; - T3_16BIT_REGISTER Flags; -#else /* BIG_ENDIAN_HOST */ - T3_16BIT_REGISTER Flags; - T3_16BIT_REGISTER MaxLen; -#endif - } s; - - T3_32BIT_REGISTER MaxLen_Flags; - } u; - - T3_32BIT_REGISTER NicRingAddr; -} T3_RCB, *PT3_RCB; - -#define T3_RCB_FLAG_USE_EXT_RECV_BD BIT_0 -#define T3_RCB_FLAG_RING_DISABLED BIT_1 - -/******************************************************************************/ -/* Status block. */ -/******************************************************************************/ - -/* - * Size of status block is actually 0x50 bytes. Use 0x80 bytes for - * cache line alignment. - */ -#define T3_STATUS_BLOCK_SIZE 0x80 - -typedef struct { - volatile LM_UINT32 Status; -#define STATUS_BLOCK_UPDATED BIT_0 -#define STATUS_BLOCK_LINK_CHANGED_STATUS BIT_1 -#define STATUS_BLOCK_ERROR BIT_2 - - volatile LM_UINT32 StatusTag; - -#ifdef BIG_ENDIAN_HOST - volatile LM_UINT16 RcvStdConIdx; - volatile LM_UINT16 RcvJumboConIdx; - - volatile LM_UINT16 Reserved2; - volatile LM_UINT16 RcvMiniConIdx; - - struct { - volatile LM_UINT16 SendConIdx; /* Send consumer index. */ - volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ - } Idx[16]; -#else /* BIG_ENDIAN_HOST */ - volatile LM_UINT16 RcvJumboConIdx; - volatile LM_UINT16 RcvStdConIdx; - - volatile LM_UINT16 RcvMiniConIdx; - volatile LM_UINT16 Reserved2; - - struct { - volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ - volatile LM_UINT16 SendConIdx; /* Send consumer index. */ - } Idx[16]; -#endif -} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK; - -/******************************************************************************/ -/* Receive buffer descriptors. */ -/******************************************************************************/ - -typedef struct { - T3_64BIT_HOST_ADDR HostAddr; - -#ifdef BIG_ENDIAN_HOST - volatile LM_UINT16 Index; - volatile LM_UINT16 Len; - - volatile LM_UINT16 Type; - volatile LM_UINT16 Flags; - - volatile LM_UINT16 IpCksum; - volatile LM_UINT16 TcpUdpCksum; - - volatile LM_UINT16 ErrorFlag; - volatile LM_UINT16 VlanTag; -#else /* BIG_ENDIAN_HOST */ - volatile LM_UINT16 Len; - volatile LM_UINT16 Index; - - volatile LM_UINT16 Flags; - volatile LM_UINT16 Type; - - volatile LM_UINT16 TcpUdpCksum; - volatile LM_UINT16 IpCksum; - - volatile LM_UINT16 VlanTag; - volatile LM_UINT16 ErrorFlag; -#endif - - volatile LM_UINT32 Reserved; - volatile LM_UINT32 Opaque; -} T3_RCV_BD, *PT3_RCV_BD; - -typedef struct { - T3_64BIT_HOST_ADDR HostAddr[3]; - -#ifdef BIG_ENDIAN_HOST - LM_UINT16 Len1; - LM_UINT16 Len2; - - LM_UINT16 Len3; - LM_UINT16 Reserved1; -#else /* BIG_ENDIAN_HOST */ - LM_UINT16 Len2; - LM_UINT16 Len1; - - LM_UINT16 Reserved1; - LM_UINT16 Len3; -#endif - - T3_RCV_BD StdRcvBd; -} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD; - -/* Error flags. */ -#define RCV_BD_ERR_BAD_CRC 0x0001 -#define RCV_BD_ERR_COLL_DETECT 0x0002 -#define RCV_BD_ERR_LINK_LOST_DURING_PKT 0x0004 -#define RCV_BD_ERR_PHY_DECODE_ERR 0x0008 -#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII 0x0010 -#define RCV_BD_ERR_MAC_ABORT 0x0020 -#define RCV_BD_ERR_LEN_LT_64 0x0040 -#define RCV_BD_ERR_TRUNC_NO_RESOURCES 0x0080 -#define RCV_BD_ERR_GIANT_FRAME_RCVD 0x0100 - -/* Buffer descriptor flags. */ -#define RCV_BD_FLAG_END 0x0004 -#define RCV_BD_FLAG_JUMBO_RING 0x0020 -#define RCV_BD_FLAG_VLAN_TAG 0x0040 -#define RCV_BD_FLAG_FRAME_HAS_ERROR 0x0400 -#define RCV_BD_FLAG_MINI_RING 0x0800 -#define RCV_BD_FLAG_IP_CHKSUM_FIELD 0x1000 -#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD 0x2000 -#define RCV_BD_FLAG_TCP_PACKET 0x4000 - -/******************************************************************************/ -/* Send buffer descriptor. */ -/******************************************************************************/ - -typedef struct { - T3_64BIT_HOST_ADDR HostAddr; - - union { - struct { -#ifdef BIG_ENDIAN_HOST - LM_UINT16 Len; - LM_UINT16 Flags; -#else /* BIG_ENDIAN_HOST */ - LM_UINT16 Flags; - LM_UINT16 Len; -#endif - } s1; - - LM_UINT32 Len_Flags; - } u1; - - union { - struct { -#ifdef BIG_ENDIAN_HOST - LM_UINT16 Reserved; - LM_UINT16 VlanTag; -#else /* BIG_ENDIAN_HOST */ - LM_UINT16 VlanTag; - LM_UINT16 Reserved; -#endif - } s2; - - LM_UINT32 VlanTag; - } u2; -} T3_SND_BD, *PT3_SND_BD; - -/* Send buffer descriptor flags. */ -#define SND_BD_FLAG_TCP_UDP_CKSUM 0x0001 -#define SND_BD_FLAG_IP_CKSUM 0x0002 -#define SND_BD_FLAG_END 0x0004 -#define SND_BD_FLAG_IP_FRAG 0x0008 -#define SND_BD_FLAG_IP_FRAG_END 0x0010 -#define SND_BD_FLAG_VLAN_TAG 0x0040 -#define SND_BD_FLAG_COAL_NOW 0x0080 -#define SND_BD_FLAG_CPU_PRE_DMA 0x0100 -#define SND_BD_FLAG_CPU_POST_DMA 0x0200 -#define SND_BD_FLAG_INSERT_SRC_ADDR 0x1000 -#define SND_BD_FLAG_CHOOSE_SRC_ADDR 0x6000 -#define SND_BD_FLAG_DONT_GEN_CRC 0x8000 - -/* MBUFs */ -typedef struct T3_MBUF_FRAME_DESC { -#ifdef BIG_ENDIAN_HOST - LM_UINT32 status_control; - union { - struct { - LM_UINT8 cqid; - LM_UINT8 reserved1; - LM_UINT16 length; - } s1; - LM_UINT32 word; - } u1; - union { - struct { - LM_UINT16 ip_hdr_start; - LM_UINT16 tcp_udp_hdr_start; - } s2; - - LM_UINT32 word; - } u2; - - union { - struct { - LM_UINT16 data_start; - LM_UINT16 vlan_id; - } s3; - - LM_UINT32 word; - } u3; - - union { - struct { - LM_UINT16 ip_checksum; - LM_UINT16 tcp_udp_checksum; - } s4; - - LM_UINT32 word; - } u4; - - union { - struct { - LM_UINT16 pseudo_checksum; - LM_UINT16 checksum_status; - } s5; - - LM_UINT32 word; - } u5; - - union { - struct { - LM_UINT16 rule_match; - LM_UINT8 class; - LM_UINT8 rupt; - } s6; - - LM_UINT32 word; - } u6; - - union { - struct { - LM_UINT16 reserved2; - LM_UINT16 mbuf_num; - } s7; - - LM_UINT32 word; - } u7; - - LM_UINT32 reserved3; - LM_UINT32 reserved4; -#else - LM_UINT32 status_control; - union { - struct { - LM_UINT16 length; - LM_UINT8 reserved1; - LM_UINT8 cqid; - } s1; - LM_UINT32 word; - } u1; - union { - struct { - LM_UINT16 tcp_udp_hdr_start; - LM_UINT16 ip_hdr_start; - } s2; - - LM_UINT32 word; - } u2; - - union { - struct { - LM_UINT16 vlan_id; - LM_UINT16 data_start; - } s3; - - LM_UINT32 word; - } u3; - - union { - struct { - LM_UINT16 tcp_udp_checksum; - LM_UINT16 ip_checksum; - } s4; - - LM_UINT32 word; - } u4; - - union { - struct { - LM_UINT16 checksum_status; - LM_UINT16 pseudo_checksum; - } s5; - - LM_UINT32 word; - } u5; - - union { - struct { - LM_UINT8 rupt; - LM_UINT8 class; - LM_UINT16 rule_match; - } s6; - - LM_UINT32 word; - } u6; - - union { - struct { - LM_UINT16 mbuf_num; - LM_UINT16 reserved2; - } s7; - - LM_UINT32 word; - } u7; - - LM_UINT32 reserved3; - LM_UINT32 reserved4; -#endif -} T3_MBUF_FRAME_DESC, *PT3_MBUF_FRAME_DESC; - -typedef struct T3_MBUF_HDR { - union { - struct { - unsigned int C:1; - unsigned int F:1; - unsigned int reserved1:7; - unsigned int next_mbuf:16; - unsigned int length:7; - } s1; - - LM_UINT32 word; - } u1; - - LM_UINT32 next_frame_ptr; -} T3_MBUF_HDR, *PT3_MBUF_HDR; - -typedef struct T3_MBUF { - T3_MBUF_HDR hdr; - union { - struct { - T3_MBUF_FRAME_DESC frame_hdr; - LM_UINT32 data[20]; - } s1; - - struct { - LM_UINT32 data[30]; - } s2; - } body; -} T3_MBUF, *PT3_MBUF; - -#define T3_MBUF_BASE (T3_NIC_MBUF_POOL_ADDR >> 7) -#define T3_MBUF_END ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7) - -/******************************************************************************/ -/* Statistics block. */ -/******************************************************************************/ - -typedef struct { - LM_UINT8 Reserved0[0x400 - 0x300]; - - /* Statistics maintained by Receive MAC. */ - T3_64BIT_REGISTER ifHCInOctets; - T3_64BIT_REGISTER Reserved1; - T3_64BIT_REGISTER etherStatsFragments; - T3_64BIT_REGISTER ifHCInUcastPkts; - T3_64BIT_REGISTER ifHCInMulticastPkts; - T3_64BIT_REGISTER ifHCInBroadcastPkts; - T3_64BIT_REGISTER dot3StatsFCSErrors; - T3_64BIT_REGISTER dot3StatsAlignmentErrors; - T3_64BIT_REGISTER xonPauseFramesReceived; - T3_64BIT_REGISTER xoffPauseFramesReceived; - T3_64BIT_REGISTER macControlFramesReceived; - T3_64BIT_REGISTER xoffStateEntered; - T3_64BIT_REGISTER dot3StatsFramesTooLong; - T3_64BIT_REGISTER etherStatsJabbers; - T3_64BIT_REGISTER etherStatsUndersizePkts; - T3_64BIT_REGISTER inRangeLengthError; - T3_64BIT_REGISTER outRangeLengthError; - T3_64BIT_REGISTER etherStatsPkts64Octets; - T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets; - T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets; - T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets; - T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets; - T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets; - T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets; - T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets; - T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets; - T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets; - - T3_64BIT_REGISTER Unused1[37]; - - /* Statistics maintained by Transmit MAC. */ - T3_64BIT_REGISTER ifHCOutOctets; - T3_64BIT_REGISTER Reserved2; - T3_64BIT_REGISTER etherStatsCollisions; - T3_64BIT_REGISTER outXonSent; - T3_64BIT_REGISTER outXoffSent; - T3_64BIT_REGISTER flowControlDone; - T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors; - T3_64BIT_REGISTER dot3StatsSingleCollisionFrames; - T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames; - T3_64BIT_REGISTER dot3StatsDeferredTransmissions; - T3_64BIT_REGISTER Reserved3; - T3_64BIT_REGISTER dot3StatsExcessiveCollisions; - T3_64BIT_REGISTER dot3StatsLateCollisions; - T3_64BIT_REGISTER dot3Collided2Times; - T3_64BIT_REGISTER dot3Collided3Times; - T3_64BIT_REGISTER dot3Collided4Times; - T3_64BIT_REGISTER dot3Collided5Times; - T3_64BIT_REGISTER dot3Collided6Times; - T3_64BIT_REGISTER dot3Collided7Times; - T3_64BIT_REGISTER dot3Collided8Times; - T3_64BIT_REGISTER dot3Collided9Times; - T3_64BIT_REGISTER dot3Collided10Times; - T3_64BIT_REGISTER dot3Collided11Times; - T3_64BIT_REGISTER dot3Collided12Times; - T3_64BIT_REGISTER dot3Collided13Times; - T3_64BIT_REGISTER dot3Collided14Times; - T3_64BIT_REGISTER dot3Collided15Times; - T3_64BIT_REGISTER ifHCOutUcastPkts; - T3_64BIT_REGISTER ifHCOutMulticastPkts; - T3_64BIT_REGISTER ifHCOutBroadcastPkts; - T3_64BIT_REGISTER dot3StatsCarrierSenseErrors; - T3_64BIT_REGISTER ifOutDiscards; - T3_64BIT_REGISTER ifOutErrors; - - T3_64BIT_REGISTER Unused2[31]; - - /* Statistics maintained by Receive List Placement. */ - T3_64BIT_REGISTER COSIfHCInPkts[16]; - T3_64BIT_REGISTER COSFramesDroppedDueToFilters; - T3_64BIT_REGISTER nicDmaWriteQueueFull; - T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull; - T3_64BIT_REGISTER nicNoMoreRxBDs; - T3_64BIT_REGISTER ifInDiscards; - T3_64BIT_REGISTER ifInErrors; - T3_64BIT_REGISTER nicRecvThresholdHit; - - T3_64BIT_REGISTER Unused3[9]; - - /* Statistics maintained by Send Data Initiator. */ - T3_64BIT_REGISTER COSIfHCOutPkts[16]; - T3_64BIT_REGISTER nicDmaReadQueueFull; - T3_64BIT_REGISTER nicDmaReadHighPriQueueFull; - T3_64BIT_REGISTER nicSendDataCompQueueFull; - - /* Statistics maintained by Host Coalescing. */ - T3_64BIT_REGISTER nicRingSetSendProdIndex; - T3_64BIT_REGISTER nicRingStatusUpdate; - T3_64BIT_REGISTER nicInterrupts; - T3_64BIT_REGISTER nicAvoidedInterrupts; - T3_64BIT_REGISTER nicSendThresholdHit; - - LM_UINT8 Reserved4[0xb00 - 0x9c0]; -} T3_STATS_BLOCK, *PT3_STATS_BLOCK; - -/******************************************************************************/ -/* PCI configuration registers. */ -/******************************************************************************/ - -typedef struct { - T3_16BIT_REGISTER VendorId; - T3_16BIT_REGISTER DeviceId; - - T3_16BIT_REGISTER Command; - T3_16BIT_REGISTER Status; - - T3_32BIT_REGISTER ClassCodeRevId; - - T3_8BIT_REGISTER CacheLineSize; - T3_8BIT_REGISTER LatencyTimer; - T3_8BIT_REGISTER HeaderType; - T3_8BIT_REGISTER Bist; - - T3_32BIT_REGISTER MemBaseAddrLow; - T3_32BIT_REGISTER MemBaseAddrHigh; - - LM_UINT8 Unused1[20]; - - T3_16BIT_REGISTER SubsystemVendorId; - T3_16BIT_REGISTER SubsystemId; - - T3_32BIT_REGISTER RomBaseAddr; - - T3_8BIT_REGISTER PciXCapiblityPtr; - LM_UINT8 Unused2[7]; - - T3_8BIT_REGISTER IntLine; - T3_8BIT_REGISTER IntPin; - T3_8BIT_REGISTER MinGnt; - T3_8BIT_REGISTER MaxLat; - - T3_8BIT_REGISTER PciXCapabilities; - T3_8BIT_REGISTER PmCapabilityPtr; - T3_16BIT_REGISTER PciXCommand; - - T3_32BIT_REGISTER PciXStatus; - - T3_8BIT_REGISTER PmCapabilityId; - T3_8BIT_REGISTER VpdCapabilityPtr; - T3_16BIT_REGISTER PmCapabilities; - - T3_16BIT_REGISTER PmCtrlStatus; -#define PM_CTRL_PME_STATUS BIT_15 -#define PM_CTRL_PME_ENABLE BIT_8 -#define PM_CTRL_PME_POWER_STATE_D0 0 -#define PM_CTRL_PME_POWER_STATE_D1 1 -#define PM_CTRL_PME_POWER_STATE_D2 2 -#define PM_CTRL_PME_POWER_STATE_D3H 3 - - T3_8BIT_REGISTER BridgeSupportExt; - T3_8BIT_REGISTER PmData; - - T3_8BIT_REGISTER VpdCapabilityId; - T3_8BIT_REGISTER MsiCapabilityPtr; - T3_16BIT_REGISTER VpdAddrFlag; -#define VPD_FLAG_WRITE (1 << 15) -#define VPD_FLAG_RW_MASK (1 << 15) -#define VPD_FLAG_READ 0 - - T3_32BIT_REGISTER VpdData; - - T3_8BIT_REGISTER MsiCapabilityId; - T3_8BIT_REGISTER NextCapabilityPtr; - T3_16BIT_REGISTER MsiCtrl; -#define MSI_CTRL_64BIT_CAP (1 << 7) -#define MSI_CTRL_MSG_ENABLE(x) (x << 4) -#define MSI_CTRL_MSG_CAP(x) (x << 1) -#define MSI_CTRL_ENABLE (1 << 0) - - T3_32BIT_REGISTER MsiAddrLow; - T3_32BIT_REGISTER MsiAddrHigh; - - T3_16BIT_REGISTER MsiData; - T3_16BIT_REGISTER Unused3; - - T3_32BIT_REGISTER MiscHostCtrl; -#define MISC_HOST_CTRL_CLEAR_INT BIT_0 -#define MISC_HOST_CTRL_MASK_PCI_INT BIT_1 -#define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP BIT_2 -#define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP BIT_3 -#define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW BIT_4 -#define MISC_HOST_CTRL_ENABLE_CLK_REG_RW BIT_5 -#define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP BIT_6 -#define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS BIT_7 -#define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE BIT_8 -#define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE BIT_9 - - T3_32BIT_REGISTER DmaReadWriteCtrl; -#define DMA_CTRL_WRITE_BOUNDARY_MASK (BIT_11 | BIT_12 | BIT_13) -#define DMA_CTRL_WRITE_BOUNDARY_DISABLE 0 -#define DMA_CTRL_WRITE_BOUNDARY_16 BIT_11 -#define DMA_CTRL_WRITE_BOUNDARY_32 BIT_12 -#define DMA_CTRL_WRITE_BOUNDARY_64 (BIT_12 | BIT_11) -#define DMA_CTRL_WRITE_BOUNDARY_128 BIT_13 -#define DMA_CTRL_WRITE_BOUNDARY_256 (BIT_13 | BIT_11) -#define DMA_CTRL_WRITE_BOUNDARY_512 (BIT_13 | BIT_12) -#define DMA_CTRL_WRITE_BOUNDARY_1024 (BIT_13 | BIT_12 | BIT_11) -#define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE BIT_14 - - T3_32BIT_REGISTER PciState; -#define T3_PCI_STATE_FORCE_PCI_RESET BIT_0 -#define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE BIT_1 -#define T3_PCI_STATE_NOT_PCI_X_BUS BIT_2 -#define T3_PCI_STATE_HIGH_BUS_SPEED BIT_3 -#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 -#define T3_PCI_STATE_PCI_ROM_ENABLE BIT_5 -#define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE BIT_6 -#define T3_PCI_STATE_FLAT_VIEW BIT_8 -#define T3_PCI_STATE_RETRY_SAME_DMA BIT_13 - - T3_32BIT_REGISTER ClockCtrl; -#define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE BIT_11 -#define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE BIT_10 -#define T3_PCI_CLKCTRL_CORE_CLK_DISABLE BIT_9 - - T3_32BIT_REGISTER RegBaseAddr; - - T3_32BIT_REGISTER MemWindowBaseAddr; - -#ifdef NIC_CPU_VIEW - /* These registers are ONLY visible to NIC CPU */ - T3_32BIT_REGISTER PowerConsumed; - T3_32BIT_REGISTER PowerDissipated; -#else /* NIC_CPU_VIEW */ - T3_32BIT_REGISTER RegData; - T3_32BIT_REGISTER MemWindowData; -#endif /* !NIC_CPU_VIEW */ - - T3_32BIT_REGISTER ModeCtrl; - - T3_32BIT_REGISTER MiscCfg; - - T3_32BIT_REGISTER MiscLocalCtrl; - - T3_32BIT_REGISTER Unused4; - - /* NOTE: Big/Little-endian clarification needed. Are these register */ - /* in big or little endian formate. */ - T3_64BIT_REGISTER StdRingProdIdx; - T3_64BIT_REGISTER RcvRetRingConIdx; - T3_64BIT_REGISTER SndProdIdx; - - LM_UINT8 Unused5[80]; -} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION; - -#define PCIX_CMD_MAX_SPLIT_MASK 0x0070 -#define PCIX_CMD_MAX_SPLIT_SHL 4 -#define PCIX_CMD_MAX_BURST_MASK 0x000c -#define PCIX_CMD_MAX_BURST_SHL 2 -#define PCIX_CMD_MAX_BURST_CPIOB 2 - -/******************************************************************************/ -/* Mac control registers. */ -/******************************************************************************/ - -typedef struct { - /* MAC mode control. */ - T3_32BIT_REGISTER Mode; -#define MAC_MODE_GLOBAL_RESET BIT_0 -#define MAC_MODE_HALF_DUPLEX BIT_1 -#define MAC_MODE_PORT_MODE_MASK (BIT_2 | BIT_3) -#define MAC_MODE_PORT_MODE_TBI (BIT_2 | BIT_3) -#define MAC_MODE_PORT_MODE_GMII BIT_3 -#define MAC_MODE_PORT_MODE_MII BIT_2 -#define MAC_MODE_PORT_MODE_NONE BIT_NONE -#define MAC_MODE_PORT_INTERNAL_LOOPBACK BIT_4 -#define MAC_MODE_TAGGED_MAC_CONTROL BIT_7 -#define MAC_MODE_TX_BURSTING BIT_8 -#define MAC_MODE_MAX_DEFER BIT_9 -#define MAC_MODE_LINK_POLARITY BIT_10 -#define MAC_MODE_ENABLE_RX_STATISTICS BIT_11 -#define MAC_MODE_CLEAR_RX_STATISTICS BIT_12 -#define MAC_MODE_FLUSH_RX_STATISTICS BIT_13 -#define MAC_MODE_ENABLE_TX_STATISTICS BIT_14 -#define MAC_MODE_CLEAR_TX_STATISTICS BIT_15 -#define MAC_MODE_FLUSH_TX_STATISTICS BIT_16 -#define MAC_MODE_SEND_CONFIGS BIT_17 -#define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE BIT_18 -#define MAC_MODE_ACPI_POWER_ON_ENABLE BIT_19 -#define MAC_MODE_ENABLE_MIP BIT_20 -#define MAC_MODE_ENABLE_TDE BIT_21 -#define MAC_MODE_ENABLE_RDE BIT_22 -#define MAC_MODE_ENABLE_FHDE BIT_23 - - /* MAC status */ - T3_32BIT_REGISTER Status; -#define MAC_STATUS_PCS_SYNCED BIT_0 -#define MAC_STATUS_SIGNAL_DETECTED BIT_1 -#define MAC_STATUS_RECEIVING_CFG BIT_2 -#define MAC_STATUS_CFG_CHANGED BIT_3 -#define MAC_STATUS_SYNC_CHANGED BIT_4 -#define MAC_STATUS_PORT_DECODE_ERROR BIT_10 -#define MAC_STATUS_LINK_STATE_CHANGED BIT_12 -#define MAC_STATUS_MI_COMPLETION BIT_22 -#define MAC_STATUS_MI_INTERRUPT BIT_23 -#define MAC_STATUS_AP_ERROR BIT_24 -#define MAC_STATUS_ODI_ERROR BIT_25 -#define MAC_STATUS_RX_STATS_OVERRUN BIT_26 -#define MAC_STATUS_TX_STATS_OVERRUN BIT_27 - - /* Event Enable */ - T3_32BIT_REGISTER MacEvent; -#define MAC_EVENT_ENABLE_PORT_DECODE_ERR BIT_10 -#define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN BIT_12 -#define MAC_EVENT_ENABLE_MI_COMPLETION BIT_22 -#define MAC_EVENT_ENABLE_MI_INTERRUPT BIT_23 -#define MAC_EVENT_ENABLE_AP_ERROR BIT_24 -#define MAC_EVENT_ENABLE_ODI_ERROR BIT_25 -#define MAC_EVENT_ENABLE_RX_STATS_OVERRUN BIT_26 -#define MAC_EVENT_ENABLE_TX_STATS_OVERRUN BIT_27 - - /* Led control. */ - T3_32BIT_REGISTER LedCtrl; -#define LED_CTRL_OVERRIDE_LINK_LED BIT_0 -#define LED_CTRL_1000MBPS_LED_ON BIT_1 -#define LED_CTRL_100MBPS_LED_ON BIT_2 -#define LED_CTRL_10MBPS_LED_ON BIT_3 -#define LED_CTRL_OVERRIDE_TRAFFIC_LED BIT_4 -#define LED_CTRL_BLINK_TRAFFIC_LED BIT_5 -#define LED_CTRL_TRAFFIC_LED BIT_6 -#define LED_CTRL_1000MBPS_LED_STATUS BIT_7 -#define LED_CTRL_100MBPS_LED_STATUS BIT_8 -#define LED_CTRL_10MBPS_LED_STATUS BIT_9 -#define LED_CTRL_TRAFFIC_LED_STATUS BIT_10 -#define LED_CTRL_MAC_MODE BIT_NONE -#define LED_CTRL_PHY_MODE_1 BIT_11 -#define LED_CTRL_PHY_MODE_2 BIT_12 -#define LED_CTRL_BLINK_RATE_MASK 0x7ff80000 -#define LED_CTRL_OVERRIDE_BLINK_PERIOD BIT_19 -#define LED_CTRL_OVERRIDE_BLINK_RATE BIT_31 - - /* MAC addresses. */ - struct { - T3_32BIT_REGISTER High; /* Upper 2 bytes. */ - T3_32BIT_REGISTER Low; /* Lower 4 bytes. */ - } MacAddr[4]; - - /* ACPI Mbuf pointer. */ - T3_32BIT_REGISTER AcpiMbufPtr; - - /* ACPI Length and Offset. */ - T3_32BIT_REGISTER AcpiLengthOffset; -#define ACPI_LENGTH_MASK 0xffff -#define ACPI_OFFSET_MASK 0x0fff0000 -#define ACPI_LENGTH(x) x -#define ACPI_OFFSET(x) ((x) << 16) - - /* Transmit random backoff. */ - T3_32BIT_REGISTER TxBackoffSeed; -#define MAC_TX_BACKOFF_SEED_MASK 0x3ff - - /* Receive MTU */ - T3_32BIT_REGISTER MtuSize; -#define MAC_RX_MTU_MASK 0xffff - - /* Gigabit PCS Test. */ - T3_32BIT_REGISTER PcsTest; -#define MAC_PCS_TEST_DATA_PATTERN_MASK 0x0fffff -#define MAC_PCS_TEST_ENABLE BIT_20 - - /* Transmit Gigabit Auto-Negotiation. */ - T3_32BIT_REGISTER TxAutoNeg; -#define MAC_AN_TX_AN_DATA_MASK 0xffff - - /* Receive Gigabit Auto-Negotiation. */ - T3_32BIT_REGISTER RxAutoNeg; -#define MAC_AN_RX_AN_DATA_MASK 0xffff - - /* MI Communication. */ - T3_32BIT_REGISTER MiCom; -#define MI_COM_CMD_MASK (BIT_26 | BIT_27) -#define MI_COM_CMD_WRITE BIT_26 -#define MI_COM_CMD_READ BIT_27 -#define MI_COM_READ_FAILED BIT_28 -#define MI_COM_START BIT_29 -#define MI_COM_BUSY BIT_29 - -#define MI_COM_PHY_ADDR_MASK 0x1f -#define MI_COM_FIRST_PHY_ADDR_BIT 21 - -#define MI_COM_PHY_REG_ADDR_MASK 0x1f -#define MI_COM_FIRST_PHY_REG_ADDR_BIT 16 - -#define MI_COM_PHY_DATA_MASK 0xffff - - /* MI Status. */ - T3_32BIT_REGISTER MiStatus; -#define MI_STATUS_ENABLE_LINK_STATUS_ATTN BIT_0 - - /* MI Mode. */ - T3_32BIT_REGISTER MiMode; -#define MI_MODE_CLOCK_SPEED_10MHZ BIT_0 -#define MI_MODE_USE_SHORT_PREAMBLE BIT_1 -#define MI_MODE_AUTO_POLLING_ENABLE BIT_4 -#define MI_MODE_CORE_CLOCK_SPEED_62MHZ BIT_15 - - /* Auto-polling status. */ - T3_32BIT_REGISTER AutoPollStatus; -#define AUTO_POLL_ERROR BIT_0 - - /* Transmit MAC mode. */ - T3_32BIT_REGISTER TxMode; -#define TX_MODE_RESET BIT_0 -#define TX_MODE_ENABLE BIT_1 -#define TX_MODE_ENABLE_FLOW_CONTROL BIT_4 -#define TX_MODE_ENABLE_BIG_BACKOFF BIT_5 -#define TX_MODE_ENABLE_LONG_PAUSE BIT_6 - - /* Transmit MAC status. */ - T3_32BIT_REGISTER TxStatus; -#define TX_STATUS_RX_CURRENTLY_XOFFED BIT_0 -#define TX_STATUS_SENT_XOFF BIT_1 -#define TX_STATUS_SENT_XON BIT_2 -#define TX_STATUS_LINK_UP BIT_3 -#define TX_STATUS_ODI_UNDERRUN BIT_4 -#define TX_STATUS_ODI_OVERRUN BIT_5 - - /* Transmit MAC length. */ - T3_32BIT_REGISTER TxLengths; -#define TX_LEN_SLOT_TIME_MASK 0xff -#define TX_LEN_IPG_MASK 0x0f00 -#define TX_LEN_IPG_CRS_MASK (BIT_12 | BIT_13) - - /* Receive MAC mode. */ - T3_32BIT_REGISTER RxMode; -#define RX_MODE_RESET BIT_0 -#define RX_MODE_ENABLE BIT_1 -#define RX_MODE_ENABLE_FLOW_CONTROL BIT_2 -#define RX_MODE_KEEP_MAC_CONTROL BIT_3 -#define RX_MODE_KEEP_PAUSE BIT_4 -#define RX_MODE_ACCEPT_OVERSIZED BIT_5 -#define RX_MODE_ACCEPT_RUNTS BIT_6 -#define RX_MODE_LENGTH_CHECK BIT_7 -#define RX_MODE_PROMISCUOUS_MODE BIT_8 -#define RX_MODE_NO_CRC_CHECK BIT_9 -#define RX_MODE_KEEP_VLAN_TAG BIT_10 - - /* Receive MAC status. */ - T3_32BIT_REGISTER RxStatus; -#define RX_STATUS_REMOTE_TRANSMITTER_XOFFED BIT_0 -#define RX_STATUS_XOFF_RECEIVED BIT_1 -#define RX_STATUS_XON_RECEIVED BIT_2 - - /* Hash registers. */ - T3_32BIT_REGISTER HashReg[4]; - - /* Receive placement rules registers. */ - struct { - T3_32BIT_REGISTER Rule; - T3_32BIT_REGISTER Value; - } RcvRules[16]; - -#define RCV_DISABLE_RULE_MASK 0x7fffffff - -#define RCV_RULE1_REJECT_BROADCAST_IDX 0x00 -#define REJECT_BROADCAST_RULE1_RULE 0xc2000000 -#define REJECT_BROADCAST_RULE1_VALUE 0xffffffff - -#define RCV_RULE2_REJECT_BROADCAST_IDX 0x01 -#define REJECT_BROADCAST_RULE2_RULE 0x86000004 -#define REJECT_BROADCAST_RULE2_VALUE 0xffffffff - -#if INCLUDE_5701_AX_FIX -#define RCV_LAST_RULE_IDX 0x04 -#else -#define RCV_LAST_RULE_IDX 0x02 -#endif - - T3_32BIT_REGISTER RcvRuleCfg; -#define RX_RULE_DEFAULT_CLASS (1 << 3) - - LM_UINT8 Reserved1[140]; - - T3_32BIT_REGISTER SerdesCfg; - T3_32BIT_REGISTER SerdesStatus; - - LM_UINT8 Reserved2[104]; - - volatile LM_UINT8 TxMacState[16]; - volatile LM_UINT8 RxMacState[20]; - - LM_UINT8 Reserved3[476]; - - T3_32BIT_REGISTER RxStats[26]; - - LM_UINT8 Reserved4[24]; - - T3_32BIT_REGISTER TxStats[28]; - - LM_UINT8 Reserved5[784]; -} T3_MAC_CONTROL, *PT3_MAC_CONTROL; - -/******************************************************************************/ -/* Send data initiator control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define T3_SND_DATA_IN_MODE_RESET BIT_0 -#define T3_SND_DATA_IN_MODE_ENABLE BIT_1 -#define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN BIT_2 - - T3_32BIT_REGISTER StatsCtrl; -#define T3_SND_DATA_IN_STATS_CTRL_ENABLE BIT_0 -#define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE BIT_1 -#define T3_SND_DATA_IN_STATS_CTRL_CLEAR BIT_2 -#define T3_SND_DATA_IN_STATS_CTRL_FLUSH BIT_3 -#define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO BIT_4 - - T3_32BIT_REGISTER StatsEnableMask; - T3_32BIT_REGISTER StatsIncMask; - - LM_UINT8 Reserved[108]; - - T3_32BIT_REGISTER ClassOfServCnt[16]; - T3_32BIT_REGISTER DmaReadQFullCnt; - T3_32BIT_REGISTER DmaPriorityReadQFullCnt; - T3_32BIT_REGISTER SdcQFullCnt; - - T3_32BIT_REGISTER NicRingSetSendProdIdxCnt; - T3_32BIT_REGISTER StatusUpdatedCnt; - T3_32BIT_REGISTER InterruptsCnt; - T3_32BIT_REGISTER AvoidInterruptsCnt; - T3_32BIT_REGISTER SendThresholdHitCnt; - - /* Unused space. */ - LM_UINT8 Unused[800]; -} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR; - -/******************************************************************************/ -/* Send data completion control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define SND_DATA_COMP_MODE_RESET BIT_0 -#define SND_DATA_COMP_MODE_ENABLE BIT_1 - - /* Unused space. */ - LM_UINT8 Unused[1020]; -} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION; - -/******************************************************************************/ -/* Send BD Ring Selector Control Registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define SND_BD_SEL_MODE_RESET BIT_0 -#define SND_BD_SEL_MODE_ENABLE BIT_1 -#define SND_BD_SEL_MODE_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define SND_BD_SEL_STATUS_ERROR_ATTN BIT_2 - - T3_32BIT_REGISTER HwDiag; - - /* Unused space. */ - LM_UINT8 Unused1[52]; - - /* Send BD Ring Selector Local NIC Send BD Consumer Index. */ - T3_32BIT_REGISTER NicSendBdSelConIdx[16]; - - /* Unused space. */ - LM_UINT8 Unused2[896]; -} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR; - -/******************************************************************************/ -/* Send BD initiator control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define SND_BD_IN_MODE_RESET BIT_0 -#define SND_BD_IN_MODE_ENABLE BIT_1 -#define SND_BD_IN_MODE_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define SND_BD_IN_STATUS_ERROR_ATTN BIT_2 - - /* Send BD initiator local NIC send BD producer index. */ - T3_32BIT_REGISTER NicSendBdInProdIdx[16]; - - /* Unused space. */ - LM_UINT8 Unused2[952]; -} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR; - -/******************************************************************************/ -/* Send BD Completion Control. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define SND_BD_COMP_MODE_RESET BIT_0 -#define SND_BD_COMP_MODE_ENABLE BIT_1 -#define SND_BD_COMP_MODE_ATTN_ENABLE BIT_2 - - /* Unused space. */ - LM_UINT8 Unused2[1020]; -} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION; - -/******************************************************************************/ -/* Receive list placement control registers. */ -/******************************************************************************/ - -typedef struct { - /* Mode. */ - T3_32BIT_REGISTER Mode; -#define RCV_LIST_PLMT_MODE_RESET BIT_0 -#define RCV_LIST_PLMT_MODE_ENABLE BIT_1 -#define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE BIT_2 -#define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE BIT_3 -#define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE BIT_4 - - /* Status. */ - T3_32BIT_REGISTER Status; -#define RCV_LIST_PLMT_STATUS_CLASS0_ATTN BIT_2 -#define RCV_LIST_PLMT_STATUS_MAPPING_ATTN BIT_3 -#define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN BIT_4 - - /* Receive selector list lock register. */ - T3_32BIT_REGISTER Lock; -#define RCV_LIST_SEL_LOCK_REQUEST_MASK 0xffff -#define RCV_LIST_SEL_LOCK_GRANT_MASK 0xffff0000 - - /* Selector non-empty bits. */ - T3_32BIT_REGISTER NonEmptyBits; -#define RCV_LIST_SEL_NON_EMPTY_MASK 0xffff - - /* Receive list placement configuration register. */ - T3_32BIT_REGISTER Config; - - /* Receive List Placement statistics Control. */ - T3_32BIT_REGISTER StatsCtrl; -#define RCV_LIST_STATS_ENABLE BIT_0 -#define RCV_LIST_STATS_FAST_UPDATE BIT_1 - - /* Receive List Placement statistics Enable Mask. */ - T3_32BIT_REGISTER StatsEnableMask; - - /* Receive List Placement statistics Increment Mask. */ - T3_32BIT_REGISTER StatsIncMask; - - /* Unused space. */ - LM_UINT8 Unused1[224]; - - struct { - T3_32BIT_REGISTER Head; - T3_32BIT_REGISTER Tail; - T3_32BIT_REGISTER Count; - - /* Unused space. */ - LM_UINT8 Unused[4]; - } RcvSelectorList[16]; - - /* Local statistics counter. */ - T3_32BIT_REGISTER ClassOfServCnt[16]; - - T3_32BIT_REGISTER DropDueToFilterCnt; - T3_32BIT_REGISTER DmaWriteQFullCnt; - T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt; - T3_32BIT_REGISTER NoMoreReceiveBdCnt; - T3_32BIT_REGISTER IfInDiscardsCnt; - T3_32BIT_REGISTER IfInErrorsCnt; - T3_32BIT_REGISTER RcvThresholdHitCnt; - - /* Another unused space. */ - LM_UINT8 Unused2[420]; -} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT; - -/******************************************************************************/ -/* Receive Data and Receive BD Initiator Control. */ -/******************************************************************************/ - -typedef struct { - /* Mode. */ - T3_32BIT_REGISTER Mode; -#define RCV_DATA_BD_IN_MODE_RESET BIT_0 -#define RCV_DATA_BD_IN_MODE_ENABLE BIT_1 -#define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED BIT_2 -#define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG BIT_3 -#define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE BIT_4 - - /* Status. */ - T3_32BIT_REGISTER Status; -#define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED BIT_2 -#define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG BIT_3 -#define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE BIT_4 - - /* Split frame minium size. */ - T3_32BIT_REGISTER SplitFrameMinSize; - - /* Unused space. */ - LM_UINT8 Unused1[0x2440 - 0x240c]; - - /* Receive RCBs. */ - T3_RCB JumboRcvRcb; - T3_RCB StdRcvRcb; - T3_RCB MiniRcvRcb; - - /* Receive Data and Receive BD Ring Initiator Local NIC Receive */ - /* BD Consumber Index. */ - T3_32BIT_REGISTER NicJumboConIdx; - T3_32BIT_REGISTER NicStdConIdx; - T3_32BIT_REGISTER NicMiniConIdx; - - /* Unused space. */ - LM_UINT8 Unused2[4]; - - /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */ - T3_32BIT_REGISTER RcvDataBdProdIdx[16]; - - /* Receive Data and Receive BD Initiator Hardware Diagnostic. */ - T3_32BIT_REGISTER HwDiag; - - /* Unused space. */ - LM_UINT8 Unused3[828]; -} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR; - -/******************************************************************************/ -/* Receive Data Completion Control Registes. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define RCV_DATA_COMP_MODE_RESET BIT_0 -#define RCV_DATA_COMP_MODE_ENABLE BIT_1 -#define RCV_DATA_COMP_MODE_ATTN_ENABLE BIT_2 - - /* Unused spaced. */ - LM_UINT8 Unused[1020]; -} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION; - -/******************************************************************************/ -/* Receive BD Initiator Control. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define RCV_BD_IN_MODE_RESET BIT_0 -#define RCV_BD_IN_MODE_ENABLE BIT_1 -#define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN BIT_2 - - T3_32BIT_REGISTER NicJumboRcvProdIdx; - T3_32BIT_REGISTER NicStdRcvProdIdx; - T3_32BIT_REGISTER NicMiniRcvProdIdx; - - T3_32BIT_REGISTER MiniRcvThreshold; - T3_32BIT_REGISTER StdRcvThreshold; - T3_32BIT_REGISTER JumboRcvThreshold; - - /* Unused space. */ - LM_UINT8 Unused[992]; -} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR; - -/******************************************************************************/ -/* Receive BD Completion Control Registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define RCV_BD_COMP_MODE_RESET BIT_0 -#define RCV_BD_COMP_MODE_ENABLE BIT_1 -#define RCV_BD_COMP_MODE_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define RCV_BD_COMP_STATUS_ERROR_ATTN BIT_2 - - T3_32BIT_REGISTER NicJumboRcvBdProdIdx; - T3_32BIT_REGISTER NicStdRcvBdProdIdx; - T3_32BIT_REGISTER NicMiniRcvBdProdIdx; - - /* Unused space. */ - LM_UINT8 Unused[1004]; -} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION; - -/******************************************************************************/ -/* Receive list selector control register. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define RCV_LIST_SEL_MODE_RESET BIT_0 -#define RCV_LIST_SEL_MODE_ENABLE BIT_1 -#define RCV_LIST_SEL_MODE_ATTN_ENABLE BIT_2 - - T3_32BIT_REGISTER Status; -#define RCV_LIST_SEL_STATUS_ERROR_ATTN BIT_2 - - /* Unused space. */ - LM_UINT8 Unused[1016]; -} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR; - -/******************************************************************************/ -/* Mbuf cluster free registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define MBUF_CLUSTER_FREE_MODE_RESET BIT_0 -#define MBUF_CLUSTER_FREE_MODE_ENABLE BIT_1 - - T3_32BIT_REGISTER Status; - - /* Unused space. */ - LM_UINT8 Unused[1016]; -} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE; - -/******************************************************************************/ -/* Host coalescing control registers. */ -/******************************************************************************/ - -typedef struct { - /* Mode. */ - T3_32BIT_REGISTER Mode; -#define HOST_COALESCE_RESET BIT_0 -#define HOST_COALESCE_ENABLE BIT_1 -#define HOST_COALESCE_ATTN BIT_2 -#define HOST_COALESCE_NOW BIT_3 -#define HOST_COALESCE_FULL_STATUS_MODE BIT_NONE -#define HOST_COALESCE_64_BYTE_STATUS_MODE BIT_7 -#define HOST_COALESCE_32_BYTE_STATUS_MODE BIT_8 -#define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT BIT_9 -#define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT BIT_10 -#define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE BIT_11 -#define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE BIT_12 - - /* Status. */ - T3_32BIT_REGISTER Status; -#define HOST_COALESCE_ERROR_ATTN BIT_2 - - /* Receive coalescing ticks. */ - T3_32BIT_REGISTER RxCoalescingTicks; - - /* Send coalescing ticks. */ - T3_32BIT_REGISTER TxCoalescingTicks; - - /* Receive max coalesced frames. */ - T3_32BIT_REGISTER RxMaxCoalescedFrames; - - /* Send max coalesced frames. */ - T3_32BIT_REGISTER TxMaxCoalescedFrames; - - /* Receive coalescing ticks during interrupt. */ - T3_32BIT_REGISTER RxCoalescedTickDuringInt; - - /* Send coalescing ticks during interrupt. */ - T3_32BIT_REGISTER TxCoalescedTickDuringInt; - - /* Receive max coalesced frames during interrupt. */ - T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt; - - /* Send max coalesced frames during interrupt. */ - T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt; - - /* Statistics tick. */ - T3_32BIT_REGISTER StatsCoalescingTicks; - - /* Unused space. */ - LM_UINT8 Unused2[4]; - - /* Statistics host address. */ - T3_64BIT_REGISTER StatsBlkHostAddr; - - /* Status block host address. */ - T3_64BIT_REGISTER StatusBlkHostAddr; - - /* Statistics NIC address. */ - T3_32BIT_REGISTER StatsBlkNicAddr; - - /* Statust block NIC address. */ - T3_32BIT_REGISTER StatusBlkNicAddr; - - /* Flow attention registers. */ - T3_32BIT_REGISTER FlowAttn; - - /* Unused space. */ - LM_UINT8 Unused3[4]; - - T3_32BIT_REGISTER NicJumboRcvBdConIdx; - T3_32BIT_REGISTER NicStdRcvBdConIdx; - T3_32BIT_REGISTER NicMiniRcvBdConIdx; - - /* Unused space. */ - LM_UINT8 Unused4[36]; - - T3_32BIT_REGISTER NicRetProdIdx[16]; - T3_32BIT_REGISTER NicSndBdConIdx[16]; - - /* Unused space. */ - LM_UINT8 Unused5[768]; -} T3_HOST_COALESCING, *PT3_HOST_COALESCING; - -/******************************************************************************/ -/* Memory arbiter registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define T3_MEM_ARBITER_MODE_RESET BIT_0 -#define T3_MEM_ARBITER_MODE_ENABLE BIT_1 - - T3_32BIT_REGISTER Status; - - T3_32BIT_REGISTER ArbTrapAddrLow; - T3_32BIT_REGISTER ArbTrapAddrHigh; - - /* Unused space. */ - LM_UINT8 Unused[1008]; -} T3_MEM_ARBITER, *PT3_MEM_ARBITER; - -/******************************************************************************/ -/* Buffer manager control register. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define BUFMGR_MODE_RESET BIT_0 -#define BUFMGR_MODE_ENABLE BIT_1 -#define BUFMGR_MODE_ATTN_ENABLE BIT_2 -#define BUFMGR_MODE_BM_TEST BIT_3 -#define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE BIT_4 - - T3_32BIT_REGISTER Status; -#define BUFMGR_STATUS_ERROR BIT_2 -#define BUFMGR_STATUS_MBUF_LOW BIT_4 - - T3_32BIT_REGISTER MbufPoolAddr; - T3_32BIT_REGISTER MbufPoolSize; - T3_32BIT_REGISTER MbufReadDmaLowWaterMark; - T3_32BIT_REGISTER MbufMacRxLowWaterMark; - T3_32BIT_REGISTER MbufHighWaterMark; - - T3_32BIT_REGISTER RxCpuMbufAllocReq; -#define BUFMGR_MBUF_ALLOC_BIT BIT_31 - T3_32BIT_REGISTER RxCpuMbufAllocResp; - T3_32BIT_REGISTER TxCpuMbufAllocReq; - T3_32BIT_REGISTER TxCpuMbufAllocResp; - - T3_32BIT_REGISTER DmaDescPoolAddr; - T3_32BIT_REGISTER DmaDescPoolSize; - T3_32BIT_REGISTER DmaLowWaterMark; - T3_32BIT_REGISTER DmaHighWaterMark; - - T3_32BIT_REGISTER RxCpuDmaAllocReq; - T3_32BIT_REGISTER RxCpuDmaAllocResp; - T3_32BIT_REGISTER TxCpuDmaAllocReq; - T3_32BIT_REGISTER TxCpuDmaAllocResp; - - T3_32BIT_REGISTER Hwdiag[3]; - - /* Unused space. */ - LM_UINT8 Unused[936]; -} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER; - -/******************************************************************************/ -/* Read DMA control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define DMA_READ_MODE_RESET BIT_0 -#define DMA_READ_MODE_ENABLE BIT_1 -#define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 -#define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 -#define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 -#define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 -#define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 -#define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 -#define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 -#define DMA_READ_MODE_LONG_READ_ATTN_ENABLE BIT_9 -#define DMA_READ_MODE_SPLIT_ENABLE BIT_11 -#define DMA_READ_MODE_SPLIT_RESET BIT_12 - - T3_32BIT_REGISTER Status; -#define DMA_READ_STATUS_TARGET_ABORT_ATTN BIT_2 -#define DMA_READ_STATUS_MASTER_ABORT_ATTN BIT_3 -#define DMA_READ_STATUS_PARITY_ERROR_ATTN BIT_4 -#define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN BIT_5 -#define DMA_READ_STATUS_FIFO_OVERRUN_ATTN BIT_6 -#define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN BIT_7 -#define DMA_READ_STATUS_FIFO_OVERREAD_ATTN BIT_8 -#define DMA_READ_STATUS_LONG_READ_ATTN BIT_9 - - /* Unused space. */ - LM_UINT8 Unused[1016]; -} T3_DMA_READ, *PT3_DMA_READ; - -typedef union T3_CPU { - struct { - T3_32BIT_REGISTER mode; -#define CPU_MODE_HALT BIT_10 -#define CPU_MODE_RESET BIT_0 - T3_32BIT_REGISTER state; - T3_32BIT_REGISTER EventMask; - T3_32BIT_REGISTER reserved1[4]; - T3_32BIT_REGISTER PC; - T3_32BIT_REGISTER Instruction; - T3_32BIT_REGISTER SpadUnderflow; - T3_32BIT_REGISTER WatchdogClear; - T3_32BIT_REGISTER WatchdogVector; - T3_32BIT_REGISTER WatchdogSavedPC; - T3_32BIT_REGISTER HardwareBp; - T3_32BIT_REGISTER reserved2[3]; - T3_32BIT_REGISTER WatchdogSavedState; - T3_32BIT_REGISTER LastBrchAddr; - T3_32BIT_REGISTER SpadUnderflowSet; - T3_32BIT_REGISTER reserved3[(0x200 - 0x50) / 4]; - T3_32BIT_REGISTER Regs[32]; - T3_32BIT_REGISTER reserved4[(0x400 - 0x280) / 4]; - } reg; -} T3_CPU, *PT3_CPU; - -/******************************************************************************/ -/* Write DMA control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define DMA_WRITE_MODE_RESET BIT_0 -#define DMA_WRITE_MODE_ENABLE BIT_1 -#define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 -#define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 -#define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 -#define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 -#define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 -#define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 -#define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 -#define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE BIT_9 - - T3_32BIT_REGISTER Status; -#define DMA_WRITE_STATUS_TARGET_ABORT_ATTN BIT_2 -#define DMA_WRITE_STATUS_MASTER_ABORT_ATTN BIT_3 -#define DMA_WRITE_STATUS_PARITY_ERROR_ATTN BIT_4 -#define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN BIT_5 -#define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN BIT_6 -#define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN BIT_7 -#define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN BIT_8 -#define DMA_WRITE_STATUS_LONG_READ_ATTN BIT_9 - - /* Unused space. */ - LM_UINT8 Unused[1016]; -} T3_DMA_WRITE, *PT3_DMA_WRITE; - -/******************************************************************************/ -/* Mailbox registers. */ -/******************************************************************************/ - -typedef struct { - /* Interrupt mailbox registers. */ - T3_64BIT_REGISTER Interrupt[4]; - - /* General mailbox registers. */ - T3_64BIT_REGISTER General[8]; - - /* Reload statistics mailbox. */ - T3_64BIT_REGISTER ReloadStat; - - /* Receive BD ring producer index registers. */ - T3_64BIT_REGISTER RcvStdProdIdx; - T3_64BIT_REGISTER RcvJumboProdIdx; - T3_64BIT_REGISTER RcvMiniProdIdx; - - /* Receive return ring consumer index registers. */ - T3_64BIT_REGISTER RcvRetConIdx[16]; - - /* Send BD ring host producer index registers. */ - T3_64BIT_REGISTER SendHostProdIdx[16]; - - /* Send BD ring nic producer index registers. */ - T3_64BIT_REGISTER SendNicProdIdx[16]; -} T3_MAILBOX, *PT3_MAILBOX; - -typedef struct { - T3_MAILBOX Mailbox; - - /* Priority mailbox registers. */ - T3_32BIT_REGISTER HighPriorityEventVector; - T3_32BIT_REGISTER HighPriorityEventMask; - T3_32BIT_REGISTER LowPriorityEventVector; - T3_32BIT_REGISTER LowPriorityEventMask; - - /* Unused space. */ - LM_UINT8 Unused[496]; -} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX; - -/******************************************************************************/ -/* Flow through queues. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Reset; - - LM_UINT8 Unused[12]; - - T3_32BIT_REGISTER DmaNormalReadFtqCtrl; - T3_32BIT_REGISTER DmaNormalReadFtqFullCnt; - T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek; - - T3_32BIT_REGISTER DmaHighReadFtqCtrl; - T3_32BIT_REGISTER DmaHighReadFtqFullCnt; - T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek; - - T3_32BIT_REGISTER DmaCompDiscardFtqCtrl; - T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt; - T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek; - - T3_32BIT_REGISTER SendBdCompFtqCtrl; - T3_32BIT_REGISTER SendBdCompFtqFullCnt; - T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek; - - T3_32BIT_REGISTER SendDataInitiatorFtqCtrl; - T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt; - T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek; - - T3_32BIT_REGISTER DmaNormalWriteFtqCtrl; - T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt; - T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek; - - T3_32BIT_REGISTER DmaHighWriteFtqCtrl; - T3_32BIT_REGISTER DmaHighWriteFtqFullCnt; - T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek; - - T3_32BIT_REGISTER SwType1FtqCtrl; - T3_32BIT_REGISTER SwType1FtqFullCnt; - T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue; - T3_32BIT_REGISTER SwType1FtqFifoWritePeek; - - T3_32BIT_REGISTER SendDataCompFtqCtrl; - T3_32BIT_REGISTER SendDataCompFtqFullCnt; - T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek; - - T3_32BIT_REGISTER HostCoalesceFtqCtrl; - T3_32BIT_REGISTER HostCoalesceFtqFullCnt; - T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek; - - T3_32BIT_REGISTER MacTxFtqCtrl; - T3_32BIT_REGISTER MacTxFtqFullCnt; - T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER MacTxFtqFifoWritePeek; - - T3_32BIT_REGISTER MbufClustFreeFtqCtrl; - T3_32BIT_REGISTER MbufClustFreeFtqFullCnt; - T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek; - - T3_32BIT_REGISTER RcvBdCompFtqCtrl; - T3_32BIT_REGISTER RcvBdCompFtqFullCnt; - T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek; - - T3_32BIT_REGISTER RcvListPlmtFtqCtrl; - T3_32BIT_REGISTER RcvListPlmtFtqFullCnt; - T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek; - - T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl; - T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt; - T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek; - - T3_32BIT_REGISTER RcvDataCompFtqCtrl; - T3_32BIT_REGISTER RcvDataCompFtqFullCnt; - T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue; - T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek; - - T3_32BIT_REGISTER SwType2FtqCtrl; - T3_32BIT_REGISTER SwType2FtqFullCnt; - T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue; - T3_32BIT_REGISTER SwType2FtqFifoWritePeek; - - /* Unused space. */ - LM_UINT8 Unused2[736]; -} T3_FTQ, *PT3_FTQ; - -/******************************************************************************/ -/* Message signaled interrupt registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define MSI_MODE_RESET BIT_0 -#define MSI_MODE_ENABLE BIT_1 - T3_32BIT_REGISTER Status; - - T3_32BIT_REGISTER MsiFifoAccess; - - /* Unused space. */ - LM_UINT8 Unused[1012]; -} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT; - -/******************************************************************************/ -/* DMA Completion registes. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Mode; -#define DMA_COMP_MODE_RESET BIT_0 -#define DMA_COMP_MODE_ENABLE BIT_1 - - /* Unused space. */ - LM_UINT8 Unused[1020]; -} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION; - -/******************************************************************************/ -/* GRC registers. */ -/******************************************************************************/ - -typedef struct { - /* Mode control register. */ - T3_32BIT_REGISTER Mode; -#define GRC_MODE_UPDATE_ON_COALESCING BIT_0 -#define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA BIT_1 -#define GRC_MODE_WORD_SWAP_NON_FRAME_DATA BIT_2 -#define GRC_MODE_BYTE_SWAP_DATA BIT_4 -#define GRC_MODE_WORD_SWAP_DATA BIT_5 -#define GRC_MODE_SPLIT_HEADER_MODE BIT_8 -#define GRC_MODE_NO_FRAME_CRACKING BIT_9 -#define GRC_MODE_INCLUDE_CRC BIT_10 -#define GRC_MODE_ALLOW_BAD_FRAMES BIT_11 -#define GRC_MODE_NO_INTERRUPT_ON_SENDS BIT_13 -#define GRC_MODE_NO_INTERRUPT_ON_RECEIVE BIT_14 -#define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE BIT_15 -#define GRC_MODE_HOST_STACK_UP BIT_16 -#define GRC_MODE_HOST_SEND_BDS BIT_17 -#define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM BIT_20 -#define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM BIT_23 -#define GRC_MODE_INT_ON_TX_CPU_ATTN BIT_24 -#define GRC_MODE_INT_ON_RX_CPU_ATTN BIT_25 -#define GRC_MODE_INT_ON_MAC_ATTN BIT_26 -#define GRC_MODE_INT_ON_DMA_ATTN BIT_27 -#define GRC_MODE_INT_ON_FLOW_ATTN BIT_28 -#define GRC_MODE_4X_NIC_BASED_SEND_RINGS BIT_29 -#define GRC_MODE_MULTICAST_FRAME_ENABLE BIT_30 - - /* Misc configuration register. */ - T3_32BIT_REGISTER MiscCfg; -#define GRC_MISC_CFG_CORE_CLOCK_RESET BIT_0 -#define GRC_MISC_PRESCALAR_TIMER_MASK 0xfe -#define GRC_MISC_BD_ID_MASK 0x0001e000 -#define GRC_MISC_BD_ID_5700 0x0001e000 -#define GRC_MISC_BD_ID_5701 0x00000000 -#define GRC_MISC_BD_ID_5703 0x00000000 -#define GRC_MISC_BD_ID_5703S 0x00002000 -#define GRC_MISC_BD_ID_5702FE 0x00004000 -#define GRC_MISC_BD_ID_5704 0x00000000 -#define GRC_MISC_BD_ID_5704CIOBE 0x00004000 - - /* Miscellaneous local control register. */ - T3_32BIT_REGISTER LocalCtrl; -#define GRC_MISC_LOCAL_CTRL_INT_ACTIVE BIT_0 -#define GRC_MISC_LOCAL_CTRL_CLEAR_INT BIT_1 -#define GRC_MISC_LOCAL_CTRL_SET_INT BIT_2 -#define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN BIT_3 -#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0 BIT_8 -#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1 BIT_9 -#define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2 BIT_10 -#define GRC_MISC_LOCAL_CTRL_GPIO_OE0 BIT_11 -#define GRC_MISC_LOCAL_CTRL_GPIO_OE1 BIT_12 -#define GRC_MISC_LOCAL_CTRL_GPIO_OE2 BIT_13 -#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 BIT_14 -#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 BIT_15 -#define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2 BIT_16 -#define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY BIT_17 -#define GRC_MISC_LOCAL_CTRL_BANK_SELECT BIT_21 -#define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE BIT_22 - -#define GRC_MISC_MEMSIZE_256K 0 -#define GRC_MISC_MEMSIZE_512K (1 << 18) -#define GRC_MISC_MEMSIZE_1024K (2 << 18) -#define GRC_MISC_MEMSIZE_2048K (3 << 18) -#define GRC_MISC_MEMSIZE_4096K (4 << 18) -#define GRC_MISC_MEMSIZE_8192K (5 << 18) -#define GRC_MISC_MEMSIZE_16M (6 << 18) -#define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM BIT_24 - - T3_32BIT_REGISTER Timer; - - T3_32BIT_REGISTER RxCpuEvent; - T3_32BIT_REGISTER RxTimerRef; - T3_32BIT_REGISTER RxCpuSemaphore; - T3_32BIT_REGISTER RemoteRxCpuAttn; - - T3_32BIT_REGISTER TxCpuEvent; - T3_32BIT_REGISTER TxTimerRef; - T3_32BIT_REGISTER TxCpuSemaphore; - T3_32BIT_REGISTER RemoteTxCpuAttn; - - T3_64BIT_REGISTER MemoryPowerUp; - - T3_32BIT_REGISTER EepromAddr; -#define SEEPROM_ADDR_WRITE 0 -#define SEEPROM_ADDR_READ (1 << 31) -#define SEEPROM_ADDR_RW_MASK 0x80000000 -#define SEEPROM_ADDR_COMPLETE (1 << 30) -#define SEEPROM_ADDR_FSM_RESET (1 << 29) -#define SEEPROM_ADDR_DEV_ID(x) (x << 26) -#define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000 -#define SEEPROM_ADDR_START (1 << 25) -#define SEEPROM_ADDR_CLK_PERD(x) (x << 16) -#define SEEPROM_ADDR_ADDRESS(x) (x & 0xfffc) -#define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff - -#define SEEPROM_CLOCK_PERIOD 60 -#define SEEPROM_CHIP_SIZE (64 * 1024) - - T3_32BIT_REGISTER EepromData; - T3_32BIT_REGISTER EepromCtrl; - - T3_32BIT_REGISTER MdiCtrl; - T3_32BIT_REGISTER SepromDelay; - - /* Unused space. */ - LM_UINT8 Unused[948]; -} T3_GRC, *PT3_GRC; - -/******************************************************************************/ -/* NVRAM control registers. */ -/******************************************************************************/ - -typedef struct { - T3_32BIT_REGISTER Cmd; -#define NVRAM_CMD_RESET BIT_0 -#define NVRAM_CMD_DONE BIT_3 -#define NVRAM_CMD_DO_IT BIT_4 -#define NVRAM_CMD_WR BIT_5 -#define NVRAM_CMD_RD BIT_NONE -#define NVRAM_CMD_ERASE BIT_6 -#define NVRAM_CMD_FIRST BIT_7 -#define NVRAM_CMD_LAST BIT_8 - - T3_32BIT_REGISTER Status; - T3_32BIT_REGISTER WriteData; - - T3_32BIT_REGISTER Addr; -#define NVRAM_ADDRESS_MASK 0xffffff - - T3_32BIT_REGISTER ReadData; - - /* Flash config 1 register. */ - T3_32BIT_REGISTER Config1; -#define FLASH_INTERFACE_ENABLE BIT_0 -#define FLASH_SSRAM_BUFFERRED_MODE BIT_1 -#define FLASH_PASS_THRU_MODE BIT_2 -#define FLASH_BIT_BANG_MODE BIT_3 -#define FLASH_COMPAT_BYPASS BIT_31 - - /* Buffered flash (Atmel: AT45DB011B) specific information */ -#define BUFFERED_FLASH_PAGE_POS 9 -#define BUFFERED_FLASH_BYTE_ADDR_MASK ((1<pMemView->OffsetName)) - -#define REG_WR(pDevice, OffsetName, Value32) \ - (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) && \ - (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) || \ - ((pDevice)->EnablePciXFix == FALSE)) ? \ - (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ - LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) - -#define MB_REG_RD(pDevice, OffsetName) \ - readl(&((pDevice)->pMemView->OffsetName)) - -#define MB_REG_WR(pDevice, OffsetName, Value32) \ - writel(Value32, &((pDevice)->pMemView->OffsetName)) - -#define REG_RD_OFFSET(pDevice, Offset) \ - readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset)) - -#define REG_WR_OFFSET(pDevice, Offset, Value32) \ - (((Offset >=0x200 ) && (Offset < 0x400)) || \ - ((pDevice)->EnablePciXFix == FALSE)) ? \ - (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \ - LM_RegWrInd(pDevice, Offset, Value32) - -#define MEM_RD(pDevice, AddrName) \ - LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) -#define MEM_WR(pDevice, AddrName, Value32) \ - LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) - -#define MEM_RD_OFFSET(pDevice, Offset) \ - LM_MemRdInd(pDevice, Offset) -#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ - LM_MemWrInd(pDevice, Offset, Value32) - -#else /* normal target access path below */ - -/* Register access. */ -#define REG_RD(pDevice, OffsetName) \ - readl(&((pDevice)->pMemView->OffsetName)) -#define REG_WR(pDevice, OffsetName, Value32) \ - writel(Value32, &((pDevice)->pMemView->OffsetName)) - -#define REG_RD_OFFSET(pDevice, Offset) \ - readl(((LM_UINT8 *) (pDevice)->pMemView + Offset)) -#define REG_WR_OFFSET(pDevice, Offset, Value32) \ - writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) - -/* There could be problem access the memory window directly. For now, */ -/* we have to go through the PCI configuration register. */ -#define MEM_RD(pDevice, AddrName) \ - LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) -#define MEM_WR(pDevice, AddrName, Value32) \ - LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) - -#define MEM_RD_OFFSET(pDevice, Offset) \ - LM_MemRdInd(pDevice, Offset) -#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ - LM_MemWrInd(pDevice, Offset, Value32) - -#endif /* PCIX_TARGET_WORKAROUND */ - -#endif /* Jimmy, merging */ - - /* Jimmy...rest of file is new stuff! */ -/******************************************************************************/ -/* NIC register read/write macros. */ -/******************************************************************************/ - -/* MAC register access. */ -LM_UINT32 LM_RegRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register); -LM_VOID LM_RegWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, - LM_UINT32 Value32); - -/* MAC memory access. */ -LM_UINT32 LM_MemRdInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr); -LM_VOID LM_MemWrInd (PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, - LM_UINT32 Value32); - -#define MB_REG_WR(pDevice, OffsetName, Value32) \ - ((pDevice)->UndiFix) ? \ - LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600, \ - Value32) : \ - (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) - -#define MB_REG_RD(pDevice, OffsetName) \ - (((pDevice)->UndiFix) ? \ - LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) : \ - __raw_readl(&((pDevice)->pMemView->OffsetName))) - -#define REG_RD(pDevice, OffsetName) \ - (((pDevice)->UndiFix) ? \ - LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) : \ - __raw_readl(&((pDevice)->pMemView->OffsetName))) - -#if PCIX_TARGET_WORKAROUND - -#define REG_WR(pDevice, OffsetName, Value32) \ - ((pDevice)->EnablePciXFix == FALSE) ? \ - (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ - LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) - -#else - -#define REG_WR(pDevice, OffsetName, Value32) \ - __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) - -#endif - -#define MEM_RD(pDevice, AddrName) \ - LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) -#define MEM_WR(pDevice, AddrName, Value32) \ - LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) - -#define MEM_RD_OFFSET(pDevice, Offset) \ - LM_MemRdInd(pDevice, Offset) -#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ - LM_MemWrInd(pDevice, Offset, Value32) - -#endif /* TIGON3_H */ diff --git a/drivers/tsec.c b/drivers/tsec.c deleted file mode 100644 index ca6284b726..0000000000 --- a/drivers/tsec.c +++ /dev/null @@ -1,1590 +0,0 @@ -/* - * Freescale Three Speed Ethernet Controller driver - * - * This software may be used and distributed according to the - * terms of the GNU Public License, Version 2, incorporated - * herein by reference. - * - * Copyright 2004, 2007 Freescale Semiconductor, Inc. - * (C) Copyright 2003, Motorola, Inc. - * author Andy Fleming - * - */ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_TSEC_ENET) -#include "tsec.h" -#include "miiphy.h" - -DECLARE_GLOBAL_DATA_PTR; - -#define TX_BUF_CNT 2 - -static uint rxIdx; /* index of the current RX buffer */ -static uint txIdx; /* index of the current TX buffer */ - -typedef volatile struct rtxbd { - txbd8_t txbd[TX_BUF_CNT]; - rxbd8_t rxbd[PKTBUFSRX]; -} RTXBD; - -struct tsec_info_struct { - unsigned int phyaddr; - u32 flags; - unsigned int phyregidx; -}; - -/* The tsec_info structure contains 3 values which the - * driver uses to determine how to operate a given ethernet - * device. The information needed is: - * phyaddr - The address of the PHY which is attached to - * the given device. - * - * flags - This variable indicates whether the device - * supports gigabit speed ethernet, and whether it should be - * in reduced mode. - * - * phyregidx - This variable specifies which ethernet device - * controls the MII Management registers which are connected - * to the PHY. For now, only TSEC1 (index 0) has - * access to the PHYs, so all of the entries have "0". - * - * The values specified in the table are taken from the board's - * config file in include/configs/. When implementing a new - * board with ethernet capability, it is necessary to define: - * TSECn_PHY_ADDR - * TSECn_PHYIDX - * - * for n = 1,2,3, etc. And for FEC: - * FEC_PHY_ADDR - * FEC_PHYIDX - */ -static struct tsec_info_struct tsec_info[] = { -#ifdef CONFIG_TSEC1 - {TSEC1_PHY_ADDR, TSEC1_FLAGS, TSEC1_PHYIDX}, -#else - {0, 0, 0}, -#endif -#ifdef CONFIG_TSEC2 - {TSEC2_PHY_ADDR, TSEC2_FLAGS, TSEC2_PHYIDX}, -#else - {0, 0, 0}, -#endif -#ifdef CONFIG_MPC85XX_FEC - {FEC_PHY_ADDR, FEC_FLAGS, FEC_PHYIDX}, -#else -#ifdef CONFIG_TSEC3 - {TSEC3_PHY_ADDR, TSEC3_FLAGS, TSEC3_PHYIDX}, -#else - {0, 0, 0}, -#endif -#ifdef CONFIG_TSEC4 - {TSEC4_PHY_ADDR, TSEC4_FLAGS, TSEC4_PHYIDX}, -#else - {0, 0, 0}, -#endif /* CONFIG_TSEC4 */ -#endif /* CONFIG_MPC85XX_FEC */ -}; - -#define MAXCONTROLLERS (4) - -static int relocated = 0; - -static struct tsec_private *privlist[MAXCONTROLLERS]; - -#ifdef __GNUC__ -static RTXBD rtx __attribute__ ((aligned(8))); -#else -#error "rtx must be 64-bit aligned" -#endif - -static int tsec_send(struct eth_device *dev, - volatile void *packet, int length); -static int tsec_recv(struct eth_device *dev); -static int tsec_init(struct eth_device *dev, bd_t * bd); -static void tsec_halt(struct eth_device *dev); -static void init_registers(volatile tsec_t * regs); -static void startup_tsec(struct eth_device *dev); -static int init_phy(struct eth_device *dev); -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value); -uint read_phy_reg(struct tsec_private *priv, uint regnum); -struct phy_info *get_phy_info(struct eth_device *dev); -void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); -static void adjust_link(struct eth_device *dev); -static void relocate_cmds(void); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ - && !defined(BITBANGMII) -static int tsec_miiphy_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value); -static int tsec_miiphy_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short *value); -#endif -#ifdef CONFIG_MCAST_TFTP -static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); -#endif - -/* Initialize device structure. Returns success if PHY - * initialization succeeded (i.e. if it recognizes the PHY) - */ -int tsec_initialize(bd_t * bis, int index, char *devname) -{ - struct eth_device *dev; - int i; - struct tsec_private *priv; - - dev = (struct eth_device *)malloc(sizeof *dev); - - if (NULL == dev) - return 0; - - memset(dev, 0, sizeof *dev); - - priv = (struct tsec_private *)malloc(sizeof(*priv)); - - if (NULL == priv) - return 0; - - privlist[index] = priv; - priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index * TSEC_SIZE); - priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR + - tsec_info[index].phyregidx * - TSEC_SIZE); - - priv->phyaddr = tsec_info[index].phyaddr; - priv->flags = tsec_info[index].flags; - - sprintf(dev->name, devname); - dev->iobase = 0; - dev->priv = priv; - dev->init = tsec_init; - dev->halt = tsec_halt; - dev->send = tsec_send; - dev->recv = tsec_recv; -#ifdef CONFIG_MCAST_TFTP - dev->mcast = tsec_mcast_addr; -#endif - - /* Tell u-boot to get the addr from the env */ - for (i = 0; i < 6; i++) - dev->enetaddr[i] = 0; - - eth_register(dev); - - /* Reset the MAC */ - priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; - priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ - && !defined(BITBANGMII) - miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); -#endif - - /* Try to initialize PHY here, and return */ - return init_phy(dev); -} - -/* Initializes data structures and registers for the controller, - * and brings the interface up. Returns the link status, meaning - * that it returns success if the link is up, failure otherwise. - * This allows u-boot to find the first active controller. - */ -int tsec_init(struct eth_device *dev, bd_t * bd) -{ - uint tempval; - char tmpbuf[MAC_ADDR_LEN]; - int i; - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - /* Make sure the controller is stopped */ - tsec_halt(dev); - - /* Init MACCFG2. Defaults to GMII */ - regs->maccfg2 = MACCFG2_INIT_SETTINGS; - - /* Init ECNTRL */ - regs->ecntrl = ECNTRL_INIT_SETTINGS; - - /* Copy the station address into the address registers. - * Backwards, because little endian MACS are dumb */ - for (i = 0; i < MAC_ADDR_LEN; i++) { - tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; - } - regs->macstnaddr1 = *((uint *) (tmpbuf)); - - tempval = *((uint *) (tmpbuf + 4)); - - regs->macstnaddr2 = tempval; - - /* reset the indices to zero */ - rxIdx = 0; - txIdx = 0; - - /* Clear out (for the most part) the other registers */ - init_registers(regs); - - /* Ready the device for tx/rx */ - startup_tsec(dev); - - /* If there's no link, fail */ - return priv->link; - -} - -/* Write value to the device's PHY through the registers - * specified in priv, modifying the register specified in regnum. - * It will wait for the write to be done (or for a timeout to - * expire) before exiting - */ -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) -{ - volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; - int timeout = 1000000; - - regbase->miimadd = (phyid << 8) | regnum; - regbase->miimcon = value; - asm("sync"); - - timeout = 1000000; - while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; -} - -/* Reads register regnum on the device's PHY through the - * registers specified in priv. It lowers and raises the read - * command, and waits for the data to become valid (miimind - * notvalid bit cleared), and the bus to cease activity (miimind - * busy bit cleared), and then returns the value - */ -uint read_phy_reg(struct tsec_private *priv, uint regnum) -{ - uint value; - volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; - - /* Put the address of the phy, and the register - * number into MIIMADD */ - regbase->miimadd = (phyid << 8) | regnum; - - /* Clear the command register, and wait */ - regbase->miimcom = 0; - asm("sync"); - - /* Initiate a read command, and wait */ - regbase->miimcom = MIIM_READ_COMMAND; - asm("sync"); - - /* Wait for the the indication that the read is done */ - while ((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ; - - /* Grab the value read from the PHY */ - value = regbase->miimstat; - - return value; -} - -/* Discover which PHY is attached to the device, and configure it - * properly. If the PHY is not recognized, then return 0 - * (failure). Otherwise, return 1 - */ -static int init_phy(struct eth_device *dev) -{ - struct tsec_private *priv = (struct tsec_private *)dev->priv; - struct phy_info *curphy; - volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR); - - /* Assign a Physical address to the TBI */ - regs->tbipa = CFG_TBIPA_VALUE; - regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE); - regs->tbipa = CFG_TBIPA_VALUE; - asm("sync"); - - /* Reset MII (due to new addresses) */ - priv->phyregs->miimcfg = MIIMCFG_RESET; - asm("sync"); - priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE; - asm("sync"); - while (priv->phyregs->miimind & MIIMIND_BUSY) ; - - if (0 == relocated) - relocate_cmds(); - - /* Get the cmd structure corresponding to the attached - * PHY */ - curphy = get_phy_info(dev); - - if (curphy == NULL) { - priv->phyinfo = NULL; - printf("%s: No PHY found\n", dev->name); - - return 0; - } - - priv->phyinfo = curphy; - - phy_run_commands(priv, priv->phyinfo->config); - - return 1; -} - -/* - * Returns which value to write to the control register. - * For 10/100, the value is slightly different - */ -uint mii_cr_init(uint mii_reg, struct tsec_private * priv) -{ - if (priv->flags & TSEC_GIGABIT) - return MIIM_CONTROL_INIT; - else - return MIIM_CR_INIT; -} - -/* Parse the status register for link, and then do - * auto-negotiation - */ -uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) -{ - /* - * Wait if the link is up, and autonegotiation is in progress - * (ie - we're capable and it's not done) - */ - mii_reg = read_phy_reg(priv, MIIM_STATUS); - if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE) - && !(mii_reg & PHY_BMSR_AUTN_COMP)) { - int i = 0; - - puts("Waiting for PHY auto negotiation to complete"); - while (!(mii_reg & PHY_BMSR_AUTN_COMP)) { - /* - * Timeout reached ? - */ - if (i > PHY_AUTONEGOTIATE_TIMEOUT) { - puts(" TIMEOUT !\n"); - priv->link = 0; - return 0; - } - - if ((i++ % 1000) == 0) { - putc('.'); - } - udelay(1000); /* 1 ms */ - mii_reg = read_phy_reg(priv, MIIM_STATUS); - } - puts(" done\n"); - priv->link = 1; - udelay(500000); /* another 500 ms (results in faster booting) */ - } else { - if (mii_reg & MIIM_STATUS_LINK) - priv->link = 1; - else - priv->link = 0; - } - - return 0; -} - -/* Generic function which updates the speed and duplex. If - * autonegotiation is enabled, it uses the AND of the link - * partner's advertised capabilities and our advertised - * capabilities. If autonegotiation is disabled, we use the - * appropriate bits in the control register. - * - * Stolen from Linux's mii.c and phy_device.c - */ -uint mii_parse_link(uint mii_reg, struct tsec_private *priv) -{ - /* We're using autonegotiation */ - if (mii_reg & PHY_BMSR_AUTN_ABLE) { - uint lpa = 0; - uint gblpa = 0; - - /* Check for gigabit capability */ - if (mii_reg & PHY_BMSR_EXT) { - /* We want a list of states supported by - * both PHYs in the link - */ - gblpa = read_phy_reg(priv, PHY_1000BTSR); - gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2; - } - - /* Set the baseline so we only have to set them - * if they're different - */ - priv->speed = 10; - priv->duplexity = 0; - - /* Check the gigabit fields */ - if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { - priv->speed = 1000; - - if (gblpa & PHY_1000BTSR_1000FD) - priv->duplexity = 1; - - /* We're done! */ - return 0; - } - - lpa = read_phy_reg(priv, PHY_ANAR); - lpa &= read_phy_reg(priv, PHY_ANLPAR); - - if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) { - priv->speed = 100; - - if (lpa & PHY_ANLPAR_TXFD) - priv->duplexity = 1; - - } else if (lpa & PHY_ANLPAR_10FD) - priv->duplexity = 1; - } else { - uint bmcr = read_phy_reg(priv, PHY_BMCR); - - priv->speed = 10; - priv->duplexity = 0; - - if (bmcr & PHY_BMCR_DPLX) - priv->duplexity = 1; - - if (bmcr & PHY_BMCR_1000_MBPS) - priv->speed = 1000; - else if (bmcr & PHY_BMCR_100_MBPS) - priv->speed = 100; - } - - return 0; -} - -/* - * Parse the BCM54xx status register for speed and duplex information. - * The linux sungem_phy has this information, but in a table format. - */ -uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv) -{ - - switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){ - - case 1: - printf("Enet starting in 10BT/HD\n"); - priv->duplexity = 0; - priv->speed = 10; - break; - - case 2: - printf("Enet starting in 10BT/FD\n"); - priv->duplexity = 1; - priv->speed = 10; - break; - - case 3: - printf("Enet starting in 100BT/HD\n"); - priv->duplexity = 0; - priv->speed = 100; - break; - - case 5: - printf("Enet starting in 100BT/FD\n"); - priv->duplexity = 1; - priv->speed = 100; - break; - - case 6: - printf("Enet starting in 1000BT/HD\n"); - priv->duplexity = 0; - priv->speed = 1000; - break; - - case 7: - printf("Enet starting in 1000BT/FD\n"); - priv->duplexity = 1; - priv->speed = 1000; - break; - - default: - printf("Auto-neg error, defaulting to 10BT/HD\n"); - priv->duplexity = 0; - priv->speed = 10; - break; - } - - return 0; - -} -/* Parse the 88E1011's status register for speed and duplex - * information - */ -uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) -{ - uint speed; - - mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); - - if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) && - !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { - int i = 0; - - puts("Waiting for PHY realtime link"); - while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { - /* Timeout reached ? */ - if (i > PHY_AUTONEGOTIATE_TIMEOUT) { - puts(" TIMEOUT !\n"); - priv->link = 0; - break; - } - - if ((i++ % 1000) == 0) { - putc('.'); - } - udelay(1000); /* 1 ms */ - mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); - } - puts(" done\n"); - udelay(500000); /* another 500 ms (results in faster booting) */ - } else { - if (mii_reg & MIIM_88E1011_PHYSTAT_LINK) - priv->link = 1; - else - priv->link = 0; - } - - if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) - priv->duplexity = 1; - else - priv->duplexity = 0; - - speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); - - switch (speed) { - case MIIM_88E1011_PHYSTAT_GBIT: - priv->speed = 1000; - break; - case MIIM_88E1011_PHYSTAT_100: - priv->speed = 100; - break; - default: - priv->speed = 10; - } - - return 0; -} - -/* Parse the cis8201's status register for speed and duplex - * information - */ -uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv) -{ - uint speed; - - if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX) - priv->duplexity = 1; - else - priv->duplexity = 0; - - speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED; - switch (speed) { - case MIIM_CIS8201_AUXCONSTAT_GBIT: - priv->speed = 1000; - break; - case MIIM_CIS8201_AUXCONSTAT_100: - priv->speed = 100; - break; - default: - priv->speed = 10; - break; - } - - return 0; -} - -/* Parse the vsc8244's status register for speed and duplex - * information - */ -uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv) -{ - uint speed; - - if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX) - priv->duplexity = 1; - else - priv->duplexity = 0; - - speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED; - switch (speed) { - case MIIM_VSC8244_AUXCONSTAT_GBIT: - priv->speed = 1000; - break; - case MIIM_VSC8244_AUXCONSTAT_100: - priv->speed = 100; - break; - default: - priv->speed = 10; - break; - } - - return 0; -} - -/* Parse the DM9161's status register for speed and duplex - * information - */ -uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv) -{ - if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) - priv->speed = 100; - else - priv->speed = 10; - - if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) - priv->duplexity = 1; - else - priv->duplexity = 0; - - return 0; -} - -/* - * Hack to write all 4 PHYs with the LED values - */ -uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv) -{ - uint phyid; - volatile tsec_t *regbase = priv->phyregs; - int timeout = 1000000; - - for (phyid = 0; phyid < 4; phyid++) { - regbase->miimadd = (phyid << 8) | mii_reg; - regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT; - asm("sync"); - - timeout = 1000000; - while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; - } - - return MIIM_CIS8204_SLEDCON_INIT; -} - -uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv) -{ - if (priv->flags & TSEC_REDUCED) - return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII; - else - return MIIM_CIS8204_EPHYCON_INIT; -} - -/* Initialized required registers to appropriate values, zeroing - * those we don't care about (unless zero is bad, in which case, - * choose a more appropriate value) - */ -static void init_registers(volatile tsec_t * regs) -{ - /* Clear IEVENT */ - regs->ievent = IEVENT_INIT_CLEAR; - - regs->imask = IMASK_INIT_CLEAR; - - regs->hash.iaddr0 = 0; - regs->hash.iaddr1 = 0; - regs->hash.iaddr2 = 0; - regs->hash.iaddr3 = 0; - regs->hash.iaddr4 = 0; - regs->hash.iaddr5 = 0; - regs->hash.iaddr6 = 0; - regs->hash.iaddr7 = 0; - - regs->hash.gaddr0 = 0; - regs->hash.gaddr1 = 0; - regs->hash.gaddr2 = 0; - regs->hash.gaddr3 = 0; - regs->hash.gaddr4 = 0; - regs->hash.gaddr5 = 0; - regs->hash.gaddr6 = 0; - regs->hash.gaddr7 = 0; - - regs->rctrl = 0x00000000; - - /* Init RMON mib registers */ - memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); - - regs->rmon.cam1 = 0xffffffff; - regs->rmon.cam2 = 0xffffffff; - - regs->mrblr = MRBLR_INIT_SETTINGS; - - regs->minflr = MINFLR_INIT_SETTINGS; - - regs->attr = ATTR_INIT_SETTINGS; - regs->attreli = ATTRELI_INIT_SETTINGS; - -} - -/* Configure maccfg2 based on negotiated speed and duplex - * reported by PHY handling code - */ -static void adjust_link(struct eth_device *dev) -{ - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - if (priv->link) { - if (priv->duplexity != 0) - regs->maccfg2 |= MACCFG2_FULL_DUPLEX; - else - regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX); - - switch (priv->speed) { - case 1000: - regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) - | MACCFG2_GMII); - break; - case 100: - case 10: - regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) - | MACCFG2_MII); - - /* Set R100 bit in all modes although - * it is only used in RGMII mode - */ - if (priv->speed == 100) - regs->ecntrl |= ECNTRL_R100; - else - regs->ecntrl &= ~(ECNTRL_R100); - break; - default: - printf("%s: Speed was bad\n", dev->name); - break; - } - - printf("Speed: %d, %s duplex\n", priv->speed, - (priv->duplexity) ? "full" : "half"); - - } else { - printf("%s: No link.\n", dev->name); - } -} - -/* Set up the buffers and their descriptors, and bring up the - * interface - */ -static void startup_tsec(struct eth_device *dev) -{ - int i; - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - /* Point to the buffer descriptors */ - regs->tbase = (unsigned int)(&rtx.txbd[txIdx]); - regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]); - - /* Initialize the Rx Buffer descriptors */ - for (i = 0; i < PKTBUFSRX; i++) { - rtx.rxbd[i].status = RXBD_EMPTY; - rtx.rxbd[i].length = 0; - rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; - } - rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; - - /* Initialize the TX Buffer Descriptors */ - for (i = 0; i < TX_BUF_CNT; i++) { - rtx.txbd[i].status = 0; - rtx.txbd[i].length = 0; - rtx.txbd[i].bufPtr = 0; - } - rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; - - /* Start up the PHY */ - if(priv->phyinfo) - phy_run_commands(priv, priv->phyinfo->startup); - - adjust_link(dev); - - /* Enable Transmit and Receive */ - regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN); - - /* Tell the DMA it is clear to go */ - regs->dmactrl |= DMACTRL_INIT_SETTINGS; - regs->tstat = TSTAT_CLEAR_THALT; - regs->rstat = RSTAT_CLEAR_RHALT; - regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); -} - -/* This returns the status bits of the device. The return value - * is never checked, and this is what the 8260 driver did, so we - * do the same. Presumably, this would be zero if there were no - * errors - */ -static int tsec_send(struct eth_device *dev, volatile void *packet, int length) -{ - int i; - int result = 0; - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - /* Find an empty buffer descriptor */ - for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { - if (i >= TOUT_LOOP) { - debug("%s: tsec: tx buffers full\n", dev->name); - return result; - } - } - - rtx.txbd[txIdx].bufPtr = (uint) packet; - rtx.txbd[txIdx].length = length; - rtx.txbd[txIdx].status |= - (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); - - /* Tell the DMA to go */ - regs->tstat = TSTAT_CLEAR_THALT; - - /* Wait for buffer to be transmitted */ - for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { - if (i >= TOUT_LOOP) { - debug("%s: tsec: tx error\n", dev->name); - return result; - } - } - - txIdx = (txIdx + 1) % TX_BUF_CNT; - result = rtx.txbd[txIdx].status & TXBD_STATS; - - return result; -} - -static int tsec_recv(struct eth_device *dev) -{ - int length; - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { - - length = rtx.rxbd[rxIdx].length; - - /* Send the packet up if there were no errors */ - if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { - NetReceive(NetRxPackets[rxIdx], length - 4); - } else { - printf("Got error %x\n", - (rtx.rxbd[rxIdx].status & RXBD_STATS)); - } - - rtx.rxbd[rxIdx].length = 0; - - /* Set the wrap bit if this is the last element in the list */ - rtx.rxbd[rxIdx].status = - RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); - - rxIdx = (rxIdx + 1) % PKTBUFSRX; - } - - if (regs->ievent & IEVENT_BSY) { - regs->ievent = IEVENT_BSY; - regs->rstat = RSTAT_CLEAR_RHALT; - } - - return -1; - -} - -/* Stop the interface */ -static void tsec_halt(struct eth_device *dev) -{ - struct tsec_private *priv = (struct tsec_private *)dev->priv; - volatile tsec_t *regs = priv->regs; - - regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); - regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS); - - while (!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))) ; - - regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN); - - /* Shut down the PHY, as needed */ - if(priv->phyinfo) - phy_run_commands(priv, priv->phyinfo->shutdown); -} - -struct phy_info phy_info_M88E1149S = { - 0x1410ca, - "Marvell 88E1149S", - 4, - (struct phy_cmd[]){ /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {0x1d, 0x1f, NULL}, - {0x1e, 0x200c, NULL}, - {0x1d, 0x5, NULL}, - {0x1e, 0x0, NULL}, - {0x1e, 0x100, NULL}, - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_88E1011_PHY_STATUS, miim_read, - &mii_parse_88E1011_psr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */ -struct phy_info phy_info_BCM5461S = { - 0x02060c1, /* 5461 ID */ - "Broadcom BCM5461S", - 0, /* not clear to me what minor revisions we can shift away */ - (struct phy_cmd[]) { /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]) { /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, - {miim_end,} - }, - (struct phy_cmd[]) { /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info phy_info_BCM5464S = { - 0x02060b1, /* 5464 ID */ - "Broadcom BCM5464S", - 0, /* not clear to me what minor revisions we can shift away */ - (struct phy_cmd[]) { /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]) { /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, - {miim_end,} - }, - (struct phy_cmd[]) { /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info phy_info_M88E1011S = { - 0x01410c6, - "Marvell 88E1011S", - 4, - (struct phy_cmd[]){ /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {0x1d, 0x1f, NULL}, - {0x1e, 0x200c, NULL}, - {0x1d, 0x5, NULL}, - {0x1e, 0x0, NULL}, - {0x1e, 0x100, NULL}, - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_88E1011_PHY_STATUS, miim_read, - &mii_parse_88E1011_psr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info phy_info_M88E1111S = { - 0x01410cc, - "Marvell 88E1111S", - 4, - (struct phy_cmd[]){ /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */ - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_88E1011_PHY_STATUS, miim_read, - &mii_parse_88E1011_psr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv) -{ - uint mii_data = read_phy_reg(priv, mii_reg); - - /* Setting MIIM_88E1145_PHY_EXT_CR */ - if (priv->flags & TSEC_REDUCED) - return mii_data | - MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY; - else - return mii_data; -} - -static struct phy_info phy_info_M88E1145 = { - 0x01410cd, - "Marvell 88E1145", - 4, - (struct phy_cmd[]){ /* config */ - /* Reset the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - - /* Errata E0, E1 */ - {29, 0x001b, NULL}, - {30, 0x418f, NULL}, - {29, 0x0016, NULL}, - {30, 0xa2da, NULL}, - - /* Configure the PHY */ - {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, - {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, - {MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, - NULL}, - {MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode}, - {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, - {MIIM_CONTROL, MIIM_CONTROL_INIT, NULL}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - {MIIM_88E1111_PHY_LED_CONTROL, - MIIM_88E1111_PHY_LED_DIRECT, NULL}, - /* Read the Status */ - {MIIM_88E1011_PHY_STATUS, miim_read, - &mii_parse_88E1011_psr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info phy_info_cis8204 = { - 0x3f11, - "Cicada Cis8204", - 6, - (struct phy_cmd[]){ /* config */ - /* Override PHY config settings */ - {MIIM_CIS8201_AUX_CONSTAT, - MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, - &mii_cis8204_fixled}, - {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, - &mii_cis8204_setmode}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_CIS8201_AUX_CONSTAT, miim_read, - &mii_parse_cis8201}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -/* Cicada 8201 */ -struct phy_info phy_info_cis8201 = { - 0xfc41, - "CIS8201", - 4, - (struct phy_cmd[]){ /* config */ - /* Override PHY config settings */ - {MIIM_CIS8201_AUX_CONSTAT, - MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, - /* Set up the interface mode */ - {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, - NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_CIS8201_AUX_CONSTAT, miim_read, - &mii_parse_cis8201}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; -struct phy_info phy_info_VSC8244 = { - 0x3f1b, - "Vitesse VSC8244", - 6, - (struct phy_cmd[]){ /* config */ - /* Override PHY config settings */ - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_VSC8244_AUX_CONSTAT, miim_read, - &mii_parse_vsc8244}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info phy_info_dm9161 = { - 0x0181b88, - "Davicom DM9161E", - 4, - (struct phy_cmd[]){ /* config */ - {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL}, - /* Do not bypass the scrambler/descrambler */ - {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL}, - /* Clear 10BTCSR to default */ - {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, - NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CR_INIT, NULL}, - /* Restart Auto Negotiation */ - {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the status */ - {MIIM_DM9161_SCSR, miim_read, - &mii_parse_dm9161_scsr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; -/* a generic flavor. */ -struct phy_info phy_info_generic = { - 0, - "Unknown/Generic PHY", - 32, - (struct phy_cmd[]) { /* config */ - {PHY_BMCR, PHY_BMCR_RESET, NULL}, - {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL}, - {miim_end,} - }, - (struct phy_cmd[]) { /* startup */ - {PHY_BMSR, miim_read, NULL}, - {PHY_BMSR, miim_read, &mii_parse_sr}, - {PHY_BMSR, miim_read, &mii_parse_link}, - {miim_end,} - }, - (struct phy_cmd[]) { /* shutdown */ - {miim_end,} - } -}; - - -uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv) -{ - unsigned int speed; - if (priv->link) { - speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK; - - switch (speed) { - case MIIM_LXT971_SR2_10HDX: - priv->speed = 10; - priv->duplexity = 0; - break; - case MIIM_LXT971_SR2_10FDX: - priv->speed = 10; - priv->duplexity = 1; - break; - case MIIM_LXT971_SR2_100HDX: - priv->speed = 100; - priv->duplexity = 0; - break; - default: - priv->speed = 100; - priv->duplexity = 1; - } - } else { - priv->speed = 0; - priv->duplexity = 0; - } - - return 0; -} - -static struct phy_info phy_info_lxt971 = { - 0x0001378e, - "LXT971", - 4, - (struct phy_cmd[]){ /* config */ - {MIIM_CR, MIIM_CR_INIT, mii_cr_init}, /* autonegotiate */ - {miim_end,} - }, - (struct phy_cmd[]){ /* startup - enable interrupts */ - /* { 0x12, 0x00f2, NULL }, */ - {MIIM_STATUS, miim_read, NULL}, - {MIIM_STATUS, miim_read, &mii_parse_sr}, - {MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown - disable interrupts */ - {miim_end,} - }, -}; - -/* Parse the DP83865's link and auto-neg status register for speed and duplex - * information - */ -uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv) -{ - switch (mii_reg & MIIM_DP83865_SPD_MASK) { - - case MIIM_DP83865_SPD_1000: - priv->speed = 1000; - break; - - case MIIM_DP83865_SPD_100: - priv->speed = 100; - break; - - default: - priv->speed = 10; - break; - - } - - if (mii_reg & MIIM_DP83865_DPX_FULL) - priv->duplexity = 1; - else - priv->duplexity = 0; - - return 0; -} - -struct phy_info phy_info_dp83865 = { - 0x20005c7, - "NatSemi DP83865", - 4, - (struct phy_cmd[]){ /* config */ - {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL}, - {miim_end,} - }, - (struct phy_cmd[]){ /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, &mii_parse_sr}, - /* Read the link and auto-neg status */ - {MIIM_DP83865_LANR, miim_read, - &mii_parse_dp83865_lanr}, - {miim_end,} - }, - (struct phy_cmd[]){ /* shutdown */ - {miim_end,} - }, -}; - -struct phy_info *phy_info[] = { - &phy_info_cis8204, - &phy_info_cis8201, - &phy_info_BCM5461S, - &phy_info_BCM5464S, - &phy_info_M88E1011S, - &phy_info_M88E1111S, - &phy_info_M88E1145, - &phy_info_M88E1149S, - &phy_info_dm9161, - &phy_info_lxt971, - &phy_info_VSC8244, - &phy_info_dp83865, - &phy_info_generic, - NULL -}; - -/* Grab the identifier of the device's PHY, and search through - * all of the known PHYs to see if one matches. If so, return - * it, if not, return NULL - */ -struct phy_info *get_phy_info(struct eth_device *dev) -{ - struct tsec_private *priv = (struct tsec_private *)dev->priv; - uint phy_reg, phy_ID; - int i; - struct phy_info *theInfo = NULL; - - /* Grab the bits from PHYIR1, and put them in the upper half */ - phy_reg = read_phy_reg(priv, MIIM_PHYIR1); - phy_ID = (phy_reg & 0xffff) << 16; - - /* Grab the bits from PHYIR2, and put them in the lower half */ - phy_reg = read_phy_reg(priv, MIIM_PHYIR2); - phy_ID |= (phy_reg & 0xffff); - - /* loop through all the known PHY types, and find one that */ - /* matches the ID we read from the PHY. */ - for (i = 0; phy_info[i]; i++) { - if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) { - theInfo = phy_info[i]; - break; - } - } - - if (theInfo == NULL) { - printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID); - return NULL; - } else { - debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID); - } - - return theInfo; -} - -/* Execute the given series of commands on the given device's - * PHY, running functions as necessary - */ -void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd) -{ - int i; - uint result; - volatile tsec_t *phyregs = priv->phyregs; - - phyregs->miimcfg = MIIMCFG_RESET; - - phyregs->miimcfg = MIIMCFG_INIT_VALUE; - - while (phyregs->miimind & MIIMIND_BUSY) ; - - for (i = 0; cmd->mii_reg != miim_end; i++) { - if (cmd->mii_data == miim_read) { - result = read_phy_reg(priv, cmd->mii_reg); - - if (cmd->funct != NULL) - (*(cmd->funct)) (result, priv); - - } else { - if (cmd->funct != NULL) - result = (*(cmd->funct)) (cmd->mii_reg, priv); - else - result = cmd->mii_data; - - write_phy_reg(priv, cmd->mii_reg, result); - - } - cmd++; - } -} - -/* Relocate the function pointers in the phy cmd lists */ -static void relocate_cmds(void) -{ - struct phy_cmd **cmdlistptr; - struct phy_cmd *cmd; - int i, j, k; - - for (i = 0; phy_info[i]; i++) { - /* First thing's first: relocate the pointers to the - * PHY command structures (the structs were done) */ - phy_info[i] = (struct phy_info *)((uint) phy_info[i] - + gd->reloc_off); - phy_info[i]->name += gd->reloc_off; - phy_info[i]->config = - (struct phy_cmd *)((uint) phy_info[i]->config - + gd->reloc_off); - phy_info[i]->startup = - (struct phy_cmd *)((uint) phy_info[i]->startup - + gd->reloc_off); - phy_info[i]->shutdown = - (struct phy_cmd *)((uint) phy_info[i]->shutdown - + gd->reloc_off); - - cmdlistptr = &phy_info[i]->config; - j = 0; - for (; cmdlistptr <= &phy_info[i]->shutdown; cmdlistptr++) { - k = 0; - for (cmd = *cmdlistptr; - cmd->mii_reg != miim_end; - cmd++) { - /* Only relocate non-NULL pointers */ - if (cmd->funct) - cmd->funct += gd->reloc_off; - - k++; - } - j++; - } - } - - relocated = 1; -} - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ - && !defined(BITBANGMII) - -struct tsec_private *get_priv_for_phy(unsigned char phyaddr) -{ - int i; - - for (i = 0; i < MAXCONTROLLERS; i++) { - if (privlist[i]->phyaddr == phyaddr) - return privlist[i]; - } - - return NULL; -} - -/* - * Read a MII PHY register. - * - * Returns: - * 0 on success - */ -static int tsec_miiphy_read(char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) -{ - unsigned short ret; - struct tsec_private *priv = get_priv_for_phy(addr); - - if (NULL == priv) { - printf("Can't read PHY at address %d\n", addr); - return -1; - } - - ret = (unsigned short)read_phy_reg(priv, reg); - *value = ret; - - return 0; -} - -/* - * Write a MII PHY register. - * - * Returns: - * 0 on success - */ -static int tsec_miiphy_write(char *devname, unsigned char addr, - unsigned char reg, unsigned short value) -{ - struct tsec_private *priv = get_priv_for_phy(addr); - - if (NULL == priv) { - printf("Can't write PHY at address %d\n", addr); - return -1; - } - - write_phy_reg(priv, reg, value); - - return 0; -} - -#endif - -#ifdef CONFIG_MCAST_TFTP - -/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ - -/* Set the appropriate hash bit for the given addr */ - -/* The algorithm works like so: - * 1) Take the Destination Address (ie the multicast address), and - * do a CRC on it (little endian), and reverse the bits of the - * result. - * 2) Use the 8 most significant bits as a hash into a 256-entry - * table. The table is controlled through 8 32-bit registers: - * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is - * gaddr7. This means that the 3 most significant bits in the - * hash index which gaddr register to use, and the 5 other bits - * indicate which bit (assuming an IBM numbering scheme, which - * for PowerPC (tm) is usually the case) in the tregister holds - * the entry. */ -static int -tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) -{ - struct tsec_private *priv = privlist[1]; - volatile tsec_t *regs = priv->regs; - volatile u32 *reg_array, value; - u8 result, whichbit, whichreg; - - result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); - whichbit = result & 0x1f; /* the 5 LSB = which bit to set */ - whichreg = result >> 5; /* the 3 MSB = which reg to set it in */ - value = (1 << (31-whichbit)); - - reg_array = &(regs->hash.gaddr0); - - if (set) { - reg_array[whichreg] |= value; - } else { - reg_array[whichreg] &= ~value; - } - return 0; -} -#endif /* Multicast TFTP ? */ - -#endif /* CONFIG_TSEC_ENET */ diff --git a/drivers/tsec.h b/drivers/tsec.h deleted file mode 100644 index 2f0092ad59..0000000000 --- a/drivers/tsec.h +++ /dev/null @@ -1,563 +0,0 @@ -/* - * tsec.h - * - * Driver for the Motorola Triple Speed Ethernet Controller - * - * This software may be used and distributed according to the - * terms of the GNU Public License, Version 2, incorporated - * herein by reference. - * - * Copyright 2004, 2007 Freescale Semiconductor, Inc. - * (C) Copyright 2003, Motorola, Inc. - * maintained by Xianghua Xiao (x.xiao@motorola.com) - * author Andy Fleming - * - */ - -#ifndef __TSEC_H -#define __TSEC_H - -#include -#include - -#ifndef CFG_TSEC1_OFFSET - #define CFG_TSEC1_OFFSET (0x24000) -#endif - -#define TSEC_SIZE 0x01000 - -/* FIXME: Should these be pushed back to 83xx and 85xx config files? */ -#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) - #define TSEC_BASE_ADDR (CFG_IMMR + CFG_TSEC1_OFFSET) -#elif defined(CONFIG_MPC83XX) - #define TSEC_BASE_ADDR (CFG_IMMR + CFG_TSEC1_OFFSET) -#endif - - -#define MAC_ADDR_LEN 6 - -/* #define TSEC_TIMEOUT 1000000 */ -#define TSEC_TIMEOUT 1000 -#define TOUT_LOOP 1000000 - -#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */ - -/* MAC register bits */ -#define MACCFG1_SOFT_RESET 0x80000000 -#define MACCFG1_RESET_RX_MC 0x00080000 -#define MACCFG1_RESET_TX_MC 0x00040000 -#define MACCFG1_RESET_RX_FUN 0x00020000 -#define MACCFG1_RESET_TX_FUN 0x00010000 -#define MACCFG1_LOOPBACK 0x00000100 -#define MACCFG1_RX_FLOW 0x00000020 -#define MACCFG1_TX_FLOW 0x00000010 -#define MACCFG1_SYNCD_RX_EN 0x00000008 -#define MACCFG1_RX_EN 0x00000004 -#define MACCFG1_SYNCD_TX_EN 0x00000002 -#define MACCFG1_TX_EN 0x00000001 - -#define MACCFG2_INIT_SETTINGS 0x00007205 -#define MACCFG2_FULL_DUPLEX 0x00000001 -#define MACCFG2_IF 0x00000300 -#define MACCFG2_GMII 0x00000200 -#define MACCFG2_MII 0x00000100 - -#define ECNTRL_INIT_SETTINGS 0x00001000 -#define ECNTRL_TBI_MODE 0x00000020 -#define ECNTRL_R100 0x00000008 -#define ECNTRL_SGMII_MODE 0x00000002 - -#define miim_end -2 -#define miim_read -1 - -#ifndef CFG_TBIPA_VALUE - #define CFG_TBIPA_VALUE 0x1f -#endif -#define MIIMCFG_INIT_VALUE 0x00000003 -#define MIIMCFG_RESET 0x80000000 - -#define MIIMIND_BUSY 0x00000001 -#define MIIMIND_NOTVALID 0x00000004 - -#define MIIM_CONTROL 0x00 -#define MIIM_CONTROL_RESET 0x00009140 -#define MIIM_CONTROL_INIT 0x00001140 -#define MIIM_CONTROL_RESTART 0x00001340 -#define MIIM_ANEN 0x00001000 - -#define MIIM_CR 0x00 -#define MIIM_CR_RST 0x00008000 -#define MIIM_CR_INIT 0x00001000 - -#define MIIM_STATUS 0x1 -#define MIIM_STATUS_AN_DONE 0x00000020 -#define MIIM_STATUS_LINK 0x0004 -#define PHY_BMSR_AUTN_ABLE 0x0008 -#define PHY_BMSR_AUTN_COMP 0x0020 - -#define MIIM_PHYIR1 0x2 -#define MIIM_PHYIR2 0x3 - -#define MIIM_ANAR 0x4 -#define MIIM_ANAR_INIT 0x1e1 - -#define MIIM_TBI_ANLPBPA 0x5 -#define MIIM_TBI_ANLPBPA_HALF 0x00000040 -#define MIIM_TBI_ANLPBPA_FULL 0x00000020 - -#define MIIM_TBI_ANEX 0x6 -#define MIIM_TBI_ANEX_NP 0x00000004 -#define MIIM_TBI_ANEX_PRX 0x00000002 - -#define MIIM_GBIT_CONTROL 0x9 -#define MIIM_GBIT_CONTROL_INIT 0xe00 - -/* Broadcom BCM54xx -- taken from linux sungem_phy */ -#define MIIM_BCM54xx_AUXSTATUS 0x19 -#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700 -#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8 - -/* Cicada Auxiliary Control/Status Register */ -#define MIIM_CIS8201_AUX_CONSTAT 0x1c -#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004 -#define MIIM_CIS8201_AUXCONSTAT_DUPLEX 0x0020 -#define MIIM_CIS8201_AUXCONSTAT_SPEED 0x0018 -#define MIIM_CIS8201_AUXCONSTAT_GBIT 0x0010 -#define MIIM_CIS8201_AUXCONSTAT_100 0x0008 - -/* Cicada Extended Control Register 1 */ -#define MIIM_CIS8201_EXT_CON1 0x17 -#define MIIM_CIS8201_EXTCON1_INIT 0x0000 - -/* Cicada 8204 Extended PHY Control Register 1 */ -#define MIIM_CIS8204_EPHY_CON 0x17 -#define MIIM_CIS8204_EPHYCON_INIT 0x0006 -#define MIIM_CIS8204_EPHYCON_RGMII 0x1100 - -/* Cicada 8204 Serial LED Control Register */ -#define MIIM_CIS8204_SLED_CON 0x1b -#define MIIM_CIS8204_SLEDCON_INIT 0x1115 - -#define MIIM_GBIT_CON 0x09 -#define MIIM_GBIT_CON_ADVERT 0x0e00 - -/* Entry for Vitesse VSC8244 regs starts here */ -/* Vitesse VSC8244 Auxiliary Control/Status Register */ -#define MIIM_VSC8244_AUX_CONSTAT 0x1c -#define MIIM_VSC8244_AUXCONSTAT_INIT 0x0000 -#define MIIM_VSC8244_AUXCONSTAT_DUPLEX 0x0020 -#define MIIM_VSC8244_AUXCONSTAT_SPEED 0x0018 -#define MIIM_VSC8244_AUXCONSTAT_GBIT 0x0010 -#define MIIM_VSC8244_AUXCONSTAT_100 0x0008 -#define MIIM_CONTROL_INIT_LOOPBACK 0x4000 - -/* Vitesse VSC8244 Extended PHY Control Register 1 */ -#define MIIM_VSC8244_EPHY_CON 0x17 -#define MIIM_VSC8244_EPHYCON_INIT 0x0006 - -/* Vitesse VSC8244 Serial LED Control Register */ -#define MIIM_VSC8244_LED_CON 0x1b -#define MIIM_VSC8244_LEDCON_INIT 0xF011 - -/* 88E1011 PHY Status Register */ -#define MIIM_88E1011_PHY_STATUS 0x11 -#define MIIM_88E1011_PHYSTAT_SPEED 0xc000 -#define MIIM_88E1011_PHYSTAT_GBIT 0x8000 -#define MIIM_88E1011_PHYSTAT_100 0x4000 -#define MIIM_88E1011_PHYSTAT_DUPLEX 0x2000 -#define MIIM_88E1011_PHYSTAT_SPDDONE 0x0800 -#define MIIM_88E1011_PHYSTAT_LINK 0x0400 - -#define MIIM_88E1011_PHY_SCR 0x10 -#define MIIM_88E1011_PHY_MDI_X_AUTO 0x0060 - -/* 88E1111 PHY LED Control Register */ -#define MIIM_88E1111_PHY_LED_CONTROL 24 -#define MIIM_88E1111_PHY_LED_DIRECT 0x4100 -#define MIIM_88E1111_PHY_LED_COMBINE 0x411C - -/* 88E1145 Extended PHY Specific Control Register */ -#define MIIM_88E1145_PHY_EXT_CR 20 -#define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 -#define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 - -#define MIIM_88E1145_PHY_PAGE 29 -#define MIIM_88E1145_PHY_CAL_OV 30 - - -/* DM9161 Control register values */ -#define MIIM_DM9161_CR_STOP 0x0400 -#define MIIM_DM9161_CR_RSTAN 0x1200 - -#define MIIM_DM9161_SCR 0x10 -#define MIIM_DM9161_SCR_INIT 0x0610 - -/* DM9161 Specified Configuration and Status Register */ -#define MIIM_DM9161_SCSR 0x11 -#define MIIM_DM9161_SCSR_100F 0x8000 -#define MIIM_DM9161_SCSR_100H 0x4000 -#define MIIM_DM9161_SCSR_10F 0x2000 -#define MIIM_DM9161_SCSR_10H 0x1000 - -/* DM9161 10BT Configuration/Status */ -#define MIIM_DM9161_10BTCSR 0x12 -#define MIIM_DM9161_10BTCSR_INIT 0x7800 - -/* LXT971 Status 2 registers */ -#define MIIM_LXT971_SR2 0x11 /* Status Register 2 */ -#define MIIM_LXT971_SR2_SPEED_MASK 0x4200 -#define MIIM_LXT971_SR2_10HDX 0x0000 /* 10 Mbit half duplex selected */ -#define MIIM_LXT971_SR2_10FDX 0x0200 /* 10 Mbit full duplex selected */ -#define MIIM_LXT971_SR2_100HDX 0x4000 /* 100 Mbit half duplex selected */ -#define MIIM_LXT971_SR2_100FDX 0x4200 /* 100 Mbit full duplex selected */ - -/* DP83865 Control register values */ -#define MIIM_DP83865_CR_INIT 0x9200 - -/* DP83865 Link and Auto-Neg Status Register */ -#define MIIM_DP83865_LANR 0x11 -#define MIIM_DP83865_SPD_MASK 0x0018 -#define MIIM_DP83865_SPD_1000 0x0010 -#define MIIM_DP83865_SPD_100 0x0008 -#define MIIM_DP83865_DPX_FULL 0x0002 - -#define MIIM_READ_COMMAND 0x00000001 - -#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN - -#define MINFLR_INIT_SETTINGS 0x00000040 - -#define DMACTRL_INIT_SETTINGS 0x000000c3 -#define DMACTRL_GRS 0x00000010 -#define DMACTRL_GTS 0x00000008 - -#define TSTAT_CLEAR_THALT 0x80000000 -#define RSTAT_CLEAR_RHALT 0x00800000 - - -#define IEVENT_INIT_CLEAR 0xffffffff -#define IEVENT_BABR 0x80000000 -#define IEVENT_RXC 0x40000000 -#define IEVENT_BSY 0x20000000 -#define IEVENT_EBERR 0x10000000 -#define IEVENT_MSRO 0x04000000 -#define IEVENT_GTSC 0x02000000 -#define IEVENT_BABT 0x01000000 -#define IEVENT_TXC 0x00800000 -#define IEVENT_TXE 0x00400000 -#define IEVENT_TXB 0x00200000 -#define IEVENT_TXF 0x00100000 -#define IEVENT_IE 0x00080000 -#define IEVENT_LC 0x00040000 -#define IEVENT_CRL 0x00020000 -#define IEVENT_XFUN 0x00010000 -#define IEVENT_RXB0 0x00008000 -#define IEVENT_GRSC 0x00000100 -#define IEVENT_RXF0 0x00000080 - -#define IMASK_INIT_CLEAR 0x00000000 -#define IMASK_TXEEN 0x00400000 -#define IMASK_TXBEN 0x00200000 -#define IMASK_TXFEN 0x00100000 -#define IMASK_RXFEN0 0x00000080 - - -/* Default Attribute fields */ -#define ATTR_INIT_SETTINGS 0x000000c0 -#define ATTRELI_INIT_SETTINGS 0x00000000 - - -/* TxBD status field bits */ -#define TXBD_READY 0x8000 -#define TXBD_PADCRC 0x4000 -#define TXBD_WRAP 0x2000 -#define TXBD_INTERRUPT 0x1000 -#define TXBD_LAST 0x0800 -#define TXBD_CRC 0x0400 -#define TXBD_DEF 0x0200 -#define TXBD_HUGEFRAME 0x0080 -#define TXBD_LATECOLLISION 0x0080 -#define TXBD_RETRYLIMIT 0x0040 -#define TXBD_RETRYCOUNTMASK 0x003c -#define TXBD_UNDERRUN 0x0002 -#define TXBD_STATS 0x03ff - -/* RxBD status field bits */ -#define RXBD_EMPTY 0x8000 -#define RXBD_RO1 0x4000 -#define RXBD_WRAP 0x2000 -#define RXBD_INTERRUPT 0x1000 -#define RXBD_LAST 0x0800 -#define RXBD_FIRST 0x0400 -#define RXBD_MISS 0x0100 -#define RXBD_BROADCAST 0x0080 -#define RXBD_MULTICAST 0x0040 -#define RXBD_LARGE 0x0020 -#define RXBD_NONOCTET 0x0010 -#define RXBD_SHORT 0x0008 -#define RXBD_CRCERR 0x0004 -#define RXBD_OVERRUN 0x0002 -#define RXBD_TRUNCATED 0x0001 -#define RXBD_STATS 0x003f - -typedef struct txbd8 -{ - ushort status; /* Status Fields */ - ushort length; /* Buffer length */ - uint bufPtr; /* Buffer Pointer */ -} txbd8_t; - -typedef struct rxbd8 -{ - ushort status; /* Status Fields */ - ushort length; /* Buffer Length */ - uint bufPtr; /* Buffer Pointer */ -} rxbd8_t; - -typedef struct rmon_mib -{ - /* Transmit and Receive Counters */ - uint tr64; /* Transmit and Receive 64-byte Frame Counter */ - uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */ - uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */ - uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */ - uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */ - uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */ - uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */ - /* Receive Counters */ - uint rbyt; /* Receive Byte Counter */ - uint rpkt; /* Receive Packet Counter */ - uint rfcs; /* Receive FCS Error Counter */ - uint rmca; /* Receive Multicast Packet (Counter) */ - uint rbca; /* Receive Broadcast Packet */ - uint rxcf; /* Receive Control Frame Packet */ - uint rxpf; /* Receive Pause Frame Packet */ - uint rxuo; /* Receive Unknown OP Code */ - uint raln; /* Receive Alignment Error */ - uint rflr; /* Receive Frame Length Error */ - uint rcde; /* Receive Code Error */ - uint rcse; /* Receive Carrier Sense Error */ - uint rund; /* Receive Undersize Packet */ - uint rovr; /* Receive Oversize Packet */ - uint rfrg; /* Receive Fragments */ - uint rjbr; /* Receive Jabber */ - uint rdrp; /* Receive Drop */ - /* Transmit Counters */ - uint tbyt; /* Transmit Byte Counter */ - uint tpkt; /* Transmit Packet */ - uint tmca; /* Transmit Multicast Packet */ - uint tbca; /* Transmit Broadcast Packet */ - uint txpf; /* Transmit Pause Control Frame */ - uint tdfr; /* Transmit Deferral Packet */ - uint tedf; /* Transmit Excessive Deferral Packet */ - uint tscl; /* Transmit Single Collision Packet */ - /* (0x2_n700) */ - uint tmcl; /* Transmit Multiple Collision Packet */ - uint tlcl; /* Transmit Late Collision Packet */ - uint txcl; /* Transmit Excessive Collision Packet */ - uint tncl; /* Transmit Total Collision */ - - uint res2; - - uint tdrp; /* Transmit Drop Frame */ - uint tjbr; /* Transmit Jabber Frame */ - uint tfcs; /* Transmit FCS Error */ - uint txcf; /* Transmit Control Frame */ - uint tovr; /* Transmit Oversize Frame */ - uint tund; /* Transmit Undersize Frame */ - uint tfrg; /* Transmit Fragments Frame */ - /* General Registers */ - uint car1; /* Carry Register One */ - uint car2; /* Carry Register Two */ - uint cam1; /* Carry Register One Mask */ - uint cam2; /* Carry Register Two Mask */ -} rmon_mib_t; - -typedef struct tsec_hash_regs -{ - uint iaddr0; /* Individual Address Register 0 */ - uint iaddr1; /* Individual Address Register 1 */ - uint iaddr2; /* Individual Address Register 2 */ - uint iaddr3; /* Individual Address Register 3 */ - uint iaddr4; /* Individual Address Register 4 */ - uint iaddr5; /* Individual Address Register 5 */ - uint iaddr6; /* Individual Address Register 6 */ - uint iaddr7; /* Individual Address Register 7 */ - uint res1[24]; - uint gaddr0; /* Group Address Register 0 */ - uint gaddr1; /* Group Address Register 1 */ - uint gaddr2; /* Group Address Register 2 */ - uint gaddr3; /* Group Address Register 3 */ - uint gaddr4; /* Group Address Register 4 */ - uint gaddr5; /* Group Address Register 5 */ - uint gaddr6; /* Group Address Register 6 */ - uint gaddr7; /* Group Address Register 7 */ - uint res2[24]; -} tsec_hash_t; - -typedef struct tsec -{ - /* General Control and Status Registers (0x2_n000) */ - uint res000[4]; - - uint ievent; /* Interrupt Event */ - uint imask; /* Interrupt Mask */ - uint edis; /* Error Disabled */ - uint res01c; - uint ecntrl; /* Ethernet Control */ - uint minflr; /* Minimum Frame Length */ - uint ptv; /* Pause Time Value */ - uint dmactrl; /* DMA Control */ - uint tbipa; /* TBI PHY Address */ - - uint res034[3]; - uint res040[48]; - - /* Transmit Control and Status Registers (0x2_n100) */ - uint tctrl; /* Transmit Control */ - uint tstat; /* Transmit Status */ - uint res108; - uint tbdlen; /* Tx BD Data Length */ - uint res110[5]; - uint ctbptr; /* Current TxBD Pointer */ - uint res128[23]; - uint tbptr; /* TxBD Pointer */ - uint res188[30]; - /* (0x2_n200) */ - uint res200; - uint tbase; /* TxBD Base Address */ - uint res208[42]; - uint ostbd; /* Out of Sequence TxBD */ - uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */ - uint res2b8[18]; - - /* Receive Control and Status Registers (0x2_n300) */ - uint rctrl; /* Receive Control */ - uint rstat; /* Receive Status */ - uint res308; - uint rbdlen; /* RxBD Data Length */ - uint res310[4]; - uint res320; - uint crbptr; /* Current Receive Buffer Pointer */ - uint res328[6]; - uint mrblr; /* Maximum Receive Buffer Length */ - uint res344[16]; - uint rbptr; /* RxBD Pointer */ - uint res388[30]; - /* (0x2_n400) */ - uint res400; - uint rbase; /* RxBD Base Address */ - uint res408[62]; - - /* MAC Registers (0x2_n500) */ - uint maccfg1; /* MAC Configuration #1 */ - uint maccfg2; /* MAC Configuration #2 */ - uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */ - uint hafdup; /* Half-duplex */ - uint maxfrm; /* Maximum Frame */ - uint res514; - uint res518; - - uint res51c; - - uint miimcfg; /* MII Management: Configuration */ - uint miimcom; /* MII Management: Command */ - uint miimadd; /* MII Management: Address */ - uint miimcon; /* MII Management: Control */ - uint miimstat; /* MII Management: Status */ - uint miimind; /* MII Management: Indicators */ - - uint res538; - - uint ifstat; /* Interface Status */ - uint macstnaddr1; /* Station Address, part 1 */ - uint macstnaddr2; /* Station Address, part 2 */ - uint res548[46]; - - /* (0x2_n600) */ - uint res600[32]; - - /* RMON MIB Registers (0x2_n680-0x2_n73c) */ - rmon_mib_t rmon; - uint res740[48]; - - /* Hash Function Registers (0x2_n800) */ - tsec_hash_t hash; - - uint res900[128]; - - /* Pattern Registers (0x2_nb00) */ - uint resb00[62]; - uint attr; /* Default Attribute Register */ - uint attreli; /* Default Attribute Extract Length and Index */ - - /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */ - uint resc00[256]; -} tsec_t; - -#define TSEC_GIGABIT (1) - -/* This flag currently only has - * meaning if we're using the eTSEC */ -#define TSEC_REDUCED (1 << 1) - -struct tsec_private { - volatile tsec_t *regs; - volatile tsec_t *phyregs; - struct phy_info *phyinfo; - uint phyaddr; - u32 flags; - uint link; - uint duplexity; - uint speed; -}; - - -/* - * struct phy_cmd: A command for reading or writing a PHY register - * - * mii_reg: The register to read or write - * - * mii_data: For writes, the value to put in the register. - * A value of -1 indicates this is a read. - * - * funct: A function pointer which is invoked for each command. - * For reads, this function will be passed the value read - * from the PHY, and process it. - * For writes, the result of this function will be written - * to the PHY register - */ -struct phy_cmd { - uint mii_reg; - uint mii_data; - uint (*funct) (uint mii_reg, struct tsec_private* priv); -}; - -/* struct phy_info: a structure which defines attributes for a PHY - * - * id will contain a number which represents the PHY. During - * startup, the driver will poll the PHY to find out what its - * UID--as defined by registers 2 and 3--is. The 32-bit result - * gotten from the PHY will be shifted right by "shift" bits to - * discard any bits which may change based on revision numbers - * unimportant to functionality - * - * The struct phy_cmd entries represent pointers to an arrays of - * commands which tell the driver what to do to the PHY. - */ -struct phy_info { - uint id; - char *name; - uint shift; - /* Called to configure the PHY, and modify the controller - * based on the results */ - struct phy_cmd *config; - - /* Called when starting up the controller */ - struct phy_cmd *startup; - - /* Called when bringing down the controller */ - struct phy_cmd *shutdown; -}; - -#endif /* __TSEC_H */ diff --git a/drivers/tsi108_eth.c b/drivers/tsi108_eth.c deleted file mode 100644 index 524e9daa4c..0000000000 --- a/drivers/tsi108_eth.c +++ /dev/null @@ -1,1036 +0,0 @@ -/*********************************************************************** - * - * Copyright (c) 2005 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Description: - * Ethernet interface for Tundra TSI108 bridge chip - * - ***********************************************************************/ - -#include - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) \ - && defined(CONFIG_TSI108_ETH) - -#if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2) -#error "CONFIG_TSI108_ETH_NUM_PORTS must be defined as 1 or 2" -#endif - -#include -#include -#include -#include - -#ifdef DEBUG -#define TSI108_ETH_DEBUG 7 -#else -#define TSI108_ETH_DEBUG 0 -#endif - -#if TSI108_ETH_DEBUG > 0 -#define debug_lev(lev, fmt, args...) \ -if (lev <= TSI108_ETH_DEBUG) \ -printf ("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) -#else -#define debug_lev(lev, fmt, args...) do{}while(0) -#endif - -#define RX_PRINT_ERRORS -#define TX_PRINT_ERRORS - -#define ETH_BASE (CFG_TSI108_CSR_BASE + 0x6000) - -#define ETH_PORT_OFFSET 0x400 - -#define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset)))) - -#define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000) -#define MAC_CONFIG_1_TX_ENABLE (0x00000001) -#define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002) -#define MAC_CONFIG_1_RX_ENABLE (0x00000004) -#define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008) -#define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010) -#define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020) -#define MAC_CONFIG_1_LOOP_BACK (0x00000100) -#define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000) -#define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000) -#define MAC_CONFIG_1_RESET_TX_MAC (0x00040000) -#define MAC_CONFIG_1_RESET_RX_MAC (0x00080000) -#define MAC_CONFIG_1_SIM_RESET (0x40000000) -#define MAC_CONFIG_1_SOFT_RESET (0x80000000) - -#define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004) -#define MAC_CONFIG_2_FULL_DUPLEX (0x00000001) -#define MAC_CONFIG_2_CRC_ENABLE (0x00000002) -#define MAC_CONFIG_2_PAD_CRC (0x00000004) -#define MAC_CONFIG_2_LENGTH_CHECK (0x00000010) -#define MAC_CONFIG_2_HUGE_FRAME (0x00000020) -#define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8) -#define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12) -#define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */ -#define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */ - -#define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010) - -#define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020) -#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7) -#define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010) -#define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020) -#define MII_MGMT_CONFIG_RESET_MGMT (0x80000000) - -#define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024) -#define MII_MGMT_COMMAND_READ_CYCLE (0x00000001) -#define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002) - -#define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028) -#define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c) -#define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030) - -#define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034) -#define MII_MGMT_INDICATORS_BUSY (0x00000001) -#define MII_MGMT_INDICATORS_SCAN (0x00000002) -#define MII_MGMT_INDICATORS_NOT_VALID (0x00000004) - -#define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c) -#define INTERFACE_STATUS_LINK_FAIL (0x00000008) -#define INTERFACE_STATUS_EXCESS_DEFER (0x00000200) - -#define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040) -#define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044) - -#define reg_PORT_CONTROL(base) __REG32(base, 0x00000200) -#define PORT_CONTROL_PRI (0x00000001) -#define PORT_CONTROL_BPT (0x00010000) -#define PORT_CONTROL_SPD (0x00040000) -#define PORT_CONTROL_RBC (0x00080000) -#define PORT_CONTROL_PRB (0x00200000) -#define PORT_CONTROL_DIS (0x00400000) -#define PORT_CONTROL_TBI (0x00800000) -#define PORT_CONTROL_STE (0x10000000) -#define PORT_CONTROL_ZOR (0x20000000) -#define PORT_CONTROL_CLR (0x40000000) -#define PORT_CONTROL_SRT (0x80000000) - -#define reg_TX_CONFIG(base) __REG32(base, 0x00000220) -#define TX_CONFIG_START_Q (0x00000003) -#define TX_CONFIG_EHP (0x00400000) -#define TX_CONFIG_CHP (0x00800000) -#define TX_CONFIG_RST (0x80000000) - -#define reg_TX_CONTROL(base) __REG32(base, 0x00000224) -#define TX_CONTROL_GO (0x00008000) -#define TX_CONTROL_MP (0x01000000) -#define TX_CONTROL_EAI (0x20000000) -#define TX_CONTROL_ABT (0x40000000) -#define TX_CONTROL_EII (0x80000000) - -#define reg_TX_STATUS(base) __REG32(base, 0x00000228) -#define TX_STATUS_QUEUE_USABLE (0x0000000f) -#define TX_STATUS_CURR_Q (0x00000300) -#define TX_STATUS_ACT (0x00008000) -#define TX_STATUS_QUEUE_IDLE (0x000f0000) -#define TX_STATUS_EOQ_PENDING (0x0f000000) - -#define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c) -#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f) -#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00) -#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) -#define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) - -#define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230) - -#define reg_TX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000270) -#define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) -#define TX_DIAGNOSTIC_ADDR_DFR (0x40000000) -#define TX_DIAGNOSTIC_ADDR_AI (0x80000000) - -#define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274) - -#define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278) -#define TX_ERROR_STATUS (0x00000278) -#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010) -#define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020) -#define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040) -#define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080) -#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000) -#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000) -#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000) - -#define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280) -#define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) -#define TX_QUEUE_0_CONFIG_BSWP (0x00000400) -#define TX_QUEUE_0_CONFIG_WSWP (0x00000800) -#define TX_QUEUE_0_CONFIG_AM (0x00004000) -#define TX_QUEUE_0_CONFIG_GVI (0x00008000) -#define TX_QUEUE_0_CONFIG_EEI (0x00010000) -#define TX_QUEUE_0_CONFIG_ELI (0x00020000) -#define TX_QUEUE_0_CONFIG_ENI (0x00040000) -#define TX_QUEUE_0_CONFIG_ESI (0x00080000) -#define TX_QUEUE_0_CONFIG_EDI (0x00100000) - -#define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284) -#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) -#define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) -#define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) -#define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) - -#define OCN_PORT_HLP 0 /* HLP Interface */ -#define OCN_PORT_PCI_X 1 /* PCI-X Interface */ -#define OCN_PORT_PROCESSOR_MASTER 2 /* Processor Interface (master) */ -#define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */ -#define OCN_PORT_MEMORY 4 /* Memory Controller */ -#define OCN_PORT_DMA 5 /* DMA Controller */ -#define OCN_PORT_ETHERNET 6 /* Ethernet Controller */ -#define OCN_PORT_PRINT 7 /* Print Engine Interface */ - -#define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288) - -#define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c) -#define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000) - -#define reg_RX_CONFIG(base) __REG32(base, 0x00000320) -#define RX_CONFIG_DEF_Q (0x00000003) -#define RX_CONFIG_EMF (0x00000100) -#define RX_CONFIG_EUF (0x00000200) -#define RX_CONFIG_BFE (0x00000400) -#define RX_CONFIG_MFE (0x00000800) -#define RX_CONFIG_UFE (0x00001000) -#define RX_CONFIG_SE (0x00002000) -#define RX_CONFIG_ABF (0x00200000) -#define RX_CONFIG_APE (0x00400000) -#define RX_CONFIG_CHP (0x00800000) -#define RX_CONFIG_RST (0x80000000) - -#define reg_RX_CONTROL(base) __REG32(base, 0x00000324) -#define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f) -#define GE_E0_RX_CONTROL_GO (0x00008000) -#define GE_E0_RX_CONTROL_EAI (0x20000000) -#define GE_E0_RX_CONTROL_ABT (0x40000000) -#define GE_E0_RX_CONTROL_EII (0x80000000) - -#define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c) -#define RX_EXTENDED_STATUS (0x0000032c) -#define RX_EXTENDED_STATUS_EOQ (0x0000000f) -#define RX_EXTENDED_STATUS_EOQ_0 (0x00000001) -#define RX_EXTENDED_STATUS_EOF (0x00000f00) -#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) -#define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) - -#define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330) - -#define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370) -#define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) -#define RX_DIAGNOSTIC_ADDR_DFR (0x40000000) -#define RX_DIAGNOSTIC_ADDR_AI (0x80000000) - -#define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374) - -#define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380) -#define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) -#define RX_QUEUE_0_CONFIG_BSWP (0x00000400) -#define RX_QUEUE_0_CONFIG_WSWP (0x00000800) -#define RX_QUEUE_0_CONFIG_AM (0x00004000) -#define RX_QUEUE_0_CONFIG_EEI (0x00010000) -#define RX_QUEUE_0_CONFIG_ELI (0x00020000) -#define RX_QUEUE_0_CONFIG_ENI (0x00040000) -#define RX_QUEUE_0_CONFIG_ESI (0x00080000) -#define RX_QUEUE_0_CONFIG_EDI (0x00100000) - -#define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384) -#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) -#define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) -#define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) -#define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) - -#define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388) - -#define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c) -#define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000) - -/* - * PHY register definitions - */ -/* the first 15 PHY registers are standard. */ -#define PHY_CTRL_REG 0 /* Control Register */ -#define PHY_STATUS_REG 1 /* Status Regiser */ -#define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */ -#define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */ -#define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */ -#define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */ - -/* - * PHY Register bit masks. - */ -#define PHY_CTRL_RESET (1 << 15) -#define PHY_CTRL_LOOPBACK (1 << 14) -#define PHY_CTRL_SPEED0 (1 << 13) -#define PHY_CTRL_AN_EN (1 << 12) -#define PHY_CTRL_PWR_DN (1 << 11) -#define PHY_CTRL_ISOLATE (1 << 10) -#define PHY_CTRL_RESTART_AN (1 << 9) -#define PHY_CTRL_FULL_DUPLEX (1 << 8) -#define PHY_CTRL_CT_EN (1 << 7) -#define PHY_CTRL_SPEED1 (1 << 6) - -#define PHY_STAT_100BASE_T4 (1 << 15) -#define PHY_STAT_100BASE_X_FD (1 << 14) -#define PHY_STAT_100BASE_X_HD (1 << 13) -#define PHY_STAT_10BASE_T_FD (1 << 12) -#define PHY_STAT_10BASE_T_HD (1 << 11) -#define PHY_STAT_100BASE_T2_FD (1 << 10) -#define PHY_STAT_100BASE_T2_HD (1 << 9) -#define PHY_STAT_EXT_STAT (1 << 8) -#define PHY_STAT_RESERVED (1 << 7) -#define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */ -#define PHY_STAT_AN_COMPLETE (1 << 5) -#define PHY_STAT_REM_FAULT (1 << 4) -#define PHY_STAT_AN_CAP (1 << 3) -#define PHY_STAT_LINK_UP (1 << 2) -#define PHY_STAT_JABBER (1 << 1) -#define PHY_STAT_EXT_CAP (1 << 0) - -#define TBI_CONTROL_2 0x11 -#define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001 -#define TBI_CONTROL_2_ENABLE_WRAP 0x0002 -#define TBI_CONTROL_2_G_MII_MODE 0x0010 -#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020 -#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100 -#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000 -#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000 -#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000 -#define TBI_CONTROL_2_SOFT_RESET 0x8000 - -/* marvel specific */ -#define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */ -#define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */ -#define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */ - -/* - * MARVELL 88E1111 PHY register bit masks - */ -/* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */ - -#define SPEC_STAT_SPEED_MASK (3 << 14) -#define SPEC_STAT_FULL_DUP (1 << 13) -#define SPEC_STAT_PAGE_RCVD (1 << 12) -#define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */ -#define SPEC_STAT_LINK_UP (1 << 10) -#define SPEC_STAT_CABLE_LEN_MASK (7 << 7)/* Cable Length (100/1000 modes only) */ -#define SPEC_STAT_MDIX (1 << 6) -#define SPEC_STAT_POLARITY (1 << 1) -#define SPEC_STAT_JABBER (1 << 0) - -#define SPEED_1000 (2 << 14) -#define SPEED_100 (1 << 14) -#define SPEED_10 (0 << 14) - -#define TBI_ADDR 0x1E /* Ten Bit Interface address */ - -/* negotiated link parameters */ -#define LINK_SPEED_UNKNOWN 0 -#define LINK_SPEED_10 1 -#define LINK_SPEED_100 2 -#define LINK_SPEED_1000 3 - -#define LINK_DUPLEX_UNKNOWN 0 -#define LINK_DUPLEX_HALF 1 -#define LINK_DUPLEX_FULL 2 - -static unsigned int phy_address[] = { 8, 9 }; - -#define vuint32 volatile u32 - -/* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte) - * This structure is accessed by the ethernet DMA engine which means it - * MUST be in LITTLE ENDIAN format */ -struct dma_descriptor { - vuint32 start_addr0; /* buffer address, least significant bytes. */ - vuint32 start_addr1; /* buffer address, most significant bytes. */ - vuint32 next_descr_addr0;/* next descriptor address, least significant bytes. Must be 64-bit aligned. */ - vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */ - vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */ - vuint32 config_status; /* Configuration/Status. */ - vuint32 reserved1; /* reserved to make the descriptor cache line aligned. */ - vuint32 reserved2; /* reserved to make the descriptor cache line aligned. */ -}; - -/* last next descriptor address flag */ -#define DMA_DESCR_LAST (1 << 31) - -/* TX DMA descriptor config status bits */ -#define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */ -#define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */ -#define DMA_DESCR_TX_PFVLAN (1 << 2) -#define DMA_DESCR_TX_HUGE (1 << 3) -#define DMA_DESCR_TX_PAD (1 << 4) -#define DMA_DESCR_TX_CRC (1 << 5) -#define DMA_DESCR_TX_DESCR_INT (1 << 14) -#define DMA_DESCR_TX_RETRY_COUNT 0x000F0000 -#define DMA_DESCR_TX_ONE_COLLISION (1 << 20) -#define DMA_DESCR_TX_LATE_COLLISION (1 << 24) -#define DMA_DESCR_TX_UNDERRUN (1 << 25) -#define DMA_DESCR_TX_RETRY_LIMIT (1 << 26) -#define DMA_DESCR_TX_OK (1 << 30) -#define DMA_DESCR_TX_OWNER (1 << 31) - -/* RX DMA descriptor status bits */ -#define DMA_DESCR_RX_EOF (1 << 0) -#define DMA_DESCR_RX_SOF (1 << 1) -#define DMA_DESCR_RX_VTF (1 << 2) -#define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3) -#define DMA_DESCR_RX_SHORT_FRAME (1 << 4) -#define DMA_DESCR_RX_HASH_MATCH (1 << 7) -#define DMA_DESCR_RX_BAD_FRAME (1 << 8) -#define DMA_DESCR_RX_OVERRUN (1 << 9) -#define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11) -#define DMA_DESCR_RX_CRC_ERROR (1 << 12) -#define DMA_DESCR_RX_DESCR_INT (1 << 13) -#define DMA_DESCR_RX_OWNER (1 << 15) - -#define RX_BUFFER_SIZE PKTSIZE -#define NUM_RX_DESC PKTBUFSRX - -static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32))); - -static struct dma_descriptor rx_descr_array[NUM_RX_DESC] - __attribute__ ((aligned(32))); - -static struct dma_descriptor *rx_descr_current; - -static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis); -static int tsi108_eth_send (struct eth_device *dev, - volatile void *packet, int length); -static int tsi108_eth_recv (struct eth_device *dev); -static void tsi108_eth_halt (struct eth_device *dev); -static unsigned int read_phy (unsigned int base, - unsigned int phy_addr, unsigned int phy_reg); -static void write_phy (unsigned int base, - unsigned int phy_addr, - unsigned int phy_reg, unsigned int phy_data); - -#if TSI108_ETH_DEBUG > 100 -/* - * print phy debug infomation - */ -static void dump_phy_regs (unsigned int phy_addr) -{ - int i; - - printf ("PHY %d registers\n", phy_addr); - for (i = 0; i <= 30; i++) { - printf ("%2d 0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i)); - } - printf ("\n"); - -} -#else -#define dump_phy_regs(base) do{}while(0) -#endif - -#if TSI108_ETH_DEBUG > 100 -/* - * print debug infomation - */ -static void tx_diag_regs (unsigned int base) -{ - int i; - unsigned long dummy; - - printf ("TX diagnostics registers\n"); - reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI; - udelay (1000); - dummy = reg_TX_DIAGNOSTIC_DATA(base); - for (i = 0x00; i <= 0x05; i++) { - udelay (1000); - printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); - } - reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI; - udelay (1000); - dummy = reg_TX_DIAGNOSTIC_DATA(base); - for (i = 0x40; i <= 0x47; i++) { - udelay (1000); - printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); - } - printf ("\n"); - -} -#else -#define tx_diag_regs(base) do{}while(0) -#endif - -#if TSI108_ETH_DEBUG > 100 -/* - * print debug infomation - */ -static void rx_diag_regs (unsigned int base) -{ - int i; - unsigned long dummy; - - printf ("RX diagnostics registers\n"); - reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI; - udelay (1000); - dummy = reg_RX_DIAGNOSTIC_DATA(base); - for (i = 0x00; i <= 0x05; i++) { - udelay (1000); - printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); - } - reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI; - udelay (1000); - dummy = reg_RX_DIAGNOSTIC_DATA(base); - for (i = 0x08; i <= 0x0a; i++) { - udelay (1000); - printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); - } - printf ("\n"); - -} -#else -#define rx_diag_regs(base) do{}while(0) -#endif - -#if TSI108_ETH_DEBUG > 100 -/* - * print debug infomation - */ -static void debug_mii_regs (unsigned int base) -{ - printf ("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base)); - printf ("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base)); - printf ("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base)); - printf ("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base)); - printf ("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base)); - printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); - printf ("\n"); - -} -#else -#define debug_mii_regs(base) do{}while(0) -#endif - -/* - * Wait until the phy bus is non-busy - */ -static void phy_wait (unsigned int base, unsigned int condition) -{ - int timeout; - - timeout = 0; - while (reg_MII_MGMT_INDICATORS(base) & condition) { - udelay (10); - if (++timeout > 10000) { - printf ("ERROR: timeout waiting for phy bus (%d)\n", - condition); - break; - } - } -} - -/* - * read phy register - */ -static unsigned int read_phy (unsigned int base, - unsigned int phy_addr, unsigned int phy_reg) -{ - unsigned int value; - - phy_wait (base, MII_MGMT_INDICATORS_BUSY); - - reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; - - /* Ensure that the Read Cycle bit is cleared prior to next read cycle */ - reg_MII_MGMT_COMMAND(base) = 0; - - /* start the read */ - reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE; - - /* wait for the read to complete */ - phy_wait (base, - MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY); - - value = reg_MII_MGMT_STATUS(base); - - reg_MII_MGMT_COMMAND(base) = 0; - - return value; -} - -/* - * write phy register - */ -static void write_phy (unsigned int base, - unsigned int phy_addr, - unsigned int phy_reg, unsigned int phy_data) -{ - phy_wait (base, MII_MGMT_INDICATORS_BUSY); - - reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; - - /* Ensure that the Read Cycle bit is cleared prior to next cycle */ - reg_MII_MGMT_COMMAND(base) = 0; - - /* start the write */ - reg_MII_MGMT_CONTROL(base) = phy_data; -} - -/* - * configure the marvell 88e1111 phy - */ -static int marvell_88e_phy_config (struct eth_device *dev, int *speed, - int *duplex) -{ - unsigned long base; - unsigned long phy_addr; - unsigned int phy_status; - unsigned int phy_spec_status; - int timeout; - int phy_speed; - int phy_duplex; - unsigned int value; - - phy_speed = LINK_SPEED_UNKNOWN; - phy_duplex = LINK_DUPLEX_UNKNOWN; - - base = dev->iobase; - phy_addr = (unsigned long)dev->priv; - - /* Take the PHY out of reset. */ - write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); - - /* Wait for the reset process to complete. */ - udelay (10); - timeout = 0; - while ((phy_status = - read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { - udelay (10); - if (++timeout > 10000) { - printf ("ERROR: timeout waiting for phy reset\n"); - break; - } - } - - /* TBI Configuration. */ - write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | - TBI_CONTROL_2_RECEIVE_CLOCK_SELECT); - /* Wait for the link to be established. */ - timeout = 0; - do { - udelay (20000); - phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG); - if (++timeout > 100) { - debug_lev(1, "ERROR: unable to establish link!!!\n"); - break; - } - } while ((phy_status & PHY_STAT_LINK_UP) == 0); - - if ((phy_status & PHY_STAT_LINK_UP) == 0) - return 0; - - value = 0; - phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); - if (phy_spec_status & SPEC_STAT_RESOLVED) { - switch (phy_spec_status & SPEC_STAT_SPEED_MASK) { - case SPEED_1000: - phy_speed = LINK_SPEED_1000; - value |= PHY_CTRL_SPEED1; - break; - case SPEED_100: - phy_speed = LINK_SPEED_100; - value |= PHY_CTRL_SPEED0; - break; - case SPEED_10: - phy_speed = LINK_SPEED_10; - break; - } - if (phy_spec_status & SPEC_STAT_FULL_DUP) { - phy_duplex = LINK_DUPLEX_FULL; - value |= PHY_CTRL_FULL_DUPLEX; - } else - phy_duplex = LINK_DUPLEX_HALF; - } - /* set TBI speed */ - write_phy (base, TBI_ADDR, PHY_CTRL_REG, value); - write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); - -#if TSI108_ETH_DEBUG > 0 - printf ("%s link is up", dev->name); - phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); - if (phy_spec_status & SPEC_STAT_RESOLVED) { - switch (phy_speed) { - case LINK_SPEED_1000: - printf (", 1000 Mbps"); - break; - case LINK_SPEED_100: - printf (", 100 Mbps"); - break; - case LINK_SPEED_10: - printf (", 10 Mbps"); - break; - } - if (phy_duplex == LINK_DUPLEX_FULL) - printf (", Full duplex"); - else - printf (", Half duplex"); - } - printf ("\n"); -#endif - - dump_phy_regs (TBI_ADDR); - if (speed) - *speed = phy_speed; - if (duplex) - *duplex = phy_duplex; - - return 1; -} - -/* - * External interface - * - * register the tsi108 ethernet controllers with the multi-ethernet system - */ -int tsi108_eth_initialize (bd_t * bis) -{ - struct eth_device *dev; - int index; - - for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { - dev = (struct eth_device *)malloc(sizeof(struct eth_device)); - - sprintf (dev->name, "TSI108_eth%d", index); - - dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); - dev->priv = (void *)(phy_address[index]); - dev->init = tsi108_eth_probe; - dev->halt = tsi108_eth_halt; - dev->send = tsi108_eth_send; - dev->recv = tsi108_eth_recv; - - eth_register(dev); - } - return index; -} - -/* - * probe for and initialize a single ethernet interface - */ -static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis) -{ - unsigned long base; - unsigned long value; - int index; - struct dma_descriptor *tx_descr; - struct dma_descriptor *rx_descr; - int speed; - int duplex; - - base = dev->iobase; - - reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT; - - /* Bring DMA/FIFO out of reset. */ - reg_TX_CONFIG(base) = 0x00000000; - reg_RX_CONFIG(base) = 0x00000000; - - reg_TX_THRESHOLDS(base) = (192 << 16) | 192; - reg_RX_THRESHOLDS(base) = (192 << 16) | 112; - - /* Bring MAC out of reset. */ - reg_MAC_CONFIG_1(base) = 0x00000000; - - /* DMA MAC configuration. */ - reg_MAC_CONFIG_1(base) = - MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE; - - reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE; - reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE; - - /* Note: Early tsi108 manual did not have correct byte order - * for the station address.*/ - reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) | - (dev->enetaddr[4] << 16) | - (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0); - - reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | - (dev->enetaddr[0] << 16); - - if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) - return 0; - - value = - MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | - MAC_CONFIG_2_CRC_ENABLE; - if (speed == LINK_SPEED_1000) - value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); - else { - value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); - reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; - } - if (duplex == LINK_DUPLEX_FULL) { - value |= MAC_CONFIG_2_FULL_DUPLEX; - reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; - } else - reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; - reg_MAC_CONFIG_2(base) = value; - - reg_RX_CONFIG(base) = RX_CONFIG_SE; - reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; - reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; - - /* initialize the RX DMA descriptors */ - rx_descr = &rx_descr_array[0]; - rx_descr_current = rx_descr; - for (index = 0; index < NUM_RX_DESC; index++) { - /* make sure the receive buffers are not in cache */ - invalidate_dcache_range((unsigned long)NetRxPackets[index], - (unsigned long)NetRxPackets[index] + - RX_BUFFER_SIZE); - rx_descr->start_addr0 = - cpu_to_le32((vuint32) NetRxPackets[index]); - rx_descr->start_addr1 = 0; - rx_descr->next_descr_addr0 = - cpu_to_le32((vuint32) (rx_descr + 1)); - rx_descr->next_descr_addr1 = 0; - rx_descr->vlan_byte_count = 0; - rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | - DMA_DESCR_RX_OWNER); - rx_descr++; - } - rx_descr--; - rx_descr->next_descr_addr0 = 0; - rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); - /* Push the descriptors to RAM so the ethernet DMA can see them */ - invalidate_dcache_range((unsigned long)rx_descr_array, - (unsigned long)rx_descr_array + - sizeof(rx_descr_array)); - - /* enable RX queue */ - reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01; - reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current; - /* enable receive DMA */ - reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; - - reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; - reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; - - /* initialize the TX DMA descriptor */ - tx_descr = &tx_descriptor; - - tx_descr->start_addr0 = 0; - tx_descr->start_addr1 = 0; - tx_descr->next_descr_addr0 = 0; - tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); - tx_descr->vlan_byte_count = 0; - tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK | - DMA_DESCR_TX_SOF | - DMA_DESCR_TX_EOF); - /* enable TX queue */ - reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01; - - return 1; -} - -/* - * send a packet - */ -static int tsi108_eth_send (struct eth_device *dev, - volatile void *packet, int length) -{ - unsigned long base; - int timeout; - struct dma_descriptor *tx_descr; - unsigned long status; - - base = dev->iobase; - tx_descr = &tx_descriptor; - - /* Wait until the last packet has been transmitted. */ - timeout = 0; - do { - /* make sure we see the changes made by the DMA engine */ - invalidate_dcache_range((unsigned long)tx_descr, - (unsigned long)tx_descr + - sizeof(struct dma_descriptor)); - - if (timeout != 0) - udelay (15); - if (++timeout > 10000) { - tx_diag_regs(base); - debug_lev(1, - "ERROR: timeout waiting for last transmit packet to be sent\n"); - return 0; - } - } while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER)); - - status = le32_to_cpu(tx_descr->config_status); - if ((status & DMA_DESCR_TX_OK) == 0) { -#ifdef TX_PRINT_ERRORS - printf ("TX packet error: 0x%08x\n %s%s%s%s\n", status, - status & DMA_DESCR_TX_OK ? "tx error, " : "", - status & DMA_DESCR_TX_RETRY_LIMIT ? - "retry limit reached, " : "", - status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "", - status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, " - : ""); -#endif - } - - debug_lev (9, "sending packet %d\n", length); - tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); - tx_descr->start_addr1 = 0; - tx_descr->next_descr_addr0 = 0; - tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); - tx_descr->vlan_byte_count = cpu_to_le32(length); - tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER | - DMA_DESCR_TX_CRC | - DMA_DESCR_TX_PAD | - DMA_DESCR_TX_SOF | - DMA_DESCR_TX_EOF); - - invalidate_dcache_range((unsigned long)tx_descr, - (unsigned long)tx_descr + - sizeof(struct dma_descriptor)); - - invalidate_dcache_range((unsigned long)packet, - (unsigned long)packet + length); - - reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr; - reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID; - - return length; -} - -/* - * Check for received packets and send them up the protocal stack - */ -static int tsi108_eth_recv (struct eth_device *dev) -{ - struct dma_descriptor *rx_descr; - unsigned long base; - int length = 0; - unsigned long status; - volatile uchar *buffer; - - base = dev->iobase; - - /* make sure we see the changes made by the DMA engine */ - invalidate_dcache_range ((unsigned long)rx_descr_array, - (unsigned long)rx_descr_array + - sizeof(rx_descr_array)); - - /* process all of the received packets */ - rx_descr = rx_descr_current; - while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) { - /* check for error */ - status = le32_to_cpu(rx_descr->config_status); - if (status & DMA_DESCR_RX_BAD_FRAME) { -#ifdef RX_PRINT_ERRORS - printf ("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", - status, - status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " - : "", - status & DMA_DESCR_RX_SHORT_FRAME ? "too short, " - : "", - status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " : - "", - status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "", - status & DMA_DESCR_RX_MAX_FRAME_LEN ? - "max length, " : "", - status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " : - ""); -#endif - } else { - length = - le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF; - - /*** process packet ***/ - buffer = - (volatile uchar - *)(le32_to_cpu (rx_descr->start_addr0)); - NetReceive (buffer, length); - - invalidate_dcache_range ((unsigned long)buffer, - (unsigned long)buffer + - RX_BUFFER_SIZE); - } - /* Give this buffer back to the DMA engine */ - rx_descr->vlan_byte_count = 0; - rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) | - DMA_DESCR_RX_OWNER); - /* move descriptor pointer forward */ - rx_descr = - (struct dma_descriptor - *)(le32_to_cpu (rx_descr->next_descr_addr0)); - if (rx_descr == 0) - rx_descr = &rx_descr_array[0]; - } - /* remember where we are for next time */ - rx_descr_current = rx_descr; - - /* If the DMA engine has reached the end of the queue - * start over at the begining */ - if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) { - - reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0; - reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0]; - reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; - } - - return length; -} - -/* - * disable an ethernet interface - */ -static void tsi108_eth_halt (struct eth_device *dev) -{ - unsigned long base; - - base = dev->iobase; - - /* Put DMA/FIFO into reset state. */ - reg_TX_CONFIG(base) = TX_CONFIG_RST; - reg_RX_CONFIG(base) = RX_CONFIG_RST; - - /* Put MAC into reset state. */ - reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET; -} - -#endif diff --git a/drivers/uli526x.c b/drivers/uli526x.c deleted file mode 100644 index 1267c5798f..0000000000 --- a/drivers/uli526x.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Roy Zang , Sep, 2007 - * - * Description: - * ULI 526x Ethernet port driver. - * Based on the Linux driver: drivers/net/tulip/uli526x.c - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -/* some kernel function compatible define */ - -#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ - defined(CONFIG_ULI526X) - -#undef DEBUG - -/* Board/System/Debug information/definition */ -#define ULI_VENDOR_ID 0x10B9 -#define ULI5261_DEVICE_ID 0x5261 -#define ULI5263_DEVICE_ID 0x5263 -/* ULi M5261 ID*/ -#define PCI_ULI5261_ID ULI5261_DEVICE_ID << 16 | ULI_VENDOR_ID -/* ULi M5263 ID*/ -#define PCI_ULI5263_ID ULI5263_DEVICE_ID << 16 | ULI_VENDOR_ID - -#define ULI526X_IO_SIZE 0x100 -#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */ -#define RX_DESC_CNT PKTBUFSRX /* Allocated Rx descriptors */ -#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */ -#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */ -#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT) -#define TX_BUF_ALLOC 0x300 -#define RX_ALLOC_SIZE PKTSIZE -#define ULI526X_RESET 1 -#define CR0_DEFAULT 0 -#define CR6_DEFAULT 0x22200000 -#define CR7_DEFAULT 0x180c1 -#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */ -#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */ -#define MAX_PACKET_SIZE 1514 -#define ULI5261_MAX_MULTICAST 14 -#define RX_COPY_SIZE 100 -#define MAX_CHECK_PACKET 0x8000 - -#define ULI526X_10MHF 0 -#define ULI526X_100MHF 1 -#define ULI526X_10MFD 4 -#define ULI526X_100MFD 5 -#define ULI526X_AUTO 8 - -#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */ -#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */ -#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */ -#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */ -#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */ -#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */ - -/* CR9 definition: SROM/MII */ -#define CR9_SROM_READ 0x4800 -#define CR9_SRCS 0x1 -#define CR9_SRCLK 0x2 -#define CR9_CRDOUT 0x8 -#define SROM_DATA_0 0x0 -#define SROM_DATA_1 0x4 -#define PHY_DATA_1 0x20000 -#define PHY_DATA_0 0x00000 -#define MDCLKH 0x10000 - -#define PHY_POWER_DOWN 0x800 - -#define SROM_V41_CODE 0x14 - -#define SROM_CLK_WRITE(data, ioaddr) do { \ - outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \ - udelay(5); \ - outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK, ioaddr); \ - udelay(5); \ - outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \ - udelay(5); \ - } while (0) - -/* Structure/enum declaration */ - -struct tx_desc { - u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */ - char *tx_buf_ptr; /* Data for us */ - struct tx_desc *next_tx_desc; -}; - -struct rx_desc { - u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */ - char *rx_buf_ptr; /* Data for us */ - struct rx_desc *next_rx_desc; -}; - -struct uli526x_board_info { - u32 chip_id; /* Chip vendor/Device ID */ - pci_dev_t pdev; - - long ioaddr; /* I/O base address */ - u32 cr0_data; - u32 cr5_data; - u32 cr6_data; - u32 cr7_data; - u32 cr15_data; - - /* pointer for memory physical address */ - dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */ - dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */ - dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */ - dma_addr_t first_tx_desc_dma; - dma_addr_t first_rx_desc_dma; - - /* descriptor pointer */ - unsigned char *buf_pool_ptr; /* Tx buffer pool memory */ - unsigned char *buf_pool_start; /* Tx buffer pool align dword */ - unsigned char *desc_pool_ptr; /* descriptor pool memory */ - struct tx_desc *first_tx_desc; - struct tx_desc *tx_insert_ptr; - struct tx_desc *tx_remove_ptr; - struct rx_desc *first_rx_desc; - struct rx_desc *rx_ready_ptr; /* packet come pointer */ - unsigned long tx_packet_cnt; /* transmitted packet count */ - - u16 PHY_reg4; /* Saved Phyxcer register 4 value */ - - u8 media_mode; /* user specify media mode */ - u8 op_mode; /* real work dedia mode */ - u8 phy_addr; - - /* NIC SROM data */ - unsigned char srom[128]; -}; - -enum uli526x_offsets { - DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20, - DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48, - DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70, - DCR15 = 0x78 -}; - -enum uli526x_CR6_bits { - CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80, - CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000, - CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000 -}; - -/* Global variable declaration -- */ - -static unsigned char uli526x_media_mode = ULI526X_AUTO; - -static struct tx_desc desc_pool_array[DESC_ALL_CNT + 0x20] - __attribute__ ((aligned(32))); -static char buf_pool[TX_BUF_ALLOC * TX_DESC_CNT + 4]; - -/* For module input parameter */ -static int mode = 8; - -/* function declaration -- */ -static int uli526x_start_xmit(struct eth_device *dev, - volatile void *packet, int length); -static const struct ethtool_ops netdev_ethtool_ops; -static u16 read_srom_word(long, int); -static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); -static void allocate_rx_buffer(struct uli526x_board_info *); -static void update_cr6(u32, unsigned long); -static u16 phy_read(unsigned long, u8, u8, u32); -static u16 phy_readby_cr10(unsigned long, u8, u8); -static void phy_write(unsigned long, u8, u8, u16, u32); -static void phy_writeby_cr10(unsigned long, u8, u8, u16); -static void phy_write_1bit(unsigned long, u32, u32); -static u16 phy_read_1bit(unsigned long, u32); -static int uli526x_rx_packet(struct eth_device *); -static void uli526x_free_tx_pkt(struct eth_device *, - struct uli526x_board_info *); -static void uli526x_reuse_buf(struct rx_desc *); -static void uli526x_init(struct eth_device *); -static void uli526x_set_phyxcer(struct uli526x_board_info *); - - -static int uli526x_init_one(struct eth_device *, bd_t *); -static void uli526x_disable(struct eth_device *); -static void set_mac_addr(struct eth_device *); - -static struct pci_device_id uli526x_pci_tbl[] = { - { ULI_VENDOR_ID, ULI5261_DEVICE_ID}, /* 5261 device */ - { ULI_VENDOR_ID, ULI5263_DEVICE_ID}, /* 5263 device */ - {} -}; - -/* ULI526X network board routine */ - -/* - * Search ULI526X board, register it - */ - -int uli526x_initialize(bd_t *bis) -{ - pci_dev_t devno; - int card_number = 0; - struct eth_device *dev; - struct uli526x_board_info *db; /* board information structure */ - - u32 iobase; - int idx = 0; - - while (1) { - /* Find PCI device */ - devno = pci_find_devices(uli526x_pci_tbl, idx++); - if (devno < 0) - break; - - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); - iobase &= ~0xf; - - dev = (struct eth_device *)malloc(sizeof *dev); - sprintf(dev->name, "uli526x#%d\n", card_number); - db = (struct uli526x_board_info *) - malloc(sizeof(struct uli526x_board_info)); - - dev->priv = db; - db->pdev = devno; - dev->iobase = iobase; - - dev->init = uli526x_init_one; - dev->halt = uli526x_disable; - dev->send = uli526x_start_xmit; - dev->recv = uli526x_rx_packet; - - /* init db */ - db->ioaddr = dev->iobase; - /* get chip id */ - - pci_read_config_dword(devno, PCI_VENDOR_ID, &db->chip_id); -#ifdef DEBUG - printf("uli526x: uli526x @0x%x\n", iobase); - printf("uli526x: chip_id%x\n", db->chip_id); -#endif - eth_register(dev); - card_number++; - pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20); - udelay(10 * 1000); - } - return card_number; -} - -static int uli526x_init_one(struct eth_device *dev, bd_t *bis) -{ - - struct uli526x_board_info *db = dev->priv; - int i; - - switch (mode) { - case ULI526X_10MHF: - case ULI526X_100MHF: - case ULI526X_10MFD: - case ULI526X_100MFD: - uli526x_media_mode = mode; - break; - default: - uli526x_media_mode = ULI526X_AUTO; - break; - } - - /* Allocate Tx/Rx descriptor memory */ - db->desc_pool_ptr = (uchar *)&desc_pool_array[0]; - db->desc_pool_dma_ptr = (dma_addr_t)&desc_pool_array[0]; - if (db->desc_pool_ptr == NULL) - return 0; - - db->buf_pool_ptr = &buf_pool[0]; - db->buf_pool_dma_ptr = (dma_addr_t)&buf_pool[0]; - if (db->buf_pool_ptr == NULL) - return 0; - - db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr; - db->first_tx_desc_dma = db->desc_pool_dma_ptr; - - db->buf_pool_start = db->buf_pool_ptr; - db->buf_pool_dma_start = db->buf_pool_dma_ptr; - -#ifdef DEBUG - printf("%s(): db->ioaddr= 0x%x\n", - __FUNCTION__, db->ioaddr); - printf("%s(): media_mode= 0x%x\n", - __FUNCTION__, uli526x_media_mode); - printf("%s(): db->desc_pool_ptr= 0x%x\n", - __FUNCTION__, db->desc_pool_ptr); - printf("%s(): db->desc_pool_dma_ptr= 0x%x\n", - __FUNCTION__, db->desc_pool_dma_ptr); - printf("%s(): db->buf_pool_ptr= 0x%x\n", - __FUNCTION__, db->buf_pool_ptr); - printf("%s(): db->buf_pool_dma_ptr= 0x%x\n", - __FUNCTION__, db->buf_pool_dma_ptr); -#endif - - /* read 64 word srom data */ - for (i = 0; i < 64; i++) - ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, - i)); - - /* Set Node address */ - if (((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0) - /* SROM absent, so write MAC address to ID Table */ - set_mac_addr(dev); - else { /*Exist SROM*/ - for (i = 0; i < 6; i++) - dev->enetaddr[i] = db->srom[20 + i]; - } -#ifdef DEBUG - for (i = 0; i < 6; i++) - printf("%c%02x", i ? ':' : ' ', dev->enetaddr[i]); -#endif - db->PHY_reg4 = 0x1e0; - - /* system variable init */ - db->cr6_data = CR6_DEFAULT ; - db->cr6_data |= ULI526X_TXTH_256; - db->cr0_data = CR0_DEFAULT; - uli526x_init(dev); - return 1; -} - -static void uli526x_disable(struct eth_device *dev) -{ -#ifdef DEBUG - printf("uli526x_disable\n"); -#endif - struct uli526x_board_info *db = dev->priv; - - if (!((inl(db->ioaddr + DCR12)) & 0x8)) { - /* Reset & stop ULI526X board */ - outl(ULI526X_RESET, db->ioaddr + DCR0); - udelay(5); - phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id); - - /* reset the board */ - db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */ - update_cr6(db->cr6_data, dev->iobase); - outl(0, dev->iobase + DCR7); /* Disable Interrupt */ - outl(inl(dev->iobase + DCR5), dev->iobase + DCR5); - } -} - -/* Initialize ULI526X board - * Reset ULI526X board - * Initialize TX/Rx descriptor chain structure - * Send the set-up frame - * Enable Tx/Rx machine - */ - -static void uli526x_init(struct eth_device *dev) -{ - - struct uli526x_board_info *db = dev->priv; - u8 phy_tmp; - u16 phy_value; - u16 phy_reg_reset; - - /* Reset M526x MAC controller */ - outl(ULI526X_RESET, db->ioaddr + DCR0); /* RESET MAC */ - udelay(100); - outl(db->cr0_data, db->ioaddr + DCR0); - udelay(5); - - /* Phy addr : In some boards,M5261/M5263 phy address != 1 */ - db->phy_addr = 1; - db->tx_packet_cnt = 0; - for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) { - /* peer add */ - phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id); - if (phy_value != 0xffff && phy_value != 0) { - db->phy_addr = phy_tmp; - break; - } - } - -#ifdef DEBUG - printf("%s(): db->ioaddr= 0x%x\n", __FUNCTION__, db->ioaddr); - printf("%s(): db->phy_addr= 0x%x\n", __FUNCTION__, db->phy_addr); -#endif - if (phy_tmp == 32) - printf("Can not find the phy address!!!"); - - /* Parser SROM and media mode */ - db->media_mode = uli526x_media_mode; - - if (!(inl(db->ioaddr + DCR12) & 0x8)) { - /* Phyxcer capability setting */ - phy_reg_reset = phy_read(db->ioaddr, - db->phy_addr, 0, db->chip_id); - phy_reg_reset = (phy_reg_reset | 0x8000); - phy_write(db->ioaddr, db->phy_addr, 0, - phy_reg_reset, db->chip_id); - udelay(500); - - /* Process Phyxcer Media Mode */ - uli526x_set_phyxcer(db); - } - /* Media Mode Process */ - if (!(db->media_mode & ULI526X_AUTO)) - db->op_mode = db->media_mode; /* Force Mode */ - - /* Initialize Transmit/Receive decriptor and CR3/4 */ - uli526x_descriptor_init(db, db->ioaddr); - - /* Init CR6 to program M526X operation */ - update_cr6(db->cr6_data, db->ioaddr); - - /* Init CR7, interrupt active bit */ - db->cr7_data = CR7_DEFAULT; - outl(db->cr7_data, db->ioaddr + DCR7); - - /* Init CR15, Tx jabber and Rx watchdog timer */ - outl(db->cr15_data, db->ioaddr + DCR15); - - /* Enable ULI526X Tx/Rx function */ - db->cr6_data |= CR6_RXSC | CR6_TXSC; - update_cr6(db->cr6_data, db->ioaddr); - while (!(inl(db->ioaddr + DCR12) & 0x8)) - udelay(10); -} - -/* - * Hardware start transmission. - * Send a packet to media from the upper layer. - */ - -static int uli526x_start_xmit(struct eth_device *dev, - volatile void *packet, int length) -{ - struct uli526x_board_info *db = dev->priv; - struct tx_desc *txptr; - unsigned int len = length; - /* Too large packet check */ - if (len > MAX_PACKET_SIZE) { - printf(": big packet = %d\n", len); - return 0; - } - - /* No Tx resource check, it never happen nromally */ - if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) { - printf("No Tx resource %ld\n", db->tx_packet_cnt); - return 0; - } - - /* Disable NIC interrupt */ - outl(0, dev->iobase + DCR7); - - /* transmit this packet */ - txptr = db->tx_insert_ptr; - memcpy((char *)txptr->tx_buf_ptr, (char *)packet, (int)length); - txptr->tdes1 = cpu_to_le32(0xe1000000 | length); - - /* Point to next transmit free descriptor */ - db->tx_insert_ptr = txptr->next_tx_desc; - - /* Transmit Packet Process */ - if ((db->tx_packet_cnt < TX_DESC_CNT)) { - txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */ - db->tx_packet_cnt++; /* Ready to send */ - outl(0x1, dev->iobase + DCR1); /* Issue Tx polling */ - } - - /* Got ULI526X status */ - db->cr5_data = inl(db->ioaddr + DCR5); - outl(db->cr5_data, db->ioaddr + DCR5); - -#ifdef TX_DEBUG - printf("%s(): length = 0x%x\n", __FUNCTION__, length); - printf("%s(): cr5_data=%x\n", __FUNCTION__, db->cr5_data); -#endif - - outl(db->cr7_data, dev->iobase + DCR7); - uli526x_free_tx_pkt(dev, db); - - return length; -} - -/* - * Free TX resource after TX complete - */ - -static void uli526x_free_tx_pkt(struct eth_device *dev, - struct uli526x_board_info *db) -{ - struct tx_desc *txptr; - u32 tdes0; - - txptr = db->tx_remove_ptr; - while (db->tx_packet_cnt) { - tdes0 = le32_to_cpu(txptr->tdes0); - /* printf(DRV_NAME ": tdes0=%x\n", tdes0); */ - if (tdes0 & 0x80000000) - break; - - /* A packet sent completed */ - db->tx_packet_cnt--; - - if (tdes0 != 0x7fffffff) { -#ifdef TX_DEBUG - printf("%s()tdes0=%x\n", __FUNCTION__, tdes0); -#endif - if (tdes0 & TDES0_ERR_MASK) { - if (tdes0 & 0x0002) { /* UnderRun */ - if (!(db->cr6_data & CR6_SFT)) { - db->cr6_data = db->cr6_data | - CR6_SFT; - update_cr6(db->cr6_data, - db->ioaddr); - } - } - } - } - - txptr = txptr->next_tx_desc; - }/* End of while */ - - /* Update TX remove pointer to next */ - db->tx_remove_ptr = txptr; -} - - -/* - * Receive the come packet and pass to upper layer - */ - -static int uli526x_rx_packet(struct eth_device *dev) -{ - struct uli526x_board_info *db = dev->priv; - struct rx_desc *rxptr; - int rxlen = 0; - u32 rdes0; - - rxptr = db->rx_ready_ptr; - - rdes0 = le32_to_cpu(rxptr->rdes0); -#ifdef RX_DEBUG - printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0); -#endif - if (!(rdes0 & 0x80000000)) { /* packet owner check */ - if ((rdes0 & 0x300) != 0x300) { - /* A packet without First/Last flag */ - /* reuse this buf */ - printf("A packet without First/Last flag"); - uli526x_reuse_buf(rxptr); - } else { - /* A packet with First/Last flag */ - rxlen = ((rdes0 >> 16) & 0x3fff) - 4; -#ifdef RX_DEBUG - printf("%s(): rxlen =%x\n", __FUNCTION__, rxlen); -#endif - /* error summary bit check */ - if (rdes0 & 0x8000) { - /* This is a error packet */ - printf("Eroor: rdes0: %lx\n", rdes0); - } - - if (!(rdes0 & 0x8000) || - ((db->cr6_data & CR6_PM) && (rxlen > 6))) { - -#ifdef RX_DEBUG - printf("%s(): rx_skb_ptr =%x\n", - __FUNCTION__, rxptr->rx_buf_ptr); - printf("%s(): rxlen =%x\n", - __FUNCTION__, rxlen); - - printf("%s(): buf addr =%x\n", - __FUNCTION__, rxptr->rx_buf_ptr); - printf("%s(): rxlen =%x\n", - __FUNCTION__, rxlen); - int i; - for (i = 0; i < 0x20; i++) - printf("%s(): data[%x] =%x\n", - __FUNCTION__, i, rxptr->rx_buf_ptr[i]); -#endif - - NetReceive(rxptr->rx_buf_ptr, rxlen); - uli526x_reuse_buf(rxptr); - - } else { - /* Reuse SKB buffer when the packet is error */ - printf("Reuse buffer, rdes0"); - uli526x_reuse_buf(rxptr); - } - } - - rxptr = rxptr->next_rx_desc; - } - - db->rx_ready_ptr = rxptr; - return rxlen; -} - -/* - * Reuse the RX buffer - */ - -static void uli526x_reuse_buf(struct rx_desc *rxptr) -{ - - if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) - rxptr->rdes0 = cpu_to_le32(0x80000000); - else - printf("Buffer reuse method error"); -} -/* - * Initialize transmit/Receive descriptor - * Using Chain structure, and allocate Tx/Rx buffer - */ - -static void uli526x_descriptor_init(struct uli526x_board_info *db, - unsigned long ioaddr) -{ - struct tx_desc *tmp_tx; - struct rx_desc *tmp_rx; - unsigned char *tmp_buf; - dma_addr_t tmp_tx_dma, tmp_rx_dma; - dma_addr_t tmp_buf_dma; - int i; - /* tx descriptor start pointer */ - db->tx_insert_ptr = db->first_tx_desc; - db->tx_remove_ptr = db->first_tx_desc; - - outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */ - - /* rx descriptor start pointer */ - db->first_rx_desc = (void *)db->first_tx_desc + - sizeof(struct tx_desc) * TX_DESC_CNT; - db->first_rx_desc_dma = db->first_tx_desc_dma + - sizeof(struct tx_desc) * TX_DESC_CNT; - db->rx_ready_ptr = db->first_rx_desc; - outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */ -#ifdef DEBUG - printf("%s(): db->first_tx_desc= 0x%x\n", - __FUNCTION__, db->first_tx_desc); - printf("%s(): db->first_rx_desc_dma= 0x%x\n", - __FUNCTION__, db->first_rx_desc_dma); -#endif - /* Init Transmit chain */ - tmp_buf = db->buf_pool_start; - tmp_buf_dma = db->buf_pool_dma_start; - tmp_tx_dma = db->first_tx_desc_dma; - for (tmp_tx = db->first_tx_desc, i = 0; - i < TX_DESC_CNT; i++, tmp_tx++) { - tmp_tx->tx_buf_ptr = tmp_buf; - tmp_tx->tdes0 = cpu_to_le32(0); - tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */ - tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma); - tmp_tx_dma += sizeof(struct tx_desc); - tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma); - tmp_tx->next_tx_desc = tmp_tx + 1; - tmp_buf = tmp_buf + TX_BUF_ALLOC; - tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC; - } - (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma); - tmp_tx->next_tx_desc = db->first_tx_desc; - - /* Init Receive descriptor chain */ - tmp_rx_dma = db->first_rx_desc_dma; - for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; - i++, tmp_rx++) { - tmp_rx->rdes0 = cpu_to_le32(0); - tmp_rx->rdes1 = cpu_to_le32(0x01000600); - tmp_rx_dma += sizeof(struct rx_desc); - tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma); - tmp_rx->next_rx_desc = tmp_rx + 1; - } - (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma); - tmp_rx->next_rx_desc = db->first_rx_desc; - - /* pre-allocate Rx buffer */ - allocate_rx_buffer(db); -} - -/* - * Update CR6 value - * Firstly stop ULI526X, then written value and start - */ - -static void update_cr6(u32 cr6_data, unsigned long ioaddr) -{ - - outl(cr6_data, ioaddr + DCR6); - udelay(5); -} - -/* - * Allocate rx buffer, - */ - -static void allocate_rx_buffer(struct uli526x_board_info *db) -{ - int index; - struct rx_desc *rxptr; - rxptr = db->first_rx_desc; - u32 addr; - - for (index = 0; index < RX_DESC_CNT; index++) { - addr = (u32)NetRxPackets[index]; - addr += (16 - (addr & 15)); - rxptr->rx_buf_ptr = (char *) addr; - rxptr->rdes2 = cpu_to_le32(addr); - rxptr->rdes0 = cpu_to_le32(0x80000000); -#ifdef DEBUG - printf("%s(): Number 0x%x:\n", __FUNCTION__, index); - printf("%s(): addr 0x%x:\n", __FUNCTION__, addr); - printf("%s(): rxptr address = 0x%x\n", __FUNCTION__, rxptr); - printf("%s(): rxptr buf address = 0x%x\n", \ - __FUNCTION__, rxptr->rx_buf_ptr); - printf("%s(): rdes2 = 0x%x\n", __FUNCTION__, rxptr->rdes2); -#endif - rxptr = rxptr->next_rx_desc; - } -} - -/* - * Read one word data from the serial ROM - */ - -static u16 read_srom_word(long ioaddr, int offset) -{ - int i; - u16 srom_data = 0; - long cr9_ioaddr = ioaddr + DCR9; - - outl(CR9_SROM_READ, cr9_ioaddr); - outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); - - /* Send the Read Command 110b */ - SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr); - SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr); - SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr); - - /* Send the offset */ - for (i = 5; i >= 0; i--) { - srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0; - SROM_CLK_WRITE(srom_data, cr9_ioaddr); - } - - outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); - - for (i = 16; i > 0; i--) { - outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr); - udelay(5); - srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) - ? 1 : 0); - outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr); - udelay(5); - } - - outl(CR9_SROM_READ, cr9_ioaddr); - return srom_data; -} - -/* - * Set 10/100 phyxcer capability - * AUTO mode : phyxcer register4 is NIC capability - * Force mode: phyxcer register4 is the force media - */ - -static void uli526x_set_phyxcer(struct uli526x_board_info *db) -{ - u16 phy_reg; - - /* Phyxcer capability setting */ - phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0; - - if (db->media_mode & ULI526X_AUTO) { - /* AUTO Mode */ - phy_reg |= db->PHY_reg4; - } else { - /* Force Mode */ - switch (db->media_mode) { - case ULI526X_10MHF: phy_reg |= 0x20; break; - case ULI526X_10MFD: phy_reg |= 0x40; break; - case ULI526X_100MHF: phy_reg |= 0x80; break; - case ULI526X_100MFD: phy_reg |= 0x100; break; - } - - } - - /* Write new capability to Phyxcer Reg4 */ - if (!(phy_reg & 0x01e0)) { - phy_reg |= db->PHY_reg4; - db->media_mode |= ULI526X_AUTO; - } - phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id); - - /* Restart Auto-Negotiation */ - phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id); - udelay(50); -} - -/* - * Write a word to Phy register - */ - -static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, - u16 phy_data, u32 chip_id) -{ - u16 i; - unsigned long ioaddr; - - if (chip_id == PCI_ULI5263_ID) { - phy_writeby_cr10(iobase, phy_addr, offset, phy_data); - return; - } - /* M5261/M5263 Chip */ - ioaddr = iobase + DCR9; - - /* Send 33 synchronization clock to Phy controller */ - for (i = 0; i < 35; i++) - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - - /* Send start command(01) to Phy */ - phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - - /* Send write command(01) to Phy */ - phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - - /* Send Phy address */ - for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, phy_addr & i ? - PHY_DATA_1 : PHY_DATA_0, chip_id); - - /* Send register address */ - for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, offset & i ? - PHY_DATA_1 : PHY_DATA_0, chip_id); - - /* written trasnition */ - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); - - /* Write a word data to PHY controller */ - for (i = 0x8000; i > 0; i >>= 1) - phy_write_1bit(ioaddr, phy_data & i ? - PHY_DATA_1 : PHY_DATA_0, chip_id); -} - -/* - * Read a word data from phy register - */ - -static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id) -{ - int i; - u16 phy_data; - unsigned long ioaddr; - - if (chip_id == PCI_ULI5263_ID) - return phy_readby_cr10(iobase, phy_addr, offset); - /* M5261/M5263 Chip */ - ioaddr = iobase + DCR9; - - /* Send 33 synchronization clock to Phy controller */ - for (i = 0; i < 35; i++) - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - - /* Send start command(01) to Phy */ - phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - - /* Send read command(10) to Phy */ - phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); - phy_write_1bit(ioaddr, PHY_DATA_0, chip_id); - - /* Send Phy address */ - for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, phy_addr & i ? - PHY_DATA_1 : PHY_DATA_0, chip_id); - - /* Send register address */ - for (i = 0x10; i > 0; i = i >> 1) - phy_write_1bit(ioaddr, offset & i ? - PHY_DATA_1 : PHY_DATA_0, chip_id); - - /* Skip transition state */ - phy_read_1bit(ioaddr, chip_id); - - /* read 16bit data */ - for (phy_data = 0, i = 0; i < 16; i++) { - phy_data <<= 1; - phy_data |= phy_read_1bit(ioaddr, chip_id); - } - - return phy_data; -} - -static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset) -{ - unsigned long ioaddr, cr10_value; - - ioaddr = iobase + DCR10; - cr10_value = phy_addr; - cr10_value = (cr10_value<<5) + offset; - cr10_value = (cr10_value<<16) + 0x08000000; - outl(cr10_value, ioaddr); - udelay(1); - while (1) { - cr10_value = inl(ioaddr); - if (cr10_value & 0x10000000) - break; - } - return (cr10_value&0x0ffff); -} - -static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, - u8 offset, u16 phy_data) -{ - unsigned long ioaddr, cr10_value; - - ioaddr = iobase + DCR10; - cr10_value = phy_addr; - cr10_value = (cr10_value<<5) + offset; - cr10_value = (cr10_value<<16) + 0x04000000 + phy_data; - outl(cr10_value, ioaddr); - udelay(1); -} -/* - * Write one bit data to Phy Controller - */ - -static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id) -{ - outl(phy_data , ioaddr); /* MII Clock Low */ - udelay(1); - outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */ - udelay(1); - outl(phy_data , ioaddr); /* MII Clock Low */ - udelay(1); -} - -/* - * Read one bit phy data from PHY controller - */ - -static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id) -{ - u16 phy_data; - - outl(0x50000 , ioaddr); - udelay(1); - phy_data = (inl(ioaddr) >> 19) & 0x1; - outl(0x40000 , ioaddr); - udelay(1); - - return phy_data; -} - -/* - * Set MAC address to ID Table - */ - -static void set_mac_addr(struct eth_device *dev) -{ - int i; - u16 addr; - struct uli526x_board_info *db = dev->priv; - outl(0x10000, db->ioaddr + DCR0); /* Diagnosis mode */ - /* Reset dianostic pointer port */ - outl(0x1c0, db->ioaddr + DCR13); - outl(0, db->ioaddr + DCR14); /* Clear reset port */ - outl(0x10, db->ioaddr + DCR14); /* Reset ID Table pointer */ - outl(0, db->ioaddr + DCR14); /* Clear reset port */ - outl(0, db->ioaddr + DCR13); /* Clear CR13 */ - /* Select ID Table access port */ - outl(0x1b0, db->ioaddr + DCR13); - /* Read MAC address from CR14 */ - for (i = 0; i < 3; i++) { - addr = dev->enetaddr[2 * i] | (dev->enetaddr[2 * i + 1] << 8); - outl(addr, db->ioaddr + DCR14); - } - /* write end */ - outl(0, db->ioaddr + DCR13); /* Clear CR13 */ - outl(0, db->ioaddr + DCR0); /* Clear CR0 */ - udelay(10); - return; -} -#endif -- cgit v1.2.1