Freetz 1.1.3 und cpmaccfg patch

M0ng0-0815

Neuer User
Mitglied seit
20 Okt 2010
Beiträge
14
Punkte für Reaktionen
0
Punkte
0
Hallo,

leider bekomme ich imer folgende fehlermeldung wenn ich versuche den "http://trac.freetz.org/wiki/help/howtos/security/switch_config" patch anzuwenden.

Code:
patch: **** malformed patch at line 17:          /* CPMAC_MODE_ATA       */ { 2, 0,

ERROR: modpatch: Error in patch-file make/linux/patches/2.6.19.2/990-cpmac.patch
make: *** [source/kernel/ref-8mb_26-7270_04.80/.unpacked] Fehler 2

So sieht meine Version vom Patch aus:
Code:
  --- linux-2.6.19.2/drivers/net/avm_cpmac/cpphy_adm6996.c_orig   2009-06-08 13:59:52.000000000 +0200
  +++ linux-2.6.19.2/drivers/net/avm_cpmac/cpphy_adm6996.c        2009-08-20 10:57:14.000000000 +0200
  @@ -137,9 +137,10 @@
                                           { {"", 0x0}
                                           }
                                      },
  -        /* CPMAC_MODE_NORMAL    */ { 1, 0xff,
  -                                        { {"eth0", 0x2f}
  -                                        }
  +        /* CPMAC_MODE_NORMAL    */ { 2, 0xff,
  +                                        { {"eth0", 0x21},
  +                                                 {"eth1", 0x22},
  +                                                        {"eth2", 0x24},
  +                                                               {"eth3", 0x28}
  +                                       }
                                      },
           /* CPMAC_MODE_ATA       */ { 2, 0,
                                           { {"wan",  0x21},

Was mache ich falsch?
 
Code:
Der folgende Patch wurde für eine 7270 mit Firmware 76 erstellt.
Ist das so bei dir?

Code:
ERROR: modpatch: Error in patch-file make/linux/patches/2.6.19.2/990-cpmac.patch
make: *** [source/kernel/ref-8mb_26-[B][COLOR="Red"]7270_04.80[/COLOR][/B]/.unpacked] Fehler 2

Code:
Hier kann noch kontrolliert werden, ob der Patch korrekt durchgeführt wird. z.B.:

  applying patch file make/linux/patches/2.6.19.2/[B][COLOR="Blue"]7270_04.76[/COLOR][/B]/990-cpmac.patch
  patching file linux-2.6.19.2/drivers/net/avm_cpmac/cpphy_adm6996.c
 
Ich habe die 7170, das habe ich aber schon geändert.
Der patch scheint ja nun an der richtigen stelle zu leigen, also er verarbeitet ihn, nur halt mit fehler...

Code:
patch: **** malformed patch at line 17:          /* CPMAC_MODE_ATA       */ { 2, 0,

ERROR: modpatch: Error in patch-file make/linux/patches/2.6.13.1/990-cpmac.patch
make: *** [source/kernel/ref-8mb_26-04.80/.unpacked] Fehler 2

Wenn ich den Origianl Code von der HP nehme verarbeitet er alles ohne fehlermeldung, nehme ich meine abgeänderte Version kommt immer der oben genannte fehler.

Oder ist der Code oben falsch den ich versuche zu patchen?
 
Poste mal die original-Datei, die Du patchen willst und die geänderte Datei (mit Angaben zum Pfad). Dann kann man den richtigen Patch erstellen.
 
OK nochmal von vorn,

Ich habe die 7170 und will mit Freetz 1.1.3 die FirmwareVersion 04.80 Patchen.

die Datei die ich Patchen möchte liegt in
Code:
/home/freetz/freetz-1.1.3/source/kernel/ref-8mb_26-04.80/linux-2.6.13.1/drivers/net/avm_cpmac/

und heisst

Code:
cpphy_adm6996.c

Original Inhalt:
Code:
*------------------------------------------------------------------------------------------*\
 *   Copyright (C) 2006,2007,2008,2009 AVM GmbH <[email protected]>
 *
 *   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 version 2 of the License.
 *
 *   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 <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <asm/atomic.h>
#include <asm/mach_avm.h>
#if defined(CONFIG_AVM_POWER)
#include <linux/avm_power.h>
#endif /*--- #if defined(CONFIG_AVM_POWER) ---*/

#if !defined(CONFIG_NETCHIP_ADM69961)
#define CONFIG_NETCHIP_ADM69961
#endif
#include <asm/mips-boards/prom.h>
#include <linux/avm_event.h>
#include <linux/avm_cpmac.h>
#include <linux/adm_reg.h>
#include "cpmac_if.h"
#include "cpmac_const.h"
#include "cpmac_debug.h"
#include "cpmac_eth.h"
#include "cpphy_const.h"
#include "cpphy_types.h"
#include "cpphy_mdio.h"
#include "cpphy_mgmt.h"
#include "cpphy_if.h"
#include "adm6996.h"
#include "tantos.h"
#include "cpphy_adm6996.h"
#include "cpphy_ar8216.h"
#include <linux/ar_reg.h>

/*------------------------------------------------------------------------------------------*\
 * Register cache
\*------------------------------------------------------------------------------------------*/
#define ADM_TANTOS_GET(mdio, addr) tantos_read((mdio), (unsigned short *) &(addr))
#define ADM_TANTOS_PUT(mdio, addr, dat) tantos_write((mdio), (unsigned short *) &(addr), (dat))
#define ADM_TANTOS_SYNC(mdio, addr) tantos_write((mdio), (unsigned short *) &(addr), *((unsigned short *) &(addr)))

#define ADM_TANTOS_PHY_GET(mdio, phy, addr) tantos_phy_access((mdio), TANTOS_MIIAC_READ, (unsigned short *) &(addr), (phy), 0)
#define ADM_TANTOS_PHY_PUT(mdio, phy, addr, data) tantos_phy_access((mdio), TANTOS_MIIAC_WRITE, (unsigned short *) &(addr), (phy), (data))
#define ADM_TANTOS_PHY_SYNC(mdio, phy, addr) tantos_phy_access((mdio), TANTOS_MIIAC_SYNC, (unsigned short *) &(addr), (phy), 0)

#define PRINT_REGISTER(x) DEB_TEST("Reg 0x%3x = 0x%4x\n", x, ADM_GET_EEPROM_REG(mdio, (x)));
#define PRINT_TANTOS_REGISTER(x) DEB_TEST("Reg 0x%3x = 0x%4x\n", x, ADM_TANTOS_GET(mdio, (x)));
#define NUMBER_OF_SERIAL_REGISTERS (0x3c + 1)
/* alle 200ms Register aktualisieren */
#define MAX_SERIAL_REGISTER_AGE (HZ / 4)
struct adm_struct adm_serial_register;
static unsigned int *serial_register = (unsigned int *) &adm_serial_register;
static unsigned long serial_register_timestamp[NUMBER_OF_SERIAL_REGISTERS];
static int adm_serial_registers[] = {
    REG_ADM_LC_ID, REG_ADM_LC_STATUS0, REG_ADM_LC_STATUS2,
    REG_ADM_LC_RXPKTCNT0, REG_ADM_LC_RXPKTCNT1, REG_ADM_LC_RXPKTCNT2, REG_ADM_LC_RXPKTCNT3, REG_ADM_LC_RXPKTCNT4, REG_ADM_LC_RXPKTCNT5,
    REG_ADM_LC_RXPKTBYTECNT0, REG_ADM_LC_RXPKTBYTECNT1, REG_ADM_LC_RXPKTBYTECNT2, REG_ADM_LC_RXPKTBYTECNT3, REG_ADM_LC_RXPKTBYTECNT4, REG_ADM_LC_RXPKTBYTECNT5,
    REG_ADM_LC_TXPKTCNT0, REG_ADM_LC_TXPKTCNT1, REG_ADM_LC_TXPKTCNT2, REG_ADM_LC_TXPKTCNT3, REG_ADM_LC_TXPKTCNT4, REG_ADM_LC_TXPKTCNT5,
    REG_ADM_LC_TXPKTBYTECNT0, REG_ADM_LC_TXPKTBYTECNT1, REG_ADM_LC_TXPKTBYTECNT2, REG_ADM_LC_TXPKTBYTECNT3, REG_ADM_LC_TXPKTBYTECNT4, REG_ADM_LC_TXPKTBYTECNT5,
    REG_ADM_LC_COLLISIONCNT0, REG_ADM_LC_COLLISIONCNT1, REG_ADM_LC_COLLISIONCNT2, REG_ADM_LC_COLLISIONCNT3, REG_ADM_LC_COLLISIONCNT4, REG_ADM_LC_COLLISIONCNT5,
    REG_ADM_LC_ERRCNT0, REG_ADM_LC_ERRCNT1, REG_ADM_LC_ERRCNT2, REG_ADM_LC_ERRCNT3, REG_ADM_LC_ERRCNT4, REG_ADM_LC_ERRCNT5,
    REG_ADM_LC_OVERFLOWFLAG0, REG_ADM_LC_OVERFLOWFLAG2, REG_ADM_LC_OVERFLOWFLAG4,
    -1
};

static const unsigned int adm_port_registers[] = {
    REG_ADM_LC_PORT0_CONF, REG_ADM_LC_PORT1_CONF, REG_ADM_LC_PORT2_CONF,
    REG_ADM_LC_PORT3_CONF, REG_ADM_LC_PORT4_CONF, REG_ADM_LC_PORT5_CONF
};

#if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
static const unsigned int adm_port_link_bits[] = {
    ADM_STATUS0_PORT0_LINKUP, ADM_STATUS0_PORT1_LINKUP, ADM_STATUS0_PORT2_LINKUP,
    ADM_STATUS0_PORT3_LINKUP, ADM_STATUS0_PORT4_LINKUP, 0, 0
};
#endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/

static const unsigned int adm_vlan_port_map[] = {
    (1 << 0), (1 << 2), (1 << 4), (1 << 6), (1 << 7), (1 << 8)
};

static tantos_switch_struct tantos_switch_memory;
static tantos_switch_struct *tantos_switch = &tantos_switch_memory;
tantos_ports_struct *tantos_ports = (tantos_ports_struct *) &tantos_switch_memory;
static tantos_phy_struct tantos_phy_memory[7];
static tantos_phy_struct *tantos_phys = tantos_phy_memory;
static tantos_counter_struct tantos_counter_memory[7];

#define read_serial_register_timestamp(reg) _read_serial_register_timestamp(reg, __FILE__, __LINE__)
inline static unsigned long _read_serial_register_timestamp(unsigned int reg, char *file, int line) {
    if(reg >= sizeof(serial_register_timestamp) / sizeof(serial_register_timestamp[0])) {
        panic("[read_serial_register_timestamp] illegal index 0x%x (max=%x) (%s, %u)\n",
                reg, sizeof(serial_register_timestamp) / sizeof(serial_register_timestamp[0]),
                file, line);
    } else {
        return serial_register_timestamp[reg];
    }
}

#define write_serial_register_timestamp(reg, value) _write_serial_register_timestamp(reg, value, __FILE__, __LINE__)
inline static void _write_serial_register_timestamp(unsigned int reg, unsigned long value, char *file, int line) {
    if(reg >= sizeof(serial_register_timestamp) / sizeof(serial_register_timestamp[0])) {
        panic("[write_serial_register_timestamp] illegal index 0x%x (max=%x, %s, %d)\n",
                reg, sizeof(serial_register_timestamp) / sizeof(serial_register_timestamp[0]),
                file, line);
    } else {
        serial_register_timestamp[reg] = value;
    }
}

cpmac_switch_configuration_t switch_configuration[CPMAC_SWITCH_CONF_MAX_PRODUCTS][CPMAC_MODE_MAX_NO] = {
    { /* 7170 */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 1, 0xff,
                                        { {"eth0", 0x2f}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 2, 0,
                                        { {"wan",  0x21},
                                          {"eth0", 0x2e},
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 4, 0xff,
                                        { {"eth0", 0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 4, 0,
                                        { {"wan",  0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28},
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x3f}
                                        }
                                   }
    }, { /* VINAX5 */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 2, 4,
                                        { {"wan",  0x30},
                                          {"eth0", 0x2f}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 2, 0,
                                        { {"wan",  0x21},
                                          {"eth0", 0x2e}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 5, 4,
                                        { {"wan",  0x30},
                                          {"eth0", 0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 4, 0,
                                        { {"wan",  0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28}
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x3f}
                                        }
                                   }
    }, { /* VINAX7 */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 2, 6,
                                        { {"wan",  0x60},
                                          {"eth0", 0x2f}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 2, 0,
                                        { {"wan",  0x21},
                                          {"eth0", 0x2e}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 5, 6,
                                        { {"wan",  0x60},
                                          {"eth0", 0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 4, 0,
                                        { {"wan",  0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28}
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x6f}
                                        }
                                   }
    }, { /* ProfiVoIP 2 CPUs */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 2, 0xff,
                                        { {"eth0", 0x2f},
                                          {"cpu",  0x30}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 3, 0,
                                        { {"wan",  0x21},
                                          {"eth0", 0x2e},
                                          {"cpu",  0x30}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 5, 0xff,
                                        { {"eth0", 0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28},
                                          {"cpu",  0x30}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 5, 0,
                                        { {"wan",  0x21},
                                          {"eth1", 0x22},
                                          {"eth2", 0x24},
                                          {"eth3", 0x28},
                                          {"cpu",  0x30}
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x3f}
                                        }
                                   }
    }, { /* ProfiVoIP 1 CPU */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 1, 0xff,
                                        { {"eth0", 0x1f}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 2, 0,
                                        { {"wan",  0x11},
                                          {"eth0", 0x1e}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 4, 0xff,
                                        { {"eth0", 0x11},
                                          {"eth1", 0x12},
                                          {"eth2", 0x14},
                                          {"eth3", 0x18}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 4, 0,
                                        { {"wan",  0x11},
                                          {"eth1", 0x12},
                                          {"eth2", 0x14},
                                          {"eth3", 0x18}
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x3f}
                                        }
                                   }
    }, { /* AR8216 */
        /* No legal mode        */ { 0, 0xff,
                                        { {"", 0x0}
                                        }
                                   },
        /* CPMAC_MODE_NORMAL    */ { 1, 0xff,
                                        { {"eth0", 0x1f}
                                        }
                                   },
        /* CPMAC_MODE_ATA       */ { 2, 1,
                                        { {"wan",  0x03},
                                          {"eth0", 0x1d},
                                        }
                                   },
        /* CPMAC_MODE_SPLIT     */ { 4, 0xff,
                                        { {"eth0", 0x03},
                                          {"eth1", 0x05},
                                          {"eth2", 0x09},
                                          {"eth3", 0x11}
                                        }
                                   },
        /* CPMAC_MODE_SPLIT_ATA */ { 4, 1,
                                        { {"wan",  0x03},
                                          {"eth1", 0x05},
                                          {"eth2", 0x09},
                                          {"eth3", 0x11},
                                        }
                                   },
        /* CPMAC_MODE_ALL_PORTS */ { 1, 0xff,
                                        { {"eth0", 0x3f}
                                        }
                                   }
    }
};



/*------------------------------------------------------------------------------------------*\
 * initialize GPIO pins.  output mode, low
\*------------------------------------------------------------------------------------------*/
#   if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
static void adm_gpio_init(void) {
    /*--- set pins GPIO, OUTPUT, LOW ---*/
    avm_gpio_ctrl(GPIO_BIT_FSER_CLK, GPIO_PIN, GPIO_OUTPUT_PIN);
    avm_gpio_ctrl(GPIO_BIT_MII_DIO, GPIO_PIN, GPIO_OUTPUT_PIN);
    avm_gpio_ctrl(GPIO_BIT_MII_DCLK, GPIO_PIN, GPIO_OUTPUT_PIN);
    avm_gpio_set_bitmask(GPIO_MASK_MII_DCLK | GPIO_MASK_MII_DIO | GPIO_MASK_FSER_CLK, 0);
}

static void adm_gpio_finit(void) {
    avm_gpio_ctrl(GPIO_BIT_FSER_CLK, FUNCTION_PIN, GPIO_OUTPUT_PIN);
    avm_gpio_ctrl(GPIO_BIT_MII_DIO, FUNCTION_PIN, GPIO_OUTPUT_PIN);
    avm_gpio_ctrl(GPIO_BIT_MII_DCLK, FUNCTION_PIN, GPIO_OUTPUT_PIN);
}

/*------------------------------------------------------------------------------------------*\
 * read one bit from mdio port
\*------------------------------------------------------------------------------------------*/
static int adm_mdio_readbit(void) {
    return avm_gpio_in_bit(GPIO_BIT_MII_DIO);
}

/*------------------------------------------------------------------------------------------*\
  MDIO mode selection
  0 -> output
  1 -> input
  switch input/output mode of GPIO 0
\*------------------------------------------------------------------------------------------*/
static void adm_mdio_mode(int mode) {
    avm_gpio_ctrl(GPIO_BIT_MII_DIO, GPIO_PIN, (GPIO_DIR)mode);
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static void adm_mdc_hi(void) {
    avm_gpio_out_bit(GPIO_BIT_MII_DCLK, 1);
}

static void adm_mdio_hi(void) {
    avm_gpio_out_bit(GPIO_BIT_MII_DIO, 1);
}

static void adm_mdcs_hi(void) {
    avm_gpio_out_bit(GPIO_BIT_FSER_CLK, 1);
}

static void adm_mdc_lo(void) {
    avm_gpio_out_bit(GPIO_BIT_MII_DCLK, 0);
}

static void adm_mdio_lo(void) {
    avm_gpio_out_bit(GPIO_BIT_MII_DIO, 0);
}

static void adm_mdcs_lo(void) {
    avm_gpio_out_bit(GPIO_BIT_FSER_CLK, 0);
}

/*------------------------------------------------------------------------------------------*\
 * mdc pulse
 * 0 -> 1 -> 0
\*------------------------------------------------------------------------------------------*/
static void adm_mdc_pulse(void) {
    adm_mdc_lo();
    udelay(ADM_SW_MDC_DOWN_DELAY);
    adm_mdc_hi();
    udelay(ADM_SW_MDC_UP_DELAY);
    adm_mdc_lo();
}

/*------------------------------------------------------------------------------------------*\
 * mdc toggle
 * 1 -> 0
\*------------------------------------------------------------------------------------------*/
static void adm_mdc_toggle(void) {
    adm_mdc_hi();
    udelay(ADM_SW_MDC_UP_DELAY);
    adm_mdc_lo();
    udelay(ADM_SW_MDC_DOWN_DELAY);
}

/*------------------------------------------------------------------------------------------*\
 * enable eeprom write
 * For ATC 93C66 type EEPROM; accessing ADM6996 internal EEPROM type registers
\*------------------------------------------------------------------------------------------*/
static void adm_eeprom_write_enable(void) {
    unsigned int op;

    adm_mdcs_lo();
    adm_mdc_lo();
    adm_mdio_hi();
    udelay(ADM_SW_CS_DELAY);
    /* enable chip select */
    adm_mdcs_hi();
    udelay(ADM_SW_CS_DELAY);
    /* start bit */
    adm_mdio_hi();
    adm_mdc_pulse();

    /* eeprom write enable */
    op = ADM_SW_BIT_MASK_4;
    while(op) {
        if(op & ADM_SW_EEPROM_WRITE_ENABLE)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
    while(op) {
        adm_mdio_lo();
        adm_mdc_pulse();
        op >>= 1;
    }
    /* disable chip select */
    adm_mdcs_lo();
    udelay(ADM_SW_CS_DELAY);
    adm_mdc_pulse();
}

/*------------------------------------------------------------------------------------------*\
 * disable eeprom write
\*------------------------------------------------------------------------------------------*/
static void adm_eeprom_write_disable(void) {
    unsigned int op;

    adm_mdcs_lo();
    adm_mdc_lo();
    adm_mdio_hi();
    udelay(ADM_SW_CS_DELAY);
    /* enable chip select */
    adm_mdcs_hi();
    udelay(ADM_SW_CS_DELAY);

    /* start bit */
    adm_mdio_hi();
    adm_mdc_pulse();
    /* eeprom write disable */
    op = ADM_SW_BIT_MASK_4;
    while(op) {
        if(op & ADM_SW_EEPROM_WRITE_DISABLE)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 3);
    while(op) {
        adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }
    /* disable chip select */
    adm_mdcs_lo();
    udelay(ADM_SW_CS_DELAY);
    adm_mdc_pulse();
}

/*------------------------------------------------------------------------------------------*\
  read registers from ADM6996
  32 Bit Mode:
    serial registers start at 0x200 (addr bit 9 = 1b)
    EEPROM registers -> shifted to 16bits; Serial registers -> 32bits
  Autodetect with addr == 0x0: (checks for EEPROM Signature)
\*------------------------------------------------------------------------------------------*/
static unsigned int adm_read_adml(unsigned int addr) {
    unsigned int op, dat;

    adm_gpio_init();

    adm_mdcs_hi();
    udelay(ADM_SW_CS_DELAY);

    adm_mdcs_lo();
    adm_mdc_lo();
    adm_mdio_lo();

    udelay(ADM_SW_CS_DELAY);

    /* preamble, 32 bit 1 */
    adm_mdio_hi();
    op = ADM_SW_BIT_MASK_32;
    while(op) {
        adm_mdc_pulse();
        op >>= 1;
    }

    /* command start (01b) */
    /*--- adm_write_bits_pulsed(ADM_SW_SMI_START, 2); ---*/
    op = ADM_SW_BIT_MASK_2;
    while(op) {
        if(op & ADM_SW_SMI_START)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    /* read command (10b) */
    /*--- adm_write_bits_pulsed(ADM_SW_SMI_READ, 2); ---*/
    op = ADM_SW_BIT_MASK_2;
    while(op) {
        if(op & ADM_SW_SMI_READ)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    /* send address A9 ~ A0 */
    /*--- adm_write_bits_pulsed(addr, 10); ---*/
    op = ADM_SW_BIT_MASK_10;
    while(op) {
        if(op & addr)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    /* set MDIO pin to input mode */
    adm_mdio_mode(ADM_SW_MDIO_INPUT);

    /* turnaround bits */
    op = ADM_SW_BIT_MASK_2;
    adm_mdio_hi();
    while(op) {
        adm_mdc_pulse();
        op >>= 1;
    }

    udelay(ADM_SW_MDC_DOWN_DELAY);

    /* start read data */
    dat = 0;
    if(!addr) {
        /* Autodetect: erstmal nur 16 Bit lesen, weil Mode unbekannt ist */
        op = ADM_SW_BIT_MASK_16;
    } else {
        op = ADM_SW_BIT_MASK_32;
    }
    while(op) {
        dat <<= 1;
        if(adm_mdio_readbit())
            dat |= 1;
        adm_mdc_toggle();
        op >>= 1;
    }
    if(!addr && (dat != 0x4154)) {
        /* Autodetect: im 32 Bit Mode die restlichen 16 Bit lesen */
        op = ADM_SW_BIT_MASK_16;
        while(op) {
            dat <<= 1;
            if(adm_mdio_readbit())
                dat |= 1;
            adm_mdc_toggle();
            op >>= 1;
        }
    }

    /* set MDIO to output mode */
    adm_mdio_mode(ADM_SW_MDIO_OUTPUT);

    /* dummy clock */
    op = ADM_SW_BIT_MASK_4;
    adm_mdio_lo();
    while(op) {
        adm_mdc_pulse();
        op >>= 1;
    }

    adm_mdc_lo();
    adm_mdio_lo();
    adm_mdcs_hi();

    /* EEPROM registers */
    if(!(addr & ADM_SERIAL_OFFSET))
    {
        if(addr & 1)
            dat >>= 16;
        else
        dat &= 0xffff;
    }
    return dat;
}
#   endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned int adm_read_32Bit_cached(cpphy_mdio_t *mdio, unsigned int addr) {
    unsigned int address, data = 0;

    if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ))
        return 0;

    /* Counter Register lesen */
    address = (addr - 0xa0) >> 1;
    /*--- if(   (mdio->Mode & CPPHY_SWITCH_MODE_16BIT) ---*/ /* No caching for 16 bit hardware mdio access */
       /*--- || (unsigned int)(jiffies - read_serial_register_timestamp(address)) > MAX_SERIAL_REGISTER_AGE) { ---*/
        /* Invalid cache value of register */
        write_serial_register_timestamp(address, jiffies);
        if(mdio->Mode & CPPHY_SWITCH_MODE_16BIT) {
            data = cpphy_mdio_user_access_read(mdio, addr & 0x1f, addr >> 5) +
                  (cpphy_mdio_user_access_read(mdio, (addr + 1) & 0x1f, (addr + 1) >> 5) << 16);
        }
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
          else {
            data = adm_read_adml(address + ADM_DEVICE_ADDRESS + ADM_SERIAL_OFFSET);
        }
#       endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        if(address >= sizeof(adm_serial_register) / sizeof(serial_register[0])) {
            panic("write: serial_register[%x] out of index (max 0x%x)\n", address, sizeof(adm_serial_register) / sizeof(serial_register[0]));
        }
        serial_register[address] = data;
        return data;
    /*--- } ---*/
    if(address >= sizeof(adm_serial_register) / sizeof(serial_register[0])) {
        panic("read: serial_register[%x] out of index (max 0x%x)\n", address, sizeof(adm_serial_register) / sizeof(serial_register[0]));
    }
    return serial_register[address];
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned int adm_read(cpphy_mdio_t *mdio, unsigned int addr) {
    if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ)) {
        DEB_INFO("adm_read called without being allowed to read!\n");
        return 0;
    }

    if(mdio->Mode & CPPHY_SWITCH_MODE_16BIT) {
        return cpphy_mdio_user_access_read(mdio, addr & 0x1f, addr >> 5);
    } else {
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
        return adm_read_adml(addr + ADM_DEVICE_ADDRESS);
#       else /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        return 0xdead;
#       endif /*--- #else ---*/ /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
    }
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned short tantos_read(cpphy_mdio_t *mdio, unsigned short *ptr) {
    unsigned int addr    = (unsigned int) (ptr - (unsigned short *) tantos_switch);
    unsigned short value = adm_read(mdio, addr);

    /*--- DEB_TEST("tantos_read: ptr = %p, tantos_switch = %p\n", ptr, tantos_switch); ---*/
    /*--- DEB_TEST("tantos_read: addr = %x, value = %x\n", addr, value); ---*/
    if(addr > sizeof(tantos_switch_memory) / sizeof(unsigned short))
        panic("[tantos_read] addr %x out of range (max %x)\n", addr, sizeof(tantos_switch_memory) / sizeof(unsigned short));
    ((unsigned short *) tantos_switch)[addr] = value;
    return value;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned int adm_safe_read(cpphy_mdio_t *mdio, unsigned int addr) {
    unsigned int count = 0, first, second;

    first = adm_read(mdio, addr);
    do {
        count++;
        second = adm_read(mdio, addr);
        if(first == second) {
            if(count > 1) {
                DEB_TEST("Value correct for register %#x on read number %u\n", addr, count);
            }
            return first;
        } else {
            DEB_TEST("Addr %#x: %#x != %#x\n", addr, first, second);
        }
        first = second;
    } while(count < 5);
    DEB_ERR("Could not read correct value for register %#x\n", addr);
    return 0;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void adm_update_error_status(cpphy_mdio_t *mdio, unsigned int port) {
    if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ))
        return;

    switch(port) {
        case 0:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT0);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT0);
            break;
        case 1:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT1);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT1);
            break;
        case 2:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT2);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT2);
            break;
        case 3:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT3);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT3);
            break;
        case 4:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT4);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT4);
            break;
        case 5:
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_COLLISIONCNT5);
            ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_ERRCNT5);
            break;
        default:
            DEB_ERR("adm_update_error_status, unhandled port %u\n", port);
            break;
    }
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void adm_update_cache(cpphy_mdio_t *mdio) {
    unsigned int i = 0;

    if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ))
        return;

    for(i = 0; adm_serial_registers[i] != -1; i++) {
        ADM_GET_SERIAL_REG(mdio, adm_serial_registers[i]);
        PRINT_REGISTER(adm_serial_registers[i]);
    }
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
#if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
static int adm_write_adml(unsigned int addr, unsigned int dat) {
    unsigned int op;

    adm_gpio_init();

    /* enable write */
    adm_eeprom_write_enable();

    /* chip select */
    adm_mdcs_hi();
    udelay(ADM_SW_CS_DELAY);

    /* issue write command */
    /* start bit */
    adm_mdio_hi();
    adm_mdc_pulse();

    /* EEPROM write command */
    op = ADM_SW_BIT_MASK_2;
    while(op) {
        if(op & ADM_SW_EEPROM_WRITE)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_pulse();
        op >>= 1;
    }

    /* send address A7 ~ A0 */
    op = ADM_SW_BIT_MASK_1 << (EEPROM_TYPE - 1);

    while(op) {
        if(op & addr)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_toggle();
        op >>= 1;
    }

    /* start write data */
    op = ADM_SW_BIT_MASK_16;
    while(op) {
        if(op & dat)
            adm_mdio_hi();
        else
            adm_mdio_lo();

        adm_mdc_toggle();
        op >>= 1;
    }

    /* disable cs & wait 1 clock */
    adm_mdcs_lo();
    udelay(ADM_SW_CS_DELAY);
    adm_mdc_toggle();

    adm_eeprom_write_disable();

    return 0;
}
#endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/


/*------------------------------------------------------------------------------------------*\
 * write register to ADM6996 eeprom registers
\*------------------------------------------------------------------------------------------*/
int adm_write(cpphy_mdio_t *mdio, unsigned int addr, unsigned int dat) {
    if(!(mdio->Mode & CPPHY_SWITCH_MODE_WRITE)) {
        return -1;
    }

    if(mdio->Mode & CPPHY_SWITCH_MODE_16BIT) {
        /*--- DEB_TEST("[adm_write] Write reg %#x: %#x -> %#x\n", addr, cpphy_mdio_user_access_read(mdio, addr & 0x1f, addr >> 5), dat); ---*/
        cpphy_mdio_user_access_write(mdio, addr & 0x1f, addr >> 5, dat);
    }
#   if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
      else {
        adm_write_adml(addr + 0x80, dat);
    }
#   endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
    return 0;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned short tantos_write(cpphy_mdio_t *mdio, unsigned short *ptr, unsigned short value) {
    unsigned int addr    = (unsigned int) (ptr - (unsigned short *) tantos_switch);

    if(addr > sizeof(tantos_switch_memory) / sizeof(unsigned short))
        panic("[tantos_write] addr %x out of range (max %x)\n", addr, sizeof(tantos_switch_memory) / sizeof(unsigned short));
    ((unsigned short *) tantos_switch)[addr] = value;
    return adm_write(mdio, addr, value);
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static void tantos_wait_for_access_complete(cpphy_mdio_t *mdio) {
    for( ;; ) {
        ADM_TANTOS_GET(mdio, tantos_switch->MIIAC);
        if(tantos_switch->MIIAC.MBUSY == 0)
            break;
        schedule();
    }
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static unsigned int tantos_phy_access(cpphy_mdio_t   *mdio,
                                      unsigned int    method,
                                      unsigned short *regadr,
                                      unsigned int    phyadr,
                                      unsigned int    data) {
    unsigned int value;
    unsigned int addr  = (unsigned int) (regadr - (unsigned short *) tantos_phys);

    if(phyadr >= sizeof(tantos_phy_memory) / sizeof(tantos_phy_memory[0])) {
        panic("[tantos_phy_access] illegal phyadr %x (max 0x%x)\n", phyadr, sizeof(tantos_phy_memory) / sizeof(tantos_phy_memory[0]));
    }
    if(addr >= sizeof(tantos_phy_memory[0]) / sizeof(unsigned short)) {
        panic("[tantos_phy_access] illegal addr %x (max 0x%x)\n", addr, sizeof(tantos_phy_memory[0]) / sizeof(unsigned short));
    }

    if(method == TANTOS_MIIAC_SYNC) {
        data = ((unsigned short *) &(tantos_phy_memory[phyadr]))[addr];
        method = TANTOS_MIIAC_WRITE;
    }
    value = data;
    down_interruptible(&mdio->semaphore_switch);
    tantos_wait_for_access_complete(mdio);  /* Wait until UserAccess ready */
    tantos_switch->MIIAC.OP    = method;
    tantos_switch->MIIAC.PHYAD = phyadr;
    tantos_switch->MIIAC.REGAD = addr;
    if(method == TANTOS_MIIAC_WRITE) {
        ((unsigned short *) &(tantos_phy_memory[phyadr]))[addr] = data;
        ADM_TANTOS_PUT(mdio, tantos_switch->MIIWD, data);
    }
    ADM_TANTOS_SYNC(mdio, tantos_switch->MIIAC);
    tantos_wait_for_access_complete(mdio);  /* Wait for Read to complete */

    if(method == TANTOS_MIIAC_READ) {
        value = ADM_TANTOS_GET(mdio, tantos_switch->MIIRD);
        ((unsigned short *) &(tantos_phy_memory[phyadr]))[addr] = value;
    }
    /*--- DEB_TRC("[tantos_phy_access] %s phy %u, reg %#x = %#x\n", ---*/
            /*--- (method == TANTOS_MIIAC_WRITE) ? "Writing" : "Reading", ---*/
            /*--- phyadr, ---*/
            /*--- addr, ---*/
            /*--- value); ---*/
    up(&mdio->semaphore_switch);
    return value;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static void tantos_wait_for_counter_access_complete(cpphy_mdio_t *mdio) {
    for( ;; ) {
        ADM_TANTOS_GET(mdio, tantos_switch->RCC);
        if(tantos_switch->RCC.BAS == 0)
            break;
        schedule();
    }
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static unsigned int tantos_counter_access(cpphy_mdio_t   *mdio,
                                          unsigned short  method,
                                          unsigned short  phy,
                                          unsigned short  offset) {
    unsigned int value = 0;
    /*--- unsigned int addr  = (unsigned int) (regadr - (unsigned short *) tantos_phys); ---*/

    /*--- if(phyadr >= sizeof(tantos_phy_memory) / sizeof(tantos_phy_memory[0])) { ---*/
        /*--- panic("[tantos_phy_access] illegal phyadr %x (max 0x%x)\n", phyadr, sizeof(tantos_phy_memory) / sizeof(tantos_phy_memory[0])); ---*/
    /*--- } ---*/
    /*--- if(addr >= sizeof(tantos_phy_memory[0]) / sizeof(unsigned short)) { ---*/
        /*--- panic("[tantos_phy_access] illegal addr %x (max 0x%x)\n", addr, sizeof(tantos_phy_memory[0]) / sizeof(unsigned short)); ---*/
    /*--- } ---*/

    if(phy >= 7) {
        panic("[tantos_counter_access] Illegal PHY number %u\n", phy);
    }
    if(offset > 27) {
        panic("[tantos_counter_access] Illegal offset %u\n", offset);
    }

    switch(method) {
        case TANTOS_COUNTER_READ:
            down_interruptible(&mdio->semaphore_switch);
            tantos_wait_for_counter_access_complete(mdio);
            tantos_switch->RCC.CAC = method;
            tantos_switch->RCC.PORTC = phy;
            tantos_switch->RCC.OFFSET = offset;
            tantos_switch->RCC.BAS = 1;
            ADM_TANTOS_SYNC(mdio, tantos_switch->RCC);
            tantos_wait_for_counter_access_complete(mdio);
            value =    ADM_TANTOS_GET(mdio, tantos_switch->RCSL)
                    + (ADM_TANTOS_GET(mdio, tantos_switch->RCSH) << 16);
            up(&mdio->semaphore_switch);
            return value;
            break;
        case TANTOS_COUNTER_READ_ALL:
            down_interruptible(&mdio->semaphore_switch);
            tantos_wait_for_counter_access_complete(mdio);
            tantos_switch->RCC.CAC = method;
            tantos_switch->RCC.PORTC = phy;
            tantos_switch->RCC.OFFSET = 0;
            tantos_switch->RCC.BAS = 1;
            ADM_TANTOS_SYNC(mdio, tantos_switch->RCC);
            tantos_counter_memory[phy].RxGoodByte = 0;
            tantos_counter_memory[phy].RxBadByte = 0;
            tantos_counter_memory[phy].TxGoodByte = 0;
            for(offset = 0; offset <= 0x27; offset++) {
                tantos_wait_for_counter_access_complete(mdio);
                value =   ADM_TANTOS_GET(mdio, tantos_switch->RCSL)
                        + (ADM_TANTOS_GET(mdio, tantos_switch->RCSH) << 16);
                ((unsigned int *) &(tantos_counter_memory[phy]))[offset] = value;
            }
            tantos_counter_memory[phy].RxGoodByte =   ((unsigned long long) (((unsigned int *) &(tantos_counter_memory[phy]))[23]) << 32)
                                                    + ((unsigned long long)  ((unsigned int *) &(tantos_counter_memory[phy]))[22]);
            tantos_counter_memory[phy].RxBadByte  =   ((unsigned long long) (((unsigned int *) &(tantos_counter_memory[phy]))[25]) << 32)
                                                    + ((unsigned long long)  ((unsigned int *) &(tantos_counter_memory[phy]))[24]);
            tantos_counter_memory[phy].TxGoodByte =   ((unsigned long long) (((unsigned int *) &(tantos_counter_memory[phy]))[27]) << 32)
                                                    + ((unsigned long long)  ((unsigned int *) &(tantos_counter_memory[phy]))[26]);
            up(&mdio->semaphore_switch);
            return 0;
            break;
        case TANTOS_COUNTER_RENEW_PORT_COUNTERS:
        case TANTOS_COUNTER_RENEW_ALL_COUNTERS:
            printk("[tantos_counter_access] Method %u not yet implemented\n", method);
            return 0;
            break;
        default:
            printk("[tantos_counter_access] Illegal method %u\n", method);
            break;
    }
    return value;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void adm_prepare_reboot(cpphy_mdio_t *mdio) {
    unsigned int i;

    adm_vlan_fbox_reset(mdio);
    ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE, ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE) & 0xffcf);
    mdio->cpmac_priv->enable_vlan = 0;
    mdio->adm_power.roundrobin = 0;
    for(i = 0; i < 5; i++) {
        mdio->adm_power.setup.mode[i] = ADM_PHY_POWER_ON;
    }
    cpphy_mgmt_power(mdio);
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
#if 0
#if defined(CONFIG_MIPS_OHIO)
static irqreturn_t adm_interrupt(int irq, void *p_param, struct pt_regs *regs) {
    cpphy_mdio_t *mdio = (cpphy_mdio_t *) p_param;
    unsigned short status = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_IS);

    DEB_TRC("adm_interrupt: %#x\n", status);
    /* Reset time stamp to ensure that the just changed value is requested */
    serial_register_timestamp[(REG_ADM_LC_STATUS0 - 0xa0) >> 1] = 0;

    return IRQ_HANDLED;
}
#endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/
#endif /*--- #if 0 ---*/


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned long switch_dump(cpphy_mdio_t *mdio) {
    unsigned int i, phy;

    #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
    DEB_TEST("Registerdump CPMAC SANGAM/OHIO\n");
    for(i = 0; i <= 0x28c; i += 4) {
        DEB_TEST("CPMAC Register 0x%x = 0x%x\n", i, *((volatile unsigned int *) (mdio->cpmac_priv->owner->base_addr + i)));
    }
    #elif defined(CONFIG_MIPS_UR8) /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
    /*--- DEB_TEST("Registerdump CPMAC UR8\n"); ---*/
    #endif /*--- #elif defined(CONFIG_MIPS_UR8) ---*/

    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
        if(mdio->switch_dump_value == 1) { /* Register dump */
            DEB_TEST("Registerdump Tantos: All values are hexadecimal!\n");
            for(i = 0x00; i < 0x20; i++) {
                DEB_TEST("Reg %3x = %4x   %3x = %4x   %3x = %4x   %3x = %4x   %3x = %4x   %3x = %4x   %3x = %4x\n",
                         0x00 + i, ADM_GET_EEPROM_REG(mdio, 0x00 + i),
                         0x20 + i, ADM_GET_EEPROM_REG(mdio, 0x20 + i),
                         0x40 + i, ADM_GET_EEPROM_REG(mdio, 0x40 + i),
                         0x60 + i, ADM_GET_EEPROM_REG(mdio, 0x60 + i),
                         0x80 + i, ADM_GET_EEPROM_REG(mdio, 0x80 + i),
                         0xa0 + i, ADM_GET_EEPROM_REG(mdio, 0xa0 + i),
                         0xc0 + i, ADM_GET_EEPROM_REG(mdio, 0xc0 + i));
            }
            for(i = 0xe0; i <= 0x122; i++) PRINT_REGISTER(i);
            DEB_TEST("Additional register dump:\n");
            for(phy = 0; phy < 7; phy++) {
                DEB_TEST("  For PHY %u\n", phy);
                for(i = 0x00; i < 0x18; i++) {
                    DEB_TEST("    Reg %3x = %4x\n", i, tantos_phy_access(mdio, TANTOS_MIIAC_READ, ((unsigned short *) tantos_phys) + i, (phy), 0));
                }
                tantos_counter_access(mdio, TANTOS_COUNTER_READ_ALL, phy, 0);
                for(i = 0x00; i <= 0x27; i++) {
                    DEB_TEST("    Counter %3x = %4x\n", i, ((unsigned int *) &(tantos_counter_memory[phy]))[i]);
                }
            }
        } else if(mdio->switch_dump_value == 2) { /* MAC Hash table */
            down_interruptible(&mdio->semaphore_switch);
            for(i = 0; i < 4; i++) { /* Search through all four possible FIDs */
                DEB_TEST("MAC table entries for FID = %u\n", i);
                do { ADM_TANTOS_GET(mdio, tantos_switch->ATS5); } while(tantos_switch->ATS5.BUSY);

                tantos_switch->ATC5.AC_CMD = TANTOS_MACTABLE_INITIAL_FIRST;
                ADM_TANTOS_SYNC(mdio, tantos_switch->ATC5);
                do { ADM_TANTOS_GET(mdio, tantos_switch->ATS5); } while(tantos_switch->ATS5.BUSY);

                do {
                    tantos_switch->ATC3.FID = i;
                    tantos_switch->ATC5.AC_CMD = TANTOS_MACTABLE_SEARCH_FID;
                    ADM_TANTOS_SYNC(mdio, tantos_switch->ATC3);
                    ADM_TANTOS_SYNC(mdio, tantos_switch->ATC5);
                    do { ADM_TANTOS_GET(mdio, tantos_switch->ATS5); } while(   tantos_switch->ATS5.BUSY
                                                                            || (tantos_switch->ATS5.RSLT == TANTOS_MACTABLE_RESULT_TEMPORARY_STATE));
                    if(tantos_switch->ATS5.RSLT == TANTOS_MACTABLE_RESULT_OK) {
                        ADM_TANTOS_GET(mdio, tantos_switch->ATS4);
                        if(!tantos_switch->ATS4.OCP) { /* Unoccupied entries are not interesting */
                            continue;
                        }
                        ADM_TANTOS_GET(mdio, tantos_switch->ATS0);
                        ADM_TANTOS_GET(mdio, tantos_switch->ATS1);
                        ADM_TANTOS_GET(mdio, tantos_switch->ATS2);
                        ADM_TANTOS_GET(mdio, tantos_switch->ATS3);
                        if(tantos_switch->ATS4.INFOTS) {
                            DEB_TEST("  static : FID %#x, ports %#2x, %04x%04x%04x, no details yet\n",
                                    tantos_switch->ATS3.FIDS,
                                    tantos_switch->ATS3.PMAPS,
                                    tantos_switch->ATS2.ADDR47_32,
                                    tantos_switch->ATS1.ADDR31_16,
                                    tantos_switch->ATS0.ADDR15_0);
                        } else {
                            DEB_TEST("  dynamic: FID %#x, ports %#2x, %04x%04x%04x, age %u\n",
                                    tantos_switch->ATS3.FIDS,
                                    tantos_switch->ATS3.PMAPS,
                                    tantos_switch->ATS2.ADDR47_32,
                                    tantos_switch->ATS1.ADDR31_16,
                                    tantos_switch->ATS0.ADDR15_0,
                                    tantos_switch->ATS4.ITATS);
                        }
                    }
                } while(tantos_switch->ATS5.RSLT == TANTOS_MACTABLE_RESULT_OK);
            }
            up(&mdio->semaphore_switch);
        } else if(mdio->switch_dump_value == 3) { /* Counter dump */
            /* TODO */
        } else { /* Unknown, probably everything */
            for(i = 1; i < 4; i++) {
                mdio->switch_dump_value = i;
                switch_dump(mdio);
            }
        }
    } else if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_ADM6996) {
        DEB_TEST("Registerdump ADM6996: All values are hexadecimal!\n");
        for(i = 0x000; i <= 0x09c; i++) PRINT_REGISTER(i);
        for(i = 0x0a0; i <= 0x0ad; i++) PRINT_REGISTER(i);
        for(i = 0x0b0; i <= 0x0b1; i++) PRINT_REGISTER(i);
        for(i = 0x0b4; i <= 0x0bb; i++) PRINT_REGISTER(i);
        for(i = 0x0be; i <= 0x0bf; i++) PRINT_REGISTER(i);
        for(i = 0x0c2; i <= 0x0c3; i++) PRINT_REGISTER(i);
        for(i = 0x0c6; i <= 0x0cd; i++) PRINT_REGISTER(i);
        for(i = 0x0d0; i <= 0x0d1; i++) PRINT_REGISTER(i);
        for(i = 0x0d4; i <= 0x0d5; i++) PRINT_REGISTER(i);
        for(i = 0x0d8; i <= 0x0df; i++) PRINT_REGISTER(i);
        for(i = 0x0e2; i <= 0x0e3; i++) PRINT_REGISTER(i);
        for(i = 0x0e6; i <= 0x0e7; i++) PRINT_REGISTER(i);
        for(i = 0x0ea; i <= 0x0f1; i++) PRINT_REGISTER(i);
        for(i = 0x0f4; i <= 0x0f5; i++) PRINT_REGISTER(i);
        for(i = 0x0f8; i <= 0x0f9; i++) PRINT_REGISTER(i);
        for(i = 0x0fc; i <= 0x103; i++) PRINT_REGISTER(i);
        for(i = 0x106; i <= 0x107; i++) PRINT_REGISTER(i);
        for(i = 0x10a; i <= 0x10b; i++) PRINT_REGISTER(i);
        for(i = 0x10e; i <= 0x119; i++) PRINT_REGISTER(i);
        for(i = 0x130; i <= 0x143; i++) PRINT_REGISTER(i);
        for(i = 0x200; i <= 0x208; i++) PRINT_REGISTER(i);
        for(i = 0x220; i <= 0x228; i++) PRINT_REGISTER(i);
        for(i = 0x240; i <= 0x248; i++) PRINT_REGISTER(i);
        for(i = 0x260; i <= 0x268; i++) PRINT_REGISTER(i);
        for(i = 0x280; i <= 0x288; i++) PRINT_REGISTER(i);

#if 0
        down_interruptible(&mdio->semaphore_switch);
        for(i = 0; i < 4; i++) { /* Search through all four possible FIDs */
            unsigned short ATS5;

            DEB_TEST("MAC table entries for FID = %u\n", i);
            do { ; } while(ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS5) & ADM_ATS5_BUSY_MASK);
            
            DEB_TEST("Initialize search\n"); /* FIXME */
            /* Initialize the MAC table access engine */
            ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_ATC5, TANTOS_MACTABLE_INITIAL_FIRST << ADM_ATC5_AC_CMD_SHIFT);
            do { ; } while(ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS5) & ADM_ATS5_BUSY_MASK);

            do {
                DEB_TEST("Search initialize start\n"); /* FIXME */
                /* Enter search criteria and start the search, then wait until it finished */
                ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_ATC3, i << ADM_ATC3_PMAP_SHIFT);
                ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_ATC5, TANTOS_MACTABLE_SEARCH_FID << ADM_ATC5_AC_CMD_SHIFT);
                DEB_TEST("Search start\n"); /* FIXME */
                do { 
                    ATS5 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS5);
                } while(   (ATS5 & ADM_ATS5_BUSY_MASK)
                        || (((ATS5 & ADM_ATS5_RSLT_MASK) >> ADM_ATS5_RSLT_SHIFT) == TANTOS_MACTABLE_RESULT_TEMPORARY_STATE));

                DEB_TEST("Result (ATS5 = %#x)('ATS6' = %#x)\n", ATS5, ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS5 + 1)); /* FIXME */
                if(((ATS5 & ADM_ATS5_RSLT_MASK) >> ADM_ATS5_RSLT_SHIFT) == TANTOS_MACTABLE_RESULT_OK) {
                    unsigned short ATS0, ATS1, ATS2, ATS3, ATS4;
                    ATS4 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS4);
                    if(!(ATS4 & ADM_ATS4_OCP_MASK)) { /* Unoccupied entries are not interesting */
                        continue;
                    }
                    ATS0 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS4);
                    ATS1 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS4);
                    ATS2 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS4);
                    ATS3 = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ATS4);
                    if(ATS4 & ADM_ATS4_INFOTS_MASK) {
                        DEB_TEST("  static : FID %#x, ports %#2x, %04x%04x%04x, no details yet\n",
                                (ATS3 & ADM_ATS3_FIDS_MASK) >> ADM_ATS3_FIDS_SHIFT,
                                (ATS3 & ADM_ATS3_PMAPS_MASK) >> ADM_ATS3_PMAPS_SHIFT,
                                ATS2, ATS1, ATS0);
                    } else {
                        DEB_TEST("  dynamic: FID %#x, ports %#2x, %04x%04x%04x, age %u\n",
                                (ATS3 & ADM_ATS3_FIDS_MASK) >> ADM_ATS3_FIDS_SHIFT,
                                (ATS3 & ADM_ATS3_PMAPS_MASK) >> ADM_ATS3_PMAPS_SHIFT,
                                ATS2, ATS1, ATS0,
                                (ATS4 & ADM_ATS4_INFOTS_MASK) >> ADM_ATS4_INFOTS_SHIFT);
                    }
                }
            } while(((ATS5 & ADM_ATS5_RSLT_MASK) >> ADM_ATS5_RSLT_SHIFT) == TANTOS_MACTABLE_RESULT_OK);
        }
        up(&mdio->semaphore_switch);
#endif /*--- #if 0 ---*/
    } else if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_AR8216) {
        display_ath_regs(mdio, ATH_PORT_CONTROL);
        display_ath_regs(mdio, ATH_CONTROL);
        display_ath_regs(mdio, ATH_MII);
    } else {
        DEB_TEST("Switch dump requested, but no known switch is connected.\n");
    }
    mdio->switch_dump_value = 0;
    cpphy_mgmt_work_del(mdio, CPMAC_WORK_SWITCH_DUMP);
    return 0;
}


/*------------------------------------------------------------------------------------------*\
 * default VLAN setting
 * port 0~3 as untag port and PVID = 1
 * VLAN1: port 0~3 and port 5 (MII)
\*------------------------------------------------------------------------------------------*/
void adm_init(cpphy_mdio_t *mdio) {
    unsigned int i;
    char *hwrev, *cpu_nr;

    for(i = 0; i < NUMBER_OF_SERIAL_REGISTERS; i++) {
        serial_register[i] = 0;
        write_serial_register_timestamp(i, 0);
    }

    mdio->Mode = 0 | CPPHY_SWITCH_MODE_WRITE | CPPHY_SWITCH_MODE_READ; /* 32 Bit, read, write */
    mdio->mode_pppoa = 0;

    if(mdio->is_vinax) {
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
        mdio->switch_config = &(switch_configuration[CPMAC_SWITCH_CONF_VINAX5][0]);
#       elif defined(CONFIG_MIPS_UR8) /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        mdio->switch_config = &(switch_configuration[CPMAC_SWITCH_CONF_VINAX7][0]);
#       else /*--- #elif defined(CONFIG_MIPS_UR8) ---*/
#       warning "There is no switch configuration for the VINAX with this architecture!"
#       endif /*--- #else ---*/ /*--- #elif defined(CONFIG_MIPS_UR8) ---*/
    } else {
        mdio->switch_config = &(switch_configuration[CPMAC_SWITCH_CONF_7170][0]);
    }
    hwrev = prom_getenv("HWRevision");
    mdio->switch_status.cpu_port = 5;
    if(hwrev && (strstr("103 ", hwrev) || strstr("104 ", hwrev))) {
        char *cmdline = prom_getcmdline();
        cpu_nr = strstr( cmdline, "CPU_NR=" );
        if(cpu_nr == NULL) {
            DEB_WARN("ProfiVoIP: running on first CPU\n");
            mdio->switch_config = switch_configuration[CPMAC_SWITCH_CONF_PROFIVOIP2];
            mdio->switch_status.cpu_port = 5;
        } else {
            DEB_WARN("ProfiVoIP: running on second CPU\n");
            mdio->Mode = 0; /* No access at all! */
            mdio->linked = 1;
            return;
        }
    } else if(hwrev && (   (!(strncmp( "94", hwrev, 2)) && (strlen(hwrev) < 4)) /* First 7170 revision */
                        || (!(strncmp( "95", hwrev, 2)) && (strlen(hwrev) < 4)) /* First 7140 revision */
                        || (!(strncmp("107", hwrev, 3)) && (strlen(hwrev) < 5)) /* First 7140 Annex A revision */
             )         ) {
        DEB_INFO("switch works in read only 32 bit mode\n");
        mdio->Mode &= ~CPPHY_SWITCH_MODE_WRITE;
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
        adm_gpio_init();
#       endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        adm_check_link(mdio);
        return;
    }

    if(hwrev && (   !(strncmp("79", hwrev, 2)) /* 3070 with ADM6996L */
                 || !(strncmp("84", hwrev, 2)) /* 2070 with ADM6996L */
                )
      ) {
        DEB_INFO("switch works in read/write 32 bit mode\n");
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
        adm_gpio_init();
#       endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
    } else {
        /* "Normal" switch with 16 bit access and hardware mdio */
#       if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
        adm_gpio_finit();
#       endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        mdio->Mode |= CPPHY_SWITCH_MODE_16BIT;
        DEB_INFO("switch is in 16bit Mode\n");
    }

    /* Check the kind of switch */
    init_MUTEX(&mdio->semaphore_switch);
    if(   (ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ID2) == 0x0007) 
       && (ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ID)  == 0x1022)) {
        DEB_INFOTRC("Identified ADM6996LC switch\n");
        mdio->cpmac_switch = AVM_CPMAC_SWITCH_ADM6996;
        mdio->switch_ports = 6;
    } else if(   (ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ID2) == 0x0007) 
              && (ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_ID)  == 0x1023)) {
        DEB_INFOTRC("Identified ADM6996FC switch\n");
        mdio->cpmac_switch = AVM_CPMAC_SWITCH_ADM6996;
        mdio->switch_ports = 6;
    } else if(   (   (ADM_TANTOS_GET(mdio, tantos_switch->CI0) == 0x1)  /* Tantos 1.2 */
                  || (ADM_TANTOS_GET(mdio, tantos_switch->CI0) == 0x2)) /* Tantos 1.3 */
              && (ADM_TANTOS_GET(mdio, tantos_switch->CI1) == 0x2599)) {
        DEB_INFOTRC("Identified TANTOS switch family\n");
        mdio->cpmac_switch = AVM_CPMAC_SWITCH_TANTOS;
        mdio->switch_ports = 7;
        ADM_PUT_EEPROM_REG(mdio, 0xa1, 0x4);
        ADM_PUT_EEPROM_REG(mdio, 0xf5, 0x777);
        for(i = 0; i < 5; i++) {
            ADM_TANTOS_PHY_GET(mdio, i, tantos_phys->PHY_CR);
            tantos_phy_memory[i].PHY_CR.DISPMG = 1;
            ADM_TANTOS_PHY_SYNC(mdio, i, tantos_phys->PHY_CR);
        }
        ADM_TANTOS_GET(mdio, tantos_switch->MIICR);
        *((unsigned short *)&tantos_switch->MIICR) = 0x777; /* MIIs: 100MBits/FD/FC */
        ADM_TANTOS_SYNC(mdio, tantos_switch->MIICR);
        for(i = 5; i <= 6; i++) {
            if((i == 6) && !(mdio->is_vinax))
                continue;
            ADM_TANTOS_GET(mdio, tantos_ports->port[i].PBC);
            tantos_ports->port[i].PBC.FLP = 1; /* Force link up for MIIs */
            ADM_TANTOS_SYNC(mdio, tantos_ports->port[i].PBC);
        }

#if 0
        /* FIXME Test mirror option */
        ADM_TANTOS_GET(mdio, tantos_switch->CMH);
        DEB_TEST("[adm_init] before CMH = %#x\n", *((unsigned int *) &tantos_switch->CMH));
        /*--- tantos_switch->CMH.CPN = 0x5; ---*/ /* CPU port is number 5     */
        tantos_switch->CMH.MSA = 0x1; /* Mirror short packets     */
        tantos_switch->CMH.MPA = 0x1; /* Mirror pause packets     */
        tantos_switch->CMH.SPN = 0x5; /* Mirror to the CPU port 5 */
        ADM_TANTOS_SYNC(mdio, tantos_switch->CMH);
        DEB_TEST("[adm_init] after CMH = %#x\n", *((unsigned int *) &tantos_switch->CMH));
        ADM_TANTOS_GET(mdio, tantos_ports->port[6].PEC);
        tantos_ports->port[6].PEC.IPMO = 0x1; /* Enable receive mirroring */
        ADM_TANTOS_SYNC(mdio, tantos_ports->port[6].PEC);
#endif /*--- #if 0 ---*/
    } else {
        DEB_INFOTRC("Could not identify switch. Assuming ADM6996 family\n");
        mdio->cpmac_switch = AVM_CPMAC_SWITCH_ADM6996;
        mdio->switch_ports = 6;
    }

    cpphy_mgmt_power_init(mdio);
    /* TODO: Would we benefit? Or is this workqueue variant better anyway? */
#   if 0
#   if defined(CONFIG_MIPS_OHIO)
    /* Check, if we can use the interrupt */
    if(hwrev && !(strncmp("94", hwrev, 2)) && (strlen(hwrev) > 2)) {
        /* We need write access to configure the switch */
        if(mdio->Mode | CPPHY_SWITCH_MODE_WRITE) {
            if(request_irq(OHIOINT_EXT_1, adm_interrupt, SA_INTERRUPT | SA_SHIRQ, "ADM6996 Driver", mdio)) {
                DEB_ERR("adm_init, failed to register the irq %u\n", OHIOINT_EXT_1);
                return;
            }
            ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_IE, ADM_IE_PStatIE);
            ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE, ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE) | 0x0004);
            /* Make sure, that all values are zero by reading the register */
            ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_IS);
            mdio->cpmac_irq = 1;
        }
    }
#   endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/
#   endif /*--- #if 0 ---*/
    adm_check_link(mdio);
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned int adm_check_link(cpphy_mdio_t *mdio) {
    unsigned int port, adm_status = 0;

    if(!(mdio->Mode & CPPHY_SWITCH_MODE_READ))
        return 0xff;

    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
        adm_status = 0;
        for(port = 0; port < TANTOS_MAX_PORTS ; port++) {
            ADM_TANTOS_GET(mdio, tantos_ports->port[port].PS);
            if(tantos_ports->port[port].PS.link) {
                adm_status |= 1 << port;
            }
        }
        /* All ports except the CPU port */
        mdio->linked = adm_status & (0x05f);
    } else {
        unsigned int linked = 0;
        /* FIXME The event changes should move */
        if(mdio->Mode & CPPHY_SWITCH_MODE_16BIT) {
            adm_status = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_STATUS0);
            linked |= ((adm_status & ADM_LC_STATUS0_PORT0_LINKUP) ? 1 : 0) << 0;
            linked |= ((adm_status & ADM_LC_STATUS0_PORT1_LINKUP) ? 1 : 0) << 1;
            mdio->event_data.port[0].link       = ((adm_status & ADM_LC_STATUS0_PORT0_LINKUP) ? 1 : 0);
            mdio->event_data.port[0].speed100   = ((adm_status & ADM_LC_STATUS0_PORT0_SPEED) ? 1 : 0);
            mdio->event_data.port[0].fullduplex = ((adm_status & ADM_LC_STATUS0_PORT0_DUPLEX) ? 1 : 0);
            mdio->event_data.port[1].link       = ((adm_status & ADM_LC_STATUS0_PORT1_LINKUP) ? 1 : 0);
            mdio->event_data.port[1].speed100   = ((adm_status & ADM_LC_STATUS0_PORT1_SPEED) ? 1 : 0);
            mdio->event_data.port[1].fullduplex = ((adm_status & ADM_LC_STATUS0_PORT1_DUPLEX) ? 1 : 0);
            adm_status = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_STATUS1);
            linked |= ((adm_status & ADM_LC_STATUS1_PORT2_LINKUP) ? 1 : 0) << 2;
            linked |= ((adm_status & ADM_LC_STATUS1_PORT3_LINKUP) ? 1 : 0) << 3;
            linked |= ((adm_status & ADM_LC_STATUS1_PORT4_LINKUP) ? 1 : 0) << 4;
            mdio->event_data.port[2].link       = ((adm_status & ADM_LC_STATUS1_PORT2_LINKUP) ? 1 : 0);
            mdio->event_data.port[2].speed100   = ((adm_status & ADM_LC_STATUS1_PORT2_SPEED) ? 1 : 0);
            mdio->event_data.port[2].fullduplex = ((adm_status & ADM_LC_STATUS1_PORT2_DUPLEX) ? 1 : 0);
            mdio->event_data.port[3].link       = ((adm_status & ADM_LC_STATUS1_PORT3_LINKUP) ? 1 : 0);
            mdio->event_data.port[3].speed100   = ((adm_status & ADM_LC_STATUS1_PORT3_SPEED) ? 1 : 0);
            mdio->event_data.port[3].fullduplex = ((adm_status & ADM_LC_STATUS1_PORT3_DUPLEX) ? 1 : 0);
            mdio->event_data.port[4].link       = ((adm_status & ADM_LC_STATUS1_PORT4_LINKUP) ? 1 : 0);
            mdio->event_data.port[4].speed100   = ((adm_status & ADM_LC_STATUS1_PORT4_SPEED) ? 1 : 0);
            mdio->event_data.port[4].fullduplex = ((adm_status & ADM_LC_STATUS1_PORT4_DUPLEX) ? 1 : 0);
            adm_status = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_STATUS2);
            linked |= ((adm_status & ADM_LC_STATUS2_PORT5_LINKUP) ? 1 : 0) << 5;
            mdio->event_data.port[5].link       = ((adm_status & ADM_LC_STATUS2_PORT5_LINKUP) ? 1 : 0);
            mdio->event_data.port[5].speed100   = ((adm_status & ADM_LC_STATUS2_PORT5_SPEED) ? 1 : 0);
            mdio->event_data.port[5].fullduplex = ((adm_status & ADM_LC_STATUS2_PORT5_DUPLEX) ? 1 : 0);
        } else {
#           if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO)
            /* Is needed for 2070, 3070, some 7170 */
            adm_status = ADM_GET_SERIAL_REG(mdio, REG_ADM_LC_STATUS0);
            for(port = 0; port < TANTOS_MAX_PORTS ; port++) {
                if(adm_status & adm_port_link_bits[port]) {
                    linked |= 1 << port;
                }
            }
            mdio->event_data.port[0].link = adm_serial_register.status.port0linkup;
            mdio->event_data.port[0].speed100 = adm_serial_register.status.port0speed;
            mdio->event_data.port[0].fullduplex = adm_serial_register.status.port0duplex;
            mdio->event_data.port[1].link = adm_serial_register.status.port1linkup;
            mdio->event_data.port[1].speed100 = adm_serial_register.status.port1speed;
            mdio->event_data.port[1].fullduplex = adm_serial_register.status.port1duplex;
            mdio->event_data.port[2].link = adm_serial_register.status.port2linkup;
            mdio->event_data.port[2].speed100 = adm_serial_register.status.port2speed;
            mdio->event_data.port[2].fullduplex = adm_serial_register.status.port2duplex;
            mdio->event_data.port[3].link = adm_serial_register.status.port3linkup;
            mdio->event_data.port[3].speed100 = adm_serial_register.status.port3speed;
            mdio->event_data.port[3].fullduplex = adm_serial_register.status.port3duplex;
            mdio->event_data.port[4].link = adm_serial_register.status.port4linkup;
            mdio->event_data.port[4].speed100 = adm_serial_register.status.port4speed;
            mdio->event_data.port[4].fullduplex = adm_serial_register.status.port4duplex;
#           endif /*--- #if defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_OHIO) ---*/
        }
        if(mdio->linked != linked) {
            mdio->linked = linked;
            cpmac_main_event_update();
        }

        mdio->linked = linked;
    }

    return mdio->linked;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void adm_switch_port_power(cpphy_mdio_t *mdio, unsigned int port, unsigned int power_on) {
    unsigned int value;

    assert(port < AVM_CPMAC_MAX_PORTS); /* To ease Klocwork checking */

    value =   ADM_PHY_CONTROL_DPLX
            | ADM_PHY_CONTROL_ANEN
            | ADM_PHY_CONTROL_SPEED_LSB
            | (power_on ? ADM_PHY_CONTROL_RST : ADM_PHY_CONTROL_PDN);
    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
        ADM_TANTOS_PHY_PUT(mdio, port, tantos_phys->CR, value);
    } else {
        ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_PHY_CONTROL_PORT0 + (0x20 * port), value);
    }
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static void adm_vlan_reset(cpphy_mdio_t *mdio) {
    unsigned int group, port;

    mdio->cpmac_priv->enable_vlan = 0;
    for(group = 0; group < AVM_CPMAC_MAX_VLAN_GROUPS; group++) {
        mdio->switch_status.vlan[group].written = 0;
        mdio->switch_status.vlan[group].active = 0;
        mdio->switch_status.vlan[group].VFL.Bits.VV = 0;
        mdio->switch_status.vlan[group].VFL.Bits.VP = 0;
        mdio->switch_status.vlan[group].VFL.Bits.VID = group + 16;
        mdio->switch_status.vlan[group].VFH.Bits.FID = 0;
        mdio->switch_status.vlan[group].VFH.Bits.TM = 0;
        mdio->switch_status.vlan[group].VFH.Bits.M = (mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) ? 0x7F : 0x3F;
    }
    for(port = 0; port <= 5; port++) {
        mdio->switch_status.port[port].written = 0;
        mdio->switch_status.port[port].vid = port + 16;
        mdio->switch_status.port[port].keep_tag_outgoing = 0;
        mdio->cpmac_priv->map_port_out[port] = port + 16;
    }
};


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned long adm_set_wan_keep_tagging(cpphy_mdio_t *mdio) {
    struct avm_new_switch_struct *status = &(mdio->switch_status);
    unsigned int port = mdio->cpmac_priv->wanport;
    unsigned int RegData;

    assert(mdio != NULL);
    assert(port < 6); /* The ADM6996xC have a maximum of six ports */
    cpphy_mgmt_work_del(mdio, CPMAC_WORK_TOGGLE_VLAN);
    if(status->port[port].keep_tag_outgoing == mdio->wan_tagging_enable) {
        DEB_WARN("[adm_set_wan_keep_tagging] Already correct setting: %stagged\n",
                 mdio->wan_tagging_enable ? "" : "un");
        cpphy_if_data_from_queues(mdio->cpmac_priv->cppi);
        return 0;
    }
    switch(mdio->cpmac_switch) {
        case AVM_CPMAC_SWITCH_TANTOS:
        case AVM_CPMAC_SWITCH_NONE:
            /* Nothing to be done in those cases */
            DEB_ERR("[adm_set_wan_keep_tagging] This should not be called for this hardware!\n");
            return 0;
        case AVM_CPMAC_SWITCH_ADM6996:
        case AVM_CPMAC_SWITCH_ADM6996L:
        case AVM_CPMAC_SWITCH_AR8216:
        default:
            break;
    }

    tasklet_disable(&mdio->cpmac_priv->tasklet);

    status->port[port].keep_tag_outgoing = mdio->wan_tagging_enable;
    switch(mdio->cpmac_switch) {
        case AVM_CPMAC_SWITCH_ADM6996:
        case AVM_CPMAC_SWITCH_ADM6996L:
            RegData = ADM_GET_EEPROM_REG(mdio, adm_port_registers[port]);
            if(status->port[port].keep_tag_outgoing)
                RegData |= ADM_SW_PORT_TAG;
            else
                RegData &= ~ADM_SW_PORT_TAG;
            ADM_PUT_EEPROM_REG(mdio, adm_port_registers[port], RegData);
            break;
        case AVM_CPMAC_SWITCH_AR8216:
            RegData = ar8216_mdio_read32(mdio, (port + 1) * AR8216_PORT0_CONTROL_BASIS + AR8216_PORT_CONTROL_OFFSET);
            RegData &= ~(3u << 8); /* Delete VLAN status */
            if(!status->port[port].keep_tag_outgoing)
                RegData |= ATH_PORT_CTRL_EG_VLAN_MODE(1);
            ar8216_mdio_write32(mdio, (port + 1) * AR8216_PORT0_CONTROL_BASIS + AR8216_PORT_CONTROL_OFFSET, RegData);
            break;
        default:
            break;
    }

    tasklet_enable(&mdio->cpmac_priv->tasklet);

    DEB_INFO("Configure wan keep_tagging to %d\n", mdio->wan_tagging_enable);
    cpphy_if_data_from_queues(mdio->cpmac_priv->cppi);
    return 0;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
unsigned long adm_set_mode_pppoa_work(cpphy_mdio_t *mdio) {
    struct avm_new_switch_struct *status = &(mdio->switch_status);
    unsigned char wanport = mdio->switch_config[mdio->cpmac_config.cpmac_mode].wanport;

    cpphy_mgmt_work_del(mdio, CPMAC_WORK_TOGGLE_PPPOA);
    tasklet_disable(&mdio->cpmac_priv->tasklet);

    DEB_INFOTRC("[adm_set_mode_pppoa_work] %sabling PPPoA\n", mdio->mode_pppoa ? "En" : "Dis");
    
    /* Asserts, to make Klocwork happy */
    assert(status->cpu_port < AVM_CPMAC_MAX_PORTS);
    assert(wanport < AVM_CPMAC_MAX_PORTS);
    /* Change MAC learning off for PPPoA, on otherwise */
    ADM_TANTOS_GET(mdio, tantos_ports->port[status->cpu_port].PEC);
    tantos_ports->port[status->cpu_port].PEC.LD = mdio->mode_pppoa;
    ADM_TANTOS_SYNC(mdio, tantos_ports->port[status->cpu_port].PEC);
    ADM_TANTOS_GET(mdio, tantos_ports->port[wanport].PEC);
    tantos_ports->port[wanport].PEC.LD = mdio->mode_pppoa;
    ADM_TANTOS_SYNC(mdio, tantos_ports->port[wanport].PEC);

    /* Switch flow control off for PPPoA, on otherwise */
    ADM_TANTOS_GET(mdio, tantos_ports->port[wanport].PS);
    tantos_ports->port[wanport].PS.flowcontrol = mdio->mode_pppoa ? 0 : 1;
    ADM_TANTOS_SYNC(mdio, tantos_ports->port[wanport].PS);

    tasklet_enable(&mdio->cpmac_priv->tasklet);

    return 0;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
cpmac_err_t adm_set_mode_pppoa(cpphy_mdio_t *mdio, unsigned int enable_pppoa) {
    if(!mdio->is_vinax || (mdio->cpmac_switch != AVM_CPMAC_SWITCH_TANTOS)) {
        DEB_ERR("[adm_set_mode_pppoa] PPPOA mode exists only for the Tantos/VINAX combination!\n");
        return CPMAC_ERR_ILL_CONTROL;
    }

    if(mdio->switch_config[mdio->cpmac_config.cpmac_mode].wanport > AVM_CPMAC_MAX_PORTS) {
        DEB_ERR("[adm_set_mode_pppoa] There seems to be no WAN port for PPPoA!?\n");
        return CPMAC_ERR_ILL_CONTROL;
    }

    mdio->mode_pppoa = enable_pppoa ? 1 : 0;
    DEB_INFOTRC("[adm_set_mode_pppoa] Enqueue %sabling PPPoA\n", mdio->mode_pppoa ? "en" : "dis");
    cpphy_mgmt_work_add(mdio, CPMAC_WORK_TOGGLE_PPPOA, adm_set_mode_pppoa_work, 0);

    return CPMAC_ERR_NOERR;
}


/*------------------------------------------------------------------------------------------*\
 * Configure VLAN on the switch                                                             *
\*------------------------------------------------------------------------------------------*/
static void adm_vlan_config(cpphy_mdio_t *mdio) {
    unsigned int vlan_mapping, group, port, RegData;

    if(!(mdio->Mode & CPPHY_SWITCH_MODE_WRITE))
        return; /*--- CPMAC_ERR_NO_VLAN_POSSIBLE; ---*/

    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
        for(port = 0; port < mdio->switch_ports; port++) {
            ADM_TANTOS_GET(mdio, tantos_ports->port[port].PBVM);
            tantos_ports->port[port].PBVM.TBVE = mdio->cpmac_priv->enable_vlan;
            ADM_TANTOS_SYNC(mdio, tantos_ports->port[port].PBVM);
        }

        for(port = 0; port < mdio->switch_ports; port++) {
            DEB_INFOTRC("Configure port %u with VLAN group %#x %stagged %s\n",
                        port,
                        mdio->switch_status.port[port].vid,
                        mdio->switch_status.port[port].keep_tag_outgoing ? "" : "un",
                        mdio->switch_status.port[port].written ? "" : "(new)");

            if(mdio->switch_status.port[port].written)
                continue;
            mdio->switch_status.port[port].written = 1;
            /* Set the default VID */
            ADM_TANTOS_GET(mdio, tantos_ports->port[port].PDVID);
            tantos_ports->port[port].PDVID.PVID = mdio->switch_status.port[port].vid;
            ADM_TANTOS_SYNC(mdio, tantos_ports->port[port].PDVID);
        }

        for(group = 0; group < AVM_CPMAC_MAX_VLAN_GROUPS; group++) {
            DEB_INFOTRC("Configure VLAN group %#x (%s): FID %#x VID %#x target 0x%x tagged 0x%x %s\n",
                        group,
                        mdio->switch_status.vlan[group].VFL.Bits.VV ? "  active" : "inactive",
                        mdio->switch_status.vlan[group].VFH.Bits.FID,
                        mdio->switch_status.vlan[group].VFL.Bits.VID,
                        mdio->switch_status.vlan[group].VFH.Bits.M,
                        mdio->switch_status.vlan[group].VFH.Bits.TM,
                        mdio->switch_status.vlan[group].written ? "" : "(new)");

            if(mdio->switch_status.vlan[group].written)
                continue;
            mdio->switch_status.vlan[group].written = 1;

            if(group < 8) {
                ADM_TANTOS_PUT(mdio, tantos_switch->VF0[group].VFH, mdio->switch_status.vlan[group].VFH.Register);
                ADM_TANTOS_PUT(mdio, tantos_switch->VF0[group].VFL, mdio->switch_status.vlan[group].VFL.Register);
            } else {
                ADM_TANTOS_PUT(mdio, tantos_switch->VF8[group - 8].VFH, mdio->switch_status.vlan[group].VFH.Register);
                ADM_TANTOS_PUT(mdio, tantos_switch->VF8[group - 8].VFL, mdio->switch_status.vlan[group].VFL.Register);
            }
        }
    } else {
        /*--- Select two bits MAC Clone, when cloning (for VLANs) is enabled ---*/
        RegData = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_MISC_CONF);
        RegData |= ADM_CONF_MISC_MCEB;
        ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_MISC_CONF, RegData);
        if(mdio->cpmac_priv->enable_vlan == 1) {
            /* MAC clone, 802.1q based VLAN */
            ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE, ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE) | 0x0030);
            /* MAC clone, 802.1q based VLAN, address aging timer 1 second */
            /*--- ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE, 0xff33); ---*/
        } else {
            /* MAC clone, Port based by-pass mode */
            ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE, ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_VLAN_MODE) & 0xffcf);
        }

        for(port = 0; port < mdio->switch_ports; port++) {
            assert(port < 6); /* The ADM6996xC have a maximum of six ports */
            DEB_INFOTRC("Configure port 0x%x with VID 0x%x %stagged %s\n",
                        port,
                        mdio->switch_status.port[port].vid,
                        mdio->switch_status.port[port].keep_tag_outgoing ? "" : "un",
                        mdio->switch_status.port[port].written ? "" : "(new)");

            if(mdio->switch_status.port[port].written)
                continue;
            mdio->switch_status.port[port].written = 1;
            RegData = ADM_GET_EEPROM_REG(mdio, adm_port_registers[port]);
            RegData &= ~(ADM_CONF_OUTPUT_PKT_TAG | ADM_CONF_PORT_VLAN_ID);
            if(mdio->switch_status.port[port].keep_tag_outgoing)
                RegData |= ADM_SW_PORT_TAG;
            RegData |= (mdio->switch_status.port[port].vid & 0xf) << ADM_SW_PORT_PVID_SHIFT;
            ADM_PUT_EEPROM_REG(mdio, adm_port_registers[port], RegData);
            if(port == 5) {
                RegData  = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_RACP) & 0xff00;
                RegData |= (mdio->switch_status.port[port].vid & 0xff0) >> 4;
                ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_RACP, RegData);
            } else if(port == 4) {
                RegData  = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_PORT34_PVID) & 0x00ff;
                RegData |= (mdio->switch_status.port[port].vid & 0xff0) << 4;
                ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_PORT34_PVID, RegData);
            } else {
                RegData  = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_PORT0_PVID + port) & 0xff00;
                RegData |= (mdio->switch_status.port[port].vid & 0xff0) >> 4;
                ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_PORT0_PVID + port, RegData);
            }
        }

        for(group = 0; group < AVM_CPMAC_MAX_VLAN_GROUPS; group++) {
            unsigned short target_register;
            DEB_INFOTRC("Configure VLAN group %#x (%s): VID 0x%x target 0x%x %s\n",
                        group,
                        mdio->switch_status.vlan[group].active ? "  active" : "inactive",
                        mdio->switch_status.vlan[group].vid,
                        mdio->switch_status.vlan[group].VFH.Bits.M,
                        mdio->switch_status.vlan[group].written ? "" : "(new)");

            if(mdio->switch_status.vlan[group].written)
                continue;
            mdio->switch_status.vlan[group].written = 1;

            vlan_mapping  = mdio->switch_status.vlan[group].VFH.Bits.M;
            vlan_mapping |= ADM_GET_TAG_GROUP(mdio->switch_status.vlan[group].vid) << 12;
            target_register = REG_ADM_LC_VLAN_FILTER0_LOW + 2 * group;
            ADM_PUT_EEPROM_REG(mdio, target_register, vlan_mapping);
            DEB_INFOTRC("[adm_new_vlan_config] Writing register %#x = %#x\n", target_register, vlan_mapping);
            vlan_mapping = (mdio->switch_status.vlan[group].active << 15) | mdio->switch_status.vlan[group].vid;
            target_register = REG_ADM_LC_VLAN_FILTER0_HIGH + 2 * group;
            ADM_PUT_EEPROM_REG(mdio, target_register, vlan_mapping);
            DEB_INFOTRC("[adm_new_vlan_config] Writing register %#x = %#x\n", target_register, vlan_mapping);
        }
    }
}


/*------------------------------------------------------------------------------------------*\
 * Reset the VLAN settings of the switch                                                    *
\*------------------------------------------------------------------------------------------*/
void adm_vlan_fbox_reset(cpphy_mdio_t *mdio) {
    /* switch off VLAN */
    adm_vlan_reset(mdio);
    adm_vlan_config(mdio);
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
struct net_device *find_or_register_device(char *name,
                                           cpmac_priv_t *cpmac_priv,
                                           unsigned short VID) {
    struct net_device *dev;
    int i;

    for(i = 0; i < AVM_CPMAC_MAX_DEVS; i++) {
        dev = cpmac_priv->olddevs[i];
        if(dev && strcmp(dev->name, name) == 0) {
            DEB_INFOTRC("Device configuration: Update '%s' with VID 0x%x\n", name, VID);
            cpmac_update_device(dev, VID);
            cpmac_priv->olddevs[i] = 0;
            return dev;
        }
    }
    if(strcmp(name, "wan") != 0) {
        DEB_INFOTRC("Device configuration: Connect outgoing '%s' with VID 0x%x\n", name, VID);
        return cpmac_register_eth_device(name, cpmac_priv->owner, VID);
    }
    DEB_INFOTRC("Device configuration: Connect outgoing '%s' with VID 0x%x (WAN)\n", name, VID);
    cpmac_priv->wanport_default_vid = VID;
    return cpmac_register_wan_device(name, cpmac_priv->owner, VID);
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
/* Find unused VLAN ID group */
#define find_unused_vlan_old() \
    for(vid_group = 0; vid_group < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group++) { \
        if(!(used_vid_mask & (1 << vid_group))) { \
            break; \
        } \
    } \
    if(vid_group == AVM_CPMAC_MAX_VLAN_GROUPS) { \
        DEB_ERR("Error! I need more VLAN groups!\n"); \
        return CPMAC_ERR_NO_VLAN_POSSIBLE; \
    } \
    used_vid_mask |= 1 << vid_group;

#define adm_get_new_vid() \
    /* Do not use VIDs < 2; ensure it by adding 4, that does not change the lower two bits */ \
    new_vid = (((vid_group << ADM_6996_TAGSHIFT) + bit_combination) & 0xfff); \
    for( ; ; ) { \
        new_vid += (1 << 2); \
        new_vid &= 0xfff; /* To make Klockworks happy */ \
        if(mdio->cpmac_priv->map_in[new_vid].used) \
            continue; \
        if(((new_vid >> ADM_6996_TAGSHIFT) & 0xf) != vid_group) { \
            DEB_ERR("Internal VLAN configuration error! Too many VIDs for this device %u?\n", device); \
        } \
        DEB_TRC("[adm_get_new_vid] new_vid = %#x\n", new_vid); \
        break; \
    }


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void set_map_in(cpphy_mdio_t *mdio,
                unsigned short vid,
                unsigned short device,
                unsigned short port) {
    assert(port < AVM_CPMAC_MAX_PORTS);
    vid &= 0xfff; /* VID is always 0-4095; this tries to make Klockworks happy */
    if(mdio->cpmac_priv->map_in[vid].used) {
        if(mdio->cpmac_priv->map_in[vid].port != port) {
            DEB_ERR("[set_map_in] Error! VID %#x port (%u - %u) already set and differs!\n",
                    vid,
                    mdio->cpmac_priv->map_in[vid].port, port);
        } else {
            DEB_INFOTRC("[set_map_in] VID %#x Port (%u) already set, but identical.\n",
                        vid, port);
        }
    } else {
        DEB_INFOTRC("[set_map_in] Setting VID %#x Device (%u), port (%u).\n", vid, device, port);
        mdio->cpmac_priv->map_in[vid].port  = port;
        mdio->cpmac_priv->map_in[vid].used = 1;
    }

    if(mdio->cpmac_priv->map_in_port_dev[port].used) {
        if(mdio->cpmac_priv->map_in_port_dev[port].dev != device) {
            DEB_ERR("[set_map_in] Error! Port %u already set to device %u instead of %u.\n",
                    port, mdio->cpmac_priv->map_in_port_dev[port].dev, device);
        } else {
            DEB_INFOTRC("[set_map_in] Port %u already set to device %u.\n",
                    port, mdio->cpmac_priv->map_in_port_dev[port].dev);
        }
    } else {
        DEB_INFOTRC("[set_map_in] Setting port %u to device %u.\n", port, device);
        mdio->cpmac_priv->map_in_port_dev[port].dev = device;
        mdio->cpmac_priv->map_in_port_dev[port].used = 1;
    }
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
cpmac_err_t adm_configure_cpmac(cpphy_mdio_t *mdio, struct avm_cpmac_config_struct *config) {
    unsigned short used_vid_mask = 0, bit_combination;
    unsigned char port, device, vid_group, used_ports = 0, roundrobin;
    unsigned int i, create_port_specific_vlan, vid, devices_old;
    unsigned short new_vid; /*--- = (1 << (4 + ADM_6996_TAGSHIFT)); ---*/
    struct avm_new_switch_struct *status = &(mdio->switch_status);

    if(!(mdio->Mode & CPPHY_SWITCH_MODE_WRITE)) {
        DEB_ERR("[adm_configure_cpmac] Illegal configuration for this hardware!\n");
        return CPMAC_ERR_NO_VLAN_POSSIBLE;
    }

    /* Check plausibility */
    if(config->cpmac_mode >= CPMAC_MODE_MAX_NO) {
        DEB_ERR("[adm_configure_cpmac] Unknown cpmac_configuration %u\n", config->cpmac_mode);
        return CPMAC_ERR_EXCEEDS_LIMIT;
    }
    assert(status->cpu_port < AVM_CPMAC_MAX_PORTS);

    /* Make sure, that nothing works in parallel */
    cpphy_mgmt_work_stop(mdio);
    tasklet_disable(&mdio->cpmac_priv->tasklet);

    /* Backup device entries */
    for(i = 0; i < AVM_CPMAC_MAX_DEVS; i++) {
        mdio->cpmac_priv->olddevs[i] = mdio->cpmac_priv->devs[i];
        mdio->cpmac_priv->devs[i] = 0;
    }

    devices_old = mdio->cpmac_priv->devices;
    mdio->cpmac_priv->devices = mdio->switch_config[config->cpmac_mode].number_of_devices;
    if(mdio->cpmac_priv->devices > AVM_CPMAC_MAX_DEVS) {
        mdio->cpmac_priv->devices = devices_old;
        DEB_ERR("[adm_configure_cpmac] Too many devices in configuration!\n");
        return CPMAC_ERR_EXCEEDS_LIMIT;
    }
    DEB_INFO("Configure cpmac to mode %u with %u devices:\n",
             config->cpmac_mode, mdio->cpmac_priv->devices);
    for(i = 0; i < mdio->cpmac_priv->devices; i++) {
        DEB_INFO("Configure cpmac device '%s' with target_mask 0x%x\n",
                 mdio->switch_config[config->cpmac_mode].device[i].name,
                 mdio->switch_config[config->cpmac_mode].device[i].target_mask);
    }

    memcpy(&mdio->cpmac_config, config, sizeof(struct avm_cpmac_config_struct));

    /* More than four devices might mean problems with port addressing */
    if(   (   (mdio->cpmac_switch == AVM_CPMAC_SWITCH_ADM6996L)
           || (mdio->cpmac_switch == AVM_CPMAC_SWITCH_ADM6996))
       && (mdio->cpmac_priv->devices > 4)) {
        DEB_WARN("[adm_configure_cpmac] Warning: Too many devices (%u). This might cause packet loss!\n",
                 mdio->cpmac_priv->devices);
    }

    adm_vlan_reset(mdio);

    if(mdio->cpmac_config.cpmac_mode == CPMAC_MODE_ALL_PORTS) {
        DEB_INFOTRC("Configure: Disable VLAN\n");
        mdio->cpmac_priv->enable_vlan = 0;
    } else {
        DEB_INFOTRC("Configure: Enable VLAN\n");
        mdio->cpmac_priv->enable_vlan = 1;
    }

    /* Determine which ports are used and therefor need a VLAN ID */
    for(device = 0; device < mdio->cpmac_priv->devices; device++) {
        used_ports |= mdio->switch_config[config->cpmac_mode].device[device].target_mask;
    }
    /* Reset VID->Port mapping */
    for(vid = 0; vid < 4096; vid++) {
        /*--- set_map_in(mdio, vid, 0, status->cpu_port); ---*/
        mdio->cpmac_priv->map_in[vid].port = status->cpu_port;
        mdio->cpmac_priv->map_in[vid].used = 0;
    }
    /* Reset port->device mapping */
    for(port = 0; port < AVM_CPMAC_MAX_PORTS; port++) {
        mdio->cpmac_priv->map_in_port_dev[port].dev = 0;
        mdio->cpmac_priv->map_in_port_dev[port].used = 0;
    }

    /* Reset PPPoA mode */
    mdio->mode_pppoa = 0;

    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
        /* Do we have predefined VLAN IDs? */
        if(config->wan_vlan_number) {
            for(device = 0; device < mdio->cpmac_priv->devices; device++) {
                if(strncmp(mdio->switch_config[config->cpmac_mode].device[device].name, "wan", 3) == 0) {
                    for(i = 0; i < config->wan_vlan_number; i++) {
                        vid = config->wan_vlan_id[i];
                        find_unused_vlan_old(); /* sets vid_group */

                        /* Make all ports that belong to the same VLAN group receive the data of the port */
                        status->vlan[vid_group].VFL.Bits.VV = 1;
                        status->vlan[vid_group].VFL.Bits.VID = vid;
                        status->vlan[vid_group].VFH.Bits.M = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
                        status->vlan[vid_group].VFH.Bits.TM = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
                        /*--- DEB_TEST("-- %u -- VID_group %#x = %#x\n", __LINE__, vid & 0xf, status->vlan[vid & 0xf].VFH.Register); ---*/ /* FIXME */
                        status->vlan[vid_group].written = 0;
                        for(port = 0; port < AVM_CPMAC_MAX_PORTS; port++) {
                            if(mdio->switch_config[config->cpmac_mode].device[device].target_mask & (1 << port)) {
                                if(port != status->cpu_port) {
                                    set_map_in(mdio, vid, device, port);
                                }
                            }
                        }
                    }
                }
            }
        }

        /* Tag incoming data with individual tags and deliver it to all interested ports */
        for(port = 0; port < AVM_CPMAC_MAX_PORTS; port++) {
            /* Do not tag incoming data from the CPU port */
            if(port == status->cpu_port)
                continue;

            /* If port is unused, it needs no VLAN tag */
            if(!(used_ports & (1 << port))) {
                continue;
            }

            /* Find unused VLAN ID group */
            find_unused_vlan_old();
            bit_combination = 0; /* Does not really matter for the Tantos */
            adm_get_new_vid();
            status->port[port].vid = new_vid;
            status->port[port].written = 0;

            if(port != mdio->switch_config[config->cpmac_mode].wanport) {
                status->port[status->cpu_port].vid = status->port[port].vid;
                status->port[status->cpu_port].written = 0;
                DEB_INFO("Setting VID of CPU-port to %#x\n", status->port[status->cpu_port].vid);
            }

            DEB_INFOTRC("Configure: Setting VLAN tagging on port %u with tag %#x\n", port, new_vid);
            /* Make all ports that belong to the same VLAN group receive the data of the port */
            create_port_specific_vlan = 0;
            for(device = 0; device < mdio->cpmac_priv->devices; device++) {
                if(mdio->switch_config[config->cpmac_mode].device[device].target_mask & (1 << port)) {
                    set_map_in(mdio, status->port[port].vid, device, port);
                    status->vlan[vid_group].VFL.Bits.VV = 1;
                    status->vlan[vid_group].VFL.Bits.VID = new_vid;
                    status->vlan[vid_group].VFH.Bits.M = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
                    status->vlan[vid_group].VFH.Bits.TM = 0x1 << status->cpu_port;
                    status->vlan[vid_group].written = 0;
                    set_map_in(mdio, status->vlan[vid_group].VFL.Bits.VID, device, port);
                    if(mdio->switch_config[config->cpmac_mode].device[device].target_mask & (1 << status->cpu_port)) {
                        create_port_specific_vlan = 1;
                    }
                }
            }

            /* Create VLANs for port specific outgoing traffic */
            if(create_port_specific_vlan == 1) {
                find_unused_vlan_old();
                bit_combination = 0; /* Does not really matter for the Tantos */
                adm_get_new_vid();
                status->vlan[vid_group].VFL.Bits.VV = 1;
                status->vlan[vid_group].VFL.Bits.VID = new_vid;
                status->vlan[vid_group].VFH.Bits.M = (0x1 << status->cpu_port) | (0x1 << port);
                status->vlan[vid_group].VFH.Bits.TM = 0x1 << status->cpu_port;
                status->vlan[vid_group].written = 0;
                /* This VID is not intended for incoming traffic. It is *\
                 * defined here to make checking for used VIDs possible */
                mdio->cpmac_priv->map_in[new_vid].port  = port;
                mdio->cpmac_priv->map_in[new_vid].used = 1;
                mdio->cpmac_priv->map_port_out[port] = status->vlan[vid_group].VFL.Bits.VID;
                DEB_INFOTRC("Configure: Setting outgoing VLAN ID for port %u to %#x\n", port, new_vid);
            }
        }
        for(vid_group = 0; vid_group < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group++) {
            for(device = 0; device < mdio->cpmac_priv->devices; device++) {
                /* Are all target ports in the device target mask? Do they belong together? */
                if(   (  mdio->switch_config[config->cpmac_mode].device[device].target_mask
                       & status->vlan[vid_group].VFH.Bits.M)
                   == status->vlan[vid_group].VFH.Bits.M) {
                    if(device >= 4) {
                        DEB_ERR("Attention! More than four devices might produce packet forwarding errors!\n");
                    }
                    status->vlan[vid_group].VFH.Bits.FID = device & 0x3;
                }
            }
        }
    } else {
        /* We need to treat the WAN case special, because of limitations of the *\
         * ADM6996 switches:                                                    *
         *   - Four consecutive bits of the VID are used as VID group           *
         *   - The MAC hash table uses only the lower two bits of the VID to    *
         *     distinguish VLANs                                                *
         *                                                                      *
         * This code assumes provided VIDs below 256 and at most three of the   *
         * four two bit combinations for the lower two bits of the VID taken.   *
         * This range is now expected and summarized in group 0. Further it is  *
         * expected, that the WAN device connects only the CPU port and the WAN *
        \* port.                                                                */
        int bit_combinations_used[4] = {-1, -1, -1, -1};

        if(4 < (mdio->cpmac_priv->devices + (config->wan_vlan_number ? (config->wan_vlan_number - 1) : 0))) {
            DEB_WARN("[adm_configure_cpmac] Warning: Too many devices (%u) and/or predefined VLAN IDs (%u). This might cause packet loss!\n",
                     mdio->cpmac_priv->devices, config->wan_vlan_number);
        }

        for(device = 0; device < mdio->cpmac_priv->devices; device++) {
            if(strncmp(mdio->switch_config[config->cpmac_mode].device[device].name, "wan", 3) == 0) {
                bit_combination = 0;

                /* There is no need to configure the switch for each provided VID, because *\
                 * there will be one configured group. The criterion to be considered is   *
                \* the VID group, which will be 0 for the provided and the default VID.    */
                for(i = 0; i < config->wan_vlan_number; i++) {
                    vid = config->wan_vlan_id[i];
                    set_map_in(mdio, vid, device, mdio->switch_config[config->cpmac_mode].wanport);
                    bit_combinations_used[vid & 0x3] = (int) device;
                    bit_combination = vid & 0x3;
                }
                vid_group = 0; /* Used by adm_get_new_vid */
                adm_get_new_vid();
                used_vid_mask |= 1 << vid_group;
                status->vlan[vid_group].vid = new_vid;
                status->vlan[vid_group].VFH.Bits.M = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
                status->vlan[vid_group].active = 1;
                status->vlan[vid_group].written = 0;
                status->port[mdio->switch_config[config->cpmac_mode].wanport].vid = new_vid;
                status->port[mdio->switch_config[config->cpmac_mode].wanport].written = 0;
                set_map_in(mdio, new_vid, device, mdio->switch_config[config->cpmac_mode].wanport);
                DEB_INFOTRC("[adm_configure_cpmac] Create WAN info: group %#x, VID %#x, mask %#x\n",
                            vid_group,
                            new_vid,
                            mdio->switch_config[config->cpmac_mode].device[device].target_mask);
            }
        }

        for(device = 0; device < mdio->cpmac_priv->devices; device++) {
            unsigned short device_vid_group;

            if(strncmp(mdio->switch_config[config->cpmac_mode].device[device].name, "wan", 3) == 0) {
                continue;
            }

            for(bit_combination = 0; bit_combination < 4; bit_combination++) {
                if(bit_combinations_used[bit_combination] != -1)
                    continue;
                break;
            }
            if(bit_combination == 4) {
                DEB_ERR("[adm_configure_cpmac] Out of bit combinations for VIDs! Using 3, expect problems!\n");
                bit_combination = 3;
            }
            bit_combinations_used[bit_combination] = device;

            find_unused_vlan_old();
            device_vid_group = vid_group;

            for(port = 0; port < AVM_CPMAC_MAX_PORTS; port++) {
                /* Skip unused ports */
                if(!((1 << port) & mdio->switch_config[config->cpmac_mode].device[device].target_mask))
                    continue;

                /* Do not tag incoming data from the CPU port */
                if(port == status->cpu_port)
                    continue;

                /* Find unused VLAN ID group */
                /* (port + 1), because it needs to be different to the outgoing VID */
                vid_group = device_vid_group;
                adm_get_new_vid();
                status->vlan[vid_group].vid = new_vid;
                status->vlan[vid_group].VFH.Bits.M = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
                status->vlan[vid_group].active = 1;
                status->vlan[vid_group].written = 0;
                status->port[port].vid = new_vid;
                status->port[port].written = 0;
                set_map_in(mdio, new_vid, device, port);
                DEB_INFOTRC("Configure: Setting incoming VLAN ID for port %u to %#x, target mask %#x\n",
                            port,
                            new_vid,
                            status->vlan[vid_group].VFH.Bits.M);
                /* Set the default VID for the CPU port to that of the last configured incoming port */
                /* This is done to enable untagged packets from the CPU to reach the ethernet */
                if(port < 4) { /* Only for ethernet ports */
                    DEB_INFO("Setting VID of CPU-port to %#x\n", new_vid);
                    status->port[status->cpu_port].vid = new_vid;
                    status->port[status->cpu_port].written = 0;
                }

                /* Create VLANs for port specific outgoing traffic */
                find_unused_vlan_old();
                adm_get_new_vid();
                status->vlan[vid_group].vid = new_vid;
                status->vlan[vid_group].VFH.Bits.M = (1 << status->cpu_port) | (1 << port);
                status->vlan[vid_group].active = 1;
                status->vlan[vid_group].written = 0;
                mdio->cpmac_priv->map_in[new_vid].port  = port;
                mdio->cpmac_priv->map_in[new_vid].used = 1;
                mdio->cpmac_priv->map_port_out[port] = new_vid;
                DEB_INFOTRC("Configure: Setting outgoing VLAN ID for port %u to %#x, target mask %#x\n",
                            port,
                            new_vid,
                            status->vlan[vid_group].VFH.Bits.M);
            }
        }
    }

    status->port[status->cpu_port].keep_tag_outgoing = 1;
    status->port[status->cpu_port].written = 0;

    mdio->cpmac_priv->wanport = mdio->switch_config[config->cpmac_mode].wanport;
    mdio->cpmac_priv->wanport_keeptags = 0;
    if(config->wan_vlan_number) {
        assert(mdio->cpmac_priv->wanport < AVM_CPMAC_MAX_PORTS);
        status->port[mdio->cpmac_priv->wanport].keep_tag_outgoing = 1;
        mdio->wan_tagging_enable = 1;
        mdio->cpmac_priv->wanport_keeptags = 1;
        DEB_INFOTRC("[adm_configure_cpmac] Configure: Keep tags on wanport\n");
    }

    if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_ADM6996) {
        /* Configure tag shift */
        unsigned short RegData = ADM_GET_EEPROM_REG(mdio, REG_ADM_LC_RACP);
        RegData &= ~ADM_CONF_RACP_TAG_SHIFT;
        RegData |= (ADM_6996_TAGSHIFT << ADM_CONF_RACP_TAG_SHIFT_SHIFT);
        ADM_PUT_EEPROM_REG(mdio, REG_ADM_LC_RACP, RegData);
    }

#   ifdef CONFIG_IP_MULTICAST_FASTFORWARD
    for(vid_group = 0; vid_group < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group++) {
        mcfw_portset *setp = &mdio->cpmac_priv->map_vid_portset[vid_group];
        mcfw_portset_reset(setp);
        for(port = 0; port < 4; port++) {
            if(port == mdio->cpmac_priv->wanport)
                continue;
            if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
                if((1 << port) & status->vlan[vid_group].VFH.Bits.M)
                    mcfw_portset_port_add(setp, port);
            } else {
                if((1 << port) & status->vlan[vid_group].VFH.Bits.M)
                    mcfw_portset_port_add(setp, port);
            }
        }
    }
#   endif

    /* Now register the devices with the corresponding VIDs */
    for(device = 0; device < mdio->cpmac_priv->devices; device++) {
        for(vid_group = 0; vid_group < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group++) {
            if(mdio->switch_config[config->cpmac_mode].device[device].target_mask == status->vlan[vid_group].VFH.Bits.M) {
                unsigned int predefined_vid = 0;

                if(mdio->cpmac_priv->devs[device])
                    continue;

                if(mdio->cpmac_switch == AVM_CPMAC_SWITCH_TANTOS) {
                    unsigned short vid_group2;
                    for(vid_group2 = 0; vid_group2 < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group2++) {
                        if(mdio->switch_config[config->cpmac_mode].device[device].target_mask == status->vlan[vid_group2].VFH.Bits.M) {
                            vid = status->vlan[vid_group2].VFL.Bits.VID;
                        }
                    }
                } else {
                    vid = status->vlan[vid_group].vid;
                }

                for(i = 0; i < config->wan_vlan_number; i++) {
                    if(vid == config->wan_vlan_id[i]) {
                        predefined_vid = 1;
                    }
                }
                if(predefined_vid) {
                    continue; /* Next vid_group */
                }

                if(vid == status->port[status->cpu_port].vid) {
                    /* Default VID of CPU port, no tagging needed */
                    DEB_INFOTRC("[adm_configure_cpmac] No extra tagging needed for device '%s'\n",
                                mdio->switch_config[config->cpmac_mode].device[device].name);
                    
                    vid = 0;
                }
                mdio->cpmac_priv->devs[device] = find_or_register_device(
                        mdio->switch_config[config->cpmac_mode].device[device].name,
                        mdio->cpmac_priv,
                        vid);
                assert(mdio->cpmac_priv->devs[device] != NULL);
            }
        }

        /* Calculate mask for LINKUP bits in status register */
        mdio->cpmac_priv->dev_ports[device] = mdio->switch_config[config->cpmac_mode].device[device].target_mask;
    }
    for(i = 0; i < AVM_CPMAC_MAX_DEVS; i++) {
        struct net_device *dev = mdio->cpmac_priv->olddevs[i];
        if(dev) {
            DEB_INFO("Unregister %s\n", dev->name);
            mdio->cpmac_priv->olddevs[i] = 0;
            cpmac_unregister_device(dev);
        }
    }
    DEB_TRC("Possible unregister done\n");

    for(vid_group = 0; vid_group < AVM_CPMAC_MAX_VLAN_GROUPS; vid_group++) {
        unsigned short vid;
        unsigned char port, devoffset;
        struct net_device *dev;

        if(!status->vlan[vid_group].active) {
            DEB_INFOTRC("Configure: VID group %#x inactive\n", vid_group);
            continue;
        }
        vid = status->vlan[vid_group].VFL.Bits.VID;
        assert(vid < 4096); /* To ease Klocwork checking */
        port = mdio->cpmac_priv->map_in[vid].port;
        assert(port < AVM_CPMAC_MAX_PORTS);
        devoffset = mdio->cpmac_priv->map_in_port_dev[port].dev;
        assert(devoffset < AVM_CPMAC_MAX_DEVS); /* To ease Klocwork checking */
        dev = mdio->cpmac_priv->map_in_port_dev[port].used ? mdio->cpmac_priv->devs[devoffset]
                                                 : NULL;
        dev = dev; /* Avoid warning, if DEB_TRC is defined to an empty command */
        DEB_INFOTRC("Configure: VID group %#x with VID %#x mapped to port %u attached to %s\n",
                    vid_group,
                    vid,
                    mdio->cpmac_priv->map_in[vid].port,
                    dev ? dev->name : "no device");
    }

    adm_vlan_config(mdio);
    /*--- switch_dump(mdio); ---*/
#   if 0
    {
        unsigned int i;
        for(i = 0x01; i < 0x01 + 9; i++) PRINT_REGISTER(i);
        for(i = 0x13; i < 0x13 + 16; i++) PRINT_REGISTER(i);
        for(i = 0x28; i <= 0x2c; i++) PRINT_REGISTER(i);
        for(i = 0x40; i < 0x40 + 32; i++) PRINT_REGISTER(i);
    }
#   endif /* #if 0 */

    /* Special treatment for fifth to seventh port */ /* TODO Is there a cleaner way for this? */
    assert(mdio->switch_ports <= AVM_CPMAC_MAX_PORTS);
    for(port = 4; port < mdio->switch_ports; port++) {
        if(used_ports & (1 << port)) {
            mdio->adm_power.setup.mode[port] = ADM_PHY_POWER_ON;
        } else {
            mdio->adm_power.setup.mode[port] = ADM_PHY_POWER_OFF;
        }
    }
    roundrobin = mdio->adm_power.roundrobin;
    mdio->adm_power.roundrobin = 0;
    cpphy_mgmt_power(mdio);
    adm_switch_port_power_config(mdio, &mdio->adm_power.setup, 1);
    mdio->adm_power.roundrobin = roundrobin;

    adm_check_link(mdio); /* Make sure that the sub devices have the correct link status */
    tasklet_enable(&mdio->cpmac_priv->tasklet);
    cpphy_mgmt_work_start(mdio);
    mdio->global_power = CPPHY_POWER_GLOBAL_ON;

    return CPMAC_ERR_NOERR;
}


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
cpmac_err_t adm_configure_special(cpphy_mdio_t *mdio, cpmac_switch_configuration_t *config) {
    memcpy((unsigned char *) &mdio->switch_config[CPMAC_MODE_SPECIAL], config, sizeof(cpmac_switch_configuration_t));
    return CPMAC_ERR_NOERR;
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
cpmac_err_t adm_get_configured(cpphy_mdio_t *mdio, cpmac_switch_configuration_t *config) {
    memcpy(config,
           &mdio->switch_config[mdio->cpmac_config.cpmac_mode],
           sizeof(cpmac_switch_configuration_t));
    return CPMAC_ERR_NOERR;
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
cpmac_err_t adm_get_config_cpmac(cpphy_mdio_t *mdio, struct avm_cpmac_config_struct *config) {
    memcpy(config, &mdio->cpmac_config, sizeof(struct avm_cpmac_config_struct));
    return CPMAC_ERR_NOERR;
}
Den Patch lege ich ab in:
Code:
/home/freetz/freetz-1.1.3/make/linux/patches/2.6.19.2
und heisst
Code:
990-cpmac.patch
da kein gesonderter ordner für 7170 existiert.

der Patch hat folgenden Inhalt:
Code:
  --- linux-2.6.19.2/drivers/net/avm_cpmac/cpphy_adm6996.c_orig   2009-06-08 13:59:52.000000000 +0200
  +++ linux-2.6.19.2/drivers/net/avm_cpmac/cpphy_adm6996.c        2009-08-20 10:57:14.000000000 +0200
  @@ -137,9 +137,10 @@
                                           { {"", 0x0}
                                           }
                                      },
  -        /* CPMAC_MODE_NORMAL    */ { 1, 0xff,
  -                                        { {"eth0", 0x2f}
  -                                        }
  +        /* CPMAC_MODE_NORMAL    */ { 2, 0xff,
  +                                        { {"eth0", 0x21},
  +                                                 {"eth1", 0x22},
  +                                                        {"eth2", 0x24},
  +                                                               {"eth3", 0x28}
  +                                       }
                                      },
           /* CPMAC_MODE_ATA       */ { 2, 0,
                                           { {"wan",  0x21},
 
Du hast doch schon eine Datei, mit der es fehlerfrei funktioniert:
Code:
Wenn ich den Origianl Code von der HP nehme verarbeitet er alles ohne fehlermeldung
Und diese Datei wird benötigt.
 
Das Original ist für:
Das folgende Beispiel beschreibt die Aufteilung des Switch in die beiden Interface eth0 mit LAN1 und LAN2 sowie eth1 mit LAN3 und LAN4.

Ich möchte aber das jeder Port des switches seperat angesprochen wird, dazu ist dieser patch leider nicht zu gebracuhen..
 
OK, dann ist dein Problem, das Du in diesem Thread angesprochen hast, gelöst.
 
Ja meinst du erlich? Dann warst du wohl auf meinem rechner hier und hast alles so gepatch das es läuft.

Guck dir meinen ersten Beitrag doch bitte nochmal genau an.
 
...
Guck dir meinen ersten Beitrag doch bitte nochmal genau an.
Dein 1. Beitrag sagt aus, dass der Patch nicht sauber durchläuft. Die Gründe dafür, haben wir ausdiskutiert. Das Du jetzt auch inhaltlich am source code (... aber was genau, weisst Du ja nicht!) was ändern willst, war bzw. ist aus deinem 1. und den folgenden (bis auf den letzten) Beiträgen nicht ersichtlich. Oder siehst Du das anders?;)
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.