diff -Nru linux/arch/mips/kernel/setup.c.orig linux/arch/mips/kernel/setup.c --- linux/arch/mips/kernel/setup.c.orig Tue Oct 30 10:28:24 2001 +++ linux/arch/mips/kernel/setup.c Tue Oct 30 11:34:30 2001 @@ -621,6 +621,7 @@ void momenco_ocelot_setup(void); void nino_setup(void); void nec_osprey_setup(void); + void nec_korva_setup(void); unsigned long bootmap_size; unsigned long start_pfn, max_pfn, first_usable_pfn; @@ -704,6 +705,11 @@ #ifdef CONFIG_NEC_OSPREY case MACH_GROUP_NEC_VR41XX: nec_osprey_setup(); + break; +#endif +#ifdef CONFIG_NEC_KORVA + case MACH_GROUP_NEC_VR41XX: + nec_korva_setup(); break; #endif #ifdef CONFIG_MIPS_EV96100 diff -Nru linux/arch/mips/Makefile.orig linux/arch/mips/Makefile --- linux/arch/mips/Makefile.orig Tue Oct 30 10:28:20 2001 +++ linux/arch/mips/Makefile Tue Oct 30 11:32:36 2001 @@ -214,6 +214,15 @@ endif # +# NEC Korva (vr4120a) board +# +ifdef CONFIG_NEC_KORVA +SUBDIRS += arch/mips/korva +LIBS += arch/mips/korva/korva.a +LOADADDR += 0x80014000 +endif + +# # Galileo EV64120 Board # ifdef CONFIG_MIPS_EV64120 diff -Nru linux/arch/mips/config.in.orig linux/arch/mips/config.in --- linux/arch/mips/config.in.orig Tue Oct 30 10:28:20 2001 +++ linux/arch/mips/config.in Tue Oct 30 11:48:13 2001 @@ -44,6 +44,7 @@ bool 'Support for NEC DDB Vrc-5476' CONFIG_DDB5476 bool 'Support for NEC DDB Vrc-5477' CONFIG_DDB5477 bool 'Support for NEC Osprey board' CONFIG_NEC_OSPREY +bool 'Support for NEC Korva board ' CONFIG_NEC_KORVA bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 bool 'Support for SGI IP22' CONFIG_SGI_IP22 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI @@ -187,6 +188,15 @@ define_bool CONFIG_IRQ_CPU y define_bool CONFIG_NEW_TIME_C y define_bool CONFIG_DUMMY_KEYB y + define_bool CONFIG_SCSI n +fi +if [ "$CONFIG_NEC_KORVA" = "y" ]; then + define_bool CONFIG_CPU_VR41XX y + define_bool CONFIG_SERIAL y + define_bool CONFIG_SERIAL_MANY_PORTS y + define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_IRQ_CPU y + define_bool CONFIG_NEW_TIME_C y define_bool CONFIG_SCSI n fi if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then diff -Nru linux/arch/mips/korva/Makefile.orig linux/arch/mips/korva/Makefile --- linux/arch/mips/korva/Makefile.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/Makefile Tue Oct 30 11:53:55 2001 @@ -0,0 +1,21 @@ +# +# Makefile for common code of NEC Korva board +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET:= korva.a + +obj-y := setup.o prom.o reset.o int_handler.o irq.o irq_korva.o candy_setup.o + +obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o + +include $(TOPDIR)/Rules.make + diff -Nru linux/arch/mips/korva/candy_setup.c.orig linux/arch/mips/korva/candy_setup.c --- linux/arch/mips/korva/candy_setup.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/candy_setup.c Tue Oct 30 11:32:36 2001 @@ -0,0 +1,79 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/korva/candy_setup.c + * NEC Candy ether driver setup routine. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include + +#define MAX_NUM_DEVS 2 + +static struct { + uint irq; + ulong base_addr; + ulong pmd_addr; + u_char mac_addr[6]; +} candy_boot_params[MAX_NUM_DEVS] = { + {4, 0xb0002000, 0x14, {0x00, 0x00, 0x4c, 0x80, 0x92, 0xa1}}, + {5, 0xb0003000, 0x16, {0x00, 0x00, 0x4c, 0x80, 0x92, 0xa2}} +}; + +int nec_candy_get_boot_params(uint * irq, + ulong * base_addr, + ulong * pmd_addr, + u_char * mac_addr) +{ + static int index=0; + int i; + + if (index == MAX_NUM_DEVS) return -1; + + *irq = candy_boot_params[index].irq; + *base_addr = candy_boot_params[index].base_addr; + *pmd_addr = candy_boot_params[index].pmd_addr; + for (i=0; i< 6; i++) + mac_addr[i] = candy_boot_params[index].mac_addr[i]; + + index ++; + return 0; +} + +EXPORT_SYMBLE(nec_candy_get_boot_params); + + +/* + * kernel boot parameters + * format: "nec_candy_mac=xx,xx,xx,xx,xx,xx [nec_candy_mac=xx,xx,xx,xx,xx,xx]" + */ +static int __init +nec_candy_boot_setup(char *str) +{ + int ints[10]; + int i; + static int index=0; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] != 6) return 0; + + if (index == MAX_NUM_DEVS) return 1; /* ignore params */ + + for (i=0; i< 6; i++) + candy_boot_params[index].mac_addr[i] = (u_char)ints[i+1]; + + index++; + return 1; +} + +__setup("nec_candy_mac=", nec_candy_boot_setup); + diff -Nru linux/arch/mips/korva/dbg_io.c.orig linux/arch/mips/korva/dbg_io.c --- linux/arch/mips/korva/dbg_io.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/dbg_io.c Tue Oct 30 11:57:40 2001 @@ -0,0 +1,124 @@ +#include + +/* ======================= CONFIG ======================== */ + +#define BASE 0xb0000080 +#define MAX_BAUD 1152000 + +/* distance in bytes between two serial registers */ +#define REG_OFFSET 4 + +/* + * 0 - kgdb does serial init + * 1 - kgdb skip serial init + */ +static int remoteDebugInitialized = 0; + +/* + * the default baud rate *if* kgdb does serial init + */ +#define BAUD_DEFAULT UART16550_BAUD_115200 + +/* ======================= END OF CONFIG ======================== */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} diff -Nru linux/arch/mips/korva/int_handler.S.orig linux/arch/mips/korva/int_handler.S --- linux/arch/mips/korva/int_handler.S.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/int_handler.S Tue Oct 30 11:32:36 2001 @@ -0,0 +1,165 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level&2nd-level interrupt dispatcher for ddb5477 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * The second level IRQ has 5 interrupt sources. So we simply lump + * it together here with the first level. + * + * The IRQ levels are hardcoded. If you change them here, you better + * change the init_IRQ() as well. + * + * CPU IRQs : + * 0 - software intr 0 + * 1 - software intr 1 + * 2 - ATM Cell Processor + * 3 - USB Controller + * 4 - Ether Controller #1 + * 5 - Ether Controller #2 + * 6 - cascading to 2nd level (korva) interrupts + * 7 - cpu timer + * + * Korva IRQs : + * 8 - Timer ch0 + * 9 - Timer ch1 + * 10 - UART + * 11 - External interrupt + * 12 - Wakeup + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * first level interrupt dispatcher for ocelot board - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + NESTED(korva_handle_irq, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + .set noreorder + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + andi t1, t0, STATUSF_IP2 + bnez t1, ll_cpu_ip2 + andi t1, t0, STATUSF_IP3 + bnez t1, ll_cpu_ip3 + andi t1, t0, STATUSF_IP4 + bnez t1, ll_cpu_ip4 + andi t1, t0, STATUSF_IP5 + bnez t1, ll_cpu_ip5 + andi t1, t0, STATUSF_IP6 + bnez t1, ll_cpu_ip6 + andi t1, t0, STATUSF_IP0 /* software int 0 */ + bnez t1, ll_cpu_ip0 + andi t1, t0, STATUSF_IP1 /* software int 1 */ + bnez t1, ll_cpu_ip1 + nop + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(korva_handle_irq) + + .align 5 + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + + +ll_cpu_ip0: + li a0, 0 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip1: + li a0, 1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip2: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip3: + li a0, 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip4: + li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip5: + li a0, 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip6: + /* it is korva 2nd level interrupts */ + /* reading ISR will clear it */ + la t0, KORVA_BASE_VIRT + KORVA_S_ISR + lw s0, 0(t0) + + /* and with the mask - just to be safe */ + la t0, KORVA_BASE_VIRT + KORVA_S_IMR + lw t0, 0(t0) + and s0, s0, t0 + + /* do we need to deliver all the pending ones? */ + li a0, 8 + li a1, 13 + li t0, 1 + +loop: + and t1, t0, s0 + bnez t1, foundone + + sll t0, t0, 1 + addiu a0, a0, 1 + + /* check if we reach the end */ + beq a0, a1, error + j loop + +foundone: + move a1, sp + jal do_IRQ + j ret_from_irq + +error: + j spurious_interrupt diff -Nru linux/arch/mips/korva/irq.c.orig linux/arch/mips/korva/irq.c --- linux/arch/mips/korva/irq.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/irq.c Tue Oct 30 11:32:36 2001 @@ -0,0 +1,60 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * init_IRQ for korva. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +extern asmlinkage void korva_handle_irq(void); +extern void breakpoint(void); +extern void mips_cpu_irq_init(u32 irq_base); +extern void korva_irq_init(u32 irq_base); + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; + +void __init init_IRQ(void) +{ + + set_except_vector(0, korva_handle_irq); + + mips_cpu_irq_init(0); + korva_irq_init(8); + + /* hack - enable uart */ + /* korva_out32(KORVA_S_IMR, 1 << 2); */ + + /* setup cascade interrupt 6 */ + setup_irq(6, &irq_cascade); + +#ifdef CONFIG_REMOTE_DEBUG + printk("Setting debug traps - please connect the remote debugger.\n"); + + set_debug_traps(); + + // you may move this line to whereever you want + breakpoint(); +#endif +} + diff -Nru linux/arch/mips/korva/irq_korva.c.orig linux/arch/mips/korva/irq_korva.c --- linux/arch/mips/korva/irq_korva.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/irq_korva.c Tue Oct 30 12:20:54 2001 @@ -0,0 +1,97 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This file define the irq handler for MIPS CPU interrupts. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* + * This file exports one global function: + * korva_irq_init(u32 irq_base); + */ + +#include +#include +#include +#include +#include +#include + +#define NUM_KORVA_IRQS 5 + +static int korva_irq_base=-1; + +static void +korva_irq_enable(unsigned int irq) +{ + db_assert(korva_irq_base != -1); + db_assert(irq >= korva_irq_base); + db_assert(irq < korva_irq_base+NUM_KORVA_IRQS); + + irq -= korva_irq_base; + korva_out32(KORVA_S_IMR, korva_in32(KORVA_S_IMR) | (1 << irq) ); +} + +static void +korva_irq_disable(unsigned int irq) +{ + db_assert(korva_irq_base != -1); + db_assert(irq >= korva_irq_base); + db_assert(irq < korva_irq_base+NUM_KORVA_IRQS); + + irq -= korva_irq_base; + korva_out32(KORVA_S_IMR, korva_in32(KORVA_S_IMR) & ~(1 << irq) ); +} + +static unsigned int korva_irq_startup(unsigned int irq) +{ + korva_irq_enable(irq); + return 0; +} + +#define korva_irq_shutdown korva_irq_disable + +/* the intr status register is already cleared when we read it */ +#define korva_irq_ack korva_irq_disable + +static void +korva_irq_end(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + korva_irq_enable(irq); +} + + +static hw_irq_controller korva_irq_controller = { + "KORVA_irq", + korva_irq_startup, + korva_irq_shutdown, + korva_irq_enable, + korva_irq_disable, + korva_irq_ack, + korva_irq_end, + NULL /* no affinity stuff for UP */ +}; + + +void +korva_irq_init(u32 irq_base) +{ + extern irq_desc_t irq_desc[]; + u32 i; + + for (i= irq_base; i< irq_base+NUM_KORVA_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &korva_irq_controller; + } + + korva_irq_base = irq_base; +} diff -Nru linux/arch/mips/korva/prom.c.orig linux/arch/mips/korva/prom.c --- linux/arch/mips/korva/prom.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/prom.c Tue Oct 30 11:32:36 2001 @@ -0,0 +1,55 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/korva/prom.c + * prom setup file for korva + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +char arcs_cmdline[COMMAND_LINE_SIZE]; + +void __init prom_init(void) +{ + u32 sdtsr; + u32 ramsize; + + strcpy(arcs_cmdline, "console=ttyS0,115200"); + strcat(arcs_cmdline, " ip=bootp"); + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_NEC_KORVA; + + /* bit 8:9 determines the RAM size */ + sdtsr = korva_in32(KORVA_SDTSR); + ramsize = 2 << (1 + ((sdtsr >> 8) & 3)); + printk("Korva board with %d MB system RAM\n", ramsize); + add_memory_region(0, ramsize << 20 , BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} + + diff -Nru linux/arch/mips/korva/reset.c.orig linux/arch/mips/korva/reset.c --- linux/arch/mips/korva/reset.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/reset.c Tue Oct 30 11:32:36 2001 @@ -0,0 +1,38 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + */ +#include +#include +#include +#include +#include +#include +#include + +void nec_korva_restart(char *command) +{ + set_cp0_status(ST0_BEV | ST0_ERL); + change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_32bit_cp0_register(CP0_WIRED, 0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void nec_korva_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1); +} + +void nec_korva_power_off(void) +{ + nec_korva_halt(); +} + diff -Nru linux/arch/mips/korva/setup.c.orig linux/arch/mips/korva/setup.c --- linux/arch/mips/korva/setup.c.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/korva/setup.c Tue Oct 30 12:21:58 2001 @@ -0,0 +1,113 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/korva/setup.c + * The setup file for korva. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for memset */ + +#include +#include +#include +#include + +#include + +// #define USE_CPU_TIMER 1 /* are we using cpu counter as timer */ + +extern void nec_korva_restart(char* c); +extern void nec_korva_halt(void); +extern void nec_korva_power_off(void); + +static void __init init_serial_ports(void) +{ + struct serial_struct s; + + /* clear memory */ + memset(&s, 0, sizeof(s)); + + s.line = 0; /* we set the first one */ + s.baud_base = 1152000; + s.irq = 10; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + s.iomem_base = (u8*)(KORVA_BASE_VIRT + KORVA_UARTDLL); + s.iomem_reg_shift = 2; + s.io_type = SERIAL_IO_MEM; + db_verify(early_serial_setup(&s), == 0); +} + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +static void __init nec_korva_timer_setup(struct irqaction *irq) +{ + +#if defined(USE_CPU_TIMER) + unsigned int count; + + setup_irq(7, irq); + + /* to generate the first CPU timer interrupt */ + count = read_32bit_cp0_register(CP0_COUNT); + write_32bit_cp0_register(CP0_COMPARE, count + 1000); +#else + + setup_irq(8,irq); + + korva_out32(KORVA_TM0CSR, mips_counter_frequency * 8 / HZ); + korva_out32(KORVA_TMMR, 0x1); /* start the timer 0 */ +#endif +} + + +#if defined(CONFIG_BLK_DEV_INITRD) +extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; +#endif + +void __init nec_korva_setup(void) +{ + db_run(printk("nec_korva_setup() starts.\n")); + +#if defined(CONFIG_BLK_DEV_INITRD) + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + board_timer_setup = nec_korva_timer_setup; + + /* figure out the bus clock frequency */ + if (korva_in32(KORVA_S_GSR) & 0x2) { + /* clock is 66MHz, counter freq is divided by 8 */ + mips_counter_frequency = 66000000 / 8; + } else { + mips_counter_frequency = 100000000 / 8; + } + + _machine_restart = nec_korva_restart; + _machine_halt = nec_korva_halt; + _machine_power_off = nec_korva_power_off; + + init_serial_ports(); + + /* ---------------- board hardware setup ---------------- */ + /* reset all peripherials, except uart */ + // korva_out32(KORVA_S_WRCR, 0x1f); + korva_out32(KORVA_S_WRCR, 0x0f); + + /* enable IBUS arbitration for peripherals */ + korva_set_bits(KORVA_S_GMR, 0x2); +} + diff -Nru linux/arch/mips/defconfig-korva.orig linux/arch/mips/defconfig-korva --- linux/arch/mips/defconfig-korva.orig Tue Oct 30 11:32:36 2001 +++ linux/arch/mips/defconfig-korva Tue Oct 30 12:28:36 2001 @@ -0,0 +1,446 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_MIPS=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_DDB5074 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_NINO is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +CONFIG_NEC_KORVA=y +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_CPU_VR41XX=y +CONFIG_SERIAL=y +CONFIG_SERIAL_MANY_PORTS=y +CONFIG_NEW_IRQ=y +CONFIG_IRQ_CPU=y +CONFIG_NEW_TIME_C=y +# CONFIG_SCSI is not set +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_PCI is not set +# CONFIG_I8259 is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_R6000 is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_ADVANCED is not set +# CONFIG_CPU_HAS_LLSC is not set +# CONFIG_CPU_HAS_LLDSCD is not set +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KCORE_ELF=y +CONFIG_ELF_KERNEL=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set +CONFIG_NEC_CANDY=y + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_GDB_CONSOLE is not set +CONFIG_DEBUG=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_MIPS_UNCACHED is not set diff -Nru linux/drivers/net/nec_candy.c.orig linux/drivers/net/nec_candy.c --- linux/drivers/net/nec_candy.c.orig Tue Oct 30 11:32:36 2001 +++ linux/drivers/net/nec_candy.c Tue Oct 30 12:09:42 2001 @@ -0,0 +1,2181 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * driver/net/nec_candy.c + * NEC candy ether driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include /* get_options(), printk(), panic().. */ +#include +#include +#include +#include /* for HZ */ +#include /* init_etherdev() */ +#include +#include + +#include /* KSEGx() */ +#include /* NR_IRQS */ +#include /* virt_to_phys(), dma_cache_xx() */ + +/*********************************************************************** + * debug + *********************************************************************** + */ + +// #define DEBUG_NEC_CANDY +// #define DEBUG_VERBOSE_NEC_CANDY +// #define SHOW_BUG /* targeted bug reporting msgs */ + +#ifdef DEBUG_VERBOSE_NEC_CANDY +#define DEBUG_NEC_CANDY +#endif + +#ifdef DEBUG_NEC_CANDY + +#define ASSERT(x) if (!(x)) { panic("%s:%d - assert failed!\n", __FILE__, __LINE__); } +#define VERIFY(x, y) ASSERT(x y) +#define DEBUG(x) do { x; } while (0) + +#else + +#define ASSERT(x) +#define VERIFY(x, y) x +#define DEBUG(x) + +#endif + +#ifdef DEBUG_VERBOSE_NEC_CANDY +#define DEBUG_VERBOSE(x) do { x; } while (0) +#else +#define DEBUG_VERBOSE(x) +#endif + +/*********************************************************************** + * Configure + *********************************************************************** + */ +/* + * This driver supports multiple nec_candy chips. + */ +#define MAX_NUM_DEVS 2 + +/* the maximum poll times for waiting on a register */ +#define MAX_POLL_TIMES 100000 + +#define TX_RING_SIZE 32 +#define RX_RING_SIZE 32 + +#define RX_BUF_SIZE 1536 +#define ETH_FRAME_SIZE 1536 + +#define TX_TIMEOUT 4*HZ + +/* rx_copybreak: for smaller packet we copy them to avoid emulated + * unaligned access overhead. + * + * Set it to 1518 to always copy ( you should do that on fast machines) + * + * Set it to 0 to avoid any copy. + * + * On Korva, some value in the middle might be appropriate. + */ +static int rx_copybreak=1518; + +/*********************************************************************** + * hardware bug workaround + *********************************************************************** + */ + +#define WORKAROUND_E7_AFCE +#define WORKAROUND_E10_PRM_AMC +#define WORKAROUND_E13_TXFC + +/*********************************************************************** + * Candy.h macros + *********************************************************************** + */ +/*---------------------------------------------------------------------------*/ +/* PHY link status */ +/*---------------------------------------------------------------------------*/ +#define LINK_UP 1 +#define LINK_DOWN 0 + +/*---------------------------------------------------------------------------*/ +/* receive mode & related definitions */ +/*---------------------------------------------------------------------------*/ +#define ACCEPT_ALL_PHYS 0x0001 +#define ACCEPT_ALL_MCASTS 0x0002 +#define ACCEPT_ALL_BCASTS 0x0004 +#define ACCEPT_QUALIFIED_MCAST 0x0008 +#define ACCEPT_STATION 0x0010 +#define MAC_LOOPBACK 0x0020 + +/*---------------------------------------------------------------------------*/ +/* MACC1 - MAC configuration register 1 (00H R/W) */ +/*---------------------------------------------------------------------------*/ +#define MACLB 0x00004000 /* MAC loopback */ +#define TXFC 0x00000800 /* Transmit flow control enable */ +#define RXFC 0x00000400 /* Receive flow control enable */ +#define SRXEN 0x00000200 /* Receive enable */ +#define PARF 0x00000100 /* Control packet pass */ +#define PUREP 0x00000080 /* Pure preamble */ +#define FLCHT 0x00000040 /* Length field check */ +#define NOBO 0x00000020 /* No Back Off */ +#define CRCEN 0x00000008 /* CRC append enable */ +#define PADEN 0x00000004 /* PAD append enable */ +#define FULLD 0x00000002 /* Full duplex enable */ +#define HUGEN 0x00000001 /* Large packet enable */ +#define MACC1_RESERVED 0x00004fef /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* MACC2 - MAC configuration register 2 (04H R/W) */ +/*---------------------------------------------------------------------------*/ +#define MCRST 0x00000400 /* MAC Control Block software reset */ +#define RFRST 0x00000200 /* Receive Function Block software reset */ +#define TFRST 0x00000100 /* Transmit Function Block software reset*/ +#define BPNB 0x00000040 /* Back Pressure No Back Off */ +#define APD 0x00000020 /* Auto VLAN PAD */ +#define VPD 0x00000010 /* VLAN PAD mode */ +#define MACC2_RESERVED 0x00000770 /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* IPGT - Back-to-Back IPG register (08H R/W) */ +/*---------------------------------------------------------------------------*/ +#define IPGT 0x00000013 /* Back-To-Back IPG default value */ +#define IPGT_RESERVED 0x0000007f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* IPGR - Non Back-to-Back IPG register (0CH R/W) */ +/*---------------------------------------------------------------------------*/ +#define IPGR1 0x00000e00 /* Back-To-Back IPG default value */ +#define IPGR2 0x00000013 /* Back-To-Back IPG default value */ +#define IPGR_RESERVED 0x00007f7f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* CLRT - Collision register (10H R/W) */ +/*---------------------------------------------------------------------------*/ +#define LCOLW 0x00003800 /* Late collision window default value */ +#define RETRY 0x0000000f /* Maximum number of retry default value */ +#define CLRT_RESERVED 0x00003f0f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* LMAX - Maximum Packet Length register (14H R/W) */ +/*---------------------------------------------------------------------------*/ +// #define MAXF 0x000005f2 /* Maximum packet length value(1522byte) */ +#define MAXF 0x000005ee /* Maximum packet length value(1518byte) */ +#define LMAX_RESERVED 0x0000ffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* RETX - Retry count register (20H R/W) */ +/*---------------------------------------------------------------------------*/ +#define RETX_MASK 0x0000000f /* Retry counter */ +#define RETX_RESERVED 0x0000000f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* LSA2 - Station address register 2 (54H R/W) */ +/*---------------------------------------------------------------------------*/ +#define LSA2_MASK 0x0000ffff /* Station address SA (47:32) */ +#define LSA2_RESERVED 0x0000ffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* LSA1 - Station address register 1 (58H R/W) */ +/*---------------------------------------------------------------------------*/ +#define LSA1_MASK 0xffffffff /* Station address SA(31:0) */ + +/*---------------------------------------------------------------------------*/ +/* PTVR - Pause timer read register (5CH Read) */ +/*---------------------------------------------------------------------------*/ +#define PTCT_MASK 0x0000ffff /* Pause timer counter */ + +/*---------------------------------------------------------------------------*/ +/* VLTP - VLAN type register (64H R/W) */ +/*---------------------------------------------------------------------------*/ +#define VLTP 0x00008100 /* VLAN type ( etpid:0x81 tci:0x00 ) */ +#define VLTP_RESERVED 0x0000ffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* MIIC - MII Configuration register (80H R/W) */ +/*---------------------------------------------------------------------------*/ +#define MISRT 0x00008000 /* MII Management Interface Block software reset */ +#define CLKS25 0x00000000 /* HCLK is equal to 25 MHz */ +#define CLKS33 0x00000004 /* HCLK is less than or equal to 33 MHz */ +#define CLKS50 0x00000008 /* HCLK is less than or equal to 50 MHz */ +#define CLKS66 0x0000000c /* HCLK is less than or equal to 66 MHz */ +#define MIIC_RESERVED 0x0000800c /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* MCMD - MII command register (94H Write) */ +/*---------------------------------------------------------------------------*/ +#define SCANC 0x00000002 /* SCAN command */ +#define RSTAT 0x00000001 /* MII management read */ + +/*---------------------------------------------------------------------------*/ +/* MADR - MII address register (98H R/W) */ +/*---------------------------------------------------------------------------*/ +#define FIAD_MASK 0x00001f00 /* MII PHY address */ +#define FIAD_SHIFT 8 +#define RGAD_MASK 0x0000001f /* MII register address */ +#define MADR_RESERVED 0x00001f1f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* MWTD - MII write data register (9CH R/W) */ +/*---------------------------------------------------------------------------*/ +#define CTLD_MASK 0x0000ffff /* MII write data */ +#define MWTD_RESERVED 0x0000ffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* MRDD - MII read data register (A0H Read) */ +/*---------------------------------------------------------------------------*/ +#define PRSD_MASK 0x0000ffff /* MII read data */ + +/*---------------------------------------------------------------------------*/ +/* MIND - MII indicator register (A4H Read) */ +/*---------------------------------------------------------------------------*/ +#define NVALID 0x00000004 /* SCAN command start status */ +#define SCANA 0x00000002 /* SCAN command active */ +#define BUSY 0x00000001 /* BUSY */ + +/*---------------------------------------------------------------------------*/ +/* STLC - STL configuration register (C0H R/W) */ +/*---------------------------------------------------------------------------*/ +#define ATZ 0x00000004 /* Statistics counter read reset */ +#define STLC_RESERVED 0x00000004 /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* AFR - Address Filter register (C8H R/W) */ +/*---------------------------------------------------------------------------*/ +#define PRO 0x00000008 /* Promiscuous mode */ +#define PRM 0x00000004 /* Accept Multicast */ +#define AMC 0x00000002 /* Accept Multicast ( qualified ) */ +#define ABC 0x00000001 /* Accept Broadcast */ +#define AFR_RESERVED 0x0000000f /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* CAR1 - CARRY register1 (DCH R/W) */ +/*---------------------------------------------------------------------------*/ +#define C1VT 0x00008000 /* RVBT counter carry bit */ +#define C1UT 0x00004000 /* TUCA counter carry bit */ +#define C1BT 0x00002000 /* TBCA counter carry bit */ +#define C1MT 0x00001000 /* TMCA counter carry bit */ +#define C1PT 0x00000800 /* TPCT counter carry bit */ +#define C1TB 0x00000400 /* TBYT counter carry bit */ +#define C1MX 0x00000200 /* RMAX counter carry bit */ +#define C11K 0x00000100 /* R1K counter carry bit */ +#define C1FE 0x00000080 /* R511 counter carry bit */ +#define C1TF 0x00000040 /* R255 counter carry bit */ +#define C1OT 0x00000020 /* R127 counter carry bit */ +#define C1SF 0x00000010 /* R64 counter carry bit */ +#define C1BR 0x00000008 /* RBCA counter carry bit */ +#define C1MR 0x00000004 /* RBCA counter carry bit */ +#define C1PR 0x00000002 /* RPKT counter carry bit */ +#define C1RB 0x00000001 /* RBYT counter carry bit */ +#define CAR1_RESERVED 0x0000ffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* CAR2 - CARRY register2 (E0H R/W) */ +/*---------------------------------------------------------------------------*/ +#define C2SV 0x80000000 /* Status vector overrun bit */ +#define C2IM 0x00400000 /* TIME counter carry bit */ +#define C2CS 0x00200000 /* TCSE counter carry bit */ +#define C2BC 0x00100000 /* TNCL counter carry bit */ +#define C2XC 0x00080000 /* TXCL counter carry bit */ +#define C2LC 0x00040000 /* TLCL counter carry bit */ +#define C2MC 0x00020000 /* TMCL counter carry bit */ +#define C2SC 0x00010000 /* TSCL counter carry bit */ +#define C2XD 0x00008000 /* TXDF counter carry bit */ +#define C2DF 0x00004000 /* TDFR counter carry bit */ +#define C2XF 0x00002000 /* TXPF counter carry bit */ +#define C2TE 0x00001000 /* TFCS counter carry bit */ +#define C2JB 0x00000800 /* RBJR counter carry bit */ +#define C2FG 0x00000400 /* RFRG counter carry bit */ +#define C2OV 0x00000200 /* ROVR counter carry bit */ +#define C2UN 0x00000100 /* RUND counter carry bit */ +#define C2FC 0x00000080 /* RFCR counter carry bit */ +#define C2CD 0x00000040 /* RCDE counter carry bit */ +#define C2FO 0x00000020 /* RFLR counter carry bit */ +#define C2AL 0x00000010 /* RALN counter carry bit */ +#define C2UO 0x00000008 /* RXUO counter carry bit */ +#define C2PF 0x00000004 /* RXPF counter carry bit */ +#define C2CF 0x00000002 /* RXCF counter carry bit */ +#define C2RE 0x00000001 /* RFCS counter carry bit */ +#define CAR2_RESERVED 0x807fffff /* reserved bit 0 */ + +/*---------------------------------------------------------------------------*/ +/* TXCFG - Transmit Configuration (200H R/W) */ +/*---------------------------------------------------------------------------*/ +#define AFCE 0x00000001 /* Automatic Flow Control Enable */ +#define DTBS1 0x00000000 /* DMA Transmit Burst Size 1 word */ +#define DTBS2 0x00010000 /* DMA Transmit Burst Size 2 word */ +#define DTBS4 0x00020000 /* DMA Transmit Burst Size 4 word */ +#define DTBS8 0x00030000 /* DMA Transmit Burst Size 8 word */ +#define DTBS16 0x00040000 /* DMA Transmit Burst Size 16 word */ +#define DTBS32 0x00050000 /* DMA Transmit Burst Size 32 word */ +#define DTBS64 0x00060000 /* DMA Transmit Burst Size 64 word */ +#define TXE 0x80000000 /* Transmit Enable */ +#define TXCFG_RESERVED 0x80070001 /* reserved bit */ + +/*---------------------------------------------------------------------------*/ +/* TXFC - Transmit FiFo Control (204H R/W) */ +/*---------------------------------------------------------------------------*/ +#define TPTV_MASK 0xffff0000 /* Transmit Pause Timer Value mask */ +#define TPTV 0x10000000 /* default 0x1000 slot time (1slot:512bit) */ +#define TX_DRTH_MASK 0x0000fc00 /* Transmit Fill Threshold Level mask */ +#define TX_DRTH 0x00004000 /* default 010000b (16word, 64byte) */ +#define TX_FLTH_MASK 0x000000fc /* Transmit Drain Threshold Level mask */ +#define TX_FLTH 0x000000c0 /* default 110000b (48word, 192byte) */ +#define TXFC_RESERVED 0xfffffcfc /* reserved bit */ + +/*---------------------------------------------------------------------------*/ +/* TXST - Transmit Status (20CH R) */ +/*---------------------------------------------------------------------------*/ +#define CSE_AB 0x80000000 /* carrier lost (abort) */ +#define TBP 0x40000000 /* back pressure occurred */ +#define TPP 0x20000000 /* packet requested during PAUSE */ +#define TPCF 0x10000000 /* transmit PAUSE control frame */ +#define TCFR 0x08000000 /* transmit control frame */ +#define TUDR_AB 0x04000000 /* underrun (abort) */ +#define TGNT_AB 0x02000000 /* greater than LMAX (abort) */ +#define LCOL_AB 0x01000000 /* late collision (abort) */ +#define ECOL_AB 0x00800000 /* excessive collisions (abort) */ +#define TEDFR_AB 0x00400000 /* excessive defer (abort) */ +#define TDFR 0x00200000 /* single defer */ +#define TBRO 0x00100000 /* broadcast packet */ +#define TMUL 0x00080000 /* multicast packet */ +#define TDONE 0x00040000 /* transmit complete */ +#define TFLOR 0x00020000 /* length field was over 1518 bytes */ +#define TFLER 0x00010000 /* length field didn't match actual length */ +#define TCRCE 0x00008000 /* CRC error */ +#define TCBC_MASK 0x00007800 /* number of collisions */ +#define TBYT_MASK 0x000007ff /* number of the transmitted bytes */ + +/*---------------------------------------------------------------------------*/ +/* RXCFG - Receive Configuration (218H R/W) */ +/*---------------------------------------------------------------------------*/ +#define DRBS1 0x00000000 /* DMA Receive Burst Size 1 word */ +#define DRBS2 0x00010000 /* DMA Receive Burst Size 2 word */ +#define DRBS4 0x00020000 /* DMA Receive Burst Size 4 word */ +#define DRBS8 0x00030000 /* DMA Receive Burst Size 8 word */ +#define DRBS16 0x00040000 /* DMA Receive Burst Size 16 word */ +#define DRBS32 0x00050000 /* DMA Receive Burst Size 32 word */ +#define DRBS64 0x00060000 /* DMA Receive Burst Size 64 word */ +#define RXE 0x80000000 /* Receive Enable */ +#define RXCFG_RESERVED 0x80070000 /* reserved bit */ + +/*---------------------------------------------------------------------------*/ +/* RXFC - Receive FiFo Control (21CH R/W) */ +/*---------------------------------------------------------------------------*/ +#define UWM_MASK 0xfc000000 /* Upper Water Mark mask */ +#define UWM 0xc0000000 /* default 110000b ( 48word, 192byte ) */ +#define LWM_MASK 0x00fc0000 /* Lower Water Mark mask */ +#define LWM 0x00400000 /* default 010000b (16word, 64byte) */ +#define RX_DRTH_MASK 0x000000fc /* Receive Drain Threshold Level */ +#define RX_DRTH16W 0x00000040 /* default 010000b (16word, 64byte) */ +#define RX_DRTH28W 0x00000070 /* default 011100b (28word, 112byte) */ +#define RXFC_RESERVED 0xfcfc00fc /* reserved bit */ + +/*---------------------------------------------------------------------------*/ +/* RXST - Receive Status (224H R) */ +/*---------------------------------------------------------------------------*/ +#define RLENE 0x80000000 /* less than 64 or larger than 1518 */ +#define VLAN 0x40000000 /* match VLTP */ +#define USOP 0x20000000 /* unknown OP code control frame */ +#define RPCF 0x10000000 /* receive PAUSE control frame */ +#define RCFR 0x08000000 /* receive control frame */ +#define DBNB 0x04000000 /* alignment error */ +#define RBRO 0x02000000 /* broadcast packet */ +#define RMUL 0x01000000 /* multicast packet */ +#define RX_OK 0x00800000 /* receive OK */ +#define RLOR 0x00400000 /* length field was over 1518 bytes */ +#define RLER 0x00200000 /* length field didn't match actual length */ +#define RCRCE 0x00100000 /* CRC error */ +#define RCVE 0x00080000 /* RXER was detected (PHY error) */ +#define CEPS 0x00040000 /* false Carrier */ +#define REPS 0x00020000 /* preamble+SFD or +one data nibble */ +#define PAIG 0x00010000 /* carrier length 3036 octets + or Short IPG or invalid preamble or invalid SFD */ +#define RBYT_MASK 0x0000ffff /* received byte count */ + +/*---------------------------------------------------------------------------*/ +/* RXPD - Receive Pool Descriptor (230H R/W) */ +/*---------------------------------------------------------------------------*/ +#define AL 0x70000000 /* Alert Level default value */ +#define AL_MASK 0x70000000 +#define RNOD_MASK 0x0000ffff /* Remaining Number of Descriptor */ +#define RXPD_RESERVED 0x7000ffff /* reserved bit */ + +/*---------------------------------------------------------------------------*/ +/* CCR - Candy Configuration Register (234H R / 240H W) */ +/*---------------------------------------------------------------------------*/ +#define SRT 0x00000001 /* Candy Software Reset */ + +/*---------------------------------------------------------------------------*/ +/* ISR - Interrupt Serves Register (238H R with clear) */ +/* MSR - Mask Serves Register (23cH R/W) */ +/*---------------------------------------------------------------------------*/ +#define BUSERR 0x80000000 /* IBUS Error */ +#define XMTDN 0x00008000 /* Transmit Done */ +#define TBDR 0x00004000 /* Transmit Buffer Descriptor Request at Null*/ +#define TFLE 0x00002000 /* Transmit Frame Length Exceed */ +#define UR 0x00001000 /* Underrun */ +#define TABR 0x00000800 /* Transmit Aborted */ +#define TCF 0x00000400 /* Transmit Control Frame */ +#define RCVDN 0x00000080 /* Receive Done */ +#define RBDRS 0x00000040 /* Receive Buffer Descriptor Request at alert level */ +#define RBDRU 0x00000020 /* Receive Buffer Descriptor Request at zero */ +#define OF 0x00000010 /* Overflow */ +#define LFAL 0x00000008 /* Link Failed */ +#define CARRY 0x00000001 /* statistics counters carry flag */ +#define ISR_RESERVED 0x8000fcf9 /* reserved bit */ + +#define INT_ISR_TX_MASK 0x0000FC00 /* ISR TX bits mask */ +#define INT_ISR_RX_MASK 0x000000F0 /* ISR RX bits mask */ + +/*---------------------------------------------------------------------------*/ +/* MII register offsets */ +/*---------------------------------------------------------------------------*/ +#define MII_CONTROL 0x0000 +#define MII_STATUS 0x0001 +#define MII_PHYID1 0x0002 +#define MII_PHYID2 0x0003 +#define MII_ANAR 0x0004 +#define MII_ANLPAR 0x0005 +#define MII_ANER 0x0006 +#define MII_LBREMR 0x0018 +#define MII_PAR 0x0019 + +/*---------------------------------------------------------------------------*/ +/* MII Control register bit definitions. */ +/*---------------------------------------------------------------------------*/ +#define MIICNTL_FDX 0x0100 +#define MIICNTL_RST_AUTO 0x0200 +#define MIICNTL_ISOLATE 0x0400 +#define MIICNTL_PWRDWN 0x0800 +#define MIICNTL_AUTO 0x1000 +#define MIICNTL_SPEED 0x2000 +#define MIICNTL_LPBK 0x4000 +#define MIICNTL_RESET 0x8000 + +/*---------------------------------------------------------------------------*/ +/* MII Status register bit significance. */ +/*---------------------------------------------------------------------------*/ +#define MIISTAT_EXT 0x0001 +#define MIISTAT_JAB 0x0002 +#define MIISTAT_LINK 0x0004 +#define MIISTAT_CAN_AUTO 0x0008 +#define MIISTAT_FAULT 0x0010 +#define MIISTAT_AUTO_DONE 0x0020 +#define MIISTAT_CAN_T 0x0800 +#define MIISTAT_CAN_T_FDX 0x1000 +#define MIISTAT_CAN_TX 0x2000 +#define MIISTAT_CAN_TX_FDX 0x4000 +#define MIISTAT_CAN_T4 0x8000 + +/*---------------------------------------------------------------------------*/ +/* MII ID2 register bits */ +/*---------------------------------------------------------------------------*/ +#define MII_ID2_OUI_LO 0xFC00 /* low bits of OUI mask */ +#define MII_ID2_MODEL 0x03F0 /* model number */ +#define MII_ID2_REV 0x000F /* model number */ + +/*---------------------------------------------------------------------------*/ +/* MII ANAR and ANLPAR register Bits */ +/*---------------------------------------------------------------------------*/ +#define MII_NWAY_NODE_SEL 0x001f +#define MII_NWAY_CSMA_CD 0x0001 +#define MII_NWAY_T 0x0020 +#define MII_NWAY_T_FDX 0x0040 +#define MII_NWAY_TX 0x0080 +#define MII_NWAY_TX_FDX 0x0100 +#define MII_NWAY_T4 0x0200 +#define MII_NWAY_RF 0x2000 +#define MII_NWAY_ACK 0x4000 +#define MII_NWAY_NP 0x8000 + +/*---------------------------------------------------------------------------*/ +/* MII Auto-Negotiation Expansion Register Bits */ +/*---------------------------------------------------------------------------*/ +#define MII_ANER_PDF 0x0010 +#define MII_ANER_LP_NP_ABLE 0x0008 +#define MII_ANER_NP_ABLE 0x0004 +#define MII_ANER_RX_PAGE 0x0002 +#define MII_ANER_LP_AN_ABLE 0x0001 + +/*---------------------------------------------------------------------------*/ +/* MII PAR register bit definitions. */ +/*---------------------------------------------------------------------------*/ +#define MIIPAR_DUPLEX 0x0080 +#define MIIPAR_SPEED 0x0040 + +/*---------------------------------------------------------------------------*/ +/* Transmit/Receive Status bit definition in Transmit/Receive Descriptor */ +/*---------------------------------------------------------------------------*/ +#define LAST 0x8000 /* Last Descriptor */ +#define DB_LP 0x4000 /* Data Buffer / Link Pointer */ +#define OWN 0x2000 /* Owner 1:used by candy, 0:host set */ +/*---------------------------------------------------------------------------*/ +/* Transmit Status bit definition in Transmit Descriptor */ +/*---------------------------------------------------------------------------*/ +#define DBRE 0x1000 /* Data Buffer Read Error */ +#define TUDR 0x0800 /* Transmit Underrun Error */ +#define CSE 0x0400 /* Carrier Sense Lost Error */ +#define LCOL 0x0200 /* Late Collision */ +#define ECOL 0x0100 /* Excessive Collision */ +#define EDFR 0x0080 /* Excessive Deferral */ +#define TGNT 0x0004 /* Transmit Giant Frame */ +#define HBF 0x0002 /* Heart Beat Fail for ENDEC mode */ +#define TOK 0x0001 /* Transmit OK */ +/*---------------------------------------------------------------------------*/ +/* Receive Status bit definition in Receive Descriptor */ +/*---------------------------------------------------------------------------*/ +#define DBWE 0x1000 /* Data Buffer Write Error */ +#define FTYP_MASK 0x0e00 /* Frame Type */ + #define BCASTF 0x0000 /* Broadcast Frame */ + #define MCASTF 0x0200 /* Multicast Frame */ + #define UCASTF 0x0400 /* Unicast Frame */ + #define VLANF 0x0600 /* VLAN Frame */ + #define PAUSEF 0x0800 /* PAUSE control Frame */ + #define CTLF 0x0a00 /* Control Frame */ +#define OVRN 0x0100 /* Overrun Error */ +#define RUNT 0x0080 /* Runt packet */ +#define FRGE 0x0040 /* Fragment Error */ +#define RCV 0x0020 /* Detects RXER */ +#define FC 0x0010 /* False Carrier */ +#define CRCE 0x0008 /* CRC Error */ +#define FAE 0x0004 /* Frame Alignment Error */ +#define RFLE 0x0002 /* Receive Frame Length Error */ +#define RXOK 0x0001 /* Receive OK */ + +/*---------------------------------------------------------------------------*/ +/* media type selection */ +/*---------------------------------------------------------------------------*/ +enum mediatype { MEDIA_AUTO, MEDIA_10_HALF, MEDIA_10_FULL, MEDIA_100_HALF, MEDIA_100_FULL }; + +/*********************************************************************** + * data structure + *********************************************************************** + */ +typedef volatile struct { + ulong macc1; /* 0x00 MAC configuration register 1 */ + ulong macc2; /* 0x04 MAC configuration register 2 */ + ulong ipgt; /* 0x08 Back-to-Back IPG register */ + ulong ipgr; /* 0x0c Non Back-to-Back IPG register */ + ulong clrt; /* 0x10 Collision register*/ + ulong lmax; /* 0x14 Max packet length register */ + ulong reserved0[2]; + ulong retx; /* 0x20 Retry count register */ + ulong reserved1[12]; + ulong lsa2; /* 0x54 Station Address register 2 */ + ulong lsa1; /* 0x58 Station Address register 1 */ + ulong ptvr; /* 0x5c Pause timer value read register */ + ulong reserved2[1]; + ulong vltp; /* 0x64 VLAN type register */ + ulong reserved3[6]; + ulong miic; /* 0x80 MII configuration register */ + ulong reserved4[4]; + ulong mcmd; /* 0x94 MII command register */ + ulong madr; /* 0x98 MII address register */ + ulong mwtd; /* 0x9c MII write data register */ + ulong mrdd; /* 0xa0 MII read data register */ + ulong mind; /* 0xa4 MII indicator register */ + ulong reserved5[6]; + ulong stlc; /* 0xc0 Statistics counter configuration register*/ + ulong reserved6[1]; + ulong afr; /* 0xc8 Address filter register */ + ulong ht1; /* 0xcc Hash table register 1 */ + ulong ht2; /* 0xd0 Hash table register 2 */ + ulong reserved7[2]; + ulong car1; /* 0xdc Carry register 1 */ + ulong car2; /* 0xe0 Carry register 2 */ + ulong reserved8[19]; + ulong cam1; /* 0x130 Carry mask register 1 */ + ulong cam2; /* 0x134 Carry mask register 2 */ + ulong reserved9[2]; + + /* RX Statistics Counter */ + ulong rbyt; /* 0x140 Receive Byte Counter */ + ulong rpkt; /* 0x144 Receive Packet Counter */ + ulong rfcs; /* 0x148 Receive FCS Error Counter */ + ulong rmca; /* 0x14c Receive Multicast Packet Counter */ + ulong rbca; /* 0x150 Receive Broadcast Packet Counter */ + ulong rxcf; /* 0x154 Receive Control Frame Packet Counter */ + ulong rxpf; /* 0x158 Receive PAUSE Frame Packet Counter */ + ulong rxuo; /* 0x15c Receive Unknown OP code Counter */ + ulong raln; /* 0x160 Receive Alignment Error Counter */ + ulong rflr; /* 0x164 Receive Frame Length Out of Range Counter*/ + ulong rcde; /* 0x168 Receive Code Error Counter */ + ulong rfcr; /* 0x16c Receive False Carrier Counter */ + ulong rund; /* 0x170 Receive Undersize Packet Counter */ + ulong rovr; /* 0x174 Receive Oversize Packet Counter */ + ulong rfrg; /* 0x178 Receive Error Undersize Packet Counter */ + ulong rjbr; /* 0x17c Receive Error Oversize Packet Counter */ + ulong r64; /* 0x180 Receive 64 Byte Frame Counter */ + ulong r127; /* 0x184 Receive 65 to 127 Byte Frame Counter */ + ulong r255; /* 0x188 Receive 128 to 255 Byte Frame Counter */ + ulong r511; /* 0x18c Receive 256 to 511 Byte Frame Counter */ + ulong r1k; /* 0x190 Receive 512 to 1023 Byte Frame Counter */ + ulong rmax; /* 0x194 Receive Over 1023 Byte Frame Counter */ + ulong rvbt; /* 0x198 Receive Valid Byte Counter */ + ulong reserved10[9]; + + /* Tx Statistics Counter */ + ulong tbyt; /* 0x1c0 Transmit Byte Counter */ + ulong tpct; /* 0x1c4 Transmit Packet Counter */ + ulong tfcs; /* 0x1c8 Transmit CRC Error Packet Counter */ + ulong tmca; /* 0x1cc Transmit Multicast Packet Counter */ + ulong tbca; /* 0x1d0 Transmit Broadcast Packet Counter */ + ulong tuca; /* 0x1d4 Transmit Unicast Packet Counter */ + ulong txpf; /* 0x1d8 Transmit PAUSE control Frame Counter */ + ulong tdfr; /* 0x1dc Transmit Single Deferral Packet Counter */ + ulong txdf; /* 0x1e0 Transmit Excessive Deferral Packet Counter */ + ulong tscl; /* 0x1e4 Transmit Single Collision Packet Counter */ + ulong tmcl; /* 0x1e8 Transmit Multiple collision Packet Counter */ + ulong tlcl; /* 0x1ec Transmit Late Collision Packet Counter */ + ulong txcl; /* 0x1f0 Transmit Excessive Collision Packet Counter */ + ulong tncl; /* 0x1f4 Transmit Total Collision Counter */ + ulong tcse; /* 0x1f8 Transmit Carrier Sense Error Counter */ + ulong time; /* 0x1fc Transmit Internal MAC Error Counter */ + +/*---------------------------------------------------------------------------*/ +/* Candy DMA and FiFo Management registers */ +/*---------------------------------------------------------------------------*/ + ulong txcfg; /* 0x200 Transmit Configuration */ + ulong txfc; /* 0x204 Transmit FiFo Control */ + ulong txd; /* 0x208 Transmit Data */ + ulong txst; /* 0x20c Transmit Status */ + ulong txfap; /* 0x210 TX FiFo access pointer */ + ulong txdp; /* 0x214 Transmit Descriptor Pointer */ + ulong rxcfg; /* 0x218 Receive Configuration */ + ulong rxfc; /* 0x21c Receive FiFo Control */ + ulong rxd; /* 0x220 Receive Data */ + ulong rxst; /* 0x224 Receive Status */ + ulong rxfap; /* 0x228 RX FiFo access pointer */ + ulong rxdp; /* 0x22c Receive Descriptor Pointer */ + ulong rxpd; /* 0x230 Receive Pool Descriptor */ + +/*---------------------------------------------------------------------------*/ +/* Candy Interrupt and Configuratioin registers */ +/*---------------------------------------------------------------------------*/ + ulong ccr; /* 0x234 CANDY Configuration Read/Write register */ + ulong isr; /* 0x238 Interrupt Serves register */ + ulong msr; /* 0x23c Mask Serves register */ +} candy_regs; + + +/* + * descriptor structure + */ +struct candy_desc { + ushort size; + ushort status; + ulong pointer; +}; + +/* + * private data structure for candy driver. + */ +struct candy_private { + struct candy_desc *tx_ring; + struct sk_buff *tx_skb[TX_RING_SIZE]; + + struct candy_desc *rx_ring; + struct sk_buff *rx_skb[RX_RING_SIZE]; + int rx_disable; + + uint rx_head; + uint tx_head, tx_stop, tx_tail; + int tx_count; + + struct net_device_stats stats; + + spinlock_t lock; + + /* MII status */ + uint mii_fullduplex:1; + uint mii_speed100:1; + uint mii_linkOK:1; + + /* hardware related */ + ulong pmd_addr; + candy_regs *regs; + + /* house keeping */ + struct net_device * dev; + struct candy_private* next; +}; + +/*********************************************************************** + * global data + *********************************************************************** + */ + +static char version[] __devinitdata = "nec_candy.c : v0.2, jsun@mvista.com"; +static struct candy_private * candy_priv_head=NULL; + + +/*********************************************************************** + * helpers + *********************************************************************** + */ +#define candy_in(x) (*(volatile ulong*)&(x)) +#define candy_out(x, y) (*(volatile ulong*)&(x)) = (y) + +#define candy_set_bits(x, mask) candy_out(x, candy_in(x) | mask) +#define candy_clear_bits(x, mask) candy_out(x, candy_in(x) & ~mask) + +#define candy_set_macc1_bits(x, mask) \ + candy_out(x, (candy_in(x) | mask) & MACC1_RESERVED) +#define candy_clear_macc1_bits(x, mask) \ + candy_out(x, (candy_in(x) & ~mask) & MACC1_RESERVED) + +#define candy_set_macc2_bits(x, mask) \ + candy_out(x, (candy_in(x) | mask) & MACC2_RESERVED) +#define candy_clear_macc2_bits(x, mask) \ + candy_out(x, (candy_in(x) & ~mask) & MACC2_RESERVED) +/* + * FIXME: how do we detect little endian vs. big endian + */ +#define SWAP16(x) (x) + +/*********************************************************************** + * low-level hardware functions + *********************************************************************** + */ + +/* + * MIIwrite: write a single MII register. + * + * INPUTS: pmdaddress = MII pmd address to write + * offset = register offset in PMD + * value = value to write + * RETURNS: None + * + */ +static void MIIwrite(struct net_device *dev, ulong offset, ushort value ) +{ + struct candy_private *pp = (struct candy_private*)dev->priv; + candy_regs *p = pp->regs; + + /* wait for busy */ + while(candy_in(p->mind) & BUSY ); + + /* start the write */ + // mac_reg->mcmd = 0; + candy_out(p->madr, + ( ( pp->pmd_addr << FIAD_SHIFT ) & FIAD_MASK ) | + ( offset & RGAD_MASK ) ); + candy_out(p->mwtd, ( ulong )value ); +} + +/* + * MIIread: read a single MII register. + * + * INPUTS: pmdaddress = MII pmd address to read + * offset = register offset in PMD + * RETURNS: value + * + */ +static ushort MIIread(struct net_device *dev, ulong offset) +{ + struct candy_private *pp = (struct candy_private*)dev->priv; + candy_regs *p = pp->regs; + + /* wait for busy */ + while(candy_in(p->mind) & BUSY ); + + /* mac_reg->mcmd = 0; */ + candy_out(p->madr, + ( ( pp->pmd_addr << FIAD_SHIFT ) & FIAD_MASK ) | + ( offset & RGAD_MASK ) ); + candy_out(p->mcmd, RSTAT); + + /* wait for busy */ + while(candy_in(p->mind) & BUSY ); + + return (ushort) candy_in(p->mrdd); +} + +/* + * keep reading a register untill the interested bit is 0 or 1, or until + * we reache the maximum number of loops + */ +static int MIIpoll(struct net_device *dev, ulong offset, ushort mask, int polarity, ushort *value) +{ + int i; + ushort result; + for (i=0; i< MAX_POLL_TIMES; i++) { + result = MIIread(dev, offset); + if (value) *value = result; + if (polarity) { + if (result & mask) return 1; + } else { + if (~result & mask) return 1; + } + } + return 0; +} + + +/* + * dump all MII registers + */ +static void MIIdump(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private*)dev->priv; + candy_regs *p = pp->regs; + + printk("nec_candy: dump MII registers at 0x%p (pmd addr=%lx)\n", + p, pp->pmd_addr); + printk("\t%-10s = 0x%04x\n", "MII_CONTROL", MIIread(dev, MII_CONTROL)); + printk("\t%-10s = 0x%04x\n", "MII_STATUS", MIIread(dev, MII_STATUS)); + printk("\t%-10s = 0x%04x\n", "MII_PHYID1", MIIread(dev, MII_PHYID1)); + printk("\t%-10s = 0x%04x\n", "MII_PHYID2", MIIread(dev, MII_PHYID2)); + printk("\t%-10s = 0x%04x\n", "MII_ANAR", MIIread(dev, MII_ANAR)); + printk("\t%-10s = 0x%04x\n", "MII_ANLPAR", MIIread(dev, MII_ANLPAR)); + printk("\t%-10s = 0x%04x\n", "MII_ANER", MIIread(dev, MII_ANER)); + printk("\t%-10s = 0x%04x\n", "MII_LBREMR", MIIread(dev, MII_LBREMR)); + printk("\t%-10s = 0x%04x\n", "MII_PAR", MIIread(dev, MII_PAR)); +} + +/* + * SetMacAddr: set MAC address + * + * INPUTS: addr = pointer to MAC address {0xaa,0xbb,0xcc,0xdd,0xee,0xff} + * RETURNS: None + * + */ +static void SetMacAddr(struct net_device *dev, u_char *addr ) +{ + candy_regs *p = ((struct candy_private*)dev->priv)->regs; + + candy_out(p->lsa2, (addr[0]<<8 | addr[1] ) & LSA2_MASK ); + candy_out(p->lsa1, + addr[2]<<24 | addr[3]<<16 | addr[4]<<8 | addr[5] ); +} + +/* + * SetRxMode: set receive mode. + * + * INPUTS: mode = ACCEPT_ALL_PHYS, ACCEPT_ALL_MCASTS, ACCEPT_ALL_BCASTS, + * ACCEPT_QUALIFIED_MCAST, ACCEPT_STATION, MAC_LOOPBACK + * RETURNS: None + * + */ +#if 0 +static void SetRxMode(struct net_device *dev, ushort mode ) +{ + candy_regs *p = ((struct candy_private*)dev->priv)->regs; + ulong value = 0; + + if( mode & ACCEPT_ALL_PHYS ) + value |= PRO; + if( mode & ACCEPT_ALL_MCASTS ) + value |= PRM; + if( mode & ACCEPT_ALL_BCASTS ) + value |= ABC; + if( mode & ACCEPT_QUALIFIED_MCAST ) + value |= AMC; + + /* if the mode is only ACCEPT_STATION, value is 0. */ + candy_out(p->afr, value ); + + if( mode & MAC_LOOPBACK ) { + candy_set_macc1_bits(p->macc1, MACLB | FULLD); + printk(KERN_INFO __FILE__ " : MAC loop back mode.\n" ); + } + + return; +} +#endif + +/* + * AutoNegotiate: (re)start auto-negotiation + * + * INPUTS: pmdaddress = MII pmd address + * RETURNS: None + * + */ +static void AutoNegotiate(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private*)dev->priv; + candy_regs *p = pp->regs; + ushort val1, val2; + + /* (re)start auto-negotiation */ + MIIwrite(dev, MII_CONTROL, 0); + MIIwrite(dev, + MII_CONTROL, + MIICNTL_AUTO | MIICNTL_RST_AUTO | MIICNTL_FDX | MIICNTL_SPEED); + + /* wait for auto-negotiation to start */ + if ( ! MIIpoll(dev, MII_CONTROL, MIICNTL_RST_AUTO, 0, NULL)) { + printk("nec_candy: Autonegotiate doesn't start.\n" ); + } + + /* wait for auto-negotiation to complete */ + if ( ! MIIpoll(dev, MII_STATUS, MIISTAT_AUTO_DONE, 1, NULL)) { + printk("nec_candy: Autonegotiate doesn't completet.\n" ); + } + + /* + * wait link + */ + if ( ! MIIpoll(dev, MII_STATUS, MIISTAT_LINK, 1, NULL)) { + pp->mii_linkOK=0; + printk(KERN_WARNING __FILE__ " : link is down!\n"); + } else { + pp->mii_linkOK=1; + } + + /* + * read capable media type + */ + udelay(500); + val1 = MIIread(dev, MII_ANAR); + val2 = MIIread(dev, MII_ANLPAR); + + /* + * set duplex for MAC + */ + if( ( val1 & MII_NWAY_TX_FDX ) && ( val2 & MII_NWAY_TX_FDX ) ) { + printk(KERN_INFO "nec_candy : AutoSense at 100Mbs, full duplex\n"); + candy_set_macc1_bits(p->macc1, FULLD); + pp->mii_speed100 = 1; + pp->mii_fullduplex = 1; + } + else if( ( val1 & MII_NWAY_TX ) && ( val2 & MII_NWAY_TX ) ) { + printk(KERN_INFO "nec_candy : AutoSense at 100Mbs, half duplex\n"); + candy_clear_macc1_bits(p->macc1, FULLD); + pp->mii_speed100 = 1; + pp->mii_fullduplex = 0; + } + else if( ( val1 & MII_NWAY_T_FDX ) && ( val2 & MII_NWAY_T_FDX ) ) { + printk(KERN_INFO "nec_candy : AutoSense at 10Mbs, full duplex\n"); + candy_set_macc1_bits(p->macc1, FULLD); + pp->mii_speed100 = 0; + pp->mii_fullduplex = 1; + } + else if( ( val1 & MII_NWAY_T ) && ( val2 & MII_NWAY_T ) ) { + printk(KERN_INFO "nec_candy : AutoSense at 10Mbs, half duplex\n"); + candy_clear_macc1_bits(p->macc1, FULLD); + pp->mii_speed100 = 0; + pp->mii_fullduplex = 0; + } + else { + /* set 10Mbps half */ + candy_clear_macc1_bits(p->macc1, FULLD); + printk(KERN_INFO "nec_candy : AutoSense found no valid connection; force 10Mbps, half-duplex.\n"); + pp->mii_speed100 = 0; + pp->mii_fullduplex = 0; + } + + /* set MII control */ + val1 = MIIread(dev, MII_CONTROL); + if (pp->mii_fullduplex) { + val1 |= MIICNTL_FDX; + } else { + val1 &= ~MIICNTL_FDX; + } + if (pp->mii_speed100) { + val1 |= MIICNTL_SPEED; + } else { + val1 &= ~MIICNTL_SPEED; + } + val1 |= MIICNTL_AUTO; + MIIwrite(dev, MII_CONTROL, val1); + + DEBUG(MIIdump(dev)); + + return; +} + + +/* + * SetMediaType: set media type selection. + * + * INPUTS: mediaType = MEDIA_AUTO / MEDIA_10_HALF / MEDIA_10_FULL + * / MEDIA_100_HALF / MEDIA_100_FULL + * RETURNS: None + * + */ +static void SetMediaType(struct net_device *dev, ushort mediaType ) +{ + candy_regs *p = ((struct candy_private*)dev->priv)->regs; + /* ushort value; */ + + /* + * MII software reset + */ + candy_out(p->miic, (candy_in(p->miic) | MISRT ) & MIIC_RESERVED ); + candy_out(p->miic, (candy_in(p->miic) & ~MISRT ) & MIIC_RESERVED ); + + /* + * PHY reset + */ + MIIwrite(dev, MII_CONTROL, MIICNTL_RESET ); + if ( ! MIIpoll(dev, MII_CONTROL, MIICNTL_RESET, 0, NULL)) { + printk(KERN_WARNING "nec_candy : SetMediaType() - PHY reset error.\n" ); + } + + /* + * set media type for PHY + */ + if( mediaType == MEDIA_AUTO ) { + + AutoNegotiate(dev); + + } else { + panic("%s: MediaType (%d) other than MEDIA_AUTO not supported.", + dev->name, mediaType); + } + +#if 0 + } else { + value = 0; + + if( mediaType == MEDIA_10_FULL || mediaType == MEDIA_100_FULL ) { + value |= MIICNTL_FDX; + } + if( mediaType == MEDIA_100_HALF || mediaType == MEDIA_100_FULL ) { + value |= MIICNTL_SPEED; + } + + /* if invalid value or MEDIA_10_HALF, set 10Mbps half */ + MIIwrite(dev, MII_CONTROL, value ); + + /* + * wait link + */ + if ( ! MIIpoll(dev, MII_STATUS, MIISTAT_LINK, 1, &value)) { + printk(KERN_WARNING "nec_candy: link is down!!!\n"); + // phy_link_stat = LINK_DOWN; + } else { + printk(KERN_INFO "nec_candy: link is up!!!\n"); + // phy_link_stat = LINK_UP; + } + + if(value & 0x2 ) { + printk(KERN_INFO "Jabber detect.\n" ); + } + + /* + * set duplex for MAC + */ + if( mediaType == MEDIA_10_FULL || + mediaType == MEDIA_100_FULL ) { + candy_set_macc1_bits(p->macc1, FULLD); + } else { + candy_clear_macc1_bits(p->macc1, FULLD); + } + + } +#endif + + return; +} + +static void +candy_down(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + + DEBUG_VERBOSE(printk("candy_down() invoked.\n")); + + candy_clear_macc1_bits(p->macc1, SRXEN); + + candy_clear_bits(p->txcfg, TXE); + candy_clear_bits(p->rxcfg, RXE); +} + +static void +candy_up(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + + DEBUG_VERBOSE(printk("candy_up() invoked.\n")); + + /* candy must be down right now */ + ASSERT((candy_in(p->txcfg) & TXE) == 0); + ASSERT((candy_in(p->rxcfg) & RXE) == 0); + + // korva_set_bits(KORVA_S_GMR, 0x1); + + /* soft reset rx/tx */ + candy_set_macc2_bits(p->macc2, TFRST); + candy_clear_macc2_bits(p->macc2, TFRST); + candy_set_macc2_bits(p->macc2, RFRST); + candy_clear_macc2_bits(p->macc2, RFRST); + + /* set default receive mode */ + // SetRxMode(dev, ACCEPT_STATION | ACCEPT_ALL_MCASTS | ACCEPT_ALL_BCASTS ); + // SetRxMode(dev, ACCEPT_STATION | ACCEPT_ALL_BCASTS ); + +#ifdef WORKAROUND_E10_PRM_AMC + candy_out(p->afr, ABC ); +#else + candy_out(p->afr, PRM | ABC | AMC); +#endif + + /* enable transmit and receive */ + candy_set_bits(p->txcfg, TXE); + candy_out(p->rxcfg, RXE | DRBS4); + + /* set number of descriptors */ + candy_out(p->rxpd, AL | (RX_RING_SIZE & RNOD_MASK)); + + /* set the receive descriptor pointer */ + candy_out(p->rxdp, virt_to_phys(&pp->rx_ring[pp->rx_head])); + + candy_set_macc1_bits(p->macc1, SRXEN); + + /* turn on interrupts */ + candy_in(p->isr); + candy_out(p->msr, 0xffffffff & ISR_RESERVED); +} + +static unsigned int +hashit(char *addr) +{ + int i; + int j; + unsigned char nibblehigh; + unsigned char nibblelow; + unsigned long da_crc = 0L; + unsigned long hash_p = 0L; + unsigned long hash_byte = 0L; + unsigned long hash_bit = 0L; + unsigned long crc32 = 0xffffffffL; + unsigned long crcpoly2 = 0xedb88320L; + + for (i = 0; i < 6; i++) { + nibblelow = addr[i] & 0x0f; + nibblehigh = addr[i] >> 4; + crc32 ^= nibblelow; + for (j = 0; j < 4; j++) { + if (crc32 & 1) { + crc32 = (crc32 >> 1) ^ crcpoly2; + } else { + crc32 >>= 1; + } + } + crc32 ^= nibblehigh; + for (j = 0; j < 4; j++) { + if (crc32 & 1) { + crc32 = (crc32 >> 1) ^ crcpoly2; + } else { + crc32 >>= 1; + } + } + } + da_crc = crc32 & 0x000001f8L; + for (j = 31; j >= 23; j--) { + hash_p = hash_p * 2 + da_crc % 2; + da_crc = da_crc / 2; + } + hash_byte = (hash_p & 0x00000038) >> 3; + hash_bit = (hash_p & 0x00000007); + return ((hash_byte << 16) | (hash_bit & 0xFFFF)); +} + +static void +candy_set_filter(struct net_device *dev, int on) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + struct dev_mc_list *mclist = dev->mc_list; + unsigned long ht1 = 0; + unsigned long ht2 = 0; + int i; + union { + unsigned long fusion; + unsigned short byte; + unsigned short bit; + } val; + + DEBUG_VERBOSE(printk("candy_set_filter() invoked - %s\n", on?"on":"off")); + + for (i = 0, mclist = dev->mc_list; + mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + val.fusion = hashit(mclist->dmi_addr); + if (val.byte > 3) + ht1 |= (1 << ((val.byte - 4) * 8 + val.bit)); + else + ht2 |= (1 << (val.byte * 8 + val.bit)); + } + + /* lock ints */ + candy_out(p->ht1, ht1); + candy_out(p->ht2, ht2); +} + +/*********************************************************************** + * hardware-independent helper routine + *********************************************************************** + */ +static void +candy_init_rings(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + int i; + + DEBUG_VERBOSE(printk("candy_init_rings() invoked.\n")); + + /* tx rings */ + for (i=0; i< TX_RING_SIZE; i++) { + pp->tx_ring[i].status = 0; + pp->tx_ring[i].size = 0; + pp->tx_ring[i].pointer = 0; + } + /* this may be not necessary, if we reset every txdpr in intr */ + pp->tx_ring[TX_RING_SIZE].status = 0; + pp->tx_ring[TX_RING_SIZE].size = 0x0; + pp->tx_ring[TX_RING_SIZE].pointer = virt_to_phys(pp->tx_ring); + + pp->tx_tail = pp->tx_stop = pp->tx_head = 0; + pp->tx_count = 0; + + /* rx rings */ + for (i=0; i< RX_RING_SIZE; i++) { + pp->rx_ring[i].status = SWAP16(DB_LP); + pp->rx_ring[i].size = RX_BUF_SIZE; + pp->rx_ring[i].pointer = virt_to_phys(pp->rx_skb[i]->data); + } + pp->rx_ring[RX_RING_SIZE].status = 0; /* link back to the beginning */ + pp->rx_ring[RX_RING_SIZE].size = 0xffff; + pp->rx_ring[RX_RING_SIZE].pointer = virt_to_phys(pp->rx_ring); + + pp->rx_head = 0; + pp->rx_disable = 0; +} + +static void +candy_check_intr(ulong isr) +{ + static const char *intr_name[32] = { + "carry flag", + "reserved", + "reserved", + "link failed", + "overflow", + "receive buffer desc request at zero", + "receive buffer desc request at alert level", + "receive done", + + "reserved", + "reserved", + "control frame transmit", + "transmit aborted", + "underrun", + "transmit frame length exceed", + "transmit buffer descriptor request at NULL", + "transmit done", + + "reserved", + "reserved", + "reserved", + "reserved", /* 4 */ + "reserved", + "reserved", + "reserved", + "reserved", + + "reserved", + "reserved", + "reserved", + "reserved", /* 4 */ + "reserved", + "reserved", + "reserved", + "IBUS error"}; + ulong i,j; + + printk("candy.c : intr happend; isr = 0x%08lx\n", isr); + for (i=0, j=1; i<32; j<<=1, i++) { + if (j & isr) printk("\t%s\n", intr_name[i]); + } +} + +static /* inline */ void +reclaim_one_rx_desc(struct net_device *dev, char *buf) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + struct candy_desc *dp = &pp->rx_ring[pp->rx_head]; + + ASSERT(KSEGX(dp) == KSEG1); + + if (buf != NULL) { + dp->pointer = virt_to_phys(buf); + } + dp->status = SWAP16(DB_LP); /* 1 stands for buffer vs link ptr */ + dp->size = RX_BUF_SIZE; + + /* we need to clean up cache here. Otherwise we may have some + * dirty cache while ether controller is feeding fresh pkt data + * to the physical RAM. Data corruption could happen. + */ + dma_cache_wback_inv(KSEG0ADDR(dp->pointer), RX_BUF_SIZE); + + if (++pp->rx_head == RX_RING_SIZE) pp->rx_head = 0; + ASSERT(pp->rx_head < RX_RING_SIZE); + + /* tell hardware we have one descriptor to work with */ + candy_out(p->rxpd, AL | 1); + + /* check rx_disable */ + if (pp->rx_disable) { + pp->rx_disable = 0; + candy_out(p->rxdp, virt_to_phys(dp)); + candy_set_macc1_bits(p->macc1, SRXEN); + DEBUG(printk(KERN_WARNING "%s : re-enable SRXEN\n", dev->name)); + } +} + +static void +handle_rx_error(struct net_device *dev, struct candy_desc* dp, ulong isr) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + + ASSERT(KSEGX(dp) == KSEG1); + +#ifdef SHOW_BUG + printk(KERN_WARNING "%s: rx_ring[%d] error, status =%04x, size=%d, isr = 0x%08lx.\n", + dev->name, pp->rx_head, dp->status, dp->size, isr); +#endif + + /* log some errors that hardware don't log */ + pp->stats.rx_errors ++; + if (isr & OF) pp->stats.rx_fifo_errors ++; + if (isr & RBDRU) pp->stats.rx_missed_errors ++; + if (dp->status & OVRN) pp->stats.rx_over_errors ++; +} + +static void +candy_rx(struct net_device *dev, ulong isr) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + struct candy_desc *dp = &pp->rx_ring[pp->rx_head]; + int pkt_len; + struct sk_buff * newskb; + struct sk_buff * rxskb; + int i; + int skb_size; + + ASSERT(KSEGX(dp) == KSEG1); + + DEBUG_VERBOSE(printk("candy_rx() invoked, rx_stat=0x%08lx\n", + candy_in(p->rxst))); + DEBUG_VERBOSE(printk("\trx_head = %d, {0x%04x, %u, 0x%08lx}\n", + pp->rx_head, + dp->status, + dp->size, + dp->pointer)); + + /* check if we still have any empty receive descriptor */ + if (isr & RBDRU) { + printk(KERN_ERR "%s : no more receive buffers. Stop receiving.", dev->name); + candy_clear_bits(p->macc1, SRXEN); + pp->rx_disable = 1; + } + + /* FIXME : we are fetching packets. How do we know where the + * end is? When OWN bit is 0 (in previous linux driver)? + */ + for(i=0;;i++) { + dp = &pp->rx_ring[pp->rx_head]; + + if ((dp->status & OWN) == 0) { + /* no frame received in this descriptor yet */ + break; + } + + /* handle the error case */ + if ((dp->status & RXOK) == 0) { + handle_rx_error(dev, dp, isr); + reclaim_one_rx_desc(dev, NULL); + continue; + } + + /* oversize? */ + if (dp->size > 1518) { + DEBUG_VERBOSE(printk("candy.c : receive oversize pkt.\n")); + pkt_len = 1518; + } else { + pkt_len = dp->size; + } + + /* we got a good packet */ + + /* STRATEGY: ether packet has 14 bytes. So we will + * suffer from emulated unaligned access if we pass + * the skb straight to upper layer. An alternative is + * to copy the buffer by offset of 2 and then pass it up. + * Then the overhead is copying. + * + * In general, it is more beneficial to copy if we have smaller + * packet. Also, it is more beneficial to copy if we have + * faster machines. + * + * To keep it flexible, we will leave rx_copybreak flexible. + */ + + if (pkt_len < rx_copybreak) { + skb_size = pkt_len + 2; + } else { + skb_size = RX_BUF_SIZE; + } + + /* allocate a new skb */ + newskb = dev_alloc_skb(skb_size); + if (newskb == NULL) { + printk(KERN_ERR + "%s: Memory squeeze, dropping packet.\n", + dev->name); + reclaim_one_rx_desc(dev, NULL); + pp->stats.rx_dropped ++; + continue; + } + + if (pkt_len <= rx_copybreak) { + /* we will copy */ + rxskb = pp->rx_skb[pp->rx_head]; + ASSERT(rxskb->data == phys_to_virt(dp->pointer)); + + newskb->dev = dev; + skb_reserve(newskb, 2); /* align IP pkt to 16-byte */ + eth_copy_and_sum(newskb, rxskb->data, pkt_len, 0); + + rxskb = newskb; + reclaim_one_rx_desc(dev, NULL); + } else { + /* use the new skb to replace the recived one */ + rxskb = pp->rx_skb[pp->rx_head]; + + newskb->dev = dev; + pp->rx_skb[pp->rx_head] = newskb; + reclaim_one_rx_desc(dev, newskb->data); + + } + + skb_put(rxskb, pkt_len); + rxskb->protocol = eth_type_trans(rxskb, dev); + rxskb->ip_summed = CHECKSUM_UNNECESSARY; + netif_rx(rxskb); + + dev->last_rx = jiffies; + } + + /* when we are out here, should rxdp be the same as + * &pp->rx_ring[pp->head]? + */ + // ASSERT(candy_in(p->rxdp) == virt_to_phys(&pp->rx_ring[pp->rx_head])); + DEBUG_VERBOSE(printk("candy_rx: processed %d frames.\n", i)); + +#ifdef SHOW_BUG + if ( (candy_in(p->rxdp) != virt_to_phys(&pp->rx_ring[pp->rx_head])) && + (candy_in(p->rxdp) != virt_to_phys(&pp->rx_ring[RX_RING_SIZE])) ) { + int i; + printk("%s : unexpected out of rx - rx_ring[rx_head] = (%04x, %d)\n", dev->name, dp->status, dp->size); + for (i=0; i< RX_RING_SIZE+1; i++) { + if (p->rxdp == virt_to_phys(&pp->rx_ring[i])) + break; + } + if (i == RX_RING_SIZE+1) panic("cannot find current rx tail"); + printk("\trx_head = %d, rx_tail = %d\n", pp->rx_head, i); + } +#endif + return; +} + +static void +append_one_tx_desc(struct net_device *dev, + ushort status, + ushort size, + ulong pointer, + struct sk_buff *skb) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + struct candy_desc *dp = &pp->tx_ring[pp->tx_tail]; + + dp->status = status; + dp->size = size; + dp->pointer = pointer; + pp->tx_skb[pp->tx_tail] = skb; + + pp->tx_count++; + if (++pp->tx_tail == TX_RING_SIZE) pp->tx_tail = 0; +} + +static void +reclaim_one_tx_desc(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + struct candy_desc *dp = &pp->tx_ring[pp->tx_head]; + + dp->status = 0; + dp->size = 0; + dp->pointer = 0; + + /* free skb */ + if (pp->tx_skb[pp->tx_head]) { + dev_kfree_skb_irq(pp->tx_skb[pp->tx_head]); + pp->tx_skb[pp->tx_head]= NULL; + } + + pp->tx_count --; + if (++pp->tx_head == TX_RING_SIZE) pp->tx_head = 0; +} + +static void +restart_tx_hw(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + struct candy_desc *dp = &pp->tx_ring[pp->tx_tail]; + + /* we need at least one desc for null descriptor */ + ASSERT(pp->tx_count < TX_RING_SIZE); + + /* the desc should already be set NULL */ + ASSERT(dp->status == 0); + ASSERT(dp->size == 0); + ASSERT(dp->pointer == 0); + append_one_tx_desc(dev, 0, 0, 0, NULL); + + /* start */ + ASSERT(pp->tx_head == pp->tx_stop); + pp->tx_stop = pp->tx_tail; + candy_out(p->txdp, virt_to_phys(&pp->tx_ring[pp->tx_head])); +} + +static void +handle_tx_error(struct net_device *dev, struct candy_desc *dp, ulong isr) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + + ASSERT(KSEGX(dp) == KSEG1); + +#ifdef SHOW_BUG + printk(KERN_WARNING "%s : tx_ring[%d] error, status = %04x, isr = 0x%08lx.\n", + dev->name, pp->tx_head, dp->status, isr); +#endif + + pp->stats.tx_errors ++; + pp->stats.tx_aborted_errors ++; + if (dp->status & TUDR) pp->stats.tx_fifo_errors ++; + if (dp->status & HBF) pp->stats.tx_heartbeat_errors ++; +} + +static void +candy_tx_done(struct net_device *dev, ulong isr) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + struct candy_desc *dp; + + DEBUG_VERBOSE(printk("candy_tx_done() invoked.\n")); + DEBUG_VERBOSE(printk("candy_tx_done() to process %d frames from %d.\n", + pp->tx_tail > pp->tx_head? + pp->tx_tail - pp->tx_head : + pp->tx_tail + TX_RING_SIZE - pp->tx_head, + pp->tx_head)); + + spin_lock(&pp->lock); /* sync with xmit() */ + + while (pp->tx_head != pp->tx_stop) { + dp = &pp->tx_ring[pp->tx_head]; + ASSERT(KSEGX(dp) == KSEG1); + + /* deal with null descriptor, the "stop" packet */ + if (dp->status == 0) { + ASSERT(dp->size == 0); + ASSERT(dp->pointer == 0); + reclaim_one_tx_desc(dev); + continue; + } + + /* how about checking OWN bit */ + if ( !(dp->status & OWN)) { + /* this normally should rarely happen */ + DEBUG_VERBOSE(printk(KERN_WARNING "%s: found pkt being sent. Break the loop.\n", dev->name)); + break; + } + + /* handle error */ + if ( ! (dp->status & TOK)) { + handle_tx_error(dev, dp, isr); + } + + /* reclaim the descriptor */ + if (!pp->tx_skb[pp->tx_head]) { + printk(KERN_ERR "candy.c: tx_done but without skb!\n"); + } + reclaim_one_tx_desc(dev); + + /* FIXME: The Japanese version has a tx restart under + * certain error conditions. Don't understand it. + */ + } + + /* check if tx has stopped */ + if ((pp->tx_head == pp->tx_stop) && (pp->tx_stop != pp->tx_tail)) { + restart_tx_hw(dev); + } + + /* check if queue were stopped */ + if (netif_queue_stopped(dev) && (pp->tx_count < TX_RING_SIZE - 2)) { + DEBUG_VERBOSE(printk("candy.c : tx queue becomes free, wake up net queue.\n")); + netif_wake_queue(dev); + } + + spin_unlock(&pp->lock); +} + +static void +candy_update_stats(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + + /* some stats we get from hardware, while the rest we do + * counting by ourselves + */ + pp->stats.rx_packets = candy_in(p->rpkt); + pp->stats.tx_packets = candy_in(p->tpct); + pp->stats.rx_bytes = candy_in(p->rbyt); + pp->stats.tx_bytes = candy_in(p->tbyt); + + /* we count rx_errors, tx_errors, rx_dropped, tx_dropped */ + + pp->stats.multicast = candy_in(p->rmca); + pp->stats.multicast = candy_in(p->tncl); + + pp->stats.rx_length_errors = candy_in(p->rund) + + candy_in(p->rovr) + + candy_in(p->rfrg) + + candy_in(p->rjbr); + + /* we count rx_over_errors */ + + pp->stats.rx_crc_errors = candy_in(p->rfcs); + pp->stats.rx_frame_errors = candy_in(p->raln); + + /* we count rx_fifo_errors and rx_missed_errors */ + + /* we count tx_aborted_errors */ + + pp->stats.tx_carrier_errors = candy_in(p->tcse); + + /* we count tx_fifo_errors, heartbeat_errors */ + + pp->stats.tx_window_errors = candy_in(p->tlcl); + + /* we don't have rx_compressed and tx_compressed */ +} + +/*********************************************************************** + * high-level linux-related functions + *********************************************************************** + */ +static int candy_open(struct net_device *dev); +static int candy_close(struct net_device *dev); +static void +candy_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)dev_instance; + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + ulong isr; + + isr = candy_in(p->isr); + + DEBUG_VERBOSE(printk("candy_interrupt() invoked.\n")); + + DEBUG_VERBOSE(candy_check_intr(isr)); + + if (isr & BUSERR) { + printk(KERN_ERR "%s: bus error ... resetting\n", dev->name); + dev->flags &= ~(IFF_UP | IFF_RUNNING); + candy_close(dev); + candy_open(dev); + return; + + } + + if (isr & INT_ISR_RX_MASK) { + candy_rx(dev, isr); + + } + if (isr & INT_ISR_TX_MASK) { + candy_tx_done(dev, isr); + } + + /* we may need to do something with other intrs too in the future */ +} + +static int +candy_open(struct net_device *dev) +{ + int retval; + + DEBUG_VERBOSE(printk("candy_open() - dev=%s\n", dev->name)); + + MOD_INC_USE_COUNT; + + candy_init_rings(dev); + + candy_up(dev); + + dev->flags |= IFF_RUNNING; + + /* request IRQ */ + retval = request_irq(dev->irq, &candy_interrupt, 0, dev->name, dev); + if (retval) { + MOD_DEC_USE_COUNT; + printk(KERN_ERR "%s: unable to get IRQ %d\n", + dev->name, dev->irq); + return retval; + } + + netif_start_queue(dev); + + return 0; +} + +static int +candy_close(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + + DEBUG_VERBOSE(printk("candy_close() invoked.\n")); + + dev->flags &= ~(IFF_UP | IFF_RUNNING); + + if (netif_device_present(dev)) { + netif_stop_queue(dev); + candy_down(dev); + + /* free tx skb */ + while (pp->tx_tail != pp->tx_head) { + if (pp->tx_skb[pp->tx_head]) { + dev_kfree_skb_irq(pp->tx_skb[pp->tx_head]); + pp->tx_skb[pp->tx_head]= NULL; + } + + pp->tx_count --; + ASSERT(pp->tx_count >= 0); + if (++pp->tx_head == TX_RING_SIZE) pp->tx_head = 0; + } + } + + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static int +candy_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + struct candy_desc *dp = &pp->tx_ring[pp->tx_tail]; + ulong flags; + + ASSERT(KSEGX(dp) == KSEG1); + + DEBUG_VERBOSE(printk("candy_xmit() invoked.\n")); + + /* check packet size */ + if (skb->len > ETH_FRAME_LEN) { + printk(KERN_ERR "%s: packet size too big, %d\n", dev->name, skb->len); + pp->stats.tx_dropped ++; + return 1; + } + + spin_lock_irqsave(&pp->lock, flags); + + /* check to see if tx_ring is full */ + if (pp->tx_count >= TX_RING_SIZE-1) { + printk(KERN_ERR "%s: TX ring full, packet dropped.\n", + dev->name); + pp->stats.tx_dropped ++; + spin_unlock_irqrestore(&pp->lock, flags); + return 1; + } + + /* add the descriptor */ + dma_cache_wback_inv((ulong)(skb->data), skb->len); + append_one_tx_desc(dev, LAST | DB_LP, skb->len, virt_to_phys(skb->data), + skb); + + /* logistics */ + dev->trans_start = jiffies; + + /* do we need to start sending or just append */ + if ((pp->tx_head == pp->tx_stop) && (pp->tx_stop != pp->tx_tail)) { + restart_tx_hw(dev); + } + + if (pp->tx_count >= TX_RING_SIZE -2) { + netif_stop_queue(dev); + } + + spin_unlock_irqrestore(&pp->lock, flags); + + return 0; +} + +static struct net_device_stats * +candy_get_stats(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + unsigned long flags; + + if (netif_device_present(dev)) { + spin_lock_irqsave(&pp->lock, flags); + candy_update_stats(dev); + spin_unlock_irqrestore(&pp->lock, flags); + } + return &pp->stats; +} + +static void +candy_set_rx_mode(struct net_device *dev) +{ + struct candy_private *pp = (struct candy_private *)dev->priv; + candy_regs *p = pp->regs; + ulong val; + + DEBUG_VERBOSE(printk("candy_set_rx_mode() invoked.\n")); + + /* TODO: need to acquire spinlock and stop receiving */ + + val = candy_in(p->afr); + val &= ~PRO; + if (dev->flags & IFF_PROMISC) { + val |= PRO; + } else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + /* disable promiscuous mode, use normal mode */ + candy_set_filter(dev, 0); + } else if (dev->mc_count) { + /* walk the address list, and load the filter */ + candy_set_filter(dev, 1); + } + +#ifdef WORKAROUND_E10_PRM_AMC + candy_out(p->afr, val & ABC); +#else + candy_out(p->afr, val); +#endif +} + +static void +candy_tx_timeout(struct net_device *dev) +{ + unsigned long flags; + struct candy_private *pp = (struct candy_private *)dev->priv; + + printk(KERN_ERR "%s : tx_timeout.\n", dev->name); + + pp->stats.tx_errors ++; + + spin_lock_irqsave(&pp->lock, flags); + candy_down(dev); + candy_up(dev); + + netif_wake_queue(dev); + + spin_unlock_irqrestore(&pp->lock, flags); +} + +static void __init +candy_init_one(uint irq, ulong base_addr, ulong pmd_addr, u_char mac_addr[]) +{ + struct net_device *dev; + candy_regs *p; + struct candy_private *pp; + int i; + + printk(KERN_INFO __FILE__ " : Probe candy chip at irq=%d, base_addr=%08lx, pmd_addr=%08lx, mac_addr=%02x:%02x:%02x:%02x:%02x:%02x\n", + irq, base_addr, pmd_addr, mac_addr[0], mac_addr[1], + mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + + /* hardware is already initialized. We just need do some Linux + * related initialization. + */ + + /* create net_device structure */ + dev = init_etherdev(NULL, sizeof(struct candy_private)); + if (!dev) { + printk(KERN_ERR "ether device alloc failed. aborting\n"); + goto bailout; + } + + printk(KERN_INFO "candy.c : dev=0x%p, priv=0x%p\n", dev, dev->priv); + + /* init some device related data/func ptrs */ + dev->base_addr = base_addr; + dev->irq = irq; + + for (i=0; i<6; i++) + dev->dev_addr[i]=mac_addr[i]; + + dev->open = candy_open; + dev->stop = candy_close; + dev->hard_start_xmit = candy_xmit; + dev->get_stats = candy_get_stats; + dev->set_multicast_list = candy_set_rx_mode; + dev->tx_timeout = candy_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + /* init private data */ + ASSERT(dev->priv != NULL); + pp = (struct candy_private*)dev->priv; + pp->pmd_addr = pmd_addr; + p = pp->regs = (candy_regs*)base_addr; + + /* alloc tx/rx rings and rx buffers */ + pp->tx_ring = kmalloc(sizeof(struct candy_desc)*(TX_RING_SIZE+1), + GFP_ATOMIC); + pp->rx_ring = kmalloc(sizeof(struct candy_desc)*(RX_RING_SIZE+1), + GFP_ATOMIC); + if (!pp->rx_ring || !pp->tx_ring) + goto bailout; + + dma_cache_inv((ulong)pp->tx_ring, + sizeof(struct candy_desc)*(TX_RING_SIZE+1)); + dma_cache_inv((ulong)pp->rx_ring, + sizeof(struct candy_desc)*(RX_RING_SIZE+1)); + + pp->tx_ring = KSEG1ADDR(pp->tx_ring); + pp->rx_ring = KSEG1ADDR(pp->rx_ring); + + /* allocate rx skbs */ + for (i=0; i< RX_RING_SIZE; i++) { + pp->rx_skb[i] = dev_alloc_skb(RX_BUF_SIZE); + if (pp->rx_skb[i] == NULL) { + panic("%s: failed to alloc rx skb!", dev->name); + } + pp->rx_skb[i]->dev = dev; + dma_cache_inv((ulong)pp->rx_skb[i]->data, RX_BUF_SIZE); + } + + /* set up links */ + pp->dev = dev; + pp->next = candy_priv_head; + candy_priv_head = pp; + + /*============================================================== + * hardware initialization + *============================================================== + */ + + /* TODO: maybe we want to make sure the chip is there */ + + /* + * software reset + */ + candy_out(p->ccr, SRT); + candy_in(p->isr); + + /* + * MAC software reset + */ + candy_out(p->macc2, MCRST); + candy_out(p->macc2, 0x0); + + /* + * MII software reset + */ + candy_out(p->miic, MISRT); + candy_out(p->miic, 0); + + /* + * PHY reset + */ + udelay(500); + MIIwrite(dev, MII_CONTROL, MIICNTL_RESET ); + if ( ! MIIpoll(dev, MII_CONTROL, MIICNTL_RESET, 0, NULL)) { + printk(KERN_WARNING "PHY reset error.\n" ); + } + + /* + * initialize MAC + */ +#ifdef WORKAROUND_E13_TXFC + candy_out(p->macc1, RXFC | CRCEN | PADEN ); +#else + candy_out(p->macc1, TXFC | RXFC | CRCEN | PADEN ); +#endif + candy_out(p->macc2, APD ); + candy_out(p->ipgt, IPGT ); + candy_out(p->ipgr, IPGR1 | IPGR2 ); + candy_out(p->clrt, LCOLW | RETRY ); + candy_out(p->lmax, MAXF ); + SetMacAddr(dev, mac_addr); + candy_out(p->vltp, VLTP ); + candy_out(p->miic, CLKS66 ); + + /* + * zero out counters + */ + candy_out(p->rbyt, 0); + candy_out(p->rpkt, 0); + candy_out(p->rfcs, 0); + candy_out(p->rmca, 0); + candy_out(p->rbca, 0); + candy_out(p->rxcf, 0); + candy_out(p->rxpf, 0); + candy_out(p->rxuo, 0); + candy_out(p->raln, 0); + candy_out(p->rflr, 0); + candy_out(p->rcde, 0); + candy_out(p->rfcr, 0); + candy_out(p->rund, 0); + candy_out(p->rovr, 0); + candy_out(p->rfrg, 0); + candy_out(p->rjbr, 0); + candy_out(p->r64 , 0); + candy_out(p->r127, 0); + candy_out(p->r255, 0); + candy_out(p->r511, 0); + candy_out(p->r1k , 0); + candy_out(p->rmax, 0); + candy_out(p->rvbt, 0); + + candy_out(p->tbyt, 0); + candy_out(p->tpct, 0); + candy_out(p->tfcs, 0); + candy_out(p->tmca, 0); + candy_out(p->tbca, 0); + candy_out(p->tuca, 0); + candy_out(p->txpf, 0); + candy_out(p->tdfr, 0); + candy_out(p->txdf, 0); + candy_out(p->tscl, 0); + candy_out(p->tmcl, 0); + candy_out(p->tlcl, 0); + candy_out(p->txcl, 0); + candy_out(p->tncl, 0); + candy_out(p->tcse, 0); + candy_out(p->time, 0); + + /* + * set media type (default: auto-negotiation) + */ + SetMediaType(dev, MEDIA_AUTO); + + /* + * initialize DMA / FIFO + */ +#ifdef WORKAROUND_E7_AFCE + candy_out(p->txcfg, DTBS4); +#else + candy_out(p->txcfg, DTBS4 | AFCE); +#endif + candy_out(p->txcfg, DTBS4 ); + candy_out(p->txfc, TPTV | TX_DRTH | TX_FLTH ); + candy_out(p->rxcfg, DRBS4 ); + candy_out(p->rxfc, UWM | LWM | RX_DRTH16W ); + candy_out(p->rxpd, AL ); + + /* + * disable all interrupts until dev is opened later + */ + candy_out(p->msr, 0); + + return; + +bailout: + if (dev) { + pp = (struct candy_private*)dev->priv; + if (pp) { + kfree(pp->tx_ring); + kfree(pp->rx_ring); + } + kfree(pp); + } + kfree(dev); + return; +} + +/*********************************************************************** + * Module hookup + *********************************************************************** + */ + +/* Board-specific code must provide nec_candy_get_parames() routines. + * It is expected that different boards will provide different parames + */ +extern int nec_candy_get_boot_params(uint * irq, + ulong * base_addr, + ulong * pmd_addr, + u_char * mac_addr); + +static int __init nec_candy_module_init(void) +{ + int i; + uint irq; + ulong base_addr; + ulong pmd_addr; + u_char mac_addr[6]; + + printk(KERN_INFO "%s\n", version); + + for (i=0; i< MAX_NUM_DEVS; i++) { + + if (nec_candy_get_boot_params(&irq, + &base_addr, + &pmd_addr, + mac_addr)) { + break; + } + + if (irq == 0) continue; + + candy_init_one(irq, base_addr, pmd_addr, mac_addr); + } + return 0; +} + +static void __exit nec_candy_module_exit(void) +{ + struct candy_private * pp; + int i; + + while (candy_priv_head != NULL) { + pp = candy_priv_head; + candy_priv_head = pp->next; + + kfree(KSEG0ADDR(pp->rx_ring)); + kfree(KSEG0ADDR(pp->tx_ring)); + + for (i=0; i< RX_RING_SIZE; i++) dev_kfree_skb(pp->rx_skb[i]); + + unregister_netdev(pp->dev); + + kfree(pp->dev); + kfree(pp); + } +} + +module_init(nec_candy_module_init); +module_exit(nec_candy_module_exit); + +#if defined(MODULE) +MODULE_AUTHOR("Jun Sun, jsun@mvista.com or jsun@junsun.net"); +MODULE_DESCRIPTION("Ether driver for NEC Candy controller"); +#endif diff -Nru linux/drivers/net/Config.in.orig linux/drivers/net/Config.in --- linux/drivers/net/Config.in.orig Mon Oct 22 14:36:24 2001 +++ linux/drivers/net/Config.in Tue Oct 30 11:32:36 2001 @@ -215,6 +215,9 @@ if [ "$CONFIG_NEC_OSPREY" = "y" ]; then bool ' Memory-mapped onboard NE2000-compatible ethernet' CONFIG_NE2000 fi + if [ "$CONFIG_NEC_KORVA" = "y" ]; then + bool ' NEC Memory-mapped onboard (Candy) Ethernet' CONFIG_NEC_CANDY + fi fi endmenu diff -Nru linux/drivers/net/Makefile.orig linux/drivers/net/Makefile --- linux/drivers/net/Makefile.orig Mon Oct 22 14:36:25 2001 +++ linux/drivers/net/Makefile Tue Oct 30 11:32:36 2001 @@ -209,6 +209,7 @@ obj-$(CONFIG_MAC89x0) += mac89x0.o obj-$(CONFIG_TUN) += tun.o obj-$(CONFIG_DL2K) += dl2k.o +obj-$(CONFIG_NEC_CANDY) += nec_candy.o ifeq ($(CONFIG_ARCH_ACORN),y) mod-subdirs += ../acorn/net diff -Nru linux/include/asm-mips/korva.h.orig linux/include/asm-mips/korva.h --- linux/include/asm-mips/korva.h.orig Tue Oct 30 11:32:36 2001 +++ linux/include/asm-mips/korva.h Tue Oct 30 11:59:07 2001 @@ -0,0 +1,331 @@ + +/* + * Based on "Preliminary User's Manual: uPD98501 Communication Controller", + * Document No. S14767EJ1V0UM00 (1st edition) + * Date Published April 2000 N CP(K) + */ + +#ifndef _korva_h_ +#define _korva_h_ + +/************************************************************************ + * ATM + ************************************************************************ + */ + +#define KORVA_A_GMR 0xF000 /* R/W General Mode Register */ +#define KORVA_A_GSR 0xF004 /* R General Status Register */ +#define KORVA_A_IMR 0xF008 /* R/W Interrupt Mask Register */ +#define KORVA_A_RQU 0xF00C /* R Receive Queue Underrunning */ +#define KORVA_A_RQA 0xF010 /* R Receive Queue Alert */ +/* ATM F014H - N/A - Reserved for future use */ +#define KORVA_A_VER 0xF018 /* R Version Number */ +/* ATM F01CH - N/A - Reserved for future use */ +#define KORVA_A_CMR 0xF020 /* R/W Command Register */ +/* ATM F024H - N/A - Reserved for future use */ +#define KORVA_A_CER 0xF028 /* R/W Command Extension Register */ +/* ATM F02CH-F04CH - N/A - Reserved for future use */ +#define KORVA_A_MSA0 0xF050 /* R/W Mailbox0 Start Address */ +#define KORVA_A_MSA1 0xF054 /* R/W Mailbox1 Start Address */ +#define KORVA_A_MSA2 0xF058 /* R/W Mailbox2 Start Address */ +#define KORVA_A_MSA3 0xF05C /* R/W Mailbox3 Start Address */ +#define KORVA_A_MBA0 0xF060 /* R/W Mailbox0 Bottom Address */ +#define KORVA_A_MBA1 0xF064 /* R/W Mailbox1 Bottom Address */ +#define KORVA_A_MBA2 0xF068 /* R/W Mailbox2 Bottom Address */ +#define KORVA_A_MBA3 0xF06C /* R/W Mailbox3 Bottom Address */ +#define KORVA_A_MTA0 0xF070 /* R/W Mailbox0 Tail Address */ +#define KORVA_A_MTA1 0xF074 /* R/W Mailbox1 Tail Address */ +#define KORVA_A_MTA2 0xF078 /* R/W Mailbox2 Tail Address */ +#define KORVA_A_MTA3 0xF07C /* R/W Mailbox3 Tail Address */ +#define KORVA_A_MWA0 0xF080 /* R/W Mailbox0 Write Address */ +#define KORVA_A_MWA1 0xF084 /* R/W Mailbox1 Write Address */ +#define KORVA_A_MWA2 0xF088 /* R/W Mailbox2 Write Address */ +#define KORVA_A_MWA3 0xF08C /* R/W Mailbox3 Write Address */ +#define KORVA_A_RCC 0xF090 /* R Valid Receiving Cell Counter */ +#define KORVA_A_TCC 0xF094 /* R Valid Transmitting Cell Counter */ +#define KORVA_A_RUEC 0xF098 /* R Receive Unprovisioned VPI/VCI Error Cell Counter */ +#define KORVA_A_RIDC 0xF09C /* R Receiving Internal Discarded Cell Counter */ +/* ATM F0A0H-F0AFH - N/A - Reserved for future use */ +/* ATM F0B0H-F0B3H 4 A_APR R/W ABR Parameter Register */ +/* ATM F0B4H-F0BCH - N/A - Reserved for future use */ +#define KORVA_A_T1R 0xF0C0 /* R/W T1 Timer Register */ +/* ATM F0C4H - N/A - Reserved for future use */ +#define KORVA_A_TSR 0xF0C8 /* R/W Time Stamp Register */ +/* ATM F200H-F2FFH - N/A - Can not access from VR4120A RISC Core. */ +#define KORVA_A_IBBAR 0xF300 /* R/W IBUS Base Address Register */ +#define KORVA_A_INBAR 0xF304 /* R/W Instruction Base Address Register */ +/* ATM F308H- F31FH - N/A - Reserved for future use */ +#define KORVA_A_UMCMD 0xF320 /* R/W UTOPIA Management Interface Command Register */ +/* ATM F324H- F3FFH - N/A - Reserved for future use */ +/* ATM F400H-F4FFH - N/A - Can not access from VR4120A RISC Core. */ +/* ATM F500H-FFFFH - N/A - Reserved for future use */ + +/************************************************************************ + * Ether + ************************************************************************ + */ + +#define KORVA_En_MACC1 0x00 /* R/W MAC configuration register 1 */ +#define KORVA_En_MACC2 0x04 /* R/W MAC configuration register 2 */ +#define KORVA_En_IPGT 0x08 /* R/W Back-to-Back IPG register */ +#define KORVA_En_IPGR 0x0C /* R/W Non Back-to-Back IPG register */ +#define KORVA_En_CLRT 0x10 /* R/W Collision register */ +#define KORVA_En_LMAX 0x14 /* R/W Max packet length register */ +/* Ether 18H-1CH - N/A - Reserved for future use */ +#define KORVA_En_RETX 0x20 /* R/W Retry count register */ +/* Ether 24H-50H - N/A - Reserved for future use */ +#define KORVA_En_LSA2 0x54 /* R/W Station Address register 2 */ +#define KORVA_En_LSA1 0x58 /* R/W Station Address register 1 */ +#define KORVA_En_PTVR 0x5C /* R Pause timer value read register */ +/* Ether 60H - N/A - Reserved for future use */ +#define KORVA_En_VLTP 0x64 /* R/W VLAN type register */ +#define KORVA_En_MIIC 0x80 /* R/W MII configuration register */ +/* Ether 84H-90H - N/A - Reserved for future use */ +#define KORVA_En_MCMD 0x94 /* W MII command register */ +#define KORVA_En_MADR 0x98 /* R/W MII address register */ +#define KORVA_En_MWTD 0x9C /* R/W MII write data register */ +#define KORVA_En_MRDD 0xA0 /* R MII read data register */ +#define KORVA_En_MIND 0xA4 /* R MII indicator register */ +/* Ether A8H-C4H - N/A - Reserved for future use */ +#define KORVA_En_HT1 0xCC /* R/W Hash table register 1 */ +#define KORVA_En_HT2 0xD0 /* R/W Hash table register 2 */ +/* Ether D4H-D8H - N/A - Reserved for future use */ +#define KORVA_En_CAR1 0xDC /* R/W Carry register 1 */ +#define KORVA_En_CAR2 0xE0 /* R/W Carry register 2 */ +/* Ether E4H-12CH - N/A - Reserved for future use */ +#define KORVA_En_CAM1 0x130 /* R/W Carry mask register 1 */ +#define KORVA_En_CAM2 0x134 /* R/W Carry mask register 2 */ +/* Ether 138H-13CH - N/A - Reserved for future use */ +#define KORVA_En_RBYT 0x140 /* R/W Receive Byte Counter */ +#define KORVA_En_RPKT 0x144 /* R/W Receive Packet Counter */ +#define KORVA_En_RFCS 0x148 /* R/W Receive FCS Error Counter */ +#define KORVA_En_RMCA 0x14C /* R/W Receive Multicast Packet Counter */ +#define KORVA_En_RBCA 0x150 /* R/W Receive Broadcast Packet Counter */ +#define KORVA_En_RXCF 0x154 /* R/W Receive Control Frame Packet Counter */ +#define KORVA_En_RXPF 0x158 /* R/W Receive PAUSE Frame Packet Counter */ +#define KORVA_En_RXUO 0x15C /* R/W Receive Unknown OP code Counter */ +#define KORVA_En_RALN 0x160 /* R/W Receive Alignment Error Counter */ +#define KORVA_En_RFLR 0x164 /* R/W Receive Frame Length Out of Range Counter */ +#define KORVA_En_RCDE 0x168 /* R/W Receive Code Error Counter */ +#define KORVA_En_RFCR 0x16C /* R/W Receive False Carrier Counter */ +#define KORVA_En_RUND 0x170 /* R/W Receive Undersize Packet Counter */ +#define KORVA_En_ROVR 0x174 /* R/W Receive Oversize Packet Counter */ +#define KORVA_En_RFRG 0x178 /* R/W Receive Error Undersize Packet Counter */ +#define KORVA_En_RJBR 0x17C /* R/W Receive Error Oversize Packet Counter */ +#define KORVA_En_R64 0x180 /* R/W Receive 64 Byte Frame Counter */ +#define KORVA_En_R127 0x184 /* R/W Receive 65 to 127 Byte Frame Counter */ +#define KORVA_En_R255 0x188 /* R/W Receive 128 to 255 Byte Frame Counter */ +#define KORVA_En_R511 0x18C /* R/W Receive 256 to 511 Byte Frame Counter */ +#define KORVA_En_R1K 0x190 /* R/W Receive 512 to 1023 Byte Frame Counter */ +#define KORVA_En_RMAX 0x194 /* R/W Receive Over 1023 Byte Frame Counter */ +#define KORVA_En_RVBT 0x198 /* R/W Receive Valid Byte Counter */ +#define KORVA_En_TBYT 0x1C0 /* R/W Transmit Byte Counter */ +#define KORVA_En_TPCT 0x1C4 /* R/W Transmit Packet Counter */ +#define KORVA_En_TFCS 0x1C8 /* R/W Transmit CRC Error Packet Counter */ +#define KORVA_En_TMCA 0x1CC /* R/W Transmit Multicast Packet Counter */ +#define KORVA_En_TBCA 0x1D0 /* R/W Transmit Broadcast Packet Counter */ +#define KORVA_En_TUCA 0x1D4 /* R/W Transmit Unicast Packet Counter */ +#define KORVA_En_TXPF 0x1D8 /* R/W Transmit PAUSE control Frame Counter */ +#define KORVA_En_TDFR 0x1DC /* R/W Transmit Single Deferral Packet Counter */ +#define KORVA_En_TXDF 0x1E0 /* R/W Transmit Excessive Deferral Packet Counter */ +#define KORVA_En_TSCL 0x1E4 /* R/W Transmit Single Collision Packet Counter */ +#define KORVA_En_TMCL 0x1E8 /* R/W Transmit Multiple collision Packet Counter */ +#define KORVA_En_TLCL 0x1EC /* R/W Transmit Late Collision Packet Counter */ +#define KORVA_En_TXCL 0x1F0 /* R/W Transmit Excessive Collision Packet Counter */ +#define KORVA_En_TNCL 0x1F4 /* R/W Transmit Total Collision Counter */ +#define KORVA_En_TCSE 0x1F8 /* R/W Transmit Carrier Sense Error Counter */ +#define KORVA_En_TIME 0x1FC /* R/W Transmit Internal MAC Error Counter */ +#define KORVA_En_TXCR 0x200 /* R/W Transmit Configuration Register */ +#define KORVA_En_TXFCR 0x204 /* R/W Transmit FIFO Control Register */ +#define KORVA_En_TXDTR 0x208 /* W Transmit Data Register */ +#define KORVA_En_TXSR 0x20C /* R Transmit Status Register */ +/* Ether 210H 4 N/A - Reserved for future use */ +#define KORVA_En_TXDPR 0x214 /* R/W Transmit Descriptor Register */ +#define KORVA_En_RXCR 0x218 /* R/W Receive Configuration Register */ +#define KORVA_En_RXFCR 0x21C /* R/W Receive FIFO Control Register */ +#define KORVA_En_RXDTR 0x220 /* R Receive Data Register */ +#define KORVA_En_RXSR 0x224 /* R Receive Status Register */ +/* Ether 228H 4 N/A - Reserved for future use */ +#define KORVA_En_RXDPR 0x22C /* R/W Receive Descriptor Register */ +#define KORVA_En_RXPDR 0x230 /* R/W Receive Pool Descriptor Register */ + +/************************************************************************ + * SYSCNT + ************************************************************************ + */ + +#define KORVA_S_GMR 0x00 /* R/W General Mode Register */ +#define KORVA_S_GSR 0x04 /* R General Status Register */ +#define KORVA_S_ISR 0x08 /* RC Interrupt Status Register */ +#define KORVA_S_IMR 0x0C /* W Interrupt Mask Register */ +#define KORVA_S_NSR 0x10 /* R NMI Status Register */ +#define KORVA_S_NMR 0x14 /* R/W NMI Enable Register */ +#define KORVA_S_VER 0x18 /* R Version Register */ +#define KORVA_S_IOR 0x1C /* R/W IO Port Register */ +/* SYSCNT 20H-2FH - N/A - Reserved */ +#define KORVA_S_WRCR 0x30 /* W Warm Reset Control Register */ +#define KORVA_S_WRSR 0x34 /* R Warm Reset Status Register */ +#define KORVA_S_PWCR 0x38 /* W Power Control Register */ +#define KORVA_S_PWSR 0x3C /* R Power Control Status Register */ +/* SYSCNT 40H-48H - N/A - Reserved */ +#define KORVA_S_ITCNTR 0x4C /* R/W IBUS Timeout Timer Control Register */ +#define KORVA_S_ITSETR 0x50 /* R/W IBUS Timeout Timer Set Register */ +/* SYSCNT 54H-7FH - N/A - Reserved */ +#define KORVA_UARTDLL 0x80 /* R/W UART, Divisor Latch LSB Register [DLAB=1] */ +#define KORVA_UARTRBR 0x80 /* R UART, Receiver Buffer Register [DLAB=0,READ] */ +#define KORVA_UARTTHR 0x80 /* W UART, Transmitter Holding Register [DLAB=0,WRITE] */ +#define KORVA_UARTDLM 0x84 /* R/W UART, Divisor Latch MSB Register [DLAB=1] */ +#define KORVA_UARTIER 0x84 /* R/W UART, Interrupt Enable Register [DLAB=0] */ +#define KORVA_UARTFCR 0x88 /* W UART, FIFO control Register [WRITE] */ +#define KORVA_UARTIIR 0x88 /* R UART, Interrupt ID Register [READ] */ +#define KORVA_UARTLCR 0x8C /* R/W UART, Line control Register */ +#define KORVA_UARTMCR 0x90 /* R/W UART, Modem Control Register */ +#define KORVA_UARTLSR 0x94 /* R/W UART, Line status Register */ +#define KORVA_UARTMSR 0x98 /* R/W UART, Modem Status Register */ +#define KORVA_UARTSCR 0x9C /* R/W UART, Scratch Register */ +#define KORVA_DSUCNTR 0xA0 /* R/W DSU Control Register */ +#define KORVA_DSUSETR 0xA4 /* R/W DSU Dead Time Set Register */ +#define KORVA_DSUCLRR 0xA8 /* W DSU Clear Register */ +#define KORVA_DSUTIMR 0xAC /* R/W DSU Elapsed Time Register */ +#define KORVA_TMMR 0xB0 /* R/W Timer Mode Register */ +#define KORVA_TM0CSR 0xB4 /* R/W Timer CH0 Count Set Register */ +#define KORVA_TM1CSR 0xB8 /* R/W Timer CH1 Count Set Register */ +#define KORVA_TM0CCR 0xBC /* R Timer CH0 Current Count Register */ +#define KORVA_TM1CCR 0xC0 /* R Timer CH1 Current Count Register */ +/* SYSCNT C4H-CFH - N/A - Reserved */ +#define KORVA_ECCR 0xD0 /* W EEPROMä Command Control Register */ +#define KORVA_ERDR 0xD4 /* R EEPROM Read Data Register */ +#define KORVA_MACAR1 0xD8 /* R MAC Address Register 1 */ +#define KORVA_MACAR2 0xDC /* R MAC Address Register 2 */ +#define KORVA_MACAR3 0xE0 /* R MAC Address Register 3 */ +/* SYSCNT E4H-FFH - N/A - Reserved */ +#define KORVA_RMMDR 0x100 /* R/W Boot ROM Mode Register */ +#define KORVA_RMATR 0x104 /* R/W Boot ROM Access Timing Register */ +#define KORVA_SDMDR 0x108 /* R/W SDRAM Mode Register */ +#define KORVA_SDTSR 0x10C /* R/W SDRAM Type Selection Register */ +#define KORVA_SDPTR 0x110 /* R/W SDRAM Precharge Timing Register */ +/* #define KORVA_SDRMR 0x114 R/W SDRAM Precharge Mode Register */ +/* #define KORVA_SDRCR 0x118 R SDRAM Precharge Timer Count Register */ +#define KORVA_SDRMR 0x11C /* R/W SDRAM Refresh Mode Register */ +#define KORVA_SDRCR 0x120 /* R SDRAM Refresh Timer Count Register */ +#define KORVA_MBCR 0x124 /* R/W Memory Bus Control Register */ +/* SYSCNT 128H-FFFH - N/A - Reserved */ + +/************************************************************************ + * USB + ************************************************************************ + */ + +#define KORVA_U_GMR 0x00 /* R/W USB General Mode Register */ +#define KORVA_U_VER 0x04 /* R USB Frame number/Version Register */ +/* USB 0x08 - N/A R/W Reserved for future use */ +/* USB 0x0c - N/A R Reserved for future use */ +#define KORVA_U_GSR1 0x10 /* R USB General Status Register 1 */ +#define KORVA_U_IMR1 0x14 /* R/W USB Interrupt Mask Register 1 */ +#define KORVA_U_GSR2 0x18 /* R USB General Status Resister 2 */ +#define KORVA_U_IMR2 0x1c /* R/W USB Interrupt Mask Register 2 */ +#define KORVA_U_EP0CR 0x20 /* R/W USB EP0 Control Register */ +#define KORVA_U_EP1CR 0x24 /* R/W USB EP1 Control Register */ +#define KORVA_U_EP2CR 0x28 /* R/W USB EP2 Control Register */ +#define KORVA_U_EP3CR 0x2c /* R/W USB EP3 Control Register */ +#define KORVA_U_EP4CR 0x30 /* R/W USB EP4 Control Register */ +#define KORVA_U_EP5CR 0x34 /* R/W USB EP5 Control Register */ +#define KORVA_U_EP6CR 0x38 /* R/W USB EP6 Control Register */ +/* USB 0x3c - N/A - Reserved for future use */ +#define KORVA_U_CMR 0x40 /* R/W USB Command Register */ +#define KORVA_U_CA 0x44 /* R/W USB Command Address Register */ +#define KORVA_U_TEPSR 0x48 /* R/W USB Tx EndPoint Status Register */ +/* USB 0x4c - N/A - Reserved for future use */ +#define KORVA_U_RP0IR 0x50 /* R/W USB Rx Pool0 Information Register */ +#define KORVA_U_RP0AR 0x54 /* R USB Rx Pool0 Address Register */ +#define KORVA_U_RP1IR 0x58 /* R/W USB Rx Pool1 Information Register */ +#define KORVA_U_RP1AR 0x5c /* R USB Rx Pool1 Address Register */ +#define KORVA_U_RP2IR 0x60 /* R/W USB Rx Pool2 Information Register */ +#define KORVA_U_RP2AR 0x64 /* R USB Rx Pool2 Address Register */ +/* USB 0x68 - N/A - Reserved for future use */ +/* USB 0x6c - N/A - Reserved for future use */ +#define KORVA_U_TMSA 0x70 /* R/W USB Tx MailBox Start Address Register */ +#define KORVA_U_TMBA 0x74 /* R/W USB Tx MailBox Bottom Address Register */ +#define KORVA_U_TMRA 0x78 /* R/W USB Tx MailBox Read Address Register */ +#define KORVA_U_TMWA 0x7c /* R USB Tx MailBox Write Address Register */ +#define KORVA_U_RMSA 0x80 /* R/W USB Rx MailBox Start Address Register */ +#define KORVA_U_RMBA 0x84 /* R/W USB Rx MailBox Bottom Address Register */ +#define KORVA_U_RMRA 0x88 /* R/W USB Rx MailBox Read Address Register */ +#define KORVA_U_RMWA 0x8c /* R USB Rx MailBox Write Address Register */ +/* USB 0x90-0xff - N/A - Reserved for future use */ +#define KORVA_U_TDN 0x100 /* R USB EP0 Tx Data Phase NAK Counter */ +#define KORVA_U_TDS 0x104 /* R USB EP0 Tx Data Phase STALL Counter */ +/* USB 0x108 - N/A - Reserved for future use */ +/* USB 0x10c - N/A - Reserved for future use */ +#define KORVA_U_THT 0x110 /* R USB EP0 Tx Handshake Phase Timeout Counter */ +/* USB 0x114 - N/A - Reserved for future use */ +/* USB 0x118 - N/A - Reserved for future use */ +/* USB 0x11c - N/A - Reserved for future use */ +#define KORVA_U_RDT 0x120 /* R USB EP0 Rx Data Phase Timeout Counter */ +#define KORVA_U_RDCER 0x124 /* R USB EP0 Rx Data Phase CRC Error Counter */ +#define KORVA_U_RDBER 0x128 /* R USB EP0 Rx Data Phase Bitstuff Error Counter */ +#define KORVA_U_RDTER 0x12c /* R USB EP0 Rx Data Phase Data Toggle Error Counter */ +#define KORVA_U_RHT 0x130 /* R USB EP0 Rx Handshake Phase Timeout Counter */ +#define KORVA_U_RHN 0x134 /* R USB EP0 Rx Handshake Phase NAK Counter */ +#define KORVA_U_RHS 0x138 /* R USB EP0 Rx Handshake Phase STALL Counter */ +/* USB 0x13c - N/A R Reserved for future use */ +/* USB 0x140-15f - N/A - Reserved for future use */ +#define KORVA_U_DT2 0x160 /* R USB EP2 Data Phase Timeout Counter */ +#define KORVA_U_DCER2 0x164 /* R USB EP2 Data Phase CRC Error Counter */ +#define KORVA_U_DBER2 0x168 /* R USB EP2 Data Phase Bitstuff Error Counter */ +/* USB 0x16c - N/A - Reserved for future use */ +/* USB 0x170-17f - N/A - Reserved for future use */ +#define KORVA_U_DN3 0x180 /* R USB EP3 Data Phase NAK Counter */ +#define KORVA_U_DS3 0x184 /* R USB EP3 Data Phase STALL Counter */ +/* USB 0x188 - N/A - Reserved for future use */ +/* USB 0x18c - N/A - Reserved for future use */ +#define KORVA_U_HT3 0x190 /* R USB EP3 Handshake Phase Timeout Counter */ +/* USB 0x194 - N/A - Reserved for future use */ +/* USB 0x198 - N/A - Reserved for future use */ +/* USB 0x19c - N/A - Reserved for future use */ +#define KORVA_U_DT4 0x1a0 /* R USB EP4 Data Phase Timeout Counter */ +#define KORVA_U_DCER4 0x1a4 /* R USB EP4 Data Phase CRC Error Counter */ +#define KORVA_U_DBER4 0x1a8 /* R USB EP4 Data Phase Bitstuff Error Counter */ +#define KORVA_U_DTER4 0x1ac /* R USB EP4 Data Phase Data Toggle Error Counter */ +#define KORVA_U_HT4 0x1b0 /* R USB EP4 Handshake Phase Timeout Counter */ +#define KORVA_U_HN4 0x1b4 /* R USB EP4 Handshake Phase NAK Counter */ +#define KORVA_U_HS4 0x1b8 /* R USB EP4 Handshake Phase STALL Counter */ +/* USB 0x1bc - N/A - Reserved for future use */ +#define KORVA_U_DN5 0x1c0 /* R USB EP5 Data Phase NAK Counter */ +#define KORVA_U_DS5 0x1c4 /* R USB EP5 Data Phase STALL Counter */ +/* USB 0x1c8 - N/A - Reserved for future use */ +/* USB 0x1cc - N/A - Reserved for future use */ +#define KORVA_U_HT5 0x1d0 /* R USB EP5 Handshake Phase Timeout Counter */ +/* USB 0x1d4 - N/A - Reserved for future use */ +/* USB 0x1d8 - N/A - Reserved for future use */ +/* USB 0x1dc - N/A - Reserved for future use */ +#define KORVA_U_DT6 0x1e0 /* R USB EP6 Data Phase Timeout Counter */ +#define KORVA_U_DCER6 0x1e4 /* R USB EP6 Data Phase CRC Error Counter */ +#define KORVA_U_DBER6 0x1e8 /* R USB EP6 Data Phase Bitstuff Error Counter */ +#define KORVA_U_DTER6 0x1ec /* R USB EP6 Data Phase Data Toggle Error Counter */ +#define KORVA_U_HT6 0x1f0 /* R USB EP6 Handshake Phase Timeout Counter */ +#define KORVA_U_HN6 0x1f4 /* R USB EP6 Handshake Phase NAK Counter */ +#define KORVA_U_HS6 0x1f8 /* R USB EP6 Handshake Phase STALL Counter */ +/* USB 0x1fc - N/A - Reserved for future use */ + + +/************************************************************************ + * additional macro + ************************************************************************ + */ +#define KORVA_BASE 0x10000000 +#define KORVA_BASE_VIRT (0xa0000000 + KORVA_BASE) + +#ifndef _LANGUAGE_ASSEMBLY + +#include + +#define korva_in32(x) *(volatile u32*)(KORVA_BASE_VIRT + (x)) +#define korva_out32(x, y) *(volatile u32*)(KORVA_BASE_VIRT + (x)) = (y) + +#define korva_set_bits(x, mask) korva_out32(x, korva_in32(x) | mask) +#define korva_clear_bits(x, mask) korva_out32(x, korva_in32(x) & ~mask) + +#endif /* _LANGUAGE_ASSEMBLY */ + +#endif /* _korva_h_ */