diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/boot/compressed/head.S linux-sl3516/arch/arm/boot/compressed/head.S --- linux-2.6.15-armeb/arch/arm/boot/compressed/head.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/boot/compressed/head.S 2006-08-02 11:31:28.000000000 +0930 @@ -53,6 +53,17 @@ mov \rb, #0x50000000 add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT .endm +/***************************************************** + * for Storlink SoC + *****************************************************/ +#elif defined(CONFIG_ARCH_SL2312) + .macro loadsp, rb + mov \rb, #0x16000000 + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm +/****************************************************/ #else .macro loadsp, rb addruart \rb @@ -110,7 +121,28 @@ .rept 8 mov r0, r0 .endr - +/***************************************************************************** + * for Storlink Soc -- on chip UART + *****************************************************************************/ +#ifndef CONFIG_SERIAL_IT8712 // Jason test +@ mov r3, #0x22000000 + mov r3, #0x42000000 + mov r11, #0x80 + strb r11, [r3, #0xc] + mov r11, #0x0 + strb r11, [r3, #0x4] +#ifndef CONFIG_SL3516_ASIC + mov r11, #0x9C /*0x9c->19200 0x4E->38400 0x34->57600 */ +#else + mov r11, #0x9C /* 0x61 for 30MHz on GeminiA chip*/ +#endif + strb r11, [r3, #0x0] + mov r11, #0x03 + strb r11, [r3, #0xc] + mov r11, #0xFB + strb r11, [r3, #0x18] +#endif +/*****************************************************************************/ b 1f .word 0x016f2818 @ Magic numbers to help the loader .word start @ absolute load/run zImage address @@ -370,6 +402,39 @@ mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs mov pc, r12 +/***************************************************************************** + * for Storlink Soc -- CPU cache + *****************************************************************************/ +__fa526_cache_on: + mov r12, lr + bl __setup_mmu + mov r0, #0 + mcr p15, 0, r0, c7, c6, 0 @ Invalidate D cache + mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer + mov r0, #-1 + mcr p15, 0, r0, c3, c0, 0 @ load domain access register + mrc p15, 0, r0, c1, c0, 0 + mov r0, r0 + mov r0, r0 +#ifndef CONFIG_CPU_DCACHE_DISABLE + orr r0, r0, #0x0004 @ .... .... .... .1.. +#endif +#ifndef CONFIG_CPU_ICACHE_DISABLE + orr r0, r0, #0x1000 @ ...1 .... .... .... +#endif + +#ifndef DEBUG + orr r0, r0, #0x0039 @ Write buffer, mmu +#endif + mcr p15, 0, r0, c1, c0 + mov r0, r0 + mov r0, r0 + mov pc, r12 +/********************************************************************************/ + __arm6_cache_on: mov r12, lr bl __setup_mmu @@ -514,6 +579,16 @@ @ These match on the architecture ID +/***************************************************************************** + * for Storlink Soc -- CPU architecture ID + *****************************************************************************/ + .word 0x66015261 @ FA526 + .word 0xff01fff1 + b __fa526_cache_on + b __fa526_cache_off + b __fa526_cache_flush +/*****************************************************************************/ + .word 0x00020000 @ ARMv4T .word 0x000f0000 b __armv4_cache_on @@ -567,6 +642,22 @@ mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 mov pc, lr +/***************************************************************************** + * for Storlink Soc -- CPU cache + *****************************************************************************/ +__fa526_cache_off: + mrc p15, 0, r0, c1, c0 + bic r0, r0, #0x000d + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate whole cache v4 + mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB v4 + mov pc, lr +/*****************************************************************************/ + __arm6_cache_off: mov r0, #0x00000030 @ ARM6 control reg. b __armv3_cache_off @@ -633,6 +724,17 @@ mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr +/***************************************************************************** + * for Storlink Soc -- CPU cache + *****************************************************************************/ +__fa526_cache_flush: + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr +/*****************************************************************************/ + __armv3_cache_flush: mov r1, #0 mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/boot/compressed/head-sl2312.S linux-sl3516/arch/arm/boot/compressed/head-sl2312.S --- linux-2.6.15-armeb/arch/arm/boot/compressed/head-sl2312.S 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/boot/compressed/head-sl2312.S 2006-04-03 18:10:31.000000000 +0930 @@ -0,0 +1,5 @@ +#include +#include + + .section ".start", "ax" + mov r7, #MACH_TYPE_SL2312 diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/boot/compressed/it8712.h linux-sl3516/arch/arm/boot/compressed/it8712.h --- linux-2.6.15-armeb/arch/arm/boot/compressed/it8712.h 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/boot/compressed/it8712.h 2006-04-03 18:10:31.000000000 +0930 @@ -0,0 +1,25 @@ + +#ifndef __IT8712_H__ +#define __IT8712_H__ + +#include "asm/arch/sl2312.h" + +#define IT8712_IO_BASE SL2312_LPC_IO_BASE +//#define IT8712_IO_BASE 0x27000000 +// Device LDN +#define LDN_SERIAL1 0x01 +#define LDN_SERIAL2 0x02 +#define LDN_PARALLEL 0x03 +#define LDN_KEYBOARD 0x05 +#define LDN_MOUSE 0x06 +#define LDN_GPIO 0x07 + +#define IT8712_UART1_PORT 0x3F8 +#define IT8712_UART2_PORT 0x2F8 + +#define IT8712_GPIO_BASE 0x800 // 0x800-0x804 for GPIO set1-set5 + +void LPCSetConfig(char LdnNumber, char Index, char data); +char LPCGetConfig(char LdnNumber, char Index); + +#endif diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/boot/compressed/Makefile linux-sl3516/arch/arm/boot/compressed/Makefile --- linux-2.6.15-armeb/arch/arm/boot/compressed/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/boot/compressed/Makefile 2006-04-03 18:10:31.000000000 +0930 @@ -25,6 +25,10 @@ OBJS += head-epxa10db.o endif +ifeq ($(CONFIG_ARCH_SL2312),y) +OBJS += head-sl2312.o +endif + ifeq ($(CONFIG_ARCH_L7200),y) OBJS += head-l7200.o endif diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/boot/compressed/misc.c linux-sl3516/arch/arm/boot/compressed/misc.c --- linux-2.6.15-armeb/arch/arm/boot/compressed/misc.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/boot/compressed/misc.c 2006-04-03 18:10:31.000000000 +0930 @@ -21,14 +21,15 @@ #include #include +#include "it8712.h" #ifdef STANDALONE_DEBUG #define putstr printf #endif #ifdef CONFIG_DEBUG_ICEDCC -#define putstr icedcc_putstr -#define putc icedcc_putc +//#define putstr icedcc_putstr +//#define putc icedcc_putc extern void icedcc_putc(int ch); @@ -44,6 +45,30 @@ #define __ptr_t void * +#ifdef CONFIG_SERIAL_IT8712 +unsigned int it8712_uart_base; +#define UART_RX 0 +#define UART_TX 0 +#define UART_DLL 0 +#define UART_TRG 0 +#define UART_DLM 1 +#define UART_IER 1 +#define UART_FCTR 1 +#define UART_IIR 2 +#define UART_FCR 2 +#define UART_EFR 2 +#define UART_LCR 3 +#define UART_MCR 4 +#define UART_LSR 5 +#define UART_MSR 6 +#define UART_SCR 7 +#define UART_EMSR 7 +void LPCEnterMBPnP(void); +void LPCExitMBPnP(void); +int SearchIT8712(void); +int InitLPCInterface(void); +#endif + /* * Optimised C version of memzero for the ARM. */ @@ -304,6 +329,9 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, int arch_id) { +#ifdef CONFIG_SERIAL_IT8712 + unsigned char *addr; +#endif output_data = (uch *)output_start; /* Points to kernel start */ free_mem_ptr = free_mem_ptr_p; free_mem_ptr_end = free_mem_ptr_end_p; @@ -311,6 +339,33 @@ arch_decomp_setup(); +#ifdef CONFIG_SERIAL_IT8712 + + InitLPCInterface(); + LPCSetConfig(0, 0x02, 0x01); + LPCSetConfig(LDN_SERIAL1, 0x30, 0x1); + LPCSetConfig(LDN_SERIAL1, 0x23, 0x0); + it8712_uart_base = IT8712_IO_BASE; + it8712_uart_base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61)); + + do { + addr = (unsigned char *)(it8712_uart_base + UART_LCR) ; + *addr = 0x80; + // Set Baud Rate + addr = (unsigned char *)(it8712_uart_base+UART_DLL); + *addr = 0x06 ; + addr = (unsigned char *)(it8712_uart_base+UART_DLM); + *addr = 0x00 ; + + addr = (unsigned char *)(it8712_uart_base+UART_LCR); // LCR + *addr = 0x07 ; + addr = (unsigned char *)(it8712_uart_base+UART_MCR); // MCR + *addr = 0x08 ; + addr = (unsigned char *)(it8712_uart_base+UART_FCR); // FCR + *addr = 0x01 ; + } while(0); +#endif + makecrc(); putstr("Uncompressing Linux..."); gunzip(); @@ -332,4 +387,119 @@ return 0; } #endif + +#ifdef CONFIG_SERIAL_IT8712 + +#define LPC_KEY_ADDR (unsigned char *)(SL2312_LPC_IO_BASE + 0x2e) +#define LPC_DATA_ADDR (unsigned char *)(SL2312_LPC_IO_BASE + 0x2f) +#define LPC_BUS_CTRL *( unsigned char*) (SL2312_LPC_HOST_BASE + 0) +#define LPC_BUS_STATUS *( unsigned char*) (SL2312_LPC_HOST_BASE + 2) +#define LPC_SERIAL_IRQ_CTRL *( unsigned char*) (SL2312_LPC_HOST_BASE + 4) + +char LPCGetConfig(char LdnNumber, char Index) +{ + char rtn; + unsigned char *addr ; + + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + + addr = LPC_KEY_ADDR; + *addr = 0x07 ; + + addr = LPC_DATA_ADDR; + *addr = LdnNumber ; + + addr = LPC_KEY_ADDR; + *addr = Index ; + + addr = LPC_DATA_ADDR ; + rtn = *addr ; + + LPCExitMBPnP(); + return rtn; + +} + +void LPCSetConfig(char LdnNumber, char Index, char data) +{ + unsigned char *addr; + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + addr = LPC_KEY_ADDR; + *addr = 0x07; + addr = LPC_DATA_ADDR; + *addr = LdnNumber; + addr = LPC_KEY_ADDR; + *addr = Index; + addr = LPC_DATA_ADDR; + *addr = data; + + LPCExitMBPnP(); +} + +//unsigned char key[4] ; +void LPCEnterMBPnP(void) +{ + unsigned char *addr; + addr = LPC_KEY_ADDR; + unsigned char key[4] = {0x87, 0x01, 0x55, 0x55}; + + do { + *addr = key[0]; + *addr = key[1]; + *addr = key[2]; + *addr = key[3]; + }while(0); +} + +void LPCExitMBPnP(void) +{ + unsigned char *addr; + addr = LPC_KEY_ADDR; + *addr = 0x02 ; + + addr = LPC_DATA_ADDR; + *addr = 0x02 ; +} + +int InitLPCInterface(void) +{ + int i; + LPC_BUS_CTRL = 0xc0; + LPC_SERIAL_IRQ_CTRL = 0xc0; + + for(i=0;i<0x2000;i++) ; + + LPC_SERIAL_IRQ_CTRL = 0x80; + if (!SearchIT8712()) ; +// while(1); + return 0; +} + +int SearchIT8712(void) +{ + unsigned char Id1, Id2; + unsigned short Id; + unsigned char *addr; + + LPCEnterMBPnP(); + addr = LPC_KEY_ADDR; + *addr = 0x20 ; + addr = LPC_DATA_ADDR; + Id1 = *addr ; + + addr = LPC_KEY_ADDR; + *addr = 0x21 ; + addr = LPC_DATA_ADDR; + Id2 = *addr ; + + Id = (Id1 << 8) | Id2; + LPCExitMBPnP(); + + if (Id == 0x8712) + return 1; + else + return 0; +} + +#endif diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/Kconfig linux-sl3516/arch/arm/Kconfig --- linux-2.6.15-armeb/arch/arm/Kconfig 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/Kconfig 2006-04-03 18:10:31.000000000 +0930 @@ -110,6 +110,9 @@ If you would like to build your kernel to run on one of these boards then you must say 'Y' here. Otherwise say 'N' +config ARCH_SL2312 + bool "SL2312" + config ARCH_FOOTBRIDGE bool "FootBridge" select FOOTBRIDGE @@ -223,6 +226,8 @@ source "arch/arm/mach-footbridge/Kconfig" +source "arch/arm/mach-sl2312/Kconfig" + source "arch/arm/mach-integrator/Kconfig" source "arch/arm/mach-iop3xx/Kconfig" @@ -310,6 +315,16 @@ information about which PCI hardware does work under Linux and which doesn't. +config SL2312_LPC + bool "LPC Host Support" + depends on ARCH_SL2312 + help + +config SL2312_LPC_IT8712 + bool "IT8712 Support" + depends on ARCH_SL2312 && SL2312_LPC + help + # Select the host bridge type config PCI_HOST_VIA82C505 bool @@ -694,6 +709,10 @@ source "drivers/mtd/Kconfig" endif +if ARCH_SL2312 +source "drivers/telephony/Kconfig" +endif + source "drivers/parport/Kconfig" source "drivers/pnp/Kconfig" @@ -704,7 +723,7 @@ if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ - || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE + || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE || ARCH_SL2312 source "drivers/ide/Kconfig" endif diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/kernel/head.S linux-sl3516/arch/arm/kernel/head.S --- linux-2.6.15-armeb/arch/arm/kernel/head.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/kernel/head.S 2006-09-05 13:16:24.000000000 +0930 @@ -295,8 +295,11 @@ add r3, r3, #1 << 20 str r3, [r0, #4]! @ KERNEL + 2MB add r3, r3, #1 << 20 - str r3, [r0, #4] @ KERNEL + 3MB - + str r3, [r0, #4]! @ KERNEL + 3MB +#ifdef CONFIG_ARCH_SL2312 + add r3, r3, #1 << 20 + str r3, [r0, #4] @ for enormous kernel (Exceed 0x3FC000 KB) +#endif /* * Then map first 1MB of ram in case it contains our boot params. */ diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/kernel/irq.c linux-sl3516/arch/arm/kernel/irq.c --- linux-2.6.15-armeb/arch/arm/kernel/irq.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/kernel/irq.c 2006-04-03 18:10:31.000000000 +0930 @@ -60,6 +60,8 @@ struct irqdesc irq_desc[NR_IRQS]; void (*init_arch_irq)(void) __initdata = NULL; +extern int fixup_irq(unsigned int irq); + /* * No architecture-specific irq_finish function defined in arm/arch/irqs.h. */ @@ -535,8 +537,11 @@ */ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { - struct irqdesc *desc = irq_desc + irq; +// struct irqdesc *desc = irq_desc + irq; + struct irqdesc *desc ; + irq = fixup_irq(irq); + desc = irq_desc + irq; /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/kernel/process.c linux-sl3516/arch/arm/kernel/process.c --- linux-2.6.15-armeb/arch/arm/kernel/process.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/kernel/process.c 2007-04-25 15:49:47.000000000 +0930 @@ -77,7 +77,7 @@ void (*pm_idle)(void); EXPORT_SYMBOL(pm_idle); -void (*pm_power_off)(void); +//void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); /* @@ -140,15 +140,51 @@ __setup("reboot=", reboot_setup); +// by Freecom +extern void set_gemini_gpio_pin_status(unsigned char pin, unsigned char high); +extern void set_gemini_gpio_fan_status(unsigned char pin, unsigned char value); + void machine_halt(void) { + unsigned int reg_v; + + printk("machine halt\n"); + + // by Freecom + set_gemini_gpio_pin_status(24+32+32, 0); // USB1 LED off + set_gemini_gpio_pin_status(25+32+32, 0); // USB2 LED off + set_gemini_gpio_pin_status(26+32+32, 0); // SYNC LED off + set_gemini_gpio_pin_status(27+32+32, 0); // POWER LED off + set_gemini_gpio_pin_status(28+32+32, 0); // ACCESS LED off + set_gemini_gpio_fan_status(0, 0); // fan off + + reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04); + reg_v &= ~0x00000002; + reg_v |= 0x1; + mdelay(5); + // Power off + __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04); + } void machine_power_off(void) { - if (pm_power_off) + unsigned int reg_v; + +// if (pm_power_off) + if (&pm_power_off!=NULL) pm_power_off(); + + printk("arch_power_off\n"); + + reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04); + reg_v &= ~0x00000002; + reg_v |= 0x1; + mdelay(5); + // Power off + __raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04); + } diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/kernel/setup.c linux-sl3516/arch/arm/kernel/setup.c --- linux-2.6.15-armeb/arch/arm/kernel/setup.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/kernel/setup.c 2007-03-07 18:30:39.000000000 +1030 @@ -834,7 +834,7 @@ { int i; - seq_printf(m, "Processor\t: %s rev %d (%s)\n", + seq_printf(m, "Processor\t\t: %s rev %d (%s)\n", cpu_name, (int)processor_id & 15, elf_platform); #if defined(CONFIG_SMP) @@ -844,26 +844,26 @@ * online processors, looking for lines beginning with * "processor". Give glibc what it expects. */ - seq_printf(m, "processor\t: %d\n", i); - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", + seq_printf(m, "processor\t\t: %d\n", i); + seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n\n", per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); } #else /* CONFIG_SMP */ - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", + seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); #endif /* dump out the processor features */ - seq_puts(m, "Features\t: "); + seq_puts(m, "Features\t\t: "); for (i = 0; hwcap_str[i]; i++) if (elf_hwcap & (1 << i)) seq_printf(m, "%s ", hwcap_str[i]); seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24); - seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]); + seq_printf(m, "CPU architecture\t: %s\n", proc_arch[cpu_architecture()]); if ((processor_id & 0x0000f000) == 0x00000000) { /* pre-ARM7 */ @@ -878,7 +878,7 @@ seq_printf(m, "CPU variant\t: 0x%x\n", (processor_id >> 20) & 15); } - seq_printf(m, "CPU part\t: 0x%03x\n", + seq_printf(m, "CPU part\t\t: 0x%03x\n", (processor_id >> 4) & 0xfff); } seq_printf(m, "CPU revision\t: %d\n", processor_id & 15); @@ -906,8 +906,8 @@ seq_puts(m, "\n"); - seq_printf(m, "Hardware\t: %s\n", machine_name); - seq_printf(m, "Revision\t: %04x\n", system_rev); + seq_printf(m, "Hardware\t\t: %s\n", machine_name); + seq_printf(m, "Revision\t\t: %04x\n", system_rev); seq_printf(m, "Serial\t\t: %08x%08x\n", system_serial_high, system_serial_low); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/kernel/time.c linux-sl3516/arch/arm/kernel/time.c --- linux-2.6.15-armeb/arch/arm/kernel/time.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/kernel/time.c 2006-04-03 18:10:31.000000000 +0930 @@ -495,8 +495,13 @@ device_initcall(timer_init_sysfs); +extern unsigned int rtc_get_time_second(void); + void __init time_init(void) { +#ifdef CONFIG_SL2312_RTC + xtime.tv_sec = rtc_get_time_second() ; +#endif if (system_timer->offset == NULL) system_timer->offset = dummy_gettimeoffset; system_timer->init(); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/arch.c linux-sl3516/arch/arm/mach-sl2312/arch.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/arch.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/arch.c 2007-04-16 18:59:26.000000000 +0930 @@ -0,0 +1,68 @@ +/* + * linux/arch/arm/mach-epxa10db/arch.c + * + * Copyright (C) 2000 Deep Blue Solutions Ltd + * Copyright (C) 2001 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include +#include +#include +#include +#include + +extern void sl2312_map_io(void); +extern void sl2312_init_irq(void); +extern unsigned long sl2312_gettimeoffset (void); +extern void __init sl2312_time_init(void); + +static struct sys_timer sl2312_timer = { + .init = sl2312_time_init, + .offset = sl2312_gettimeoffset, +}; + +static void __init +sl2312_fixup(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = 0; + mi->bank[0].size = (64*1024*1024); // 64MB memory + mi->bank[0].node = 0; +} + +/* MACHINE_START(SL2312, "GeminiA") + MAINTAINER("Storlink Semi") + BOOT_MEM(0x00000000, 0x90000000, 0xf0000000) + FIXUP(sl2312_fixup) + MAPIO(sl2312_map_io) + INITIRQ(sl2312_init_irq) + .timer = &sl2312_timer, +MACHINE_END */ + +MACHINE_START(SL2312, "GeminiA") + .phys_ram = 0x00000000, + .phys_io = 0x7fffc000, + .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc, + .boot_params = 0x1000, + .fixup = sl2312_fixup, + .map_io = sl2312_map_io, + .init_irq = sl2312_init_irq, + .timer = &sl2312_timer, +MACHINE_END diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/gemini_ipi.c linux-sl3516/arch/arm/mach-sl2312/gemini_ipi.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/gemini_ipi.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/gemini_ipi.c 2006-06-14 18:58:21.000000000 +0930 @@ -0,0 +1,594 @@ +/* + * FILE NAME sl_cir.c + * + * BRIEF MODULE DESCRIPTION + * IPI Driver for CPU1. + * + * Author: StorLink, Corp. + * Jason Lee + * + * Copyright 2002~2006 StorLink, Corp. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMit8712D TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMit8712D TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, writ8712 to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include + +#include +#include +#include +#include +#include + +#include + + +static int sl_ipi_debug = 1 ; +#define DEB(x) if(sl_ipi_debug>=1) x + +#define SRAM_PTR IO_ADDRESS(SL2312_SRAM_BASE) +volatile JSCALE_REQ_T *req=(JSCALE_REQ_T*)SRAM_PTR; +volatile JSCALE_RSP_T *rsp=(JSCALE_RSP_T*)(SRAM_PTR+0x20); + +unsigned int jscale_status=0; + +#define JSCALE_WAIT 0 +#define XXXXXX_WAIT 1 +#define MAX_WAIT_Q 8 +wait_queue_head_t gemini_ipi_wait[MAX_WAIT_Q]; + +#define DRAMCTL_DMA_CTL 0X20 +#define DRAMCTL_DMA_SA 0X24 +#define DRAMCTL_DMA_DA 0X28 +#define DRAMCTL_DMA_CNT 0X2C +#define MEMCPY_UNIT 0x40000 +int hw_memcpy(const void *to, const void *from, unsigned int bytes) +{ + unsigned int reg_a,reg_d; + int count = bytes,i=0; + + consistent_sync((unsigned int *)to, bytes, DMA_BIDIRECTIONAL); + consistent_sync((unsigned int *)from,bytes, DMA_TO_DEVICE); + + DEB(printk("hwmemcpy:count %d\n",count)); + while(count>0){ + // SA + reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_SA; + reg_d = (unsigned int )__virt_to_phys(from) + i*MEMCPY_UNIT; + DEB(printk("hwmemcpy:from 0x%08x\n",reg_d)); + writel(reg_d,reg_a); + // DA + reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_DA; + reg_d = (unsigned int )__virt_to_phys(to) + i*MEMCPY_UNIT; + writel(reg_d,reg_a); + DEB(printk("hwmemcpy:to 0x%08x\n",reg_d)); + // byte count + reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CNT; + reg_d = (count>=MEMCPY_UNIT)?MEMCPY_UNIT:count; + writel(reg_d,reg_a); + // start DMA + reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL; + writel(0x80000001,reg_a); + + do{ + cond_resched(); +// msleep(4); + reg_d = readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL); + }while(reg_d&0x1); + + count -= MEMCPY_UNIT; + i++; + } + + return bytes; +} + +static irqreturn_t ipi_interrupt() +{ + unsigned int id=getcpuid(),tmp; + + //dmac_inv_range(__phys_to_virt(SL2312_SRAM_BASE),__phys_to_virt(SHAREADDR)+0x2000); + + + // Clear Interrupt + if(id==CPU0) { + tmp = readl(CPU1_STATUS); + tmp &= ~CPU_IPI_BIT_MASK; + writel(tmp,CPU1_STATUS); + } + else{ + tmp = readl(CPU0_STATUS); + tmp &= ~CPU_IPI_BIT_MASK; + writel(tmp,CPU0_STATUS); + } + + // + DEB(printk("ipi interrupt:0x%x\n",rsp->status)); + switch(rsp->status){ + case JSCALE_STATUS_OK: + + break; + case JSCALE_UNKNOWN_MSG_TYPE: + + break; + case JSCALE_FAILED_FILE_SIZE: + + break; + case JSCALE_FAILED_MALLOC: + + break; + case JSCALE_FAILED_FORMAT: + + break; + case JSCALE_DECODE_ERROR: + + break; + + } + jscale_status = rsp->status; +// wake_up(&gemini_ipi_wait[JSCALE_WAIT]); + + return IRQ_HANDLED; +} + +static int gemini_ipi_open(struct inode *inode, struct file *file) +{ + DEB(printk("ipi open\n")); + return 0; +} + + +static int gemini_ipi_release(struct inode *inode, struct file *file) +{ + DEB(printk("ipi release\n")); + return 0; +} + + +static int gemini_ipi_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + JSCALE_RSP_T tmp; + + switch(cmd) { + case GEMINI_IPI_JSCALE_REQ: + DEB(printk("ipi:ioctl jscale request %dX%d Q:%d\n",req->ScaledImageWidth,req->ScaledImageHeight,req->ScaledImageQuality)); + if (copy_from_user(req, (JSCALE_REQ_T *)arg, sizeof(JSCALE_REQ_T))) + return -EFAULT; + req->hdr.type = IPC_JSCALE_REQ_MSG; + req->hdr.length = sizeof(JSCALE_REQ_T); + req->input_location = CPU_1_DATA_OFFSET; + req->output_location = CPU_1_DATA_OFFSET; + break; + case GEMINI_IPI_JSCALE_STAT: + DEB(printk("ipi:ioctl jscale stat \n")); + if(jscale_status==JSCALE_BUSY){ // not yet + tmp.status = JSCALE_BUSY; + if (copy_to_user((JSCALE_RSP_T *)arg,&tmp, sizeof(JSCALE_RSP_T))) + return -EFAULT; + } + else{ // finish or error + if (copy_to_user((JSCALE_RSP_T *)arg,rsp, sizeof(JSCALE_RSP_T))) + return -EFAULT; + } + break; + default: + printk("IPI: Error IOCTL number\n"); + return -ENOIOCTLCMD; + } + + return 0; +} + +#define SRAM_SIZE 0x2000 +static ssize_t gemini_ipi_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos) +{ + int i=0,tmp=0,j; + const char *ptr=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET); + DEB(printk("ipi:write 0x%x to 0x%x length:%d\n",&buf,ptr,count)); + memcpy(ptr,buf,count); + consistent_sync(ptr,count, DMA_TO_DEVICE); + //hw_memcpy(ptr,&buf,count); + +/* if(count>SRAM_SIZE){ + for(i=0;i<(count/SRAM_SIZE);i++) + raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,SRAM_SIZE); + if(count%SRAM_SIZE) + raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,count%SRAM_SIZE); + } + else + raid_memcpy(ptr,buf,count); +*/ + +/* for(i=0;iSRAM_SIZE){ + for(i=0;i<(count/SRAM_SIZE);i++) + raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,SRAM_SIZE); + if(count%0xFFFF) + raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,length%SRAM_SIZE); + } + else + raid_memcpy(buf,p_mbox->message,length); +*/ + return length; +} + +void do_mapping_read(struct address_space *mapping, + struct file_ra_state *_ra, + struct file *filp, + loff_t *ppos, + read_descriptor_t *desc, + read_actor_t actor) +{ + struct inode *inode = mapping->host; + unsigned long index; + unsigned long end_index; + unsigned long offset; + unsigned long last_index; + unsigned long next_index; + unsigned long prev_index; + loff_t isize; + struct page *cached_page; + int error; + struct file_ra_state ra = *_ra; + + cached_page = NULL; + index = *ppos >> PAGE_CACHE_SHIFT; + next_index = index; + prev_index = ra.prev_page; + last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; + offset = *ppos & ~PAGE_CACHE_MASK; + + isize = i_size_read(inode); + if (!isize) + goto out; + + end_index = (isize - 1) >> PAGE_CACHE_SHIFT; + for (;;) { + struct page *page; + unsigned long nr, ret; + + /* nr is the maximum number of bytes to copy from this page */ + nr = PAGE_CACHE_SIZE; + if (index >= end_index) { + if (index > end_index) + goto out; + nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; + if (nr <= offset) { + goto out; + } + } + nr = nr - offset; + + cond_resched(); + if (index == next_index) + next_index = page_cache_readahead(mapping, &ra, filp, + index, last_index - index); + +find_page: + page = find_get_page(mapping, index); + if (unlikely(page == NULL)) { + handle_ra_miss(mapping, &ra, index); + goto no_cached_page; + } + if (!PageUptodate(page)) + goto page_not_up_to_date; +page_ok: + + /* If users can be writing to this page using arbitrary + * virtual addresses, take care about potential aliasing + * before reading the page on the kernel side. + */ + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + + /* + * When (part of) the same page is read multiple times + * in succession, only mark it as accessed the first time. + */ + if (prev_index != index) + mark_page_accessed(page); + prev_index = index; + + /* + * Ok, we have the page, and it's up-to-date, so + * now we can copy it to user space... + * + * The actor routine returns how many bytes were actually used.. + * NOTE! This may not be the same as how much of a user buffer + * we filled up (we may be padding etc), so we can only update + * "pos" here (the actor routine has to update the user buffer + * pointers and the remaining count). + */ + ret = actor(desc, page, offset, nr); + offset += ret; + index += offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + + page_cache_release(page); + if (ret == nr && desc->count) + continue; + goto out; + +page_not_up_to_date: + /* Get exclusive access to the page ... */ + lock_page(page); + + /* Did it get unhashed before we got the lock? */ + if (!page->mapping) { + unlock_page(page); + page_cache_release(page); + continue; + } + + /* Did somebody else fill it already? */ + if (PageUptodate(page)) { + unlock_page(page); + goto page_ok; + } + +readpage: + /* Start the actual read. The read will unlock the page. */ + error = mapping->a_ops->readpage(filp, page); + + if (unlikely(error)) + goto readpage_error; + + if (!PageUptodate(page)) { + lock_page(page); + if (!PageUptodate(page)) { + if (page->mapping == NULL) { + /* + * invalidate_inode_pages got it + */ + unlock_page(page); + page_cache_release(page); + goto find_page; + } + unlock_page(page); + error = -EIO; + goto readpage_error; + } + unlock_page(page); + } + + /* + * i_size must be checked after we have done ->readpage. + * + * Checking i_size after the readpage allows us to calculate + * the correct value for "nr", which means the zero-filled + * part of the page is not copied back to userspace (unless + * another truncate extends the file - this is desired though). + */ + isize = i_size_read(inode); + end_index = (isize - 1) >> PAGE_CACHE_SHIFT; + if (unlikely(!isize || index > end_index)) { + page_cache_release(page); + goto out; + } + + /* nr is the maximum number of bytes to copy from this page */ + nr = PAGE_CACHE_SIZE; + if (index == end_index) { + nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; + if (nr <= offset) { + page_cache_release(page); + goto out; + } + } + nr = nr - offset; + goto page_ok; + +readpage_error: + /* UHHUH! A synchronous read error occurred. Report it */ + desc->error = error; + page_cache_release(page); + goto out; + +no_cached_page: + /* + * Ok, it wasn't cached, so we need to create a new + * page.. + */ + if (!cached_page) { + cached_page = page_cache_alloc_cold(mapping); + if (!cached_page) { + desc->error = -ENOMEM; + goto out; + } + } + error = add_to_page_cache_lru(cached_page, mapping, + index, GFP_KERNEL); + if (error) { + if (error == -EEXIST) + goto find_page; + desc->error = error; + goto out; + } + page = cached_page; + cached_page = NULL; + goto readpage; + } + +out: + *_ra = ra; + + *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; + if (cached_page) + page_cache_release(cached_page); + if (filp) + file_accessed(filp); +} + +int ipi_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) +{ + ssize_t written; + unsigned long count = desc->count; + struct file *file = desc->arg.data; + unsigned int *ptr_to=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET) + desc->written; + void *ptr_from; + + if (size > count) + size = count; + + ptr_from = page_address(page)+offset; + written = memcpy(ptr_to,ptr_from,size); + + if (written < 0) { + desc->error = written; + written = 0; + } + desc->count = count - written; + desc->written += written; + return written; +} + +ssize_t gemini_ipi_sendfile(struct file *in_file, loff_t *ppos, + size_t count, read_actor_t actor, void *TARGET) +{ + read_descriptor_t desc; + + if (!count) + return 0; + + desc.written = 0; + desc.count = count; + desc.arg.data = TARGET; + desc.error = 0; + + do_mapping_read(in_file->f_mapping,&in_file->f_ra,in_file, ppos, &desc, ipi_send_actor); + + if (desc.written) + return desc.written; + return desc.error; +} +static struct file_operations gemini_ipi_fops = { + .owner = THIS_MODULE, + .ioctl = gemini_ipi_ioctl, + .open = gemini_ipi_open, + .release= gemini_ipi_release, + .write = gemini_ipi_write, + .read = gemini_ipi_read, + .sendfile = gemini_ipi_sendfile, +}; + +#ifndef STORLINK_IPI +#define STORLINK_IPI 242 // Documents/devices.txt suggest to use 240~255 for local driver!! +#endif + +static struct miscdevice gemini_ipi_miscdev = +{ + STORLINK_IPI, + "slave_ipc", + &gemini_ipi_fops +}; + +int __init sl_ipi_init(void) +{ + + printk("Gemini IPI Driver Initialization...\n"); + printk("REQ Head :0x%x(phy:0x%x)\n",(unsigned int)req,(unsigned int)SL2312_SRAM_BASE); + printk("RSP Head :0x%x(phy:0x%x)\n",(unsigned int)rsp,(unsigned int)SL2312_SRAM_BASE+0x20); + printk("Data buff:0x%x(phy:0x%x)\n",__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET),CPU_1_MEM_BASE+CPU_1_DATA_OFFSET); + + misc_register(&gemini_ipi_miscdev); + + if (request_irq(IRQ_CPU0_IP_IRQ_OFFSET, ipi_interrupt, SA_INTERRUPT, "ipi", NULL)) + printk("Error: Register IRQ for Storlink IPI failed\n"); + + return 0; +} + +void __exit sl_ipi_exit(void) +{ + +} + +module_init(sl_ipi_init); +module_exit(sl_ipi_exit); + +MODULE_AUTHOR("Jason Lee "); +MODULE_DESCRIPTION("Storlink IPI driver"); +MODULE_LICENSE("GPL"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/hw_xor.h linux-sl3516/arch/arm/mach-sl2312/hw_xor.h --- linux-2.6.15-armeb/arch/arm/mach-sl2312/hw_xor.h 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/hw_xor.h 2006-10-24 17:27:01.000000000 +0930 @@ -0,0 +1,573 @@ +/* +* linux/include/asm-arm/xor.h +* +* Copyright (C) 2001 Storlink Semi. +* Jason Lee +* +*/ +#include +#include +//#include + +#undef BIG_ENDIAN +#define CPU 0 +#define DMA 1 + +#define DESC_NO 8 +#define TX_DESC_NUM DESC_NO +#define RX_DESC_NUM DESC_NO + +#define RAID_BASE_ADDR IO_ADDRESS(SL2312_RAID_BASE) + +#define SRAM_PAR_0k 0 +#define SRAM_PAR_4k 1 +#define SRAM_PAR_8k 2 +#define SRAM_PAR_16k 3 +#define SRAM_PAR_SIZE SRAM_PAR_8k + +#define RUNNING 0x1 +#define COMPLETE 0x2 +#define ERROR 0x4 + +#define CMD_XOR 0x0 +#define CMD_FILL 0x1 +#define CMD_CPY 0x3 +#define CMD_CHK 0x4 + +enum RAID_DMA_REGISTER { + RAID_DMA_DEVICE_ID = 0xff00, + RAID_DMA_STATUS = 0xff04, + RAID_FCHDMA_CTRL = 0xff08, + RAID_FCHDMA_FIRST_DESC = 0xff0C, + RAID_FCHDMA_CURR_DESC = 0xff10, + RAID_STRDMA_CTRL = 0xff14, + RAID_STRDMA_FIRST_DESC = 0xff18, + RAID_STRDMA_CURR_DESC = 0xff1C, + RAID_TX_FLG_REG = 0xff24, + RAID_RX_FLG_REG = 0xff34, + RAID_PCR = 0xff50, + SMC_CMD_REG = 0xff60, + SMC_STATUS_REG = 0xff64 + }; + +enum RAID_FUNC_MODE { + RAID_XOR = 0, + RAID_MIX = 2, + RAID_SRAM = 3, + RAID_ENDIAN = 4, + RAID_MEM_BLK = 5, + RAID_MEM2MEM = 7, + RAID_BUF_SIZE = 8, + RAID_ERR_TEST = 9, + RAID_BURST = 10, + RAID_BUS = 11 + }; + +typedef struct reg_info { + int mask; + char err[32]; + int offset; +} REG_INFO; + +/********************************************************/ +/* the definition of RAID DMA Module Register */ +/********************************************************/ +typedef union +{ + unsigned int bit32; + struct bits_ff00 + { + #ifdef BIG_ENDIAN + unsigned int : 8; + unsigned int teytPerr : 4; /* define protocol error under tsPErrI*/ + unsigned int reytPerr : 14; /* define protocol error under rsPErrI */ + unsigned int device_id : 12; + unsigned int revision_id : 4; + #else + unsigned int revision_id : 4; + unsigned int device_id : 12; + unsigned int reytPerr : 14; /* define protocol error under rsPErrI */ + unsigned int teytPerr : 4; /* define protocol error under tsPErrI*/ + unsigned int : 8; + #endif + } bits; +} RAID_DMA_DEVICE_ID_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff04 + { + #ifdef BIG_ENDIAN + unsigned int tsFinishI : 1; /* owner bit error interrupt */ + unsigned int tsDErrI : 1; /* AHB bus error interrupt */ + unsigned int tsPErrI : 1; /* RAID XOR fetch descriptor protocol error interrupt */ + unsigned int tsEODI : 1; /* RAID XOR fetch DMA end of descriptor interrupt */ + unsigned int tsEOFI : 1; /* RAID XOR fetch DMA end of frame interrupt */ + unsigned int rsFinishI : 1; /* owner bit error interrupt */ + unsigned int rsDErrI : 1; /* AHB bus error while RAID XOR store interrupt */ + unsigned int rsPErrI : 1; /* RAID XOR store descriptor protocol error interrupt */ + unsigned int rsEODI : 1; /* RAID XOR store DMA end of descriptor interrupt */ + unsigned int rsEOFI : 1; /* RAID XOR store DMA end of frame interrupt */ + unsigned int inter : 8; /* pattern check error interrupt */ + unsigned int : 5; + unsigned int Loopback : 1; /* loopback */ + unsigned int intEnable : 8; /*pattern check error interrupt enable */ + #else + unsigned int intEnable : 8; /*pattern check error interrupt enable */ + unsigned int Loopback : 1; /* loopback */ + unsigned int : 5; + unsigned int inter : 8; /* pattern check error interrupt */ + unsigned int rsEOFI : 1; /* RAID XOR store DMA end of frame interrupt */ + unsigned int rsEODI : 1; /* RAID XOR store DMA end of descriptor interrupt */ + unsigned int rsPErrI : 1; /* RAID XOR store descriptor protocol error interrupt */ + unsigned int rsDErrI : 1; /* AHB bus error while RAID XOR store interrupt */ + unsigned int rsFinishI : 1; /* owner bit error interrupt */ + unsigned int tsEOFI : 1; /* RAID XOR fetch DMA end of frame interrupt */ + unsigned int tsEODI : 1; /* RAID XOR fetch DMA end of descriptor interrupt */ + unsigned int tsPErrI : 1; /* RAID XOR fetch descriptor protocol error interrupt */ + unsigned int tsDErrI : 1; /* AHB bus error interrupt */ + unsigned int tsFinishI : 1; /* owner bit error interrupt */ + #endif + } bits; +} RAID_DMA_STATUS_T; + + +typedef union +{ + unsigned int bits32; + struct bits_ff08 + { + #ifdef BIG_ENDIAN + unsigned int td_start : 1; /* Start DMA transfer */ + unsigned int td_continue : 1; /* Continue DMA operation */ + unsigned int td_chain_mode : 1; /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/ + unsigned int : 1; + unsigned int td_prot : 4; /* DMA protection control */ + unsigned int td_burst_size : 2; /* DMA max burst size for every AHB request */ + unsigned int td_bus : 2; /* peripheral bus width */ + unsigned int td_endian : 1; /* AHB Endian. 0-little endian; 1-big endian */ + unsigned int td_finish_en : 1; /* DMA Finish Event Interrupt Enable;1-enable;0-mask */ + unsigned int td_fail_en : 1; /* DMA Fail Interrupt Enable;1-enable;0-mask */ + unsigned int td_perr_en : 1; /* Protocol Failure Interrupt Enable;1-enable;0-mask */ + unsigned int td_eod_en : 1; /* End of Descriptor interrupt Enable;1-enable;0-mask */ + unsigned int td_eof_en : 1; /* End of frame interrupt Enable;1-enable;0-mask */ + unsigned int : 14; + #else + unsigned int : 14; + unsigned int td_eof_en : 1; /* End of frame interrupt Enable;1-enable;0-mask */ + unsigned int td_eod_en : 1; /* End of Descriptor interrupt Enable;1-enable;0-mask */ + unsigned int td_perr_en : 1; /* Protocol Failure Interrupt Enable;1-enable;0-mask */ + unsigned int td_fail_en : 1; /* DMA Fail Interrupt Enable;1-enable;0-mask */ + unsigned int td_finish_en : 1; /* DMA Finish Event Interrupt Enable;1-enable;0-mask */ + unsigned int td_endian : 1; /* AHB Endian. 0-little endian; 1-big endian */ + unsigned int td_bus : 2; /* peripheral bus width;0 - 8 bits;1 - 16 bits */ + unsigned int td_burst_size : 2; /* TxDMA max burst size for every AHB request */ + unsigned int td_prot : 4; /* TxDMA protection control */ + unsigned int : 1; + unsigned int td_chain_mode : 1; /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/ + unsigned int td_continue : 1; /* Continue DMA operation */ + unsigned int td_start : 1; /* Start DMA transfer */ + #endif + } bits; +} RAID_TXDMA_CTRL_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff0c + { + #ifdef BIG_ENDIAN + unsigned int td_first_des_ptr : 28;/* first descriptor address */ + unsigned int td_busy : 1;/* 1-TxDMA busy; 0-TxDMA idle */ + unsigned int : 3; + #else + unsigned int : 3; + unsigned int td_busy : 1;/* 1-TxDMA busy; 0-TxDMA idle */ + unsigned int td_first_des_ptr : 28;/* first descriptor address */ + #endif + } bits; +} RAID_TXDMA_FIRST_DESC_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff10 + { + #ifdef BIG_ENDIAN + unsigned int ndar : 28; /* next descriptor address */ + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int : 1; + unsigned int sof_eof : 2; + #else + unsigned int sof_eof : 2; + unsigned int : 1; + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int ndar : 28; /* next descriptor address */ + #endif + } bits; +} RAID_TXDMA_CURR_DESC_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff14 + { + #ifdef BIG_ENDIAN + unsigned int rd_start : 1; /* Start DMA transfer */ + unsigned int rd_continue : 1; /* Continue DMA operation */ + unsigned int rd_chain_mode : 1; /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/ + unsigned int : 1; + unsigned int rd_prot : 4; /* DMA protection control */ + unsigned int rd_burst_size : 2; /* DMA max burst size for every AHB request */ + unsigned int rd_bus : 2; /* peripheral bus width;0 - 8 bits;1 - 16 bits */ + unsigned int rd_endian : 1; /* AHB Endian. 0-little endian; 1-big endian */ + unsigned int rd_finish_en : 1; /* DMA Finish Event Interrupt Enable;1-enable;0-mask */ + unsigned int rd_fail_en : 1; /* DMA Fail Interrupt Enable;1-enable;0-mask */ + unsigned int rd_perr_en : 1; /* Protocol Failure Interrupt Enable;1-enable;0-mask */ + unsigned int rd_eod_en : 1; /* End of Descriptor interrupt Enable;1-enable;0-mask */ + unsigned int rd_eof_en : 1; /* End of frame interrupt Enable;1-enable;0-mask */ + unsigned int : 14; + #else + unsigned int : 14; + unsigned int rd_eof_en : 1; /* End of frame interrupt Enable;1-enable;0-mask */ + unsigned int rd_eod_en : 1; /* End of Descriptor interrupt Enable;1-enable;0-mask */ + unsigned int rd_perr_en : 1; /* Protocol Failure Interrupt Enable;1-enable;0-mask */ + unsigned int rd_fail_en : 1; /* DMA Fail Interrupt Enable;1-enable;0-mask */ + unsigned int rd_finish_en : 1; /* DMA Finish Event Interrupt Enable;1-enable;0-mask */ + unsigned int rd_endian : 1; /* AHB Endian. 0-little endian; 1-big endian */ + unsigned int rd_bus : 2; /* peripheral bus width;0 - 8 bits;1 - 16 bits */ + unsigned int rd_burst_size : 2; /* DMA max burst size for every AHB request */ + unsigned int rd_prot : 4; /* DMA protection control */ + unsigned int : 1; + unsigned int rd_chain_mode : 1; /* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/ + unsigned int rd_continue : 1; /* Continue DMA operation */ + unsigned int rd_start : 1; /* Start DMA transfer */ + #endif + } bits; +} RAID_RXDMA_CTRL_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff18 + { + #ifdef BIG_ENDIAN + unsigned int rd_first_des_ptr : 28;/* first descriptor address */ + unsigned int rd_busy : 1;/* 1-RxDMA busy; 0-RxDMA idle */ + unsigned int : 3; + #else + unsigned int : 3; + unsigned int rd_busy : 1;/* 1-RxDMA busy; 0-RxDMA idle */ + unsigned int rd_first_des_ptr : 28;/* first descriptor address */ + #endif + } bits; +} RAID_RXDMA_FIRST_DESC_T; + +typedef union +{ + unsigned int bits32; + struct bits_ff1c + { + #ifdef BIG_ENDIAN + unsigned int ndar : 28; /* next descriptor address */ + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int dec : 1; /* AHB bus address increment(0)/decrement(1) */ + unsigned int sof_eof : 2; + #else + unsigned int sof_eof : 2; + unsigned int dec : 1; /* AHB bus address increment(0)/decrement(1) */ + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int ndar : 28; /* next descriptor address */ + #endif + } bits; +} RAID_RXDMA_CURR_DESC_T; + +typedef union +{ + unsigned int bit32; + struct bits_ff50 + { + unsigned int pat : 32; /* data for pattern check */ + } bits; +} RAID_PACR_T; + +/******************************************************/ +/* the definition of DMA Descriptor Register */ +/******************************************************/ +typedef struct raid_descriptor_t +{ + union func_ctrl_t + { + unsigned int bit32; + struct bits_0000 + { + #ifdef BIG_ENDIAN + unsigned int own : 1; /* owner bit */ + unsigned int derr : 1; /* data error during processing this descriptor */ + unsigned int perr : 1; /* protocol error during processing this descriptor */ + unsigned int raid_ctrl_status : 7; /* pass RAID XOR fetch/store control status to CPU */ + unsigned int desc_cnt : 6; + unsigned int buffer_size : 16; /* transfer buffer size associated with current description*/ + #else + unsigned int buffer_size : 16; /* transfer buffer size associated with current description*/ + unsigned int desc_cnt : 6; + unsigned int raid_ctrl_status : 7; /* pass RAID XOR fetch/store control status to CPU */ + unsigned int perr : 1; /* protocol error during processing this descriptor */ + unsigned int derr : 1; /* data error during processing this descriptor */ + unsigned int own : 1; /* owner bit */ + #endif + } bits; + } func_ctrl; + + union flg_status_t + { + unsigned int bits32; + struct bit_004 + { + #ifdef BIG_ENDIAN + unsigned int bcc : 16; + unsigned int : 13 + unsigned int mode : 3; + #else + unsigned int mode : 3; + unsigned int : 13; + unsigned int bcc : 16; + #endif + } bits_cmd_status; + } flg_status; //Sanders + + unsigned int buf_addr; + + union next_desc_addr_t + { + unsigned int bits32; + struct bits_000c + { + #ifdef BIG_ENDIAN + unsigned int ndar : 28; /* next descriptor address */ + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int : 1; + unsigned int sof_eof : 2; /* the position of the descriptor in chain */ + #else + unsigned int sof_eof : 2; /* the position of the descriptor in chain */ + unsigned int : 1; + unsigned int eofie : 1; /* end of frame interrupt enable */ + unsigned int ndar : 28; /* next descriptor address */ + #endif + } bits; + } next_desc_addr; +} RAID_DESCRIPTOR_T; + +/******************************************************/ +/* the offset of RAID SMC register */ +/******************************************************/ +enum RAID_SMC_REGISTER { + RAID_SMC_CMD_REG = 0xff60, + RAID_SMC_STATUS_REG = 0xff64 + }; + +/******************************************************/ +/* the definition of RAID SMC module register */ +/******************************************************/ +typedef union +{ + unsigned int bits32; + struct bits_ff60 + { + #ifdef BIG_ENDIAN + unsigned int pat_mode : 2; /* partition mode selection */ + unsigned int : 14; + unsigned int device_id : 12; + unsigned int revision_id : 4; + #else + unsigned int revision_id : 4; + unsigned int device_id : 12; + unsigned int : 14; + unsigned int pat_mode : 2; /* partition mode selection */ + #endif + } bits; +} RAID_SMC_CMD; + +typedef union +{ + unsigned int bits32; + struct bits_ff64 + { + #ifdef BIG_ENDIAN + unsigned int addr_err1 : 1; /* address is out of range for controller 1 */ + unsigned int ahb_err1 : 1; /* AHB bus error for controller 1 */ + unsigned int : 14; + unsigned int addr_err2 : 1; /* address is out of range for controller 2 */ + unsigned int ahb_err2 : 1; /* AHB bus error for controller 2 */ + unsigned int : 14; + #else + unsigned int : 14; + unsigned int ahb_err2 : 1; /* AHB bus error for controller 2 */ + unsigned int addr_err2 : 1; /* address is out of range for controller 2 */ + unsigned int : 14; + unsigned int ahb_err1 : 1; /* AHB bus error for controller 1 */ + unsigned int addr_err1 : 1; /* address is out of range for controller 1 */ + #endif + } bits; +} RAID_SMC_STATUS; + +typedef struct RAID_S +{ + const char *device_name; + wait_queue_head_t wait; + unsigned int busy; + int irq; + unsigned int status; + RAID_DESCRIPTOR_T *tx_desc; /* point to virtual TX descriptor address */ + RAID_DESCRIPTOR_T *rx_desc; /* point ot virtual RX descriptor address */ + RAID_DESCRIPTOR_T *tx_cur_desc; /* current TX descriptor */ + RAID_DESCRIPTOR_T *rx_cur_desc; /* current RX descriptor */ + RAID_DESCRIPTOR_T *tx_finished_desc; + RAID_DESCRIPTOR_T *rx_finished_desc; + RAID_DESCRIPTOR_T *tx_first_desc; + RAID_DESCRIPTOR_T *rx_first_desc; + +// unsigned int *tx_buf[TX_DESC_NUM]; + unsigned int *rx_desc_dma; // physical address of rx_descript + unsigned int *tx_desc_dma; // physical address of tx_descript + unsigned int *rx_bufs_dma; + unsigned int *tx_bufs_dma; + +} RAID_T; + +struct reg_ioctl +{ + unsigned int reg_addr; + unsigned int val_in; + unsigned int val_out; +}; + +typedef struct dma_ctrl { + int sram; + int prot; + int burst; + int bus; + int endian; + int mode; +} DMA_CTRL; + + +#ifdef XOR_SW_FILL_IN + +#define __XOR(a1, a2) a1 ^= a2 + +#define GET_BLOCK_2(dst) \ + __asm__("ldmia %0, {%1, %2}" \ + : "=r" (dst), "=r" (a1), "=r" (a2) \ + : "0" (dst)) + +#define GET_BLOCK_4(dst) \ + __asm__("ldmia %0, {%1, %2, %3, %4}" \ + : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \ + : "0" (dst)) + +#define XOR_BLOCK_2(src) \ + __asm__("ldmia %0!, {%1, %2}" \ + : "=r" (src), "=r" (b1), "=r" (b2) \ + : "0" (src)); \ + __XOR(a1, b1); __XOR(a2, b2); + +#define XOR_BLOCK_4(src) \ + __asm__("ldmia %0!, {%1, %2, %3, %4}" \ + : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \ + : "0" (src)); \ + __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4) + +#define PUT_BLOCK_2(dst) \ + __asm__ __volatile__("stmia %0!, {%2, %3}" \ + : "=r" (dst) \ + : "0" (dst), "r" (a1), "r" (a2)) + +#define PUT_BLOCK_4(dst) \ + __asm__ __volatile__("stmia %0!, {%2, %3, %4, %5}" \ + : "=r" (dst) \ + : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4)) + +static void +xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) +{ + unsigned int lines = bytes / sizeof(unsigned long) / 4; + register unsigned int a1 __asm__("r4"); + register unsigned int a2 __asm__("r5"); + register unsigned int a3 __asm__("r6"); + register unsigned int a4 __asm__("r7"); + register unsigned int b1 __asm__("r8"); + register unsigned int b2 __asm__("r9"); + register unsigned int b3 __asm__("ip"); + register unsigned int b4 __asm__("lr"); + + do { + GET_BLOCK_4(p1); + XOR_BLOCK_4(p2); + PUT_BLOCK_4(p1); + } while (--lines); +} + +static void +xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3) +{ + unsigned int lines = bytes / sizeof(unsigned long) / 4; + register unsigned int a1 __asm__("r4"); + register unsigned int a2 __asm__("r5"); + register unsigned int a3 __asm__("r6"); + register unsigned int a4 __asm__("r7"); + register unsigned int b1 __asm__("r8"); + register unsigned int b2 __asm__("r9"); + register unsigned int b3 __asm__("ip"); + register unsigned int b4 __asm__("lr"); + + do { + GET_BLOCK_4(p1); + XOR_BLOCK_4(p2); + XOR_BLOCK_4(p3); + PUT_BLOCK_4(p1); + } while (--lines); +} + +static void +xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4) +{ + unsigned int lines = bytes / sizeof(unsigned long) / 2; + register unsigned int a1 __asm__("r8"); + register unsigned int a2 __asm__("r9"); + register unsigned int b1 __asm__("ip"); + register unsigned int b2 __asm__("lr"); + + do { + GET_BLOCK_2(p1); + XOR_BLOCK_2(p2); + XOR_BLOCK_2(p3); + XOR_BLOCK_2(p4); + PUT_BLOCK_2(p1); + } while (--lines); +} + +static void +xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4, unsigned long *p5) +{ + unsigned int lines = bytes / sizeof(unsigned long) / 2; + register unsigned int a1 __asm__("r8"); + register unsigned int a2 __asm__("r9"); + register unsigned int b1 __asm__("ip"); + register unsigned int b2 __asm__("lr"); + + do { + GET_BLOCK_2(p1); + XOR_BLOCK_2(p2); + XOR_BLOCK_2(p3); + XOR_BLOCK_2(p4); + XOR_BLOCK_2(p5); + PUT_BLOCK_2(p1); + } while (--lines); +} +#endif //XOR_SW_FILL_IN + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/irq.c linux-sl3516/arch/arm/mach-sl2312/irq.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/irq.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/irq.c 2006-09-01 12:07:56.000000000 +0930 @@ -0,0 +1,200 @@ +/* + * linux/arch/arm/mach-epxa10db/irq.c + * + * Copyright (C) 2001 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PCI +#include +#endif + +int fixup_irq(unsigned int irq) +{ +#ifdef CONFIG_PCI + if (irq == IRQ_PCI) { + return sl2312_pci_get_int_src(); + } +#endif + return irq; +} + +static void sl2312_ack_irq(unsigned int irq) +{ + __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))); +} + +static void sl2312_mask_irq(unsigned int irq) +{ + unsigned int mask; + +#ifdef CONFIG_PCI + if (irq >= PCI_IRQ_OFFSET) + { + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask &= ~IRQ_PCI_MASK ; + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + sl2312_pci_mask_irq(irq - PCI_IRQ_OFFSET); + } + else +#endif + if(irq >= FIQ_OFFSET) + { + mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask &= ~(1 << (irq - FIQ_OFFSET)); + __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + } + else + { + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask &= ~(1 << irq); + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + } + +} + +static void sl2312_unmask_irq(unsigned int irq) +{ + unsigned int mask; + +#ifdef CONFIG_PCI + if (irq >= PCI_IRQ_OFFSET) + { + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask |= IRQ_PCI_MASK ; + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + sl2312_pci_unmask_irq(irq - PCI_IRQ_OFFSET); + } + else +#endif + if(irq >= FIQ_OFFSET) + { + mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask |= (1 << (irq - FIQ_OFFSET)); + __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + } + else + { + mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + mask |= (1 << irq); + __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + } +} + +static struct irqchip sl2312_level_irq = { + .ack = sl2312_mask_irq, + .mask = sl2312_mask_irq, + .unmask = sl2312_unmask_irq, +}; + +static struct irqchip sl2312_edge_irq = { + .ack = sl2312_ack_irq, + .mask = sl2312_mask_irq, + .unmask = sl2312_unmask_irq, +}; + +static struct resource irq_resource = { + .name = "irq_handler", + .start = IO_ADDRESS(SL2312_INTERRUPT_BASE), + .end = IO_ADDRESS(FIQ_STATUS(SL2312_INTERRUPT_BASE))+4, +}; + +void __init sl2312_init_irq(void) +{ + unsigned int i, mode, level; + + request_resource(&iomem_resource, &irq_resource); + + for (i = 0; i < NR_IRQS; i++) + { + if((i>=IRQ_TIMER1 && i<=IRQ_TIMER3)||(i>=IRQ_SERIRQ0 && i<=IRQ_SERIRQ_MAX)) + { + set_irq_handler(i, do_edge_IRQ); + set_irq_chip(i, &sl2312_edge_irq); + } + else + { + set_irq_handler(i,do_level_IRQ); + set_irq_chip(i, &sl2312_level_irq); + } + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + } + + /* Disable all interrupt */ + __raw_writel(0,IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + __raw_writel(0,FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + + /* Set interrupt mode */ + /* emac & ipsec type is level trigger and high active */ + mode = __raw_readl(IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + level = __raw_readl(IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + + mode &= ~IRQ_GMAC0_MASK; + level &= ~IRQ_GMAC0_MASK; + + mode &= ~IRQ_GMAC1_MASK; + level &= ~IRQ_GMAC1_MASK; + + mode &= ~IRQ_IPSEC_MASK; + level &= ~IRQ_IPSEC_MASK; + + // for IDE0,1, high active and level trigger + mode &= ~IRQ_IDE0_MASK; + level &= ~IRQ_IDE0_MASK; + mode &= ~IRQ_IDE1_MASK; + level &= ~IRQ_IDE1_MASK; + + + // for PCI, high active and level trigger + mode &= ~IRQ_PCI_MASK; + level &= ~IRQ_PCI_MASK; + + // for USB, high active and level trigger + mode &= ~IRQ_USB0_MASK; + level &= ~IRQ_USB0_MASK; + + mode &= ~IRQ_USB1_MASK; + level &= ~IRQ_USB1_MASK; + + // for LPC, high active and edge trigger + mode |= 0xffff0000; + level &= 0x0000ffff; + + // for GPIO, high active and level trigger + mode &= ~(IRQ_GPIO_MASK); + level &= ~(IRQ_GPIO_MASK); + + mode &= ~(IRQ_GPIO1_MASK); + level &= ~(IRQ_GPIO1_MASK); + + mode &= ~(IRQ_GPIO2_MASK); + level &= ~(IRQ_GPIO2_MASK); + + __raw_writel(mode,IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + __raw_writel(level,IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))); + +} diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/Kconfig linux-sl3516/arch/arm/mach-sl2312/Kconfig --- linux-2.6.15-armeb/arch/arm/mach-sl2312/Kconfig 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/Kconfig 2006-05-09 16:23:17.000000000 +0930 @@ -0,0 +1,33 @@ + +menu "SL2312" + +config SL3516_ASIC + bool "SL3516 ASIC version" + depends on ARCH_SL2312 + help + This option to select AISC or FPGA +config PCI + bool "SL2312 PCI" + depends on ARCH_SL2312 + help + This option to enable Storlink PCI controller + +config SL2312_LPC + bool "SL2312 LPC" + depends on ARCH_SL2312 + help + This option to enable Low Pin Count controller + +config SL2312_USB + bool "SL2312 USB" + depends on ARCH_SL2312 + help + This option to enable USB OTG host contrller + +config GEMINI_IPI + bool "Gemini IPI test" + depends on ARCH_SL2312 + help + Enable this option to test dual cpu Inter-Processor-Interrupt +endmenu + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/lpc.c linux-sl3516/arch/arm/mach-sl2312/lpc.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/lpc.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/lpc.c 2006-04-03 18:10:32.000000000 +0930 @@ -0,0 +1,124 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * ITE Semi IT8712 Super I/O functions. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +// MB PnP configuration register +#define LPC_KEY_ADDR (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2e) +#define LPC_DATA_ADDR (IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2f) + +#define LPC_BUS_CTRL *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 0) +#define LPC_BUS_STATUS *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 2) +#define LPC_SERIAL_IRQ_CTRL *(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 4) + +int it8712_exist; + +static void LPCEnterMBPnP(void) +{ + int i; + unsigned char key[4] = {0x87, 0x01, 0x55, 0x55}; + + for (i = 0; i<4; i++) + outb(key[i], LPC_KEY_ADDR); + +} + +static void LPCExitMBPnP(void) +{ + outb(0x02, LPC_KEY_ADDR); + outb(0x02, LPC_DATA_ADDR); +} + +void LPCSetConfig(char LdnNumber, char Index, char data) +{ + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + outb(0x07, LPC_KEY_ADDR); + outb(LdnNumber, LPC_DATA_ADDR); + outb(Index, LPC_KEY_ADDR); + outb(data, LPC_DATA_ADDR); + LPCExitMBPnP(); +} + +char LPCGetConfig(char LdnNumber, char Index) +{ + char rtn; + + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + outb(0x07, LPC_KEY_ADDR); + outb(LdnNumber, LPC_DATA_ADDR); + outb(Index, LPC_KEY_ADDR); + rtn = inb(LPC_DATA_ADDR); + LPCExitMBPnP(); + return rtn; +} + +static int SearchIT8712(void) +{ + unsigned char Id1, Id2; + unsigned short Id; + + LPCEnterMBPnP(); + outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */ + Id1 = inb(LPC_DATA_ADDR); + outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */ + Id2 = inb(LPC_DATA_ADDR); + Id = (Id1 << 8) | Id2; + LPCExitMBPnP(); + if (Id == 0x8712) + return TRUE; + else + return FALSE; +} + +int InitLPCInterface(void) +{ + LPC_BUS_CTRL = 0xc0; + LPC_SERIAL_IRQ_CTRL = 0xc0; + mdelay(1); // wait for 1 serial IRQ cycle + LPC_SERIAL_IRQ_CTRL = 0x80; + it8712_exist = SearchIT8712(); + printk("IT8712 %s exist\n", it8712_exist?"":"doesn't"); + return 0; +} + +//__initcall(InitLPCInterface); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/Makefile linux-sl3516/arch/arm/mach-sl2312/Makefile --- linux-2.6.15-armeb/arch/arm/mach-sl2312/Makefile 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/Makefile 2006-05-03 15:46:55.000000000 +0930 @@ -0,0 +1,16 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := arch.o irq.o mm.o time.o sl3516_device.o +obj-m := +obj-n := + + +obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_SL2312_LPC) += lpc.o +obj-$(CONFIG_SL2312_USB) += sl2312-otg.o sl2312-otg-1.o +obj-$(CONFIG_GEMINI_XOR_ACCE) += xor.o +obj-$(CONFIG_GEMINI_IPI) += gemini_ipi.o diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/Makefile.boot linux-sl3516/arch/arm/mach-sl2312/Makefile.boot --- linux-2.6.15-armeb/arch/arm/mach-sl2312/Makefile.boot 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/Makefile.boot 2006-04-03 18:10:32.000000000 +0930 @@ -0,0 +1,4 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00508100 +initrd_phys-y := 0x00800000 + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/mm.c linux-sl3516/arch/arm/mach-sl2312/mm.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/mm.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/mm.c 2006-12-15 13:34:35.000000000 +1030 @@ -0,0 +1,80 @@ +/* + * linux/arch/arm/mach-epxa10db/mm.c + * + * MM routines for Altera'a Epxa10db board + * + * Copyright (C) 2001 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* Page table mapping for I/O region */ +static struct map_desc sl2312_io_desc[] __initdata = { +#ifdef CONFIG_GEMINI_IPI +{__phys_to_virt(CPU_1_MEM_BASE), __phys_to_pfn(CPU_1_MEM_BASE), SZ_64M, MT_MEMORY}, +#endif +{IO_ADDRESS(SL2312_SRAM_BASE), __phys_to_pfn(SL2312_SRAM_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_DRAM_CTRL_BASE), __phys_to_pfn(SL2312_DRAM_CTRL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GLOBAL_BASE), __phys_to_pfn(SL2312_GLOBAL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_WAQTCHDOG_BASE), __phys_to_pfn(SL2312_WAQTCHDOG_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_UART_BASE), __phys_to_pfn(SL2312_UART_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_TIMER_BASE), __phys_to_pfn(SL2312_TIMER_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_LCD_BASE), __phys_to_pfn(SL2312_LCD_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_RTC_BASE), __phys_to_pfn(SL2312_RTC_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_SATA_BASE), __phys_to_pfn(SL2312_SATA_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_LPC_HOST_BASE), __phys_to_pfn(SL2312_LPC_HOST_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_LPC_IO_BASE), __phys_to_pfn(SL2312_LPC_IO_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_INTERRUPT_BASE), __phys_to_pfn(SL2312_INTERRUPT_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_INTERRUPT1_BASE), __phys_to_pfn(SL2312_INTERRUPT1_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_SSP_CTRL_BASE), __phys_to_pfn(SL2312_SSP_CTRL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_POWER_CTRL_BASE), __phys_to_pfn(SL2312_POWER_CTRL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_CIR_BASE), __phys_to_pfn(SL2312_CIR_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GPIO_BASE), __phys_to_pfn(SL2312_GPIO_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GPIO_BASE1), __phys_to_pfn(SL2312_GPIO_BASE1), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GPIO_BASE2), __phys_to_pfn(SL2312_GPIO_BASE2), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_PCI_IO_BASE), __phys_to_pfn(SL2312_PCI_IO_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_PCI_MEM_BASE), __phys_to_pfn(SL2312_PCI_MEM_BASE), SZ_512K, MT_DEVICE}, +#ifdef CONFIG_NET_SL351X +{IO_ADDRESS(SL2312_TOE_BASE), __phys_to_pfn(SL2312_TOE_BASE) , SZ_512K, MT_DEVICE}, +#endif +{IO_ADDRESS(SL2312_GMAC0_BASE), __phys_to_pfn(SL2312_GMAC0_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GMAC1_BASE), __phys_to_pfn(SL2312_GMAC1_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_SECURITY_BASE), __phys_to_pfn(SL2312_SECURITY_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_IDE0_BASE), __phys_to_pfn(SL2312_IDE0_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_IDE1_BASE), __phys_to_pfn(SL2312_IDE1_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_RAID_BASE), __phys_to_pfn(SL2312_RAID_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_FLASH_CTRL_BASE), __phys_to_pfn(SL2312_FLASH_CTRL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_DRAM_CTRL_BASE), __phys_to_pfn(SL2312_DRAM_CTRL_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_GENERAL_DMA_BASE), __phys_to_pfn(SL2312_GENERAL_DMA_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_USB0_BASE), __phys_to_pfn(SL2312_USB_BASE), SZ_512K, MT_DEVICE}, +{IO_ADDRESS(SL2312_USB1_BASE), __phys_to_pfn(SL2312_USB1_BASE), SZ_512K, MT_DEVICE}, +{FLASH_VADDR(SL2312_FLASH_BASE), __phys_to_pfn(SL2312_FLASH_BASE), SZ_16M, MT_DEVICE}, +}; + +void __init sl2312_map_io(void) +{ + iotable_init(sl2312_io_desc, ARRAY_SIZE(sl2312_io_desc)); +} diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/pci.c linux-sl3516/arch/arm/mach-sl2312/pci.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/pci.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/pci.c 2006-10-17 18:39:04.000000000 +0930 @@ -0,0 +1,358 @@ +/* + * linux/arch/arm/mach-sl2312/pci_sl2312.c + * + * PCI functions for sl2312 host PCI bridge + * + * Copyright (C) 2003 StorLink Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define DEBUG + +// sl2312 PCI bridge access routines + +#define PCI_IOSIZE_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE))) +#define PCI_PROT_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x04)) +#define PCI_CTRL_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x08)) +#define PCI_SOFTRST_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x10)) +#define PCI_CONFIG_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x28)) +#define PCI_DATA_REG (*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x2C)) + +static spinlock_t sl2312_pci_lock = SPIN_LOCK_UNLOCKED; +// for initialize PCI devices +struct resource pci_ioport_resource = { "PCI IO", IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x100, IO_ADDRESS(SL2312_PCI_IO_BASE) + SZ_512K - 1, IORESOURCE_IO }; +struct resource pci_iomem_resource = { "PCI mem", SL2312_PCI_MEM_BASE, SL2312_PCI_MEM_BASE + SZ_128M - 1, IORESOURCE_MEM }; + +extern struct irqdesc irq_desc[NR_IRQS]; + +static int sl2312_read_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 *val) +{ + unsigned long addr,data; + unsigned long flags; + + spin_lock_irqsave(&sl2312_pci_lock, flags); + addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3); + PCI_CONFIG_REG = addr; + data = PCI_DATA_REG; + + switch (size) { + case 1: + *val = (u8) (data >> ((where & 0x03) * 8)); + break; + case 2: + *val = (u16) (data >> ((where & 0x02) * 8)); + break; + case 4: + *val = data; + if ((where >= 0x10) && (where <= 0x24)) { + if ((*val & 0xfff00000) == SL2312_PCI_IO_BASE) { + *val &= 0x000fffff; + *val |= IO_ADDRESS(SL2312_PCI_IO_BASE); + } + } + break; + } + spin_unlock_irqrestore(&sl2312_pci_lock, flags); +// printk("READ==>slot=%d fn=%d where=%d value=%x\n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,*val); + return PCIBIOS_SUCCESSFUL; +} + +static int sl2312_write_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 val) +{ + unsigned long addr,data; + unsigned long flags; + + spin_lock_irqsave(&sl2312_pci_lock, flags); + addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3); + PCI_CONFIG_REG = addr; + data = PCI_DATA_REG; + + switch (size) { + case 1: + data &= ~(0xff << ((where & 0x03) * 8)); + data |= (val << ((where & 0x03) * 8)); + PCI_DATA_REG = data; + break; + case 2: + data &= ~(0xffff << ((where & 0x02) * 8)); + data |= (val << ((where & 0x02) * 8)); + PCI_DATA_REG = data; + break; + case 4: + if ((where >= 0x10) && (where <= 0x24)) { + if ((val & 0xfff00000) == IO_ADDRESS(SL2312_PCI_IO_BASE)) { + val &= 0x000fffff; + val |= SL2312_PCI_IO_BASE; + } + } + PCI_DATA_REG = val; + break; + } + spin_unlock_irqrestore(&sl2312_pci_lock, flags); + +// printk("WRITE==> slot=%d fn=%d where=%d value=%x \n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,val); + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops sl2312_pci_ops = { + .read = sl2312_read_config, + .write = sl2312_write_config, +}; + + +int __init sl2312_pci_setup_resources(struct resource **resource) +{ + PCI_IOSIZE_REG = 0; // 1M IO size + PCI_CTRL_REG = 0x06; + + resource[0] = &pci_ioport_resource; + resource[1] = &pci_iomem_resource; + resource[2] = NULL; + + return 1; +} + +//static int sl2312_pci_fault(unsigned long addr, struct pt_regs *regs) +//{ +// return 1; +//} + + +/********************************************************************** + * MASK(disable) PCI interrupt + * 0: PCI INTA, 1: PCI INTB, ... // for Linux interrupt routing + * 16: PERR // for PCI module internal use + * 17: SERR,.. respect to PCI CTRL2 REG + **********************************************************************/ +void sl2312_pci_mask_irq(unsigned int irq) +{ + struct pci_bus bus; + unsigned int tmp; + + bus.number = 0; + sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp); + if (irq < 16) { // for linux int routing + tmp &= ~(1 << (irq + 16 + 6)); + } + else { + tmp &= ~(1 << irq); + } + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); +} + +/* UNMASK(enable) PCI interrupt */ +void sl2312_pci_unmask_irq(unsigned int irq) +{ + struct pci_bus bus; + unsigned int tmp; + + bus.number = 0; + sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp); + if (irq < 16) { // for linux int routing + tmp |= (1 << (irq + 16 + 6)); + } + else { + tmp |= (1 << irq); + } + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); +} + +/* Get PCI interrupt source */ +int sl2312_pci_get_int_src(void) +{ + struct pci_bus bus; + unsigned int tmp=0; + + bus.number = 0; + sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp); + if (tmp & (1 << 28)) { // PCI INTA + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); + return IRQ_PCI_INTA; + } + if (tmp & (1 << 29)) { // PCI INTB + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); + return IRQ_PCI_INTB; + } + if (tmp & (1 << 30)) { // PCI INTC + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); + return IRQ_PCI_INTC; + } + if (tmp & (1 << 31)) { // PCI INTD + sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp); + return IRQ_PCI_INTD; + } + // otherwise, it should be a PCI error + return IRQ_PCI; +} + +static irqreturn_t sl2312_pci_irq(int irq, void *devid, struct pt_regs *regs) +{ + struct irqdesc *desc; + struct irqaction *action; + int retval = 0; + + return 1; + + irq = sl2312_pci_get_int_src(); + desc = &irq_desc[irq]; + action = desc->action; + do { + retval |= action->handler(irq, devid, regs); + action = action->next; + } while (action); + + return 1; +} + +//extern int (*external_fault)(unsigned long addr, struct pt_regs *regs); + +void __init sl2312_pci_preinit(void) +{ + struct pci_bus bus; + unsigned long flags; + unsigned int temp; + int ret; + + /* + * Hook in our fault handler for PCI errors + */ +// external_fault = sl2312_pci_fault; + + spin_lock_irqsave(&sl2312_pci_lock, flags); + + /* + * Grab the PCI interrupt. + */ + ret = request_irq(IRQ_PCI, sl2312_pci_irq, 0, "sl2312 pci int", NULL); + if (ret) + printk(KERN_ERR "PCI: unable to grab PCI error " + "interrupt: %d\n", ret); + + spin_unlock_irqrestore(&sl2312_pci_lock, flags); + + // setup pci bridge + bus.number = 0; /* device 0, function 0 */ + temp = (SL2312_PCI_DMA_MEM1_BASE & 0xfff00000) | (SL2312_PCI_DMA_MEM1_SIZE << 16); + sl2312_write_config(&bus, 0, SL2312_PCI_MEM1_BASE_SIZE, 4, temp); + +} + +/* + * No swizzle on SL2312 + */ +static u8 __init sl2312_pci_swizzle(struct pci_dev *dev, u8 *pinp) +{ + return PCI_SLOT(dev->devfn); +} + +/* + * map the specified device/slot/pin to an IRQ. This works out such + * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1. + */ +static int __init sl2312_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int intnr = ((slot + (pin - 1)) & 3) + 4; /* the IRQ number of PCI bridge */ + + printk("%s : slot = %d pin = %d \n",__func__,slot,pin); + switch (slot) + { + case 12: + if (pin==1) + { + intnr = 3; + } + else + { + intnr = 0; + } + break; + case 11: + intnr = (2 + (pin - 1)) & 3; + break; + case 10: + intnr = (1 + (pin - 1)) & 3; + break; + case 9: + intnr = (pin - 1) & 3; + break; + } +// if (slot == 10) +// intnr = (1 + (pin - 1)) & 3; +// else if (slot == 9) +// intnr = (pin - 1) & 3; + return (IRQ_PCI_INTA + intnr); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +struct pci_bus * __init sl2312_pci_scan_bus(int nr, struct pci_sys_data *sysdata) +{ + return (pci_scan_bus(0, &sl2312_pci_ops, sysdata)); + +} + +int __init sl2312_pci_setup(int nr, struct pci_sys_data *sys) +{ + int ret = 0; + + if (nr == 0) { + ret = sl2312_pci_setup_resources(sys->resource); + } + + return ret; +} + + +struct hw_pci sl2312_pci __initdata = { + .setup = sl2312_pci_setup, + .preinit = sl2312_pci_preinit, + .nr_controllers = 1, + .swizzle = sl2312_pci_swizzle, + .map_irq = sl2312_pci_map_irq, + .scan = sl2312_pci_scan_bus, +}; + +static int __init sl2312_pci_init(void) +{ + if (machine_is_sl2312()) + pci_common_init(&sl2312_pci); + return 0; +} + +subsys_initcall(sl2312_pci_init); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/sl2312-otg-1.c linux-sl3516/arch/arm/mach-sl2312/sl2312-otg-1.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/sl2312-otg-1.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/sl2312-otg-1.c 2006-04-21 12:42:01.000000000 +0930 @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/mach-pxa/sl2312.c + * + * Author: Nicolas Pitre + * Created: Nov 05, 2002 + * Copyright: MontaVista Software Inc. + * + * Code specific to sl2312 aka Bulverde. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include "asm/arch/sl2312.h" +#include "asm/arch/irqs.h" +#include +#include +#include + +/* + * device registration specific to sl2312. + */ + +static u64 sl2312_dmamask_1 = 0xffffffffUL; + +static struct resource sl2312_otg_resources_1[] = { + [0] = { + .start = 0x69000000, + .end = 0x69000fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB1, + .end = IRQ_USB1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ehci_1_device = { + .name = "ehci-hcd-FOTG2XX-1", + .id = -1, + .dev = { + .dma_mask = &sl2312_dmamask_1, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(sl2312_otg_resources_1), + .resource = sl2312_otg_resources_1, +}; + +static struct platform_device *devices[] __initdata = { + &ehci_1_device, +}; + +static int __init sl2312_1_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(sl2312_1_init); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/sl2312-otg.c linux-sl3516/arch/arm/mach-sl2312/sl2312-otg.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/sl2312-otg.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/sl2312-otg.c 2006-04-12 16:11:02.000000000 +0930 @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/mach-pxa/sl2312.c + * + * Author: Nicolas Pitre + * Created: Nov 05, 2002 + * Copyright: MontaVista Software Inc. + * + * Code specific to sl2312 aka Bulverde. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include "asm/arch/sl2312.h" +#include "asm/arch/irqs.h" +#include +#include +#include + +/* + * device registration specific to sl2312. + */ + +static u64 sl2312_dmamask = 0xffffffffUL; + +static struct resource sl2312_otg_resources[] = { + [0] = { + .start = 0x68000000, + .end = 0x68000fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB0, + .end = IRQ_USB0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ehci_device = { + .name = "ehci-hcd-FOTG2XX", + .id = -1, + .dev = { + .dma_mask = &sl2312_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(sl2312_otg_resources), + .resource = sl2312_otg_resources, +}; + +static struct platform_device *devices[] __initdata = { + &ehci_device, +}; + +static int __init sl2312_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(sl2312_init); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/sl3516_device.c linux-sl3516/arch/arm/mach-sl2312/sl3516_device.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/sl3516_device.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/sl3516_device.c 2006-11-03 17:24:03.000000000 +1030 @@ -0,0 +1,90 @@ +/* + * linux/arch/arm/mach-2312/sl3516_device.c + * + * Author: Nicolas Pitre + * Created: Nov 05, 2002 + * Copyright: MontaVista Software Inc. + * + * Code specific to sl2312 aka Bulverde. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include "asm/arch/sl2312.h" +#include "asm/arch/irqs.h" +#include +#include + +/* + * device registration specific to sl2312. + */ + +static u64 sl3516_dmamask = 0xffffffffUL; + +static struct resource sl3516_sata_resources[] = { + [0] = { + .start = 0x63400000, + .end = 0x63400040, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IDE1, + .end = IRQ_IDE1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sata_device = { + .name = "lepus-sata", + .id = -1, + .dev = { + .dma_mask = &sl3516_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(sl3516_sata_resources), + .resource = sl3516_sata_resources, +}; + +static struct resource sl3516_sata0_resources[] = { + [0] = { + .start = 0x63000000, + .end = 0x63000040, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IDE0, + .end = IRQ_IDE0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sata0_device = { + .name = "lepus-sata0", + .id = -1, + .dev = { + .dma_mask = &sl3516_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(sl3516_sata0_resources), + .resource = sl3516_sata0_resources, +}; + +static struct platform_device *sata_devices[] __initdata = { + &sata_device, + &sata0_device, +}; + +static int __init sl3516_init(void) +{ + return platform_add_devices(sata_devices, ARRAY_SIZE(sata_devices)); +} + +subsys_initcall(sl3516_init); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/time.c linux-sl3516/arch/arm/mach-sl2312/time.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/time.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/time.c 2006-06-21 19:08:04.000000000 +0930 @@ -0,0 +1,134 @@ +/* + * linux/include/asm-arm/arch-epxa10db/time.h + * + * Copyright (C) 2001 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#define TIMER_TYPE (volatile unsigned int*) +#include +// #define FIQ_PLUS 1 + + +/* + * IRQ handler for the timer + */ +static irqreturn_t sl2312_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ +// unsigned int led; + // ...clear the interrupt +#ifdef FIQ_PLUS + *((volatile unsigned int *)FIQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK); +#else + *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK); +#endif + +#if 0 + if(!(jiffies % HZ)) + { + led = jiffies / HZ; +// printk("ticks %x \n", led); + } + do_leds(); + do_timer(regs); + do_profile(regs); +#endif + timer_tick(regs); + return IRQ_HANDLED; +} + +static struct irqaction sl2312_timer_irq = { + .name = "SL2312 Timer Tick", + .flags = SA_INTERRUPT, + .handler = sl2312_timer_interrupt, +}; + +unsigned long sl2312_gettimeoffset (void) +{ + return 0L; +} + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init sl2312_time_init(void) +{ + // For clock rate adjusting + unsigned int tick_rate=0; + +#ifdef CONFIG_SL3516_ASIC + unsigned int clock_rate_base = 130000000; + unsigned int reg_v=0; + + //--> Add by jason for clock adjust + reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_STATUS))); + reg_v >>= 15; + tick_rate = (clock_rate_base + (reg_v & 0x07)*10000000); + + // FPGA use AHB bus tick rate + printk("Bus: %dMHz",tick_rate/1000000); + + tick_rate /= 6; // APB bus run AHB*(1/6) + + switch((reg_v>>3)&3){ + case 0: printk("(1/1)\n") ; + break; + case 1: printk("(3/2)\n") ; + break; + case 2: printk("(24/13)\n") ; + break; + case 3: printk("(2/1)\n") ; + break; + } + //<-- +#else + printk("Bus: %dMHz(1/1)\n",CLOCK_TICK_RATE/1000000); // FPGA use 20MHz + tick_rate = CLOCK_TICK_RATE; +#endif + + + /* + * Make irqs happen for the system timer + */ + // initialize timer interrupt + // low active and edge trigger +#ifdef FIQ_PLUS + *((volatile unsigned int *)FIQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK); + *((volatile unsigned int *)FIQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK); + setup_irq(IRQ_TIMER1, &sl2312_timer_irq); + /* Start the timer */ + *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ); + *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ); + *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_1_CR_ENABLE_MSK|TIMER_1_CR_INT_MSK); +#else + *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK); + *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK); + setup_irq(IRQ_TIMER2, &sl2312_timer_irq); + /* Start the timer */ + *TIMER_COUNT(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ); + *TIMER_LOAD(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ); + *TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_2_CR_ENABLE_MSK|TIMER_2_CR_INT_MSK); +#endif + +} + + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mach-sl2312/xor.c linux-sl3516/arch/arm/mach-sl2312/xor.c --- linux-2.6.15-armeb/arch/arm/mach-sl2312/xor.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mach-sl2312/xor.c 2006-10-24 17:26:38.000000000 +0930 @@ -0,0 +1,1200 @@ +/* + * arch/arm/mach-sl2312/xor.c + * + * Support functions for the Gemini Soc. This is + * a HW XOR unit that is specifically designed for use with RAID5 + * applications. This driver provides an interface that is used by + * the Linux RAID stack. + * + * Original Author: Jason Lee + * + * Contributors:Sanders + Jason Lee + * + * + * Maintainer: Jason Lee + * + * Copyright (C) 2005 Storlink Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * History: (06/25/2005, DJ) Initial Creation + * + * Versing 1.0.0 Initial version + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * pick up local definitions + */ +#define XOR_SW_FILL_IN +#include "hw_xor.h" + + +//#define XOR_DEBUG +//#define XOR_TEST 1 +#ifdef XOR_TEST +#define TEST_ITERATION 1000 +#define SPIN_WAIT 1 +#endif +#ifdef XOR_DEBUG +#define DPRINTK(s, args...) printk("Gemini XOR: " s "\n", ## args) +#define DENTER() DPRINTK("Entered...\n"); +#define DEXIT() DPRINTK("Exited...\n"); +#else +#define DPRINTK(s, args...) +#define DENTER() +#define DEXIT() +#endif + +//#define SPIN_WAIT + +/* globals */ +static RAID_T tp; +static RAID_TXDMA_CTRL_T txdma_ctrl; +RAID_RXDMA_CTRL_T rxdma_ctrl; + +//#ifndef SPIN_WAIT +static spinlock_t raid_lock; +//#endif + +static unsigned int tx_desc_virtual_base; +static unsigned int rx_desc_virtual_base; +RAID_DESCRIPTOR_T *tx_desc_ptr; +RAID_DESCRIPTOR_T *rx_desc_ptr; + +/* static prototypes */ +#define DMA_MALLOC(size,handle) pci_alloc_consistent(NULL,size,handle) +#define DMA_MFREE(mem,size,handle) pci_free_consistent(NULL,size,mem,handle) + +static int gemini_xor_init_desc(void); + +static unsigned int raid_read_reg(unsigned int offset) +{ + unsigned int reg_val; + + reg_val = readl(RAID_BASE_ADDR + offset); + return (reg_val); +} + +static void raid_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask) +{ + unsigned int reg_val; + unsigned int *addr; + + reg_val = ( raid_read_reg(offset) & (~bit_mask) ) | (data & bit_mask); + addr = (unsigned int *)(RAID_BASE_ADDR + offset); + writel(reg_val,addr); + return; +} + +#ifndef SPIN_WAIT +__inline__ void xor_queue_descriptor(void) +{ + unsigned int flags,status=1; + + DPRINTK("Going to sleep"); + + while(status){ + yield(); + //schedule(); + spin_lock_irqsave(&raid_lock,flags); + status = tp.busy; + spin_unlock_irqrestore(&raid_lock, flags); + } +// tp.status = COMPLETE; + DPRINTK("woken up!"); + +} +#endif + +#ifdef SPIN_WAIT +static void gemini_xor_isr(int d_n) +#else +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28) +static void gemini_xor_isr(int irq, void *dev_id, struct pt_regs *regs) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static irqreturn_t gemini_xor_isr(int irq, void *dev_instance, struct pt_regs *regs) +#endif +#endif +{ + + unsigned int err; + RAID_DMA_STATUS_T dma_status; +// RAID_DESCRIPTOR_T *rdesc,*tdesc; +// unsigned int *paddr; + + dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS); +#ifdef SPIN_WAIT + while( (dma_status.bits32& (1<<31) ) ==0 ){ + udelay(1); + dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS); + } + +/* tdesc = tp.tx_first_desc; + rdesc = tp.rx_first_desc; + for(d_n;d_n>0;d_n--){ + if( tdesc->func_ctrl.bits.own == DMA ){ + paddr = tdesc; + printk("error tx desc:0x%x\n",*paddr++); + printk("error tx desc:0x%x\n",*paddr++); + printk("error tx desc:0s%x\n",*paddr++); + printk("error tx desc:0x%x\n",*paddr); + while(1); + } + tdesc = (RAID_DESCRIPTOR_T *)((tdesc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + } + + if( rdesc->func_ctrl.bits.own == DMA ){ + paddr = rdesc; + printk("error rx desc:0x%x\n",*paddr++); + printk("error rx desc:0x%x\n",*paddr++); + printk("error rx desc:0s%x\n",*paddr++); + printk("error rx desc:0x%x\n",*paddr); + while(1); + } +*/ +#endif + + if(dma_status.bits32 & ((1<<31)|(1<<26))){ + // if no bug , we can turn off rx finish interrupt + dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS); + err = raid_read_reg(RAID_DMA_DEVICE_ID); + tp.busy = 0; + + if(err&0x00FF0000){ + tp.status = ERROR; + printk("XOR:%s error code %x\n",(err&0x00F00000)?"tx":"rx",err); + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28) + return ; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#ifndef SPIN_WAIT + return IRQ_RETVAL(IRQ_HANDLED); +#endif +#endif + } + // 16~19 rx error code + // 20~23 tx error codd + + dma_status.bits.tsFinishI = 1; + dma_status.bits.rsFinishI = 1; + raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0x84000000); // clear INT + +// printk("xor %d\n",d_n); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28) + return ; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#ifndef SPIN_WAIT + return IRQ_RETVAL(IRQ_HANDLED); +#endif +#endif + } + + #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28) + return ; + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + #ifndef SPIN_WAIT + printk("XOR: DMA status register(0x%8x)\n",dma_status.bits32); + return IRQ_RETVAL(IRQ_HANDLED); + #endif + #endif +} + +void +xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) +{ + int status=0; + unsigned int flags; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + spin_lock_irqsave(&raid_lock,flags); + while(tp.status != COMPLETE){ + spin_unlock_irqrestore(&raid_lock, flags); + //printk("XOR yield2\n"); +#ifdef XOR_SW_FILL_IN + xor_arm4regs_2(bytes,p1,p2); + return ; +#else + yield(); +#endif + } + spin_unlock_irqrestore(&raid_lock, flags); + tp.status = RUNNING; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + consistent_sync(p2, bytes, DMA_TO_DEVICE); + + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 2; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00020000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + wmb(); + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p2); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 1; // last descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00010000; + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); // keep last descript + + wmb(); + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf); + tp.rx_desc->buf_addr = (unsigned int)__pa(p1); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR +// tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return ; + } + + // change status +// tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(2); +#else + xor_queue_descriptor(); +#endif + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*2) ; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; +// tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} + +void +xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3) +{ + int status=0; + unsigned int flags; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + spin_lock_irqsave(&raid_lock,flags); + if(tp.status != COMPLETE){ + spin_unlock_irqrestore(&raid_lock, flags); + //printk("XOR yield3\n"); +#ifdef XOR_SW_FILL_IN + xor_arm4regs_3(bytes,p1,p2,p3); + return; +#else + yield(); +#endif + } + spin_unlock_irqrestore(&raid_lock, flags); + tp.status = RUNNING; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + consistent_sync(p2, bytes, DMA_TO_DEVICE); + consistent_sync(p3, bytes, DMA_TO_DEVICE); + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 2; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00020000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p2); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x0000000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p3); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 1; // last descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00010000; + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); // keep last descript + + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf); + tp.rx_desc->buf_addr = (unsigned int)__pa(p1); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR +// tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript \n"); + return ; + } + + // change status +// tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + wmb(); + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(3); +#else + xor_queue_descriptor(); +#endif + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*3) | 0x0B; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B; + //tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} + +void +xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4) +{ + int status=0; + unsigned int flags; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + spin_lock_irqsave(&raid_lock,flags); + if(tp.status != COMPLETE){ + spin_unlock_irqrestore(&raid_lock, flags); + //printk("S\n"); +#ifdef XOR_SW_FILL_IN + xor_arm4regs_4(bytes,p1,p2,p3,p4); + return; +#else + msleep(1); + yield(); +#endif + } + spin_unlock_irqrestore(&raid_lock, flags); + + tp.status = RUNNING; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + consistent_sync(p2, bytes, DMA_TO_DEVICE); + consistent_sync(p3, bytes, DMA_TO_DEVICE); + consistent_sync(p4, bytes, DMA_TO_DEVICE); + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 2; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00020000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_cur_desc->buf_addr = (unsigned int)__pa(p2); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00000000; + tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p3); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00000000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p4); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 1; // last descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00010000; +// tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); // keep last descript + + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF); + tp.rx_desc->buf_addr = (unsigned int)__pa(p1); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR +// tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return ; + } + + // change status +// tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + wmb(); + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(4); +#else + xor_queue_descriptor(); +#endif + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*4) | 0x0B; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B; + //tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} + +void +xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4, unsigned long *p5) +{ + + int status=0; + unsigned int flags; + + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + spin_lock_irqsave(&raid_lock,flags); + while(tp.status != COMPLETE){ + spin_unlock_irqrestore(&raid_lock, flags); + //printk("XOR yield5\n"); +#ifdef XOR_SW_FILL_IN + xor_arm4regs_5(bytes,p1,p2,p3,p4,p5); + return; +#else + msleep(1); + yield(); +#endif + } + spin_unlock_irqrestore(&raid_lock, flags); + tp.status = RUNNING; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + consistent_sync(p2, bytes, DMA_TO_DEVICE); + consistent_sync(p3, bytes, DMA_TO_DEVICE); + consistent_sync(p4, bytes, DMA_TO_DEVICE); + consistent_sync(p5, bytes, DMA_TO_DEVICE); + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 2; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00020000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + wmb(); + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p2); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00000000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + wmb(); + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p3); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00000000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + wmb(); + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p4); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 0; // first descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command + tp.tx_desc->flg_status.bits32 = 0x00000000; + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + wmb(); + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + + + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc->buf_addr = (unsigned int)__pa(p5); // pysical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ +// tp.tx_desc->flg_status.bits_cmd_status.bcc = 1; // last descript +// tp.tx_desc->flg_status.bits_cmd_status.mode = 0; // only support XOR command +// tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->flg_status.bits32 = 0x00010000; + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base); + tp.tx_finished_desc = tp.tx_desc; // keep last descript + + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF); + tp.rx_desc->buf_addr = (unsigned int)__pa(p1); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR +// tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return ; + } + + // change status +// tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + wmb(); + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(5); +#else + xor_queue_descriptor(); +#endif + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*5) | 0x0B; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B; + //tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} + +#ifdef XOR_TEST +void +raid_memset(unsigned int *p1, unsigned int pattern, unsigned int bytes) +{ + int status=0,i; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + *p1 = pattern; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + + while(tp.status != COMPLETE){ + DPRINTK("XOR yield\n"); + //schedule(); + yield(); + } + tp.status = RUNNING; + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = 4; /* total frame byte count */ + tp.tx_desc->flg_status.bits_cmd_status.bcc = bytes; // bytes to fill + tp.tx_desc->flg_status.bits_cmd_status.mode = CMD_FILL; // only support memory FILL command + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b; +// tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base); + + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF); + tp.rx_desc->buf_addr = (unsigned int)__pa(p1); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR + tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ +// tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base); + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + tp.rx_finished_desc = tp.rx_desc; + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return ; + } + + // change status + //tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(2); +#else + xor_queue_descriptor(); +#endif + + for(i=1; i<(bytes/sizeof(int)); i++) { + if(p1[0]!=p1[i]){ + printk("pattern set error!\n"); + while(1); + } + } + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; + //tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} +#endif + +void +raid_memcpy(unsigned int *to, unsigned int *from, unsigned int bytes) +{ + int status=0,i; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + // flush the cache to memory before H/W XOR touches them + consistent_sync(to, bytes, DMA_BIDIRECTIONAL); + consistent_sync(from,bytes, DMA_TO_DEVICE); + + while(tp.status != COMPLETE){ + DPRINTK("XOR yield\n"); + //schedule(); + yield(); + } + tp.status = RUNNING; + + tp.tx_desc = tp.tx_first_desc; + tp.rx_desc = tp.rx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF); + tp.tx_desc->buf_addr = (unsigned int)__pa(from); // physical address + tp.tx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.tx_desc->flg_status.bits32 = CMD_CPY; // only support memory FILL command + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b; +// tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base); + + // prepare rx descript + raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF); + tp.rx_desc->buf_addr = (unsigned int)__pa(to); + tp.rx_desc->func_ctrl.bits.buffer_size = bytes; /* total frame byte count */ + tp.rx_desc->flg_status.bits32 = 0; // link data from XOR + tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.rx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ +// tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base); + tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return ; + } + + // change status + //tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + rxdma_ctrl.bits.rd_start = 1; + // start rx DMA + txdma_ctrl.bits.td_start = 1; + + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(2); +#else + xor_queue_descriptor(); +#endif + +#ifdef XOR_TEST + for(i=1; i<(bytes/sizeof(int)); i++) { + if(to[i]!=from[i]){ + printk("pattern check error!\n"); + printk("offset=0x%x p1=%x p2=%x\n",i*4,to[i],from[i]); + while(1); + } + } +#endif + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; + tp.status = COMPLETE; +// tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; + //tp.rx_desc = tp.rx_first_desc ; +// tp.rx_desc->func_ctrl.bits.own = DMA; + +} +EXPORT_SYMBOL(raid_memcpy); + +#ifdef XOR_TEST +int +raid_memchk(unsigned int *p1, unsigned int pattern, unsigned int bytes) +{ + int status=0; + RAID_DMA_STATUS_T dma_status; + + if(bytes > (1<<(SRAM_PAR_SIZE+11))){ + printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes); + } + + status = ((pattern&0xFFFF)%bytes )/4; + p1[status] = pattern; + + while(tp.status != COMPLETE){ + DPRINTK("XOR yield\n"); + //schedule(); + yield(); + } + tp.status = RUNNING; + + // flush the cache to memory before H/W XOR touches them + consistent_sync(p1, bytes, DMA_BIDIRECTIONAL); + + tp.tx_desc = tp.tx_first_desc; + if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){ + // prepare tx descript + raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF); + tp.tx_desc->buf_addr = (unsigned int)__pa(p1); // physical address + tp.tx_desc->func_ctrl.bits.raid_ctrl_status = 0; + tp.tx_desc->func_ctrl.bits.buffer_size = bytes ; /* total frame byte count */ + tp.tx_desc->flg_status.bits32 = CMD_CHK; // only support memory FILL command + tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03; /*only one descriptor*/ + tp.tx_desc->func_ctrl.bits.own = DMA; /* set owner bit */ + tp.tx_desc->next_desc_addr.bits32 = 0x0000000b; +// tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base); + + } + else{ + /* no free tx descriptor */ + printk("XOR:no free tx descript"); + return -1; + } + + // change status + //tp.status = RUNNING; + status = tp.busy = 1; + + // start tx DMA + txdma_ctrl.bits.td_start = 1; + + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000); +// raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000); + +#ifdef SPIN_WAIT + gemini_xor_isr(2); +#else + xor_queue_descriptor(); +#endif + +// dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS); +// if (dma_status.bits32 & (1<<15)) { + + if((tp.tx_first_desc->func_ctrl.bits.raid_ctrl_status & 0x2)) { + status = 1; +// raid_write_reg(RAID_DMA_STATUS,0x00008000,0x00080000); + } + else{ + status = 0; + } + + tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ; + tp.status = COMPLETE; +// tp.rx_desc->func_ctrl.bits.own = DMA; + return status ; +} +#endif + +int __init gemini_xor_init(void) +{ + unsigned int res; + unsigned int *paddr1,*paddr2,*paddr3,i; + unsigned volatile char *charact; + unsigned volatile short *two_char; + unsigned volatile int *four_char; + + // init descript + res = gemini_xor_init_desc(); + if(res) { + printk("Init RAID Descript Fail!!\n"); + return -res; + } + + tp.device_name = "Gemini XOR Acceleration"; + + // request irq +#ifndef SPIN_WAIT + res = request_irq(IRQ_RAID, gemini_xor_isr, SA_INTERRUPT, tp.device_name, NULL); +#endif + if(res){ + printk(KERN_ERR "%s: unable to request IRQ %d for " + "HW XOR %d\n", tp.device_name, IRQ_RAID, res); + return -EBUSY; + } + +#ifdef XOR_TEST + +RETEST: + paddr1 = kmalloc(0x1000,GFP_KERNEL); + paddr2 = kmalloc(0x1000,GFP_KERNEL); + paddr3 = kmalloc(0x1000,GFP_KERNEL); + for(i=0;ifunc_ctrl.bits.own = CPU; + tp.tx_desc->func_ctrl.bits.buffer_size = 0; + tp.tx_desc_dma = tp.tx_desc_dma + sizeof(RAID_DESCRIPTOR_T); +// tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tp.tx_desc_dma | 0x0B; + tp.tx_desc->next_desc_addr.bits32 = ((unsigned int)tx_first_desc_dma | 0x0B) + i*0x10; + tp.tx_desc = &tp.tx_desc[1]; + } + tp.tx_desc->func_ctrl.bits.own = DMA; + tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tx_first_desc_dma|0x0b; + tp.tx_desc = tp.tx_cur_desc; + tp.tx_desc_dma = (unsigned int*)tx_first_desc_dma; + tp.tx_first_desc = tp.tx_desc ; + + tp.rx_cur_desc = tp.rx_desc; /* virtual address */ + tp.rx_finished_desc = tp.rx_desc; /* virtual address */ + rx_first_desc_dma = (dma_addr_t)tp.rx_desc_dma; /* physical address */ + for (i = 1; i < RX_DESC_NUM; i++) { + tp.rx_desc->func_ctrl.bits.own = DMA; + tp.rx_desc->func_ctrl.bits.buffer_size = 0; + tp.rx_desc_dma = tp.rx_desc_dma + sizeof(RAID_DESCRIPTOR_T); +// tp.rx_desc->next_desc_addr.bits32 = (unsigned int)tp.rx_desc_dma | 0x0B; + tp.rx_desc->next_desc_addr.bits32 = ((unsigned int)rx_first_desc_dma | 0x0B) + i*0x10; + tp.rx_desc = &tp.rx_desc[1]; + } + tp.rx_desc->func_ctrl.bits.own = DMA; + tp.rx_desc->next_desc_addr.bits32 = rx_first_desc_dma|0x0b; + tp.rx_desc = tp.rx_cur_desc; + tp.rx_desc_dma = (unsigned int*)rx_first_desc_dma; + tp.rx_first_desc = tp.rx_desc ; + tp.busy = 0; + tp.status = COMPLETE; + + // Partition SRAM size + raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003); + + // config tx DMA controler + txdma_ctrl.bits32 = 0; + txdma_ctrl.bits.td_start = 0; + txdma_ctrl.bits.td_continue = 1; + txdma_ctrl.bits.td_chain_mode = 1; + txdma_ctrl.bits.td_prot = 0; + txdma_ctrl.bits.td_burst_size = 1; + txdma_ctrl.bits.td_bus = 3; + txdma_ctrl.bits.td_endian = 0; + txdma_ctrl.bits.td_finish_en = 1; + txdma_ctrl.bits.td_fail_en = 1; + txdma_ctrl.bits.td_perr_en = 1; + txdma_ctrl.bits.td_eod_en = 0; // enable tx descript + txdma_ctrl.bits.td_eof_en = 0; + raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0xFFFFFFFF); + + // config rx DMA controler + rxdma_ctrl.bits32 = 0; + rxdma_ctrl.bits.rd_start = 0; + rxdma_ctrl.bits.rd_continue = 1; + rxdma_ctrl.bits.rd_chain_mode = 1; + rxdma_ctrl.bits.rd_prot = 0; + rxdma_ctrl.bits.rd_burst_size = 1; + rxdma_ctrl.bits.rd_bus = 3; + rxdma_ctrl.bits.rd_endian = 0; + rxdma_ctrl.bits.rd_finish_en = 0; + rxdma_ctrl.bits.rd_fail_en = 1; + rxdma_ctrl.bits.rd_perr_en = 1; + rxdma_ctrl.bits.rd_eod_en = 0; + rxdma_ctrl.bits.rd_eof_en = 0; + raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0xFFFFFFFF); + + // enable interrupt + dma_status.bits32 = 3; // enable RpInt + raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0xFFFFFFFF); + + return 0; +} + +module_init(gemini_xor_init); +module_exit(gemini_xor_exit); + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/Makefile linux-sl3516/arch/arm/Makefile --- linux-2.6.15-armeb/arch/arm/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/Makefile 2006-04-03 18:10:31.000000000 +0930 @@ -51,6 +51,7 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi +tune-$(CONFIG_CPU_FA52X) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale @@ -85,6 +86,7 @@ machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_L7200) := l7200 machine-$(CONFIG_ARCH_INTEGRATOR) := integrator + machine-$(CONFIG_ARCH_SL2312) := sl2312 machine-$(CONFIG_ARCH_CAMELOT) := epxa10db textaddr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 machine-$(CONFIG_ARCH_CLPS711X) := clps711x diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/cache-fa.S linux-sl3516/arch/arm/mm/cache-fa.S --- linux-2.6.15-armeb/arch/arm/mm/cache-fa.S 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mm/cache-fa.S 2006-06-14 12:18:12.000000000 +0930 @@ -0,0 +1,359 @@ +/* + * linux/arch/arm/mm/cache-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Processors: FA520 FA526 FA626 + * 03/31/2005 : Luke Lee created, modified from cache-v4wb.S + * 04/06/2005 : 1. Read CR0-1 and determine the cache size dynamically, + * to suit all Faraday CPU series + * 2. Fixed all functions + * 04/08/2005 : insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE + * 04/12/2005 : TODO: make this processor dependent or a self-modifying code to + * inline cache len/size info into the instructions, as reading cache + * size and len info in memory could cause another cache miss. + * 05/05/2005 : Modify fa_flush_user_cache_range to comply APCS. + * 05/19/2005 : Adjust for boundary conditions. + */ +#include +#include +#include +#include +#include +#include "proc-macros.S" + +#define CACHE_DLINESIZE 16 +#ifdef CONFIG_SL3516_ASIC +#define CACHE_DSIZE 8192 +#else +#define CACHE_DSIZE 16384 +#endif +#define CACHE_ILINESIZE 16 +#define CACHE_ISIZE 16384 + +/* Luke Lee 04/06/2005 ins begin */ +/* + * initialize_cache_info() + * + * Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to + * system register CR0-1 + * Destroyed register: r0, r1, r2, r3, ip + */ + .align +ENTRY(fa_initialize_cache_info) + mov r3, #1 @ r3 always = 1 + adr ip, __fa_cache_ilen + + mrc p15, 0, r0, c0, c0, 1 + /* ILEN */ + and r1, r0, #3 @ bits [1:0] + add r1, r1, #3 @ cache line size is at least 8 bytes (2^3) + mov r2, r3, lsl r1 @ r2 = 1<= limit? + bhs __flush_whole_cache @ flush whole D cache + +1: /* Luke Lee 04/06/2005 del 2 ins 5 */ + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif + /* Luke Lee 04/06/2005 mod 1 */ + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 +#endif /* CONFIG_CPU_DCACHE_DISABLE */ + +#ifndef CONFIG_CPU_FA_WB_DISABLE + tst r2, #VM_EXEC + /* Luke Lee 04/06/2005 mod 1 tofix todo : ne->eq */ + mcreq p15, 0, r4, c7, c10, 4 @ drain write buffer +#endif + + /* Luke Lee 04/06/2005 ins block */ +#ifdef CONFIG_CPU_FA_BTB + tst r2, #VM_EXEC + mov ip, #0 + mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB + nop + nop +#endif + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(fa_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ + /* fall through */ + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_coherent_kern_range) + /* fall through */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_coherent_user_range) +/* Luke Lee 04/06/2005 mod ok */ + /* Luke Lee 04/06/2005 ins 3 mod 1 */ + bic r0, r0, #CACHE_DLINESIZE-1 + +#if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) +1: /* Luke Lee 04/06/2005 del 2 ins 5 mod 1 */ +#ifndef CONFIG_CPU_DCACHE_DISABLE +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry +#endif +#endif /* CONFIG_CPU_DCACHE_DISABLE */ + +#ifndef CONFIG_CPU_ICACHE_DISABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 blo->bls +#endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */ + + mov ip, #0 +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB + nop + nop +#endif + +/* Luke Lee 04/08/2005 ins 1 skp 1 ins 1 */ +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, ip, c7, c10, 4 @ drain WB +#endif + + mov pc, lr + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_dma_inv_range) +/* Luke Lee 04/06/2005 mod ok */ + +#ifndef CONFIG_CPU_DCACHE_DISABLE + /* Luke Lee 04/06/2005 ins 4 mod 2 */ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + tst r0, #CACHE_DLINESIZE -1 + bic r0, r0, #CACHE_DLINESIZE -1 + mcrne p15, 0, r0, c7, c10, 1 @ clean boundary D entry + /* Luke Lee 04/06/2005 mod 1 */ + /* Luke Lee 05/19/2005 always clean the end-point boundary mcrne->mcr */ + //tst r1, #CACHE_DLINESIZE -1 + mcr p15, 0, r1, c7, c10, 1 @ clean boundary D entry + /* Luke Lee 04/06/2005 ins 1 */ +#else + bic r0, r0, #CACHE_DLINESIZE -1 +#endif + +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + /* Luke Lee 04/06/2005 mod 1 */ + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 blo->bls +#endif /* CONFIG_CPU_DCACHE_DISABLE */ + + /* Luke Lee 04/06/2005 ins 1 */ +#ifndef CONFIG_CPU_FA_WB_DISABLE + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer +#endif + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(fa_dma_clean_range) +/* Luke Lee 04/06/2005 mod ok */ +#ifndef CONFIG_CPU_DCACHE_DISABLE + /* Luke Lee 04/06/2005 ins 4 mod 2 */ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 blo->bls + /* Luke Lee 04/06/2005 ins 2 */ +#endif +#endif /* CONFIG_CPU_DCACHE_DISABLE */ + +#ifndef CONFIG_CPU_FA_WB_DISABLE + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer +#endif + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + * + * This is actually the same as fa_coherent_kern_range() + */ + .globl fa_dma_flush_range + .set fa_dma_flush_range, fa_coherent_kern_range + + __INITDATA + + .type fa_cache_fns, #object +ENTRY(fa_cache_fns) + .long fa_flush_kern_cache_all + .long fa_flush_user_cache_all + .long fa_flush_user_cache_range + .long fa_coherent_kern_range + .long fa_coherent_user_range + .long fa_flush_kern_dcache_page + .long fa_dma_inv_range + .long fa_dma_clean_range + .long fa_dma_flush_range + .size fa_cache_fns, . - fa_cache_fns diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/copypage-fa.S linux-sl3516/arch/arm/mm/copypage-fa.S --- linux-2.6.15-armeb/arch/arm/mm/copypage-fa.S 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mm/copypage-fa.S 2006-04-03 18:10:32.000000000 +0930 @@ -0,0 +1,106 @@ +/* + * linux/arch/arm/lib/copypage-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ASM optimised string functions + * 05/18/2005 : Luke Lee created, modified from copypage-v4wb.S + */ +#include +#include +#include + + .text +/* + * ARMv4 optimised copy_user_page for Faraday processors + * + * We flush the destination cache lines just before we write the data into the + * corresponding address. Since the Dcache is read-allocate, this removes the + * Dcache aliasing issue. The writes will be forwarded to the write buffer, + * and merged as appropriate. + * + * Note: We rely on all ARMv4 processors implementing the "invalidate D line" + * instruction. If your processor does not supply this, you have to write your + * own copy_user_page that does the right thing. + * + * copy_user_page(to,from,vaddr) + */ + .align 4 +ENTRY(fa_copy_user_page) +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + /* Write through */ + stmfd sp!, {r4, lr} @ 2 + mov r2, #PAGE_SZ/32 @ 1 + + ldmia r1!, {r3, r4, ip, lr} @ 4 +1: stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmneia r1!, {r3, r4, ip, lr} @ 4 + bne 1b @ 1 + + mcr p15, 0, r2, c7, c7, 0 @ flush ID cache + ldmfd sp!, {r4, pc} @ 3 +#else + /* Write back */ + stmfd sp!, {r4, lr} @ 2 + mov r2, #PAGE_SZ/32 @ 1 + +1: ldmia r1!, {r3, r4, ip, lr} @ 4 + mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4 + mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r3, r4, ip, lr} @ 4 + subs r2, r2, #1 @ 1 + bne 1b + mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB + ldmfd sp!, {r4, pc} @ 3 +#endif + +/* + * ARMv4 optimised clear_user_page + * + * Same story as above. + */ + .align 4 +ENTRY(fa_clear_user_page) + str lr, [sp, #-4]! + mov r1, #PAGE_SZ/32 @ 1 + mov r2, #0 @ 1 + mov r3, #0 @ 1 + mov ip, #0 @ 1 + mov lr, #0 @ 1 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + /* Write through */ +1: stmia r0!, {r2, r3, ip, lr} @ 4 + stmia r0!, {r2, r3, ip, lr} @ 4 + subs r1, r1, #1 @ 1 + bne 1b @ 1 + + mcr p15, 0, r1, c7, c7, 0 @ flush ID cache + ldr pc, [sp], #4 +#else + /* Write back */ +1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r2, r3, ip, lr} @ 4 + mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r2, r3, ip, lr} @ 4 + subs r1, r1, #1 @ 1 + bne 1b @ 1 + mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB + ldr pc, [sp], #4 +#endif + + __INITDATA + + .type fa_user_fns, #object +ENTRY(fa_user_fns) + .long fa_clear_user_page + .long fa_copy_user_page + .size fa_user_fns, . - fa_user_fns diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/init.c linux-sl3516/arch/arm/mm/init.c --- linux-2.6.15-armeb/arch/arm/mm/init.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/mm/init.c 2006-04-17 12:05:44.000000000 +0930 @@ -25,6 +25,7 @@ #include #include +#include #define TABLE_SIZE (2 * PTRS_PER_PTE * sizeof(pte_t)) @@ -310,6 +311,11 @@ initrd_end = initrd_start + phys_initrd_size; } #endif +#ifdef CONFIG_GEMINI_IPI + printk("CPU ID:%d\n",getcpuid()); +// reserve_bootmem_node(NODE_DATA(0), 0x400000, 0x400000); //CPU0 space +// reserve_bootmem_node(NODE_DATA(0), SHAREADDR, SHARE_MEM_SIZE); //share memory +#endif /* * Finally, reserve any node zero regions. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/Kconfig linux-sl3516/arch/arm/mm/Kconfig --- linux-2.6.15-armeb/arch/arm/mm/Kconfig 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/mm/Kconfig 2006-08-31 17:43:41.000000000 +0930 @@ -136,6 +136,25 @@ Say Y if you want support for the ARM926T processor. Otherwise, say N. +###### for Storlink SoC ###### +config CPU_FA526 + bool "FA526 processor" + depends on ARCH_SL2312 + default y + select CPU_32v4 + select CPU_ABRT_EV4 + select CPU_CACHE_FA + select CPU_CACHE_VIVT + select CPU_COPY_FA + select CPU_TLB_FA + select CPU_FA_BTB + help + The FA526 is a version of the ARM9 compatible processor, but with smaller + instruction and data caches. It is used in Storlink Sword device family. + + Say Y if you want support for the FA526 processor. + Otherwise, say N. + # ARM1020 - needs validating config CPU_ARM1020 bool "Support ARM1020T (rev 0) processor" @@ -317,6 +336,9 @@ config CPU_CACHE_VIPT bool +config CPU_CACHE_FA + bool + # The copy-page model config CPU_COPY_V3 bool @@ -330,6 +352,12 @@ config CPU_COPY_V6 bool +config CPU_COPY_FA + bool + +config CPU_FA_BTB + bool + # This selects the TLB model config CPU_TLB_V3 bool @@ -355,6 +383,14 @@ config CPU_TLB_V6 bool +config CPU_TLB_FA + bool + help + //TODO + Faraday ARM FA526 architecture, unified TLB with writeback cache + and invalidate instruction cache entry. Branch target buffer is also + supported. + comment "Processor Features" config ARM_THUMB @@ -382,21 +418,21 @@ config CPU_ICACHE_DISABLE bool "Disable I-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 || CPU_FA526 help Say Y here to disable the processor instruction cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_DISABLE bool "Disable D-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 || CPU_FA526 help Say Y here to disable the processor data cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" - depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE + depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 || CPU_FA526) && !CPU_DCACHE_DISABLE default y if CPU_ARM925T help Say Y here to use the data cache in writethrough mode. Unless you diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/Makefile linux-sl3516/arch/arm/mm/Makefile --- linux-2.6.15-armeb/arch/arm/mm/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/mm/Makefile 2006-04-03 18:10:32.000000000 +0930 @@ -23,6 +23,7 @@ obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o +obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o @@ -30,12 +31,14 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o +obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o +obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o @@ -44,6 +47,7 @@ obj-$(CONFIG_CPU_ARM922T) += proc-arm922.o obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o +obj-$(CONFIG_CPU_FA526) += proc-fa526.o obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o obj-$(CONFIG_CPU_ARM1022) += proc-arm1022.o diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/proc-fa526.S linux-sl3516/arch/arm/mm/proc-fa526.S --- linux-2.6.15-armeb/arch/arm/mm/proc-fa526.S 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mm/proc-fa526.S 2006-04-03 18:10:32.000000000 +0930 @@ -0,0 +1,403 @@ +/* + * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526 + * + * Copyright (C) 2005 Faraday Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * These are the low level assembler for performing cache and TLB + * functions on the fa526. + * + * Written by : Luke Lee + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc-macros.S" + +#define CACHE_DLINESIZE 16 + + .text +/* + * cpu_fa526_proc_init() + */ +ENTRY(cpu_fa526_proc_init) + /* MMU is already ON here, ICACHE, DCACHE conditionally disabled */ + + mov r0, #1 + nop + nop + mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR + nop + nop + + mrc p15, 0, r0, c1, c0, 0 @ read ctrl register + +#ifdef CONFIG_CPU_FA_BTB + orr r0, r0, #CR_Z +#else + bic r0, r0, #CR_Z +#endif +#ifdef CONFIG_CPU_FA_WB_DISABLE + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 @ drain write buffer + nop + nop + bic r0, r0, #CR_W +#else + orr r0, r0, #CR_W +#endif +#ifdef CONFIG_CPU_DCACHE_DISABLE + bic r0, r0, #CR_C +#else + orr r0, r0, #CR_C +#endif +#ifdef CONFIG_CPU_ICACHE_DISABLE + bic r0, r0, #CR_I +#else + orr r0, r0, #CR_I +#endif + + nop + nop + mcr p15, 0, r0, c1, c0, 0 + nop + nop + + mov r5, lr + bl fa_initialize_cache_info @ destroy r0~r4 + mov pc, r5 @ return + + +/* + * cpu_fa526_proc_fin() + */ +ENTRY(cpu_fa526_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + + bl fa_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + + nop + nop + ldmfd sp!, {pc} + +/* + * cpu_fa526_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 4 +ENTRY(cpu_fa526_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, ip, c7, c10, 4 @ drain WB +#endif + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + + bic ip, ip, #0x0800 @ BTB off + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + nop + nop + mov pc, r0 + +/* + * cpu_fa526_do_idle() + */ + .align 4 +ENTRY(cpu_fa526_do_idle) + +#ifdef CONFIG_CPU_FA_IDLE + nop + nop + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt (IDLE mode) +#endif + mov pc, lr + + +ENTRY(cpu_fa526_dcache_clean_area) + +#ifndef CONFIG_CPU_DCACHE_DISABLE +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif +#endif + mov pc, lr + + +/* =============================== PageTable ============================== */ + +/* + * cpu_fa526_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 4 + + .globl fault_address +fault_address: + .long 0 + +ENTRY(cpu_fa526_switch_mm) + + mov ip, #0 +#ifndef CONFIG_CPU_DCACHE_DISABLE +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else + mcr p15, 0, ip, c7, c14, 0 @ Clean and invalidate whole DCache +#endif +#endif /*CONFIG_CPU_DCACHE_DISABLE*/ + +#ifndef CONFIG_CPU_ICACHE_DISABLE + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache +#endif + +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, ip, c7, c10, 4 @ drain WB +#endif + +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed + nop + nop +#endif + bic r0, r0, #0xff @ clear bits [7:0] + bic r0, r0, #0x3f00 @ clear bits [13:8] + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB + nop + nop + mov pc, lr + +/* + * cpu_fa526_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 4 +ENTRY(cpu_fa526_set_pte) + str r1, [r0], #-2048 @ linux version + + eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY + + bic r2, r1, #PTE_SMALL_AP_MASK + bic r2, r2, #PTE_TYPE_MASK + orr r2, r2, #PTE_TYPE_SMALL + + tst r1, #L_PTE_USER @ User? + orrne r2, r2, #PTE_SMALL_AP_URO_SRW + + tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + orreq r2, r2, #PTE_SMALL_AP_UNO_SRW + + tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + movne r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r3, r2, #0x0a @ C & small page? 1010 + tst r3, #0x0b @ 1011 + biceq r2, r2, #4 +#endif + str r2, [r0] @ hardware version + + mov r2, #0 + mcr p15, 0, r2, c7, c10, 0 @ clean D cache all + +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, r2, c7, c10, 4 @ drain WB +#endif +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, r2, c7, c5, 6 @ invalidate BTB + nop + nop +#endif + mov pc, lr + + __INIT + + .type __fa526_setup, #function +__fa526_setup: + /* On return of this routine, r0 must carry correct flags for CFG register */ + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 + + mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM + + mov r0, #1 + mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR + + mrc p15, 0, r0, c9, c1, 0 @ DScratchpad + bic r0, r0, #1 + mcr p15, 0, r0, c9, c1, 0 + mrc p15, 0, r0, c9, c1, 1 @ IScratchpad + bic r0, r0, #1 + mcr p15, 0, r0, c9, c1, 1 + + mov r0, #0 + mcr p15, 0, r0, c1, c1, 0 @ turn-off ECR + +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All + nop + nop +#endif + + mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + + mrc p15, 0, r0, c1, c0 @ get control register v4 + ldr r5, fa526_cr1_clear + bic r0, r0, r5 + ldr r5, fa526_cr1_set + orr r0, r0, r5 + +#ifdef CONFIG_CPU_FA_BTB + orr r0, r0, #CR_Z +#else + bic r0, r0, #CR_Z +#endif +#ifdef CONFIG_CPU_FA_WB_DISABLE + mov r12, #0 + mcr p15, 0, r12, c7, c10, 4 @ drain write buffer + nop + nop + bic r0, r0, #CR_W @ .... .... .... 1... +#else + orr r0, r0, #CR_W +#endif + + mov pc, lr + .size __fa526_setup, . - __fa526_setup + + /* + * .RVI ZFRS BLDP WCAM + * ..11 0001 .111 1101 + * + */ + .type fa526_cr1_clear, #object + .type fa526_cr1_set, #object +fa526_cr1_clear: + .word 0x3f3f +fa526_cr1_set: + .word 0x317D + + __INITDATA + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type fa526_processor_functions, #object +fa526_processor_functions: + .word v4_early_abort + .word cpu_fa526_proc_init + .word cpu_fa526_proc_fin + .word cpu_fa526_reset + .word cpu_fa526_do_idle + .word cpu_fa526_dcache_clean_area + .word cpu_fa526_switch_mm + .word cpu_fa526_set_pte + .size fa526_processor_functions, . - fa526_processor_functions + + .section ".rodata" + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv4" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + + .type cpu_fa526_name, #object +cpu_fa526_name: + .ascii "FA526" +#ifndef CONFIG_CPU_ICACHE_DISABLE + .ascii "i" +#endif +#ifndef CONFIG_CPU_DCACHE_DISABLE + .ascii "d" +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + .ascii "(wt)" +#else + .ascii "(wb)" +#endif +#endif + .ascii "\0" + .size cpu_fa526_name, . - cpu_fa526_name + + .align + + .section ".proc.info.init", #alloc, #execinstr + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH +#define __PMD_SECT_BUFFERABLE 0 +#else +#define __PMD_SECT_BUFFERABLE PMD_SECT_BUFFERABLE +#endif + + .type __fa526_proc_info,#object +__fa526_proc_info: + .long 0x66015261 + .long 0xff01fff1 + .long PMD_TYPE_SECT | \ + __PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __fa526_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF + .long cpu_fa526_name + .long fa526_processor_functions + .long fa_tlb_fns + .long fa_user_fns + .long fa_cache_fns + .size __fa526_proc_info, . - __fa526_proc_info + + diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/mm/tlb-fa.S linux-sl3516/arch/arm/mm/tlb-fa.S --- linux-2.6.15-armeb/arch/arm/mm/tlb-fa.S 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/arch/arm/mm/tlb-fa.S 2006-04-03 18:10:32.000000000 +0930 @@ -0,0 +1,96 @@ +/* + * linux/arch/arm/mm/tlb-fa.S + * + * Copyright (C) 2005 Faraday Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ARM architecture version 4, Faraday variation. + * This assume an unified TLBs, with a write buffer, and branch target buffer (BTB) + * + * Processors: FA520 FA526 FA626 + * 03/31/2005 : Created by Luke Lee, modified from tlb-v4wbi.S + * 05/06/2005 : Fixed buggy CPU versions that did not invalidate the associated + * data cache entries when invalidating TLB entries. + */ +#include +#include +#include +#include +#include "proc-macros.S" + + +/* + * flush_user_tlb_range(start, end, mm) + * + * Invalidate a range of TLB entries in the specified address space. + * + * - start - range start address + * - end - range end address + * - mm - mm_struct describing address space + */ + .align 4 +ENTRY(fa_flush_user_tlb_range) + + vma_vm_mm ip, r2 + act_mm r3 @ get current->active_mm + eors r3, ip, r3 @ == mm ? + movne pc, lr @ no, we dont do anything + mov r3, #0 + +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, r3, c7, c10, 4 @ drain WB +#endif + + vma_vm_flags r2, r2 + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 + +1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 blo -> bls + +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB + nop + nop +#endif + mov pc, lr + + +ENTRY(fa_flush_kern_tlb_range) + mov r3, #0 + + mcr p15, 0, r3, c7, c10, 0 @ clean Dcache all 06/03/2005 + +#ifndef CONFIG_CPU_FA_WB_DISABLE + mcr p15, 0, r3, c7, c10, 4 @ drain WB +#endif + + bic r0, r0, #0x0ff + bic r0, r0, #0xf00 +1: + mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry + add r0, r0, #PAGE_SZ + cmp r0, r1 + bls 1b @ Luke Lee 05/19/2005 blo -> bls + +#ifdef CONFIG_CPU_FA_BTB + mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB + nop + nop +#endif + mov pc, lr + + + __INITDATA + + .type fa_tlb_fns, #object +ENTRY(fa_tlb_fns) + .long fa_flush_user_tlb_range + .long fa_flush_kern_tlb_range + .long fa_tlb_flags + .size fa_tlb_fns, . - fa_tlb_fns diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/arm/tools/mach-types linux-sl3516/arch/arm/tools/mach-types --- linux-2.6.15-armeb/arch/arm/tools/mach-types 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/arm/tools/mach-types 2006-04-03 18:10:32.000000000 +0930 @@ -208,7 +208,8 @@ fester SA1100_FESTER FESTER 191 gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 -i519 ARCH_I519 I519 194 +#i519 ARCH_I519 I519 194 +sl2312 ARCH_SL2312 SL2312 194 nexio SA1100_NEXIO NEXIO 195 bitbox SA1100_BITBOX BITBOX 196 g200 SA1100_G200 G200 197 diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/drivers/axisflashmap.c linux-sl3516/arch/cris/arch-v10/drivers/axisflashmap.c --- linux-2.6.15-armeb/arch/cris/arch-v10/drivers/axisflashmap.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/drivers/axisflashmap.c 2006-04-03 18:10:32.000000000 +0930 @@ -11,6 +11,9 @@ * partition split defined below. * * $Log: axisflashmap.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.11 2004/11/15 10:27:14 starvik * Corrected typo (Thanks to Milton Miller ). * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/drivers/ds1302.c linux-sl3516/arch/cris/arch-v10/drivers/ds1302.c --- linux-2.6.15-armeb/arch/cris/arch-v10/drivers/ds1302.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/drivers/ds1302.c 2006-04-03 18:10:32.000000000 +0930 @@ -7,6 +7,9 @@ *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init *! *! $Log: ds1302.c,v $ +*! Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee +*! initial +*! *! Revision 1.18 2005/01/24 09:11:26 mikaelam *! Minor changes to get DS1302 RTC chip driver to work *! diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/drivers/eeprom.c linux-sl3516/arch/cris/arch-v10/drivers/eeprom.c --- linux-2.6.15-armeb/arch/cris/arch-v10/drivers/eeprom.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/drivers/eeprom.c 2006-04-03 18:10:32.000000000 +0930 @@ -20,6 +20,9 @@ *! in the spin-lock. *! *! $Log: eeprom.c,v $ +*! Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee +*! initial +*! *! Revision 1.12 2005/06/19 17:06:46 starvik *! Merge of Linux 2.6.12. *! diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/drivers/gpio.c linux-sl3516/arch/cris/arch-v10/drivers/gpio.c --- linux-2.6.15-armeb/arch/cris/arch-v10/drivers/gpio.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/drivers/gpio.c 2006-04-03 18:10:32.000000000 +0930 @@ -9,6 +9,9 @@ * Johan Adolfsson (read/set directions, write, port G) * * $Log: gpio.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.17 2005/06/19 17:06:46 starvik * Merge of Linux 2.6.12. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/drivers/i2c.c linux-sl3516/arch/cris/arch-v10/drivers/i2c.c --- linux-2.6.15-armeb/arch/cris/arch-v10/drivers/i2c.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/drivers/i2c.c 2006-04-03 18:10:32.000000000 +0930 @@ -12,6 +12,9 @@ *! don't use PB_I2C if DS1302 uses same bits, *! use PB. *! $Log: i2c.c,v $ +*! Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee +*! initial +*! *! Revision 1.13 2005/03/07 13:13:07 starvik *! Added spinlocks to protect states etc *! diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/kernel/debugport.c linux-sl3516/arch/cris/arch-v10/kernel/debugport.c --- linux-2.6.15-armeb/arch/cris/arch-v10/kernel/debugport.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/kernel/debugport.c 2006-04-03 18:10:32.000000000 +0930 @@ -12,6 +12,9 @@ * init_etrax_debug() * * $Log: debugport.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.27 2005/06/10 10:34:14 starvik * Real console support * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/kernel/entry.S linux-sl3516/arch/cris/arch-v10/kernel/entry.S --- linux-2.6.15-armeb/arch/cris/arch-v10/kernel/entry.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/kernel/entry.S 2006-04-03 18:10:32.000000000 +0930 @@ -7,6 +7,9 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: entry.S,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.28 2005/06/20 05:06:30 starvik * Remove unnecessary diff to kernel.org tree * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/kernel/fasttimer.c linux-sl3516/arch/cris/arch-v10/kernel/fasttimer.c --- linux-2.6.15-armeb/arch/cris/arch-v10/kernel/fasttimer.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/kernel/fasttimer.c 2006-04-03 18:10:32.000000000 +0930 @@ -5,6 +5,9 @@ * This may be useful in other OS than Linux so use 2 space indentation... * * $Log: fasttimer.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.9 2005/03/04 08:16:16 starvik * Merge of Linux 2.6.11. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/kernel/head.S linux-sl3516/arch/cris/arch-v10/kernel/head.S --- linux-2.6.15-armeb/arch/cris/arch-v10/kernel/head.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/kernel/head.S 2006-04-03 18:10:32.000000000 +0930 @@ -7,6 +7,9 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: head.S,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.10 2005/06/20 05:12:54 starvik * Remove unnecessary diff to kernel.org tree * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/kernel/kgdb.c linux-sl3516/arch/cris/arch-v10/kernel/kgdb.c --- linux-2.6.15-armeb/arch/cris/arch-v10/kernel/kgdb.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/kernel/kgdb.c 2006-04-03 18:10:32.000000000 +0930 @@ -18,6 +18,9 @@ *! Jul 21 1999 Bjorn Wesen eLinux port *! *! $Log: kgdb.c,v $ +*! Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee +*! initial +*! *! Revision 1.6 2005/01/14 10:12:17 starvik *! KGDB on separate port. *! Console fixes from 2.4. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/lib/dram_init.S linux-sl3516/arch/cris/arch-v10/lib/dram_init.S --- linux-2.6.15-armeb/arch/cris/arch-v10/lib/dram_init.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/lib/dram_init.S 2006-04-03 18:10:32.000000000 +0930 @@ -11,6 +11,9 @@ * Authors: Mikael Starvik (starvik@axis.com) * * $Log: dram_init.S,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.4 2003/09/22 09:21:59 starvik * Decompresser is linked to 0x407xxxxx and sdram commands are at 0x000xxxxx * so we need to mask off 12 bits. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v10/README.mm linux-sl3516/arch/cris/arch-v10/README.mm --- linux-2.6.15-armeb/arch/cris/arch-v10/README.mm 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v10/README.mm 2006-04-03 18:10:32.000000000 +0930 @@ -3,6 +3,9 @@ HISTORY: $Log: README.mm,v $ +Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee +initial + Revision 1.1 2001/12/17 13:59:27 bjornw Initial revision diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v32/drivers/gpio.c linux-sl3516/arch/cris/arch-v32/drivers/gpio.c --- linux-2.6.15-armeb/arch/cris/arch-v32/drivers/gpio.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v32/drivers/gpio.c 2006-04-03 18:10:32.000000000 +0930 @@ -10,6 +10,9 @@ * port to ETRAX FS. * * $Log: gpio.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.16 2005/06/19 17:06:49 starvik * Merge of Linux 2.6.12. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/arch-v32/kernel/fasttimer.c linux-sl3516/arch/cris/arch-v32/kernel/fasttimer.c --- linux-2.6.15-armeb/arch/cris/arch-v32/kernel/fasttimer.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/arch-v32/kernel/fasttimer.c 2006-04-03 18:10:32.000000000 +0930 @@ -5,6 +5,9 @@ * This may be useful in other OS than Linux so use 2 space indentation... * * $Log: fasttimer.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.11 2005/01/04 11:15:46 starvik * Don't share timer IRQ. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/kernel/process.c linux-sl3516/arch/cris/kernel/process.c --- linux-2.6.15-armeb/arch/cris/kernel/process.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/kernel/process.c 2006-04-03 18:10:32.000000000 +0930 @@ -8,6 +8,9 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: process.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.21 2005/03/04 08:16:17 starvik * Merge of Linux 2.6.11. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/kernel/ptrace.c linux-sl3516/arch/cris/kernel/ptrace.c --- linux-2.6.15-armeb/arch/cris/kernel/ptrace.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/kernel/ptrace.c 2006-04-03 18:10:32.000000000 +0930 @@ -8,6 +8,9 @@ * Authors: Bjorn Wesen * * $Log: ptrace.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.10 2004/09/22 11:50:01 orjanf * * Moved get_reg/put_reg to arch-specific files. * * Added functions to access debug registers (CRISv32). diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/mm/fault.c linux-sl3516/arch/cris/mm/fault.c --- linux-2.6.15-armeb/arch/cris/mm/fault.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/mm/fault.c 2006-04-03 18:10:32.000000000 +0930 @@ -6,6 +6,9 @@ * Authors: Bjorn Wesen * * $Log: fault.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.20 2005/03/04 08:16:18 starvik * Merge of Linux 2.6.11. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/cris/mm/init.c linux-sl3516/arch/cris/mm/init.c --- linux-2.6.15-armeb/arch/cris/mm/init.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/cris/mm/init.c 2006-04-03 18:10:32.000000000 +0930 @@ -7,6 +7,9 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: init.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:32 amos_lee + * initial + * * Revision 1.11 2004/05/28 09:28:56 starvik * Calculation of loops_per_usec moved because initalization order has changed * in Linux 2.6. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/boot/setup.S linux-sl3516/arch/m32r/boot/setup.S --- linux-2.6.15-armeb/arch/m32r/boot/setup.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/boot/setup.S 2006-04-03 18:10:34.000000000 +0930 @@ -5,7 +5,7 @@ * and Hitoshi Yamamoto * */ -/* $Id$ */ +/* $Id: setup.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/kernel/head.S linux-sl3516/arch/m32r/kernel/head.S --- linux-2.6.15-armeb/arch/m32r/kernel/head.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/kernel/head.S 2006-04-03 18:10:34.000000000 +0930 @@ -7,7 +7,7 @@ * Hitoshi Yamamoto */ -/* $Id$ */ +/* $Id: head.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include __INIT diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/ashxdi3.S linux-sl3516/arch/m32r/lib/ashxdi3.S --- linux-2.6.15-armeb/arch/m32r/lib/ashxdi3.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/ashxdi3.S 2006-04-03 18:10:34.000000000 +0930 @@ -4,7 +4,7 @@ * Copyright (C) 2001,2002 Hiroyuki Kondo, and Hirokazu Takata * */ -/* $Id$ */ +/* $Id: ashxdi3.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/checksum.S linux-sl3516/arch/m32r/lib/checksum.S --- linux-2.6.15-armeb/arch/m32r/lib/checksum.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/checksum.S 2006-04-03 18:10:34.000000000 +0930 @@ -25,7 +25,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -/* $Id$ */ +/* $Id: checksum.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/delay.c linux-sl3516/arch/m32r/lib/delay.c --- linux-2.6.15-armeb/arch/m32r/lib/delay.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/delay.c 2006-04-03 18:10:34.000000000 +0930 @@ -5,7 +5,7 @@ * Copyright (c) 2004 Hirokazu Takata */ -/* $Id$ */ +/* $Id: delay.c,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/memcpy.S linux-sl3516/arch/m32r/lib/memcpy.S --- linux-2.6.15-armeb/arch/m32r/lib/memcpy.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/memcpy.S 2006-04-03 18:10:34.000000000 +0930 @@ -10,7 +10,7 @@ * src: r1 * n : r2 */ -/* $Id$ */ +/* $Id: memcpy.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ .text diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/memset.S linux-sl3516/arch/m32r/lib/memset.S --- linux-2.6.15-armeb/arch/m32r/lib/memset.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/memset.S 2006-04-03 18:10:34.000000000 +0930 @@ -12,7 +12,7 @@ * ret: r0 * */ -/* $Id$ */ +/* $Id: memset.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/lib/strlen.S linux-sl3516/arch/m32r/lib/strlen.S --- linux-2.6.15-armeb/arch/m32r/lib/strlen.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/lib/strlen.S 2006-04-03 18:10:34.000000000 +0930 @@ -6,7 +6,7 @@ * size_t strlen(const char *s); * */ -/* $Id$ */ +/* $Id: strlen.S,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ */ #include diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/mappi/dot.gdbinit.nommu linux-sl3516/arch/m32r/mappi/dot.gdbinit.nommu --- linux-2.6.15-armeb/arch/m32r/mappi/dot.gdbinit.nommu 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/mappi/dot.gdbinit.nommu 2006-04-03 18:10:34.000000000 +0930 @@ -1,5 +1,5 @@ # .gdbinit file -# $Id$ +# $Id: dot.gdbinit.nommu,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ #----- # NOTE: this file is generated by a script, "gen_gdbinit.pl". # (Please type "gen_gdbinit.pl --help" and check the help message). diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/m32r/mappi/dot.gdbinit.smp linux-sl3516/arch/m32r/mappi/dot.gdbinit.smp --- linux-2.6.15-armeb/arch/m32r/mappi/dot.gdbinit.smp 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/m32r/mappi/dot.gdbinit.smp 2006-04-03 18:10:34.000000000 +0930 @@ -1,5 +1,5 @@ # .gdbinit file -# $Id$ +# $Id: dot.gdbinit.smp,v 1.1.1.1 2006/04/03 08:40:34 amos_lee Exp $ # setting set width 0d70 diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/x86_64/kernel/entry.S linux-sl3516/arch/x86_64/kernel/entry.S --- linux-2.6.15-armeb/arch/x86_64/kernel/entry.S 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/x86_64/kernel/entry.S 2006-04-03 18:10:44.000000000 +0930 @@ -5,7 +5,7 @@ * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs * Copyright (C) 2000 Pavel Machek * - * $Id$ + * $Id: entry.S,v 1.1.1.1 2006/04/03 08:40:44 amos_lee Exp $ */ /* diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/arch/x86_64/kernel/setup.c linux-sl3516/arch/x86_64/kernel/setup.c --- linux-2.6.15-armeb/arch/x86_64/kernel/setup.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/arch/x86_64/kernel/setup.c 2006-04-03 18:10:44.000000000 +0930 @@ -6,7 +6,7 @@ * Nov 2001 Dave Jones * Forked from i386 setup code. * - * $Id$ + * $Id: setup.c,v 1.1.1.1 2006/04/03 08:40:44 amos_lee Exp $ */ /* diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/block/ll_rw_blk.c linux-sl3516/block/ll_rw_blk.c --- linux-2.6.15-armeb/block/ll_rw_blk.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/block/ll_rw_blk.c 2006-10-02 18:59:42.000000000 +0930 @@ -27,6 +27,7 @@ #include #include #include +#include /* * for max sense size @@ -37,6 +38,16 @@ static void blk_unplug_timeout(unsigned long data); static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); +#ifdef CONFIG_SL2312_SHARE_PIN +DECLARE_WAIT_QUEUE_HEAD(flash_wait); +extern struct wait_queue_head_t *wq; +extern unsigned int share_pin_flag; +extern unsigned int check_sleep_flag; +int check_and_wait_flash_idle(int); +extern unsigned int ide0_base; +extern unsigned int flash_req; +#endif + /* * For the allocated request tables */ @@ -73,6 +84,48 @@ /* Number of requests a "batching" process may submit */ #define BLK_BATCH_REQ 32 +#ifdef CONFIG_SL2312_SHARE_PIN +int check_and_wait_flash_idle(int bit) +{ + unsigned int flag; + + if(test_bit(FLASH_SHARE_BIT, &share_pin_flag)||flash_req) + { + DECLARE_WAITQUEUE(wait, current); + + wake_up_interruptible(&wq); + + add_wait_queue(&flash_wait, &wait); + local_save_flags(flag); + do + { + set_current_state(TASK_INTERRUPTIBLE); + if(!test_bit(FLASH_SHARE_BIT, &share_pin_flag)&&(flash_req==0)) + { + set_bit(bit ,&share_pin_flag); +// printk("IDE running\n"); + local_irq_restore(flag|0x80); + break; + } + check_sleep_flag |= 0x00000002; + //printk("IDE yield\n"); + local_irq_restore(flag&(~0x80)); + yield(); + } while (1); + check_sleep_flag &= ~0x00000002; + current->state = TASK_RUNNING; + remove_wait_queue(&flash_wait, &wait); + return 0; + } + else { + local_save_flags(flag); + set_bit(bit ,&share_pin_flag); + check_sleep_flag &= ~0x00000002; + local_irq_restore(flag); + } +} +#endif + /* * Return the threshold (number of used requests) at which the queue is * considered to be congested. It include a little hysteresis to keep the @@ -2755,6 +2808,16 @@ req->ioprio = prio; req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; +#ifdef CONFIG_SL2312_SHARE_PIN + unsigned char *ptmp=req->q->queuedata; + if((ptmp[0]=='h')&&(ptmp[1]=='d')){ + ide_drive_t *drive = req->rq_disk->queue->queuedata; + if(drive){ + if(drive->hwif->io_ports[0]==ide0_base) + check_and_wait_flash_idle(IDE_RW_SHARE_BIT); + } + } +#endif spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) @@ -2834,7 +2897,8 @@ request_queue_t *q; sector_t maxsector; int ret, nr_sectors = bio_sectors(bio); - + + might_sleep(); /* Test device or partition size, when known. */ maxsector = bio->bi_bdev->bd_inode->i_size >> 9; @@ -3010,7 +3074,13 @@ { int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; - +#ifdef CONFIG_SL2312_SHARE_PIN + unsigned char *ptmp=req->q->queuedata; + ide_drive_t *drive; + if((ptmp[0]=='h')&&(ptmp[1]=='d')){ + drive= req->q->queuedata; + } +#endif /* * extend uptodate bool to allow < 0 value to be direct io error */ @@ -3042,6 +3112,18 @@ while ((bio = req->bio) != NULL) { int nbytes; +#if 0 // CONFIG_SL2312_SHARE_PIN + if(drive->hwif->io_ports[0]==ide0_base){ + clear_bit(IDE_RW_SHARE_BIT,&share_pin_flag); + check_sleep_flag &= ~0x00000002; + if(check_sleep_flag & 0x00000001) + { + check_sleep_flag &= ~(0x00000001); + wake_up_interruptible(&wq); + } + } +#endif + if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; @@ -3090,6 +3172,20 @@ } } +#ifdef CONFIG_SL2312_SHARE_PIN + if((ptmp[0]=='h')&&(ptmp[1]=='d')){ + if(drive->hwif->io_ports[0]==ide0_base){ + clear_bit(IDE_RW_SHARE_BIT,&share_pin_flag); + check_sleep_flag &= ~0x00000002; + if(check_sleep_flag & 0x00000001) + { + check_sleep_flag &= ~(0x00000001); + // wake_up_interruptible(&wq); + } + } + } +#endif + /* * completely done */ diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/cipher.c linux-sl3516/crypto/cipher.c --- linux-2.6.15-armeb/crypto/cipher.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/cipher.c 2006-10-25 16:22:14.000000000 +0930 @@ -1,7 +1,7 @@ /* * Cryptographic API. * - * Cipher operations. + * Cipher operations.p * * Copyright (c) 2002 James Morris * Copyright (c) 2005 Herbert Xu @@ -19,10 +19,37 @@ #include #include #include + +//debug_Aaron +#include #include #include "internal.h" #include "scatterwalk.h" +#ifdef CONFIG_SL2312_IPSEC +#include +#include +#include +#include + +unsigned long crypto_flags; +#define IPSEC_TEXT_LEN 32768 //2048 +unsigned char p[IPSEC_TEXT_LEN]; +spinlock_t crypto_done_lock = SPIN_LOCK_UNLOCKED; +//DECLARE_WAIT_QUEUE_HEAD(cipher_queue); +unsigned int crypto_done = 1, crypto_go = 1; +struct IPSEC_PACKET_S crypto_op; + + +void crypto_callback(struct IPSEC_PACKET_S *op_info) +{ + spin_lock_irqsave(&crypto_done_lock,crypto_flags); + crypto_done = 1; + spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// wake_up(&cipher_queue); +} +#endif + static inline void xor_64(u8 *a, const u8 *b) { ((u32 *)a)[0] ^= ((u32 *)b)[0]; @@ -58,6 +85,24 @@ return bsize; } + +void hw_memcpy(char *to, char *from, unsigned long n) +{ + unsigned int i; + unsigned int p_to = __pa(to); + unsigned int p_from = __pa(from); + + consistent_sync(to,n,DMA_BIDIRECTIONAL); + //consistent_sync(from,n,DMA_BIDIRECTIONAL); + writel(p_from,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x24); /* set source address */ + writel(p_to,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x28); /* set destination address */ + writel(n,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x2c); /* set byte count */ + wmb(); + writel(0x00000001,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20); + + while (readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20)==0x00000001); +} + static inline unsigned int crypt_fast(const struct cipher_desc *desc, struct scatter_walk *in, struct scatter_walk *out, @@ -267,14 +312,90 @@ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else +#ifdef CONFIG_SL2312_IPSEC + { + /* get key & key length */ + crypto_op.cipher_key_size = keylen; + memcpy(crypto_op.cipher_key,key,keylen); + return 0; + } +#else return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, &tfm->crt_flags); +#endif } static int ecb_encrypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { +#ifdef CONFIG_SL2312_IPSEC + //wait_queue_t wait; +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if(crypto_done == 0) +// { +// //printk("%s :cipher not ready !!\n",__func__); +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// return -1; +// } +// crypto_done = 0; + int i=0, len=0; + unsigned char *q; + + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x \n",__func__,crypto_go,crypto_done); + return -1; + } + //crypto_done = 0; + crypto_go = 0; + +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + crypto_op.op_mode = CIPHER_ENC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)tfm->__crt_alg->cra_name,ECB);; + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; +// memcpy(crypto_op.iv,tfm->crt_cipher.cit_iv,tfm->crt_cipher.cit_ivsize); +// crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p;//kmap(src->page) + src->offset; + crypto_op.pkt_len = nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + crypto_op.out_packet = (u8 *)&p;//kmap(dst->page) + dst->offset; + ipsec_crypto_hw_process(&crypto_op); + +// //add_wait_queue(&cipher_queue, &wait); +// while (1) { +// //udelay(10); +//// set_current_state(TASK_INTERRUPTIBLE); +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if (crypto_done) /* whatever test your driver needs */ +// { +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// break; +// } +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// //udelay(1); +// schedule(); +// } + //set_current_state(TASK_RUNNING); + //remove_wait_queue(&cipher_queue, &wait); + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //consistent_sync(p, nbytes, DMA_BIDIRECTIONAL); + len+=dst[i].length; + i++; + }; + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; @@ -283,6 +404,7 @@ desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process; return crypt(&desc, dst, src, nbytes); +#endif } static int ecb_decrypt(struct crypto_tfm *tfm, @@ -290,6 +412,76 @@ struct scatterlist *src, unsigned int nbytes) { +#ifdef CONFIG_SL2312_IPSEC + + + //wait_queue_t wait; +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if(crypto_done == 0) +// { +// //printk("%s :cipher not ready !!\n",__func__); +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// return -1; +// } +// crypto_done = 0; + int i=0, len=0; + unsigned char *q; + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x\n",__func__,crypto_go, crypto_done); + return -1; + } + // crypto_done = 0; + crypto_go = 0; + + +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + crypto_op.op_mode = CIPHER_DEC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)tfm->__crt_alg->cra_name,ECB);; + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; +// memcpy(crypto_op.iv,tfm->crt_cipher.cit_iv,tfm->crt_cipher.cit_ivsize); +// crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p;//kmap(src->page) + src->offset; + crypto_op.pkt_len = nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + crypto_op.out_packet = (u8 *)&p;//kmap(dst->page) + dst->offset; + ipsec_crypto_hw_process(&crypto_op); + + //add_wait_queue(&cipher_queue, &wait); +// while (1) { +// //udelay(10); +// // set_current_state(TASK_INTERRUPTIBLE); +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if (crypto_done) /* whatever test your driver needs */ +// { +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// break; +// } +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// //udelay(1); +// schedule(); +// } + //set_current_state(TASK_RUNNING); + //remove_wait_queue(&cipher_queue, &wait); + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //consistent_sync(p, nbytes, DMA_BIDIRECTIONAL); + + len+=dst[i].length; + i++; + }; + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; @@ -298,6 +490,7 @@ desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process; return crypt(&desc, dst, src, nbytes); +#endif } static int cbc_encrypt(struct crypto_tfm *tfm, @@ -305,15 +498,136 @@ struct scatterlist *src, unsigned int nbytes) { +#ifdef CONFIG_SL2312_IPSEC + //wait_queue_t wait; + int i=0,len=0; + unsigned char *q; + + + + //spin_lock_irqsave(&crypto_done_lock,crypto_flags); + //if(crypto_done == 0) + //{ + // printk("%s :<-- not ready\n",__func__); + // printk("%s :cipher not ready !!\n",__func__); + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // return -1; + //} + //printk("%s :-->\n",__func__); + //printk("-->HW IPSEC cbc_encrypt : %x\n",nbytes); + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x\n",__func__,crypto_go, crypto_done); + return -1; + } + // crypto_done = 0; + crypto_go = 0; + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + + // p = kmalloc(nbytes,GFP_ATOMIC); + //if (p == NULL) { + // printk("P failed to load transform.\n"); + // return -1; + //} + + //printk("1--nbytes : %x \n",nbytes); +//len_err: + //memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + + i=0; len=0; + + crypto_op.op_mode = CIPHER_ENC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)&tfm->__crt_alg->cra_name,CBC); + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; //nbytes; + //printk("***2\n"); + memcpy(crypto_op.iv,tfm->crt_cipher.cit_iv,tfm->crt_cipher.cit_ivsize); + + crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p; + crypto_op.pkt_len = nbytes; //nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + memset(&p, 0x0, IPSEC_TEXT_LEN); + crypto_op.out_packet = (u8 *)&p; + // printk("\n*********1-1***********\n"); + //hexdump((p+len), src[i].length); + // hexdump((p), nbytes); + ipsec_crypto_hw_process(&crypto_op); + //printk("***2-1\n"); + //add_wait_queue(&cipher_queue, &wait); + + //while (1) { + // //udelay(10); +// // set_current_state(TASK_INTERRUPTIBLE); + // spin_lock_irqsave(&crypto_done_lock,crypto_flags); + // if (crypto_done) /* whatever test your driver needs */ + // { + // printk("%s :-->2\n",__func__); + // len=0; + // i=0; + // //printk("***2-2\n"); + // while(len < total_len){ + // q = kmap(dst[i].page) + dst[i].offset; + // //printk("***3\n"); + // memcpy((u8 *)q, (u8 *)(&p+len), dst[i].length); + // consistent_sync(&p, total_len, DMA_BIDIRECTIONAL); + // len+=dst[i].length; + // i++; + // printk("%s :-->2-0 len: %x q:0x%x\n",__func__, len, q); + // }; + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // printk("%s :-->2-1 len : %x\n",__func__, len); + // break; + // } + // printk("%s :-->2-2\n",__func__); + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // //udelay(1); + // schedule(); + //} + + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + //printk("***3\n"); + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //hw_memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //consistent_sync(p, nbytes, DMA_BIDIRECTIONAL); + + len+=dst[i].length; + i++; + + }; + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + + + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - + + int i=0,len=0; + static unsigned char *p; + //printk("-->SW IPSEC cbc_encrypt : %x\n",nbytes); desc.tfm = tfm; desc.crfn = cipher->cia_encrypt; desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt; desc.info = tfm->crt_cipher.cit_iv; + //printk("<--SW IPSEC cbc_encrypt : %x\n",nbytes); + + return crypt(&desc, dst, src, nbytes); + + + + //return 0; +#endif } static int cbc_encrypt_iv(struct crypto_tfm *tfm, @@ -321,15 +635,91 @@ struct scatterlist *src, unsigned int nbytes, u8 *iv) { +#ifdef CONFIG_SL2312_IPSEC + //wait_queue_t wait; +int i=0,len=0; +unsigned char *q; + + + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x \n",__func__,crypto_go,crypto_done); + return -1; + } + //crypto_done = 0; + crypto_go = 0; + + + +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if(crypto_done == 0) +// { +// //printk("%s :cipher not ready !!\n",__func__); +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// return -1; +// } + //printk("-->HW IPSEC cbc_encrypt_iv : %x\n",nbytes); + //printk("cbc_encrypt_iv : %x src[i].length : %d\n",i,src[i].length); + // crypto_done = 0; +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + + crypto_op.op_mode = CIPHER_ENC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)&tfm->__crt_alg->cra_name,CBC); + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; + memcpy(crypto_op.iv,iv,tfm->crt_cipher.cit_ivsize); + crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p;//p; + crypto_op.pkt_len = nbytes; //nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + crypto_op.out_packet = (u8 *)&p;//p; + ipsec_crypto_hw_process(&crypto_op); + + //add_wait_queue(&cipher_queue, &wait); +// while (1) { +// //udelay(10); +//// set_current_state(TASK_INTERRUPTIBLE); +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if (crypto_done) /* whatever test your driver needs */ +// { +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// break; +// } +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// //udelay(1); +// schedule(); +// } + //printk("<--HW IPSEC cbc_encrypt_iv : %x\n",nbytes); + //set_current_state(TASK_RUNNING); + //remove_wait_queue(&cipher_queue, &wait); + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //consistent_sync(p, nbytes, DMA_BIDIRECTIONAL); + len+=dst[i].length; + i++; + }; + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + //kfree(p); + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - +//printk("-->SW IPSEC cbc_encrypt_iv : %x\n",nbytes); desc.tfm = tfm; desc.crfn = cipher->cia_encrypt; desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt; desc.info = iv; - +//printk("<--SW IPSEC cbc_encrypt_iv : %x\n",nbytes); return crypt_iv_unaligned(&desc, dst, src, nbytes); +#endif } static int cbc_decrypt(struct crypto_tfm *tfm, @@ -337,15 +727,106 @@ struct scatterlist *src, unsigned int nbytes) { +#ifdef CONFIG_SL2312_IPSEC + //wait_queue_t wait; + int i=0, len=0; + unsigned char *q; + + + + //spin_lock_irqsave(&crypto_done_lock,crypto_flags); + //if(crypto_done == 0) + //{ + // //printk("%s :cipher not ready !!\n",__func__); + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // return -1; + //} + + //printk("%s :-->\n",__func__); + //printk("-->HW IPSEC cbc_decrypt : %x\n",nbytes); + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x \n",__func__,crypto_go,crypto_done); + return -1; + } + //crypto_done = 0; + crypto_go = 0; + //spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + + + + //crypto_op.cipher_key_size = tfm->crt_u.cipher.keylen; + //memcpy(crypto_op.cipher_key, tfm->crt_u.cipher.key, tfm->crt_u.cipher.keylen); + //printk("cbc_decrypt : %x src[i].length : %d\n",i,src[i].length); + crypto_op.op_mode = CIPHER_DEC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)&tfm->__crt_alg->cra_name,CBC); + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; + memcpy(crypto_op.iv,tfm->crt_cipher.cit_iv,tfm->crt_cipher.cit_ivsize); + crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p; //kmap(src[i].page) + src[i].offset; + crypto_op.pkt_len = nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + memset(&p, 0x0, IPSEC_TEXT_LEN); + crypto_op.out_packet = (u8 *)&p; //kmap(dst[i].page) + dst[i].offset; + + ipsec_crypto_hw_process(&crypto_op); + + //add_wait_queue(&cipher_queue, &wait); + //while (1) { + // //udelay(10); +// // set_current_state(TASK_INTERRUPTIBLE); + // spin_lock_irqsave(&crypto_done_lock,crypto_flags); + // if (crypto_done) /* whatever test your driver needs */ + // { + // len=0; + // i=0; + // while(len < total_len){ + // q = kmap(dst[i].page) + dst[i].offset; + // memcpy((u8 *)q, (u8 *)(&p+len), dst[i].length); + // consistent_sync(&p, total_len, DMA_BIDIRECTIONAL); + // printk("%s :--> len: %x q:0x%x\n",__func__, len, q); + // len+=dst[i].length; + // i++; + // }; + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // printk("%s :--> len : %x\n",__func__, len); + // break; + // } + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // //udelay(1); + // schedule(); + //} + + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //hw_memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + //consistent_sync(p, nbytes, DMA_BIDIRECTIONAL); + len+=dst[i].length; + i++; + }; + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - +//printk("-->SW IPSEC cbc_decrypt : %x\n",nbytes); desc.tfm = tfm; desc.crfn = cipher->cia_decrypt; desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt; desc.info = tfm->crt_cipher.cit_iv; - +//printk("<--SW IPSEC cbc_decrypt : %x\n",nbytes); return crypt(&desc, dst, src, nbytes); +#endif } static int cbc_decrypt_iv(struct crypto_tfm *tfm, @@ -353,15 +834,91 @@ struct scatterlist *src, unsigned int nbytes, u8 *iv) { +#ifdef CONFIG_SL2312_IPSEC + //wait_queue_t wait; + int i=0, len=0; + unsigned char *q; + + + + if(crypto_go == 0) + { + //printk("%s crypto_go : %x crypto_done:%x \n",__func__,crypto_go,crypto_done); + return -1; + } + //crypto_done = 0; + crypto_go = 0; + + + + + // spin_lock_irqsave(&crypto_done_lock,crypto_flags); + //if(crypto_done == 0) + //{ + // //printk("%s :cipher not ready !!\n",__func__); + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + // return -1; + //} + //printk("-->HW IPSEC cbc_decrypt_iv : %x\n",nbytes); + //printk("cbc_decrypt_iv : %x src[i].length : %d\n",i,src[i].length); + // crypto_done = 0; + // spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); + crypto_op.op_mode = CIPHER_DEC; + crypto_op.cipher_algorithm = ipsec_get_cipher_algorithm((unsigned char *)&tfm->__crt_alg->cra_name,CBC); + crypto_op.cipher_header_len = 0; + crypto_op.cipher_algorithm_len = nbytes; + memcpy(crypto_op.iv,iv,tfm->crt_cipher.cit_ivsize); + crypto_op.iv_size = tfm->crt_cipher.cit_ivsize; + crypto_op.in_packet = src;//(u8 *)&p;; //kmap(src[i].page) + src[i].offset; + crypto_op.pkt_len = nbytes; + if(crypto_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return -1; + } + crypto_op.callback = crypto_callback; + crypto_op.out_packet = (u8 *)&p;; //kmap(src[i].page) + src[i].offset; + ipsec_crypto_hw_process(&crypto_op); + + //add_wait_queue(&cipher_queue, &wait); +// while (1) { +// //udelay(10); +//// set_current_state(TASK_INTERRUPTIBLE); +// spin_lock_irqsave(&crypto_done_lock,crypto_flags); +// if (crypto_done) /* whatever test your driver needs */ +// { +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// break; +// } +// spin_unlock_irqrestore(&crypto_done_lock, crypto_flags); +// // udelay(1); +// schedule(); +// } + //printk("<--HW IPSEC cbc_decrypt_iv : %x\n",nbytes); + //set_current_state(TASK_RUNNING); + //remove_wait_queue(&cipher_queue, &wait); + len=0; + i=0; + while(len < nbytes){ + q = kmap(dst[i].page) + dst[i].offset; + memcpy((u8 *)q, (u8 *)(p+len), dst[i].length); + len+=dst[i].length; + i++; + }; + //kfree(p); + memset(&crypto_op, 0x0, sizeof(struct IPSEC_PACKET_S)); + return 0; +#else struct cipher_desc desc; struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - +//printk("-->SW IPSEC cbc_decrypt_iv : %x\n",nbytes); desc.tfm = tfm; desc.crfn = cipher->cia_decrypt; desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt; desc.info = iv; - +//printk("<--SW IPSEC cbc_decrypt_iv : %x\n",nbytes); return crypt_iv_unaligned(&desc, dst, src, nbytes); +#endif } static int nocrypt(struct crypto_tfm *tfm, diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/digest.c linux-sl3516/crypto/digest.c --- linux-2.6.15-armeb/crypto/digest.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/digest.c 2006-10-25 16:21:07.000000000 +0930 @@ -18,9 +18,34 @@ #include #include "internal.h" +#ifdef CONFIG_SL2312_IPSEC +#include +#include + +#define IPSEC_TEXT_LEN 32768 //2048 +#define DSG_NUMBER 32 +unsigned char di_packet[IPSEC_TEXT_LEN]; + +struct scatterlist dsg[DSG_NUMBER]; +/////////// + +extern unsigned long crypto_flags; +extern spinlock_t crypto_done_lock; +extern unsigned int crypto_done,crypto_go ; +//extern struct IPSEC_PACKET_S digest_op; +struct IPSEC_PACKET_S digest_op; + +extern void crypto_callback(struct IPSEC_PACKET_S *op_info); + +#endif + static void init(struct crypto_tfm *tfm) { tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); +#ifdef CONFIG_SL2312_IPSEC + memset(&dsg,0x00,DSG_NUMBER*sizeof(struct scatterlist)); + memset(&digest_op, 0x0, sizeof(struct IPSEC_PACKET_S)); +#endif } static void update(struct crypto_tfm *tfm, @@ -28,6 +53,56 @@ { unsigned int i; +#ifdef CONFIG_SL2312_IPSEC + + unsigned int plen=0; + unsigned char *in_packet; + + + if(crypto_go == 0) + printk("%s: crypto_go = %x\n",__func__,crypto_go); + crypto_go = 0; + + + + for(i=0;i__crt_alg->cra_name,0); //(0) AUTH; (1) HMAC + digest_op.callback = crypto_callback; + digest_op.auth_header_len = 0; + + +#else for (i = 0; i < nsg; i++) { struct page *pg = sg[i].page; @@ -50,29 +125,72 @@ l -= bytes_from_page; } while (l > 0); } +#endif +} + +static void +hexdump(unsigned char *buf, unsigned int len) +{ + while (len--) + printk("%02x", *buf++); + + printk("\n"); } static void final(struct crypto_tfm *tfm, u8 *out) { +#ifdef CONFIG_SL2312_IPSEC + + if(digest_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :length too long !!\n",__func__); + return; + } + digest_op.in_packet = &dsg; + digest_op.out_packet = (u8 *)&di_packet; + + + + ipsec_crypto_hw_process(&digest_op); + + //memcpy(out, (u8 *)(digest_op.out_packet+digest_op.pkt_len),crypto_tfm_alg_digestsize(tfm)); + memcpy(out, &di_packet[digest_op.pkt_len],crypto_tfm_alg_digestsize(tfm)); + + + +#else tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); +#endif } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { +#ifdef CONFIG_SL2312_IPSEC + { + digest_op.auth_key_size = keylen; + memcpy(digest_op.auth_key,key,keylen); + return 0; + } +#else u32 flags; if (tfm->__crt_alg->cra_digest.dia_setkey == NULL) return -ENOSYS; return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm), key, keylen, &flags); +#endif } static void digest(struct crypto_tfm *tfm, struct scatterlist *sg, unsigned int nsg, u8 *out) { - unsigned int i; +// tfm->crt_digest.dit_init(tfm); - +#ifdef CONFIG_SL2312_IPSEC + update(tfm,sg,nsg); + final(tfm,out); +#else + unsigned int i; for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), @@ -81,6 +199,7 @@ crypto_yield(tfm); } crypto_digest_final(tfm, out); +#endif } int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/hmac.c linux-sl3516/crypto/hmac.c --- linux-2.6.15-armeb/crypto/hmac.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/hmac.c 2006-10-25 16:20:43.000000000 +0930 @@ -19,8 +19,28 @@ #include #include #include +#include #include "internal.h" +#ifdef CONFIG_SL2312_IPSEC + +#include + +#define IPSEC_TEXT_LEN 32768 //2048 + 256 +unsigned char packet[IPSEC_TEXT_LEN]; +#define HSG_NUMBER 32 +struct scatterlist hsg[HSG_NUMBER]; + +extern unsigned long crypto_flags,crypto_go; +extern spinlock_t crypto_done_lock; +extern unsigned int crypto_done ; +//extern struct IPSEC_PACKET_S hmac_op; +struct IPSEC_PACKET_S hmac_op; + +extern void crypto_callback(struct IPSEC_PACKET_S *op_info); + +#endif + static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) { struct scatterlist tmp; @@ -51,6 +71,54 @@ void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) { +#ifdef CONFIG_SL2312_IPSEC + + int error = 0; + struct scatterlist tmpsc; + + + crypto_digest_init(tfm); + + if(*keylen > tfm->__crt_alg->cra_blocksize) + { + unsigned char *tk = kmalloc(tfm->__crt_alg->cra_blocksize, GFP_KERNEL); + if (!tk) { + printk(KERN_ERR "%s: tk is not allocated\n", __FUNCTION__); + error = -ENOMEM; + + } + + memset(tk, 0, tfm->__crt_alg->cra_blocksize); + + tmpsc.page = virt_to_page(key); + tmpsc.offset = offset_in_page(key); + tmpsc.length = *keylen; + + + tfm->crt_digest.dit_init(tfm); + tfm->crt_digest.dit_update(tfm, &tmpsc, 1); //nsg); + tfm->crt_digest.dit_final(tfm, tk); + crypto_go = 1; + memcpy(key,tk,tfm->__crt_alg->cra_blocksize); + *keylen = tfm->__crt_alg->cra_blocksize; + + kfree(tk); + } + + + + if(crypto_go == 0) + printk("%s: crypto_go = %x\n",__func__,crypto_go); + + + crypto_go = 0; + + + memset(&hmac_op,0x00,sizeof(struct IPSEC_PACKET_S)); + memset(&packet,0x00,IPSEC_TEXT_LEN); + memset(&hsg,0x00,HSG_NUMBER*sizeof(struct scatterlist)); + +#else unsigned int i; struct scatterlist tmp; char *ipad = tfm->crt_digest.dit_hmac_block; @@ -70,17 +138,81 @@ crypto_digest_init(tfm); crypto_digest_update(tfm, &tmp, 1); +#endif } void crypto_hmac_update(struct crypto_tfm *tfm, struct scatterlist *sg, unsigned int nsg) { +#ifdef CONFIG_SL2312_IPSEC + unsigned int plen=0,i; + unsigned char *in_packet; + + for(i=0;i__crt_alg->cra_name,1); //(0) AUTH; (1) HMAC + hmac_op.auth_key_size = *keylen; + memcpy(hmac_op.auth_key, key, *keylen); + + hmac_op.in_packet = &hsg; + hmac_op.out_packet = (u8 *)&packet; + + hmac_op.callback = crypto_callback; + hmac_op.auth_header_len = 0; + if(hmac_op.pkt_len > IPSEC_TEXT_LEN) + { + printk("%s :crypto_done not ready !!\n",__func__); + return; + } + + ipsec_crypto_hw_process(&hmac_op); + + //memcpy(out, (u8 *)(hmac_op.out_packet+hmac_op.pkt_len),crypto_tfm_alg_digestsize(tfm)); + memcpy(out, &packet[hmac_op.pkt_len],crypto_tfm_alg_digestsize(tfm)); + + hmac_op.pkt_len =0; + hmac_op.auth_algorithm_len =0; + +#else unsigned int i; struct scatterlist tmp; char *opad = tfm->crt_digest.dit_hmac_block; @@ -107,6 +239,7 @@ crypto_digest_update(tfm, &tmp, 1); crypto_digest_final(tfm, out); +#endif } void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/Kconfig linux-sl3516/crypto/Kconfig --- linux-2.6.15-armeb/crypto/Kconfig 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/Kconfig 2006-04-13 19:24:03.000000000 +0930 @@ -310,6 +310,13 @@ help Quick & dirty crypto test module. +#for test module +#config SL2312_IPSEC +# tristate "Storlink H/W IPSec Acceleration Engine" +# depends on CRYPTO +# help +# Storlink H/W crypto engine include MD5,SHA1,HMAC-MD5,HMAC-SHA1, +# DES,3DES and AES. source "drivers/crypto/Kconfig" endmenu diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/Makefile linux-sl3516/crypto/Makefile --- linux-2.6.15-armeb/crypto/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/Makefile 2006-04-13 19:23:05.000000000 +0930 @@ -31,4 +31,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o -obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o +#for test module +#obj-$(CONFIG_SL2312_IPSEC) += sl2312_ipsec.o + +obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o sl2312_ipsec_sw.o diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/sl2312_ipsec_sw.c linux-sl3516/crypto/sl2312_ipsec_sw.c --- linux-2.6.15-armeb/crypto/sl2312_ipsec_sw.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/crypto/sl2312_ipsec_sw.c 2006-04-13 19:22:24.000000000 +0930 @@ -0,0 +1,2339 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +/* define cipher algorithm */ +enum CIPHER { + DES_ECB_E =20, + DES_ECB_D =21, + DES_CBC_E =22, + DES_CBC_D =23, + TDES_ECB_E =24, + TDES_ECB_D =25, + TDES_CBC_E =26, + TDES_CBC_D =27, + AES_ECB_E =28, + AES_ECB_D =29, + AES_CBC_E =30, + AES_CBC_D =31, + A_SHA1 =12, + A_HMAC_SHA1 =13, + A_MD5 =14, + A_HMAC_MD5 =15, +}; +#endif + +/********************************************** + Basic data struct in DES +**********************************************/ +typedef struct +{ + BYTE byte[8]; +} KEY_STRUCT; +typedef struct +{ + BYTE byte[8]; +} DES_DATA; +/********************************************** + Basic data struct in AES +**********************************************/ +typedef union +{ + struct + { + BYTE byte3,byte2,byte1,byte0; + } bytes; + UINT word32; +} AES_STATE_STRUCT; +typedef struct +{ + AES_STATE_STRUCT state[4]; +} AES_STATE; +typedef struct +{ + BYTE byte[16]; // support 128 bit block size +} AES_DATA; +/************** + Support up to 256 bits key +**************/ +typedef struct +{ + BYTE byte[32]; + UINT Nk; +} AES_KEY_STRUCT; + +enum +{ + AES_128=0, + AES_192, + AES_256 +} ; +/********************************************** + Basic Data Struct for AH +*********************************************/ +typedef struct +{ + UINT word32[16]; +} SHA_BLOCK_STRUCT; +//===Authentication Head 160 bits +typedef struct +{ + BYTE byte[20]; +} SHA_HEAD_STRUCT; + +/********************************************** + Coommon functions for all modules +**********************************************/ +//void FAKE_GenKey(BYTE * pKey); +//void GenRandBytes(BYTE * pByte,UINT nLength); +/********************************************** + All prototypes in implementation of DES +***********************************************/ +void DES_KeyCheckSum(KEY_STRUCT * pKey); +void DES_IP(DES_DATA * pData); +void DES_IP_R(DES_DATA * pData); +void DES_LRSplit(DES_DATA * pData, UINT *pL, UINT *pR); +void DES_LRCombine(DES_DATA * pData, UINT L, UINT R); +void DES_E( UINT R, UINT * pEh32, UINT * pEl16); +void DES_SSplit( UINT h32, UINT l16, UINT * S); +void DES_SCombine(UINT * S,UINT * pP); +void DES_P(UINT * pP); +void DES_S(UINT * S); +void DES_KS_LShift(UINT n,UINT * pReg); +void DES_KeyCombine(UINT * K,UINT * Kh32, UINT * Kl16); +void DES_KS(KEY_STRUCT Key, int * Kh32, int * Kl16); +UINT DES_F(UINT R, UINT Kh32, UINT Kl16); +void DES_Cipher(UINT * Kh32, UINT * Kl16, DES_DATA * pData); +void DES_Decipher(UINT * Kh32,UINT * Kl16,DES_DATA * pData); +void DES_ECB_Cipher(DES_DATA * pData,UINT nLength,KEY_STRUCT Key); +void TDES_ECB_Cipher(DES_DATA * pData,UINT nLength,KEY_STRUCT Key1,KEY_STRUCT Key2,KEY_STRUCT Key3); +void DES_ECB_Decipher(DES_DATA * pData,UINT nLength,KEY_STRUCT Key); +void TDES_ECB_Decipher(DES_DATA * pData,UINT nLength,KEY_STRUCT Key1,KEY_STRUCT Key2,KEY_STRUCT Key3); +void DES_CBC_Cipher(DES_DATA * pData,UINT nLength,DES_DATA IV,KEY_STRUCT Key); +void TDES_CBC_Cipher(DES_DATA * pData,UINT nLength,DES_DATA IV,KEY_STRUCT Key1,KEY_STRUCT Key2,KEY_STRUCT Key3); +void DES_CBC_Decipher(DES_DATA * pData,UINT nLength,DES_DATA IV,KEY_STRUCT Key); +void TDES_CBC_Decipher(DES_DATA * pData,UINT nLength,DES_DATA IV,KEY_STRUCT Key1,KEY_STRUCT Key2,KEY_STRUCT Key3); +#if DEBUG_DES +UINT DES_IsEqual(DES_DATA data1,DES_DATA data2); +#endif //DEBUG_DES +/********************************************** + All prototypes in implementation of AES +***********************************************/ +void AES_DATA2STATE(AES_DATA * pData,AES_STATE * pState); +void AES_STATE2DATA(AES_DATA * pData,AES_STATE * pState); +BYTE AES_SubByte(BYTE iByte); +BYTE AES_InvSubByte(BYTE iByte); +UINT AES_SubWord(UINT wWord); +UINT AES_InvSubWord(UINT wWord); +UINT AES_RotWord(UINT wWord); +void AES_ShiftRowLeft(int no,BYTE * pByte0,BYTE * pByte1,BYTE * pByte2,BYTE * pByte3); +void AES_ShiftRowRight(int no,BYTE * pByte0,BYTE * pByte1,BYTE * pByte2,BYTE * pByte3); +void AES_MixColumns(AES_STATE_STRUCT * pAES_State_Column); +void AES_InvMixColumns(AES_STATE_STRUCT * pAES_State_Column); +void AES_AddRoundKey(AES_STATE * pAES_State,UINT * wKey); +void AES_KeyExpansion(AES_KEY_STRUCT Key,UINT * w); +void AES_SubBytesState(AES_STATE * state); +void AES_ShiftRowsState(AES_STATE * pAES_State); +void AES_MixColumnsState(AES_STATE * pAES_State); +void AES_InvSubBytesState(AES_STATE * state); +void AES_InvShiftRowsState(AES_STATE * pAES_State); +void AES_InvMixColumnsState(AES_STATE * pAES_State); +void AES_Cipher(AES_DATA * pData,UINT * w,UINT AES_Type ); +void AES_Decipher(AES_DATA * pData,UINT * w,UINT AES_Type); +void AES_ECB_Cipher(AES_DATA * Data,UINT nLength,AES_KEY_STRUCT Key); +void AES_ECB_Decipher(AES_DATA * Data,UINT nLength,AES_KEY_STRUCT Key); +void AES_CBC_Cipher(AES_DATA * Data,UINT nLength,AES_KEY_STRUCT Key,AES_DATA IV); +void AES_CBC_Decipher(AES_DATA * Data,UINT nLength,AES_KEY_STRUCT Key,AES_DATA IV); +#if DEBUG_AES +int AES_IsEqual(AES_DATA data1,AES_DATA data2); +#endif //DEBUG_AES +/********************************************************* + All prototypes in implementation SHA-1 +*********************************************************/ +UINT SHA_BuildBlock512(BYTE * iBytes,UINT nLength,SHA_BLOCK_STRUCT * Blocks); +void SHA_Process(SHA_BLOCK_STRUCT * pBlock,UINT nBlockNo,SHA_HEAD_STRUCT * pHeader); +#ifdef DEBUG_SHA +int SHA_IsEqual(BYTE * b1,BYTE * b2); +#endif //DEBUG_SHA +/****************************** + Data Structure for MD5 +*******************************/ +typedef struct +{ + BYTE byte[16]; +}MD5_HEAD_STRUCT; +/****************************** + Prototypes for MD5 +******************************/ +UINT MD5_BuildBlock512(BYTE * iBytes,UINT nLength,SHA_BLOCK_STRUCT * Blocks); +void MD5_Process(SHA_BLOCK_STRUCT * pBlock,UINT nBlockNo,MD5_HEAD_STRUCT * pHeader); +#if DEBUG_MD5 +UINT MD5_IsEqual(BYTE * b1,BYTE * b2); +#endif //DEBUG_MD5 + +void HMAC_MD5_Process(BYTE * Key,UINT nKeyLength,BYTE * Text,UINT nTextLength,MD5_HEAD_STRUCT * pHead); +void HMAC_SHA_Process(BYTE * Key,UINT nKeyLength,BYTE * Text,UINT nTextLength,SHA_HEAD_STRUCT * pHead); + +/***************************************************** + Same definition as simdefs.h in verilog environment +******************************************************/ +// opMode +#define CIPHER_ENC 0x1 +#define CIPHER_DEC 0x3 +#define AUTH 0x4 +#define ENC_AUTH 0x5 +#define AUTH_DEC 0x7 + +// cipherAlgorithm +#define CBC_DES 0x4 +#define CBC_3DES 0x5 +#define CBC_AES 0x6 +#define ECB_DES 0x0 +#define ECB_3DES 0x1 +#define ECB_AES 0x2 + +// authAlgorithm +#define SHA1 0 +#define MD5 1 +#define HMAC_SHA1 2 +#define HMAC_MD5 3 + +// authMode +#define AUTH_APPEND 0 +#define AUTH_CHKVAL 1 + +void ipsec_sw_authentication(char *data,unsigned int data_len,char *authkey,char authAlgorithm,char *auth_result) +{ + static SHA_BLOCK_STRUCT Block[200]; + SHA_HEAD_STRUCT SHA_Header; + MD5_HEAD_STRUCT MD5_Header; + unsigned char *pByte=0; + unsigned int Blockno; + unsigned int count=0; + + switch(authAlgorithm) + { + case A_SHA1: + case SHA1: + Blockno=SHA_BuildBlock512(data,data_len*8,Block); + SHA_Process(Block,Blockno,&SHA_Header); + count=20; + pByte=SHA_Header.byte; + break; + case A_HMAC_SHA1: + case HMAC_SHA1: + HMAC_SHA_Process(authkey,64,data,data_len,&SHA_Header); + count=20; + pByte=SHA_Header.byte; + break; + case A_MD5: + case MD5: + Blockno=MD5_BuildBlock512(data,data_len*8,Block); + MD5_Process(Block,Blockno,&MD5_Header); + count=16; + pByte=MD5_Header.byte; + break; + case A_HMAC_MD5: + case HMAC_MD5: + HMAC_MD5_Process(authkey,64,data,data_len,&MD5_Header); + count=16; + pByte=MD5_Header.byte; + break; + } + memcpy(auth_result,pByte,count); + auth_result[count] = 0x00; +} + + +void ipsec_sw_cipher(unsigned char *pt,unsigned int pt_len, unsigned char *cipher_key, unsigned int key_size, + unsigned char *iv,unsigned int cipherAlgorithm,unsigned char *ct) +{ + static DES_DATA DES_data[1600]; + static AES_DATA AES_data[1600]; + DES_DATA DES_iv; + AES_DATA AES_iv; + KEY_STRUCT DES_key0,DES_key1,DES_key2; + AES_KEY_STRUCT AES_key; + BYTE *pByte; + unsigned int DES_count,AES_count; + unsigned int i,j; + + DES_count = pt_len/8; + AES_count = pt_len/16; + pByte=&pt[0]; + for (i=0;iword32[j]=(UINT)((p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]); + p+=4; + } + pBlock++; + } + residue_length=(nLength-orig_blocks*512)/8; + + WordIndex=0; + while(residue_length>=4) + { + pBlock->word32[WordIndex++]=(UINT)((p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]); + p+=4; + residue_length-=4; + } + switch(residue_length) + { + case 0: + pBlock->word32[WordIndex++]=0x00000080; + break; + case 1: + pBlock->word32[WordIndex++]=(UINT)(p[0]|0x00008000); + break; + case 2: + pBlock->word32[WordIndex++]=(UINT)(p[0]|(p[1]<<8)|0x00800000); + break; + case 3: + pBlock->word32[WordIndex++]=(UINT)(p[0]|(p[1]<<8)|(p[2]<<16)|0x80000000); + break; + } + if (WordIndex>16) printk("Should not happen!!!\n"); + if (WordIndex==16) + { + pBlock++; + WordIndex=0; + } + if (WordIndex==15) + { + pBlock->word32[WordIndex]=0x0; + pBlock++; + WordIndex=0; + } + for (i=0;i<(14-WordIndex);i++) + { + pBlock->word32[i+WordIndex]=0x0; + } + pBlock->word32[14]=nLength; + pBlock->word32[15]=0; + pBlock++; + t=pBlock-Blocks; + return(t); +} +/********************************************************************** + The following codes are mainly "Copy&Paste" from RFC1321 Sample Code +***********************************************************************/ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) +/* ROTATE_LEFT rotates x left n bits.*/ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. +*/ + +#define FF(a, b, c, d, x, s, ac) { \ +(a) += F ((b), (c), (d)) + (x) + (ac); \ +(a) = ROTATE_LEFT ((a), (s)); \ +(a) += (b); \ +} +#define GG(a, b, c, d, x, s, ac) { \ +(a) += G ((b), (c), (d)) + (x) + (ac); \ +(a) = ROTATE_LEFT ((a), (s)); \ +(a) += (b); \ +} +#define HH(a, b, c, d, x, s, ac) { \ +(a) += H ((b), (c), (d)) + (x) + (ac); \ +(a) = ROTATE_LEFT ((a), (s)); \ +(a) += (b); \ +} +#define II(a, b, c, d, x, s, ac) { \ +(a) += I ((b), (c), (d)) + (x) + (ac); \ +(a) = ROTATE_LEFT ((a), (s)); \ +(a) += (b); \ +} +void MD5_Process(SHA_BLOCK_STRUCT * pBlock,UINT nBlockNo,MD5_HEAD_STRUCT * pHeader) +{ + UINT a,b,c,d; + UINT aa,bb,cc,dd; + UINT * x; + UINT i; + a=0x67452301; + b=0xefcdab89; + c=0x98badcfe; + d=0x10325476; + for (i=0;ibyte[0]=a&0xff; + pHeader->byte[1]=(a>>8)&0xff; + pHeader->byte[2]=(a>>16)&0xff; + pHeader->byte[3]=(a>>24)&0xff; + pHeader->byte[4]=b&0xff; + pHeader->byte[5]=(b>>8)&0xff; + pHeader->byte[6]=(b>>16)&0xff; + pHeader->byte[7]=(b>>24)&0xff; + pHeader->byte[8]=c&0xff; + pHeader->byte[9]=(c>>8)&0xff; + pHeader->byte[10]=(c>>16)&0xff; + pHeader->byte[11]=(c>>24)&0xff; + pHeader->byte[12]=d&0xff; + pHeader->byte[13]=(d>>8)&0xff; + pHeader->byte[14]=(d>>16)&0xff; + pHeader->byte[15]=(d>>24)&0xff; +} + + +unsigned long _lrotl( unsigned long value, int shift ) +{ + unsigned int i; + + for (i=0;iword32[j]=(UINT)((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); + p+=4; + } + pBlock++; + } + residue_length=(nLength-orig_blocks*512)/8; + + WordIndex=0; + while(residue_length>=4) + { + pBlock->word32[WordIndex++]=(UINT)((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); + p+=4; + residue_length-=4; + } + switch(residue_length) + { + case 0: + pBlock->word32[WordIndex++]=0x80000000; + break; + case 1: + pBlock->word32[WordIndex++]=(UINT)((p[0]<<24)|0x00800000); + break; + case 2: + pBlock->word32[WordIndex++]=(UINT)((p[0]<<24)|(p[1]<<16)|0x00008000); + break; + case 3: + pBlock->word32[WordIndex++]=(UINT)((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|0x80); + break; + } + if (WordIndex>16) printk("Should not happen!!!\n"); + if (WordIndex==16) + { + pBlock++; + WordIndex=0; + } + + if (WordIndex==15) + { + pBlock->word32[WordIndex]=0x0; + pBlock++; + WordIndex=0; + } + for (i=0;i<(14-WordIndex);i++) + { + pBlock->word32[i+WordIndex]=0x0; + } + pBlock->word32[14]=0x0; + pBlock->word32[15]=nLength; + pBlock++; + t=pBlock-Blocks; + return(t); +} +//========== 0<=t<=19 +UINT f0(UINT B,UINT C,UINT D) +{ + UINT t; + t=(B & C)|((~B) & D); + return(t); +} +//======20<=t<=39; 60<=t<=79 +UINT f1(UINT B,UINT C,UINT D) +{ + UINT t; + t=B ^ C ^ D; + return(t); +} +//== 40<=t<=59 +UINT f2(UINT B,UINT C,UINT D) +{ + UINT t; + t=(B & C)|(B & D)|(C & D); + return(t); +} +#define K0 0x5a827999 +#define K1 0x6ed9eba1 +#define K2 0x8f1bbcdc +#define K3 0xca62c1d6 +void SHA_Process(SHA_BLOCK_STRUCT * pBlock,UINT nBlockNo,SHA_HEAD_STRUCT * pHeader) +{ + UINT H0,H1,H2,H3,H4,A,B,C,D,E,TEMP; + UINT W[80]; + UINT i,j; + H0=0x67452301; + H1=0xefcdab89; + H2=0x98badcfe; + H3=0x10325476; + H4=0xc3d2e1f0; + for (i=0;ibyte[0]=(H0>>24)&0xff; + pHeader->byte[1]=(H0>>16)&0xff; + pHeader->byte[2]=(H0>>8) &0xff; + pHeader->byte[3]=H0 &0xff; + pHeader->byte[4]=(H1>>24)&0xff; + pHeader->byte[5]=(H1>>16)&0xff; + pHeader->byte[6]=(H1>>8) &0xff; + pHeader->byte[7]=H1 &0xff; + pHeader->byte[8]=(H2>>24)&0xff; + pHeader->byte[9]=(H2>>16)&0xff; + pHeader->byte[10]=(H2>>8) &0xff; + pHeader->byte[11]=H2 &0xff; + pHeader->byte[12]=(H3>>24)&0xff; + pHeader->byte[13]=(H3>>16)&0xff; + pHeader->byte[14]=(H3>>8) &0xff; + pHeader->byte[15]=H3 &0xff; + pHeader->byte[16]=(H4>>24)&0xff; + pHeader->byte[17]=(H4>>16)&0xff; + pHeader->byte[18]=(H4>>8) &0xff; + pHeader->byte[19]=H4 &0xff; +} + +#define IPAD 0x36 +#define OPAD 0x5c + +/***************************** + nKeyLength should be less than 64 bytes, greater than 128 bytes, nTextLength should be less than + 6336 bytes +*****************************/ +void HMAC_MD5_Process(BYTE * Key,UINT nKeyLength,BYTE * Text,UINT nTextLength,MD5_HEAD_STRUCT * pHead) +{ + static SHA_BLOCK_STRUCT Blocks[100]; // Support up to 100*64 =6400 bytes + static BYTE tByte[6400]; + MD5_HEAD_STRUCT tHead; + UINT nByte ; + UINT nBlock; + UINT i; + nByte=0; + for (i=0;istate[i].bytes.byte0=pData->byte[4*i]; + pState->state[i].bytes.byte1=pData->byte[4*i+1]; + pState->state[i].bytes.byte2=pData->byte[4*i+2]; + pState->state[i].bytes.byte3=pData->byte[4*i+3]; + } +} +void AES_STATE2DATA(AES_DATA * pData,AES_STATE * pState) +{ + UINT i; + for (i=0;i<4;i++) + { + pData->byte[4*i]=pState->state[i].bytes.byte0; + pData->byte[4*i+1]=pState->state[i].bytes.byte1; + pData->byte[4*i+2]=pState->state[i].bytes.byte2; + pData->byte[4*i+3]=pState->state[i].bytes.byte3; + } +} + +BYTE Mul(BYTE a,BYTE b) +{ + BYTE c,d; + if (a && b) + { + c=Log[a]; + d=Log[b]; + c=(c+d)%255; + c=Exp[c]; + } + else + c=0; + return(c); +} +BYTE Mul_Inv(BYTE a) +{ + BYTE b; + if (a) + { + b=Log[a]; + b=255-b; + b=Exp[b]; + return(b); + } + else + return(a); +} +BYTE AES_SubByte(BYTE iByte) +{ + static BYTE SubByte_Table[256]= + { + 99,124,119,123,242,107,111,197, 48, 1,103, 43,254,215,171,118, + 202,130,201,125,250, 89, 71,240,173,212,162,175,156,164,114,192, + 183,253,147, 38, 54, 63,247,204, 52,165,229,241,113,216, 49, 21, + 4,199, 35,195, 24,150, 5,154, 7, 18,128,226,235, 39,178,117, + 9,131, 44, 26, 27,110, 90,160, 82, 59,214,179, 41,227, 47,132, + 83,209, 0,237, 32,252,177, 91,106,203,190, 57, 74, 76, 88,207, + 208,239,170,251, 67, 77, 51,133, 69,249, 2,127, 80, 60,159,168, + 81,163, 64,143,146,157, 56,245,188,182,218, 33, 16,255,243,210, + 205, 12, 19,236, 95,151, 68, 23,196,167,126, 61,100, 93, 25,115, + 96,129, 79,220, 34, 42,144,136, 70,238,184, 20,222, 94, 11,219, + 224, 50, 58, 10, 73, 6, 36, 92,194,211,172, 98,145,149,228,121, + 231,200, 55,109,141,213, 78,169,108, 86,244,234,101,122,174, 8, + 186,120, 37, 46, 28,166,180,198,232,221,116, 31, 75,189,139,138, + 112, 62,181,102, 72, 3,246, 14, 97, 53, 87,185,134,193, 29,158, + 225,248,152, 17,105,217,142,148,155, 30,135,233,206, 85, 40,223, + 140,161,137, 13,191,230, 66,104, 65,153, 45, 15,176, 84,187, 22, + }; + return(SubByte_Table[iByte]); +} +BYTE AES_InvSubByte(BYTE iByte) +{ + static BYTE InvSubByte_Table[256]= + { + 82, 9,106,213, 48, 54,165, 56,191, 64,163,158,129,243,215,251, + 124,227, 57,130,155, 47,255,135, 52,142, 67, 68,196,222,233,203, + 84,123,148, 50,166,194, 35, 61,238, 76,149, 11, 66,250,195, 78, + 8, 46,161,102, 40,217, 36,178,118, 91,162, 73,109,139,209, 37, + 114,248,246,100,134,104,152, 22,212,164, 92,204, 93,101,182,146, + 108,112, 72, 80,253,237,185,218, 94, 21, 70, 87,167,141,157,132, + 144,216,171, 0,140,188,211, 10,247,228, 88, 5,184,179, 69, 6, + 208, 44, 30,143,202, 63, 15, 2,193,175,189, 3, 1, 19,138,107, + 58,145, 17, 65, 79,103,220,234,151,242,207,206,240,180,230,115, + 150,172,116, 34,231,173, 53,133,226,249, 55,232, 28,117,223,110, + 71,241, 26,113, 29, 41,197,137,111,183, 98, 14,170, 24,190, 27, + 252, 86, 62, 75,198,210,121, 32,154,219,192,254,120,205, 90,244, + 31,221,168, 51,136, 7,199, 49,177, 18, 16, 89, 39,128,236, 95, + 96, 81,127,169, 25,181, 74, 13, 45,229,122,159,147,201,156,239, + 160,224, 59, 77,174, 42,245,176,200,235,187, 60,131, 83,153, 97, + 23, 43, 4,126,186,119,214, 38,225,105, 20, 99, 85, 33, 12,125, + }; + return(InvSubByte_Table[iByte]); +} + + +UINT AES_SubWord(UINT wWord) +{ + UINT t; + UINT w; + w=0; + t=(wWord & 0xff000000)>>24; + t=AES_SubByte((BYTE)t); + w|=(t<<24); + t=(wWord & 0xff0000)>>16; + t=AES_SubByte((BYTE)t); + w|=(t<<16); + t=(wWord & 0xff00)>>8; + t=AES_SubByte((BYTE)t); + w|=(t<<8); + t=(wWord & 0xff); + t=AES_SubByte((BYTE)t); + w|=t; + return(w); +} +UINT AES_InvSubWord(UINT wWord) +{ + UINT t; + UINT w; + w=0; + t=(wWord & 0xff000000)>>24; + t=AES_InvSubByte((BYTE)t); + w|=(t<<24); + t=(wWord & 0xff0000)>>16; + t=AES_InvSubByte((BYTE)t); + w|=(t<<16); + t=(wWord & 0xff00)>>8; + t=AES_InvSubByte((BYTE)t); + w|=(t<<8); + t=(wWord & 0xff); + t=AES_InvSubByte((BYTE)t); + w|=t; + return(w); +} + + +UINT AES_RotWord(UINT wWord) +{ + UINT t; + UINT w; + w=0; + t=(wWord&0xff000000)>>24; + w|=t; + t=(wWord&0xff0000)>>16; + w|=(t<<24); + t=(wWord&0xff00)>>8; + w|=(t<<16); + t=(wWord&0xff); + w|=(t<<8); + return(w); +} +/********************************* + support only 1,2,3 left shift +*********************************/ +void AES_ShiftRowLeft(int no,BYTE * pByte0,BYTE * pByte1,BYTE * pByte2,BYTE * pByte3) +{ + BYTE b0,b1,b2,b3; + b0=*pByte0; + b1=*pByte1; + b2=*pByte2; + b3=*pByte3; + switch(no) + { + case 1: + *pByte0=b1; + *pByte1=b2; + *pByte2=b3; + *pByte3=b0; + break; + case 2: + *pByte0=b2; + *pByte1=b3; + *pByte2=b0; + *pByte3=b1; + break; + case 3: + *pByte0=b3; + *pByte1=b0; + *pByte2=b1; + *pByte3=b2; + break; + } +} +void AES_ShiftRowRight(int no,BYTE * pByte0,BYTE * pByte1,BYTE * pByte2,BYTE * pByte3) +{ + BYTE b0,b1,b2,b3; + b0=*pByte0; + b1=*pByte1; + b2=*pByte2; + b3=*pByte3; + switch(no) + { + case 1: + *pByte0=b3; + *pByte1=b0; + *pByte2=b1; + *pByte3=b2; + break; + case 2: + *pByte0=b2; + *pByte1=b3; + *pByte2=b0; + *pByte3=b1; + break; + case 3: + *pByte0=b1; + *pByte1=b2; + *pByte2=b3; + *pByte3=b0; + break; + } +} + +void AES_MixColumns(AES_STATE_STRUCT * pAES_State_Column) +{ + AES_STATE_STRUCT Column; + Column.bytes.byte0=Mul(0x02,pAES_State_Column->bytes.byte0)^ + Mul(0x03,pAES_State_Column->bytes.byte1)^ + pAES_State_Column->bytes.byte2^ + pAES_State_Column->bytes.byte3; + Column.bytes.byte1=pAES_State_Column->bytes.byte0^ + Mul(0x02,pAES_State_Column->bytes.byte1)^ + Mul(0x03,pAES_State_Column->bytes.byte2)^ + pAES_State_Column->bytes.byte3; + Column.bytes.byte2=pAES_State_Column->bytes.byte0^ + pAES_State_Column->bytes.byte1^ + Mul(0x02,pAES_State_Column->bytes.byte2)^ + Mul(0x03,pAES_State_Column->bytes.byte3); + Column.bytes.byte3=Mul(0x03,pAES_State_Column->bytes.byte0)^ + pAES_State_Column->bytes.byte1^ + pAES_State_Column->bytes.byte2^ + Mul(0x02,pAES_State_Column->bytes.byte3); + *pAES_State_Column=Column; +} +void AES_InvMixColumns(AES_STATE_STRUCT * pAES_State_Column) +{ + AES_STATE_STRUCT Column; + Column.bytes.byte0=Mul(0x0e,pAES_State_Column->bytes.byte0)^ + Mul(0x0b,pAES_State_Column->bytes.byte1)^ + Mul(0x0d,pAES_State_Column->bytes.byte2)^ + Mul(0x09,pAES_State_Column->bytes.byte3); + Column.bytes.byte1=Mul(0x09,pAES_State_Column->bytes.byte0)^ + Mul(0x0e,pAES_State_Column->bytes.byte1)^ + Mul(0x0b,pAES_State_Column->bytes.byte2)^ + Mul(0x0d,pAES_State_Column->bytes.byte3); + Column.bytes.byte2=Mul(0x0d,pAES_State_Column->bytes.byte0)^ + Mul(0x09,pAES_State_Column->bytes.byte1)^ + Mul(0x0e,pAES_State_Column->bytes.byte2)^ + Mul(0x0b,pAES_State_Column->bytes.byte3); + Column.bytes.byte3=Mul(0x0b,pAES_State_Column->bytes.byte0)^ + Mul(0x0d,pAES_State_Column->bytes.byte1)^ + Mul(0x09,pAES_State_Column->bytes.byte2)^ + Mul(0x0e,pAES_State_Column->bytes.byte3); + *pAES_State_Column=Column; +} +void AES_AddRoundKey(AES_STATE * pAES_State,UINT * wKey) +{ + UINT i; + UINT t; + for (i=0;i<4;i++) + { + t=(pAES_State->state[i].word32 ^ wKey[i]); + pAES_State->state[i].word32 = t; + } +} +/**************************************************** + Gernerate 4*(Nr+1) key words +****************************************************/ +void AES_KeyExpansion(AES_KEY_STRUCT Key,UINT * w) +{ + UINT Nk,Nr=0; + UINT t=0,i; + static UINT Rcon[31]= + { + 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, + 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, + 0x9a000000, 0x2f000000, 0x5e000000, 0xbc000000, 0x63000000, + 0xc6000000, 0x97000000, 0x35000000, 0x6a000000, 0xd4000000, + 0xb3000000, 0x7d000000, 0xfa000000, 0xef000000, 0xc5000000, + 0x91000000 + }; + + Nk=Key.Nk; + switch(Nk) + { + case 4: + Nr=10; + break; + case 6: + Nr=12; + break; + case 8: + Nr=14; + break; + } + for (i=0;i6)&&((i%Nk)==4)) + t=AES_SubWord(t); + t^=w[i-Nk]; + w[i]=t; + } +} +void AES_SubBytesState(AES_STATE * state) +{ + UINT i; + for (i=0;i<4;i++) + { + state->state[i].word32=AES_SubWord(state->state[i].word32); + } +} +void AES_ShiftRowsState(AES_STATE * pAES_State) +{ + AES_ShiftRowLeft(1,&(pAES_State->state[0].bytes.byte1),&(pAES_State->state[1].bytes.byte1), + &(pAES_State->state[2].bytes.byte1),&(pAES_State->state[3].bytes.byte1)); + AES_ShiftRowLeft(2,&(pAES_State->state[0].bytes.byte2),&(pAES_State->state[1].bytes.byte2), + &(pAES_State->state[2].bytes.byte2),&(pAES_State->state[3].bytes.byte2)); + AES_ShiftRowLeft(3,&(pAES_State->state[0].bytes.byte3),&(pAES_State->state[1].bytes.byte3), + &(pAES_State->state[2].bytes.byte3),&(pAES_State->state[3].bytes.byte3)); +} +void AES_MixColumnsState(AES_STATE * pAES_State) +{ + UINT i; + for (i=0;i<4;i++) + { + AES_MixColumns(&pAES_State->state[i]); + } +} +void AES_InvSubBytesState(AES_STATE * state) +{ + UINT i; + for (i=0;i<4;i++) + { + state->state[i].word32=AES_InvSubWord(state->state[i].word32); + } +} +void AES_InvShiftRowsState(AES_STATE * pAES_State) +{ + AES_ShiftRowRight(1,&(pAES_State->state[0].bytes.byte1),&(pAES_State->state[1].bytes.byte1), + &(pAES_State->state[2].bytes.byte1),&(pAES_State->state[3].bytes.byte1)); + AES_ShiftRowRight(2,&(pAES_State->state[0].bytes.byte2),&(pAES_State->state[1].bytes.byte2), + &(pAES_State->state[2].bytes.byte2),&(pAES_State->state[3].bytes.byte2)); + AES_ShiftRowRight(3,&(pAES_State->state[0].bytes.byte3),&(pAES_State->state[1].bytes.byte3), + &(pAES_State->state[2].bytes.byte3),&(pAES_State->state[3].bytes.byte3)); +} +void AES_InvMixColumnsState(AES_STATE * pAES_State) +{ + UINT i; + for (i=0;i<4;i++) + { + AES_InvMixColumns(&pAES_State->state[i]); + } +} + +void AES_Cipher(AES_DATA * pData,UINT * w,UINT AES_Type ) +{ + UINT Nr; + UINT i; + AES_STATE State; + switch(AES_Type) + { + default: + case AES_128: + Nr=10; + break; + case AES_192: + Nr=12; + break; + case AES_256: + Nr=14; + break; + } + AES_DATA2STATE(pData,&State); + AES_AddRoundKey(&State,w); + for (i=1;i=1;i--) + { + AES_AddRoundKey(&State,&w[4*i]); + AES_InvMixColumnsState(&State); + AES_InvShiftRowsState(&State); + AES_InvSubBytesState(&State); + } + AES_AddRoundKey(&State,w); + AES_STATE2DATA(pData,&State); +} +void AES_ECB_Cipher(AES_DATA * Data,UINT nLength,AES_KEY_STRUCT Key) +{ + UINT w[60]; + UINT AES_Type=0; + UINT i; + switch(Key.Nk) + { + case 4: + AES_Type=AES_128; + break; + case 6: + AES_Type=AES_192; + break; + case 8: + AES_Type=AES_256; + break; + } + AES_KeyExpansion(Key,w); + for (i=0;ibyte[i]>>j)&0x1); + } + pKey->byte[i]&=0xfe; + pKey->byte[i]|=chksum; + } +} +/************************** +Generate 64 bits random data, these data is output to 8 bytes +**************************/ +#if 0 +void FAKE_GenKey(BYTE * bytes) +{ + UINT i; + //srand((unsigned)time(0)); + for (i=0;i<8;i++) + bytes[i]=rand() & 0xff; +} +#endif + +void DES_IP(DES_DATA * pData) +{ + static UINT IP_Sequence[64]= + { 57,49,41,33,25,17, 9, 1, + 59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5, + 63,55,47,39,31,23,15, 7, + 56,48,40,32,24,16, 8, 0, + 58,50,42,34,26,18,10, 2, + 60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6, + }; + UINT D1[64],D2[64]; + UINT i,j; + BYTE t; + for (i=0;i<8;i++) + { + for (j=0;j<8;j++) + { + D1[i*8+j]=(pData->byte[i]>>(7-j))&0x1; + } + } + for (i=0;i<64;i++) + { + D2[i]=D1[IP_Sequence[i]]; + } + for (i=0;i<8;i++) + { + t=0; + for (j=0;j<8;j++) + { + t=t|(D2[8*i+j]<<(7-j)); + } + pData->byte[i]=t; + } +} +void DES_IP_R(DES_DATA * pData) +{ + static UINT IP_Sequence_R[64]= + { 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25, + 32, 0,40, 8,48,16,56,24, + }; + UINT D1[64],D2[64]; + UINT i,j; + BYTE t; + for (i=0;i<8;i++) + { + for (j=0;j<8;j++) + { + D1[i*8+j]=(pData->byte[i]>>(7-j))&0x1; + } + } + for (i=0;i<64;i++) + { + D2[i]=D1[IP_Sequence_R[i]]; + } + for (i=0;i<8;i++) + { + t=0; + for (j=0;j<8;j++) + { + t=t|(D2[8*i+j]<<(7-j)); + } + pData->byte[i]=t; + } +} +void DES_LRSplit(DES_DATA * pData, UINT *pL, UINT *pR) +{ + *pL = (pData->byte[0]<<24)+(pData->byte[1]<<16)+(pData->byte[2]<<8)+pData->byte[3]; + *pR = (pData->byte[4]<<24)+(pData->byte[5]<<16)+(pData->byte[6]<<8)+pData->byte[7]; +} +void DES_LRCombine(DES_DATA * pData, UINT L, UINT R) +{ + pData->byte[0]=(L & 0xff000000)>>24; + pData->byte[1]=(L & 0x00ff0000)>>16; + pData->byte[2]=(L & 0x0000ff00)>>8; + pData->byte[3]=(L & 0x000000ff); + pData->byte[4]=(R & 0xff000000)>>24; + pData->byte[5]=(R & 0x00ff0000)>>16; + pData->byte[6]=(R & 0x0000ff00)>>8; + pData->byte[7]=(R & 0x000000ff); +} +void DES_E( UINT R, UINT * pEh32, UINT * pEl16) +{ + static UINT E_Sequence[48]= + { 31, 0, 1, 2, 3, 4, 3, 4, + 5, 6, 7, 8, 7, 8, 9,10, + 11,12,11,12,13,14,15,16, + 15,16,17,18,19,20,19,20, + 21,22,23,24,23,24,25,26, + 27,28,27,28,29,30,31, 0, + + }; + UINT D1[32],D2[48]; + UINT i,t; + for (i=0;i<32;i++) + { + D1[i]=(R >> (31-i))&0x1; + } + for (i=0;i<48;i++) + { + D2[i]=D1[E_Sequence[i]]; + } + t=0; + for (i=0;i<32;i++) + { + t=t|(D2[i]<<(31-i)); + } + *pEh32=t; + t=0; + for (i=0;i<16;i++) + { + t=t|(D2[i+32]<<(15-i)); + } + *pEl16=t; +} +void DES_SSplit( UINT h32, UINT l16, UINT * S) +{ + S[0]=(h32&0xfc000000)>>26; + S[1]=(h32&0x03f00000)>>20; + S[2]=(h32&0x000fc000)>>14; + S[3]=(h32&0x00003f00)>>8; + S[4]=(h32&0x000000fc)>>2; + S[5]=((h32&0x3)<<4)+((l16&0xf000)>>12); + S[6]=(l16&0x0fc0)>>6; + S[7]=(l16&0x003f); +} +void DES_SCombine(UINT * S,UINT * pP) +{ + UINT i; + *pP=0; + for (i=0;i<8;i++) + { + *pP|=(S[i]<<(28-4*i)); + } +} +void DES_P(UINT * pP) +{ + static UINT P_Sequence[32]= + { + 15, 6,19,20,28,11,27,16, + 0,14,22,25, 4,17,30, 9, + 1, 7,23,13,31,26, 2, 8, + 18,12,29, 5,21,10, 3,24, + }; + UINT D1[32],D2[32]; + UINT i,t; + for (i=0;i<32;i++) + { + D1[i]=((*pP)>>(31-i))&0x1; + } + for (i=0;i<32;i++) + { + D2[i]=D1[P_Sequence[i]]; + } + t=0; + for (i=0;i<32;i++) + { + t|=(D2[i]<<(31-i)); + } + *pP = t; +} +void DES_S(UINT * S) +{ + UINT i,t; + static UINT S_Sequence[8][64]= + { + { + 14, 0, 4,15,13, 7, 1, 4, + 2,14,15, 2,11,13, 8, 1, + 3,10,10, 6, 6,12,12,11, + 5, 9, 9, 5, 0, 3, 7, 8, + 4,15, 1,12,14, 8, 8, 2, + 13, 4, 6, 9, 2, 1,11, 7, + 15, 5,12,11, 9, 3, 7,14, + 3,10,10, 0, 5, 6, 0,13 + }, + { + 15, 3, 1,13, 8, 4,14, 7, + 6,15,11, 2, 3, 8, 4,14, + 9,12, 7, 0, 2, 1,13,10, + 12, 6, 0, 9, 5,11,10, 5, + 0,13,14, 8, 7,10,11, 1, + 10, 3, 4,15,13, 4, 1, 2, + 5,11, 8, 6,12, 7, 6,12, + 9, 0, 3, 5, 2,14,15, 9 + }, + { + 10,13, 0, 7, 9, 0,14, 9, + 6, 3, 3, 4,15, 6, 5,10, + 1, 2,13, 8,12, 5, 7,14, + 11,12, 4,11, 2,15, 8, 1, + 13, 1, 6,10, 4,13, 9, 0, + 8, 6,15, 9, 3, 8, 0, 7, + 11, 4, 1,15, 2,14,12, 3, + 5,11,10, 5,14, 2, 7,12 + }, + { + 7,13,13, 8,14,11, 3, 5, + 0, 6, 6,15, 9, 0,10, 3, + 1, 4, 2, 7, 8, 2, 5,12, + 11, 1,12,10, 4,14,15, 9, + 10, 3, 6,15, 9, 0, 0, 6, + 12,10,11, 1, 7,13,13, 8, + 15, 9, 1, 4, 3, 5,14,11, + 5,12, 2, 7, 8, 2, 4,14 + }, + { + 2,14,12,11, 4, 2, 1,12, + 7, 4,10, 7,11,13, 6, 1, + 8, 5, 5, 0, 3,15,15,10, + 13, 3, 0, 9,14, 8, 9, 6, + 4,11, 2, 8, 1,12,11, 7, + 10, 1,13,14, 7, 2, 8,13, + 15, 6, 9,15,12, 0, 5, 9, + 6,10, 3, 4, 0, 5,14, 3 + }, + { + 12,10, 1,15,10, 4,15, 2, + 9, 7, 2,12, 6, 9, 8, 5, + 0, 6,13, 1, 3,13, 4,14, + 14, 0, 7,11, 5, 3,11, 8, + 9, 4,14, 3,15, 2, 5,12, + 2, 9, 8, 5,12,15, 3,10, + 7,11, 0,14, 4, 1,10, 7, + 1, 6,13, 0,11, 8, 6,13 + }, + { + 4,13,11, 0, 2,11,14, 7, + 15, 4, 0, 9, 8, 1,13,10, + 3,14,12, 3, 9, 5, 7,12, + 5, 2,10,15, 6, 8, 1, 6, + 1, 6, 4,11,11,13,13, 8, + 12, 1, 3, 4, 7,10,14, 7, + 10, 9,15, 5, 6, 0, 8,15, + 0,14, 5, 2, 9, 3, 2,12 + }, + { + 13, 1, 2,15, 8,13, 4, 8, + 6,10,15, 3,11, 7, 1, 4, + 10,12, 9, 5, 3, 6,14,11, + 5, 0, 0,14,12, 9, 7, 2, + 7, 2,11, 1, 4,14, 1, 7, + 9, 4,12,10,14, 8, 2,13, + 0,15, 6,12,10, 9,13, 0, + 15, 3, 3, 5, 5, 6, 8,11 + } + }; + for (i=0;i<8;i++) + { + t=S[i]; + S[i]=S_Sequence[i][t]; + } +} +void DES_KS_LShift(UINT n,UINT * pReg) // pReg is 28 bit long,n is 1 or 2 +{ + UINT Reg_Tmp1,Reg_Tmp2; + UINT i; + switch (n) + { + default: + case 1: + Reg_Tmp1=pReg[0]; + for (i=0;i<27;i++) + { + pReg[i]=pReg[i+1]; + } + pReg[27]=Reg_Tmp1; + break; + case 2: + Reg_Tmp1=pReg[0]; + Reg_Tmp2=pReg[1]; + for (i=0;i<26;i++) + { + pReg[i]=pReg[i+2]; + } + pReg[26]=Reg_Tmp1; + pReg[27]=Reg_Tmp2; + break; + } + +} +void DES_KeyCombine(UINT * K,UINT * Kh32, UINT * Kl16) +{ + UINT i; + UINT t; + t=0; + for (i=0;i<32;i++) + { + t=t|(K[i]<<(31-i)); + } + * Kh32= t; + t=0; + for (i=0;i<16;i++) + { + t=t|(K[i+32]<<(15-i)); + } + * Kl16= t; +} + + + + + +void DES_KS(KEY_STRUCT Key, int * Kh32, int * Kl16) +{ + static UINT PC1_CSequence[28]= + { + 56,48,40,32,24,16, 8, + 0, 57,49,41,33,25,17, + 9, 1,58,50,42,34,26, + 18,10, 2,59,51,43,35, + }; + static UINT PC1_DSequence[28]= + { + 62,54,46,38,30,22,14, + 6, 61,53,45,37,29,21, + 13, 5,60,52,44,36,28, + 20,12, 4,27,19,11, 3, + }; + static UINT ShiftTable[16]= + { + 1,1,2,2,2,2,2,2, + 1,2,2,2,2,2,2,1 + }; + static UINT PC2_Sequence[48]= + { + 13,16,10,23, 0, 4, 2,27, + 14, 5,20, 9,22,18,11, 3, + 25, 7,15, 6,26,19,12, 1, + 40,51,30,36,46,54,29,39, + 50,44,32,47,43,48,38,55, + 33,52,45,41,49,35,28,31, + }; + + UINT C[28],D[28]; + UINT D1[64]; + UINT i,j,n1,n2; + for (i=0;i<8;i++) + { + for (j=0;j<8;j++) + { + D1[i*8+j]=(Key.byte[i]>>(7-j))&0x1; + } + } + for (i=0;i<28;i++) + { + C[i]=D1[PC1_CSequence[i]]; + D[i]=D1[PC1_DSequence[i]]; + } + for (i=0;i<16;i++) + { + n1=ShiftTable[i]; + DES_KS_LShift(n1,C); + DES_KS_LShift(n1,D); + for (j=0;j<48;j++) + { + n2=PC2_Sequence[j]; + if (n2<=27) + { + D1[j]=C[n2]; + } + else + { + n2-=28; + D1[j]=D[n2]; + } + } + DES_KeyCombine(D1,(UINT *)&Kh32[i],(UINT *)&Kl16[i]); + } +} +UINT DES_F(UINT R, UINT Kh32, UINT Kl16) +{ + UINT Eh32,El16; + UINT S[8],P; + DES_E(R,&Eh32,&El16); + Eh32^=Kh32; + El16^=Kl16; + DES_SSplit(Eh32,El16,S); + DES_S(S); + DES_SCombine(S,&P); + DES_P(&P); + return(P); +} +void DES_Cipher(UINT * Kh32, UINT * Kl16, DES_DATA * pData) +{ + UINT L0,R0,L,R; + UINT i; + + DES_IP(pData); + DES_LRSplit(pData,&L0,&R0); + for (i=0;i<16;i++) + { + L=R0; + R=DES_F(R0,Kh32[i],Kl16[i]); + R=L0^R; + L0=L; + R0=R; + } + L=R0; + R=L0; + DES_LRCombine(pData,L,R); + DES_IP_R(pData); +} +void DES_Decipher(UINT * Kh32,UINT * Kl16,DES_DATA * pData) +{ + UINT L0,R0,L,R; + UINT i; + + DES_IP(pData); + DES_LRSplit(pData,&L,&R); + L0=R; + R0=L; + for (i=0;i<16;i++) + { + R=L0; + L=R0^DES_F(L0,Kh32[15-i],Kl16[15-i]); + L0=L; + R0=R; + } + DES_LRCombine(pData,L0,R0); + DES_IP_R(pData); +} +/***************************** + Tripple DES is a evolution of single DES with three 64 bits keys K1,K2,K3 + 3DES.Cipher:=DES.Cipher(K3,DES.Decipher(K2,DES.Cipher(K1,input))); + 3DES.Decipher:=DES.Decipher(K1,DES.Cipher(K2,DES.Desipher(K3,input))); +*****************************/ +void TDES_Cipher(UINT * K1h32,UINT * K1l16, + UINT * K2h32,UINT * K2l16, + UINT * K3h32,UINT * K3l16, + DES_DATA * pData) +{ + DES_Cipher(K1h32,K1l16,pData); + DES_Decipher(K2h32,K2l16,pData); + DES_Cipher(K3h32,K3l16,pData); +} +void TDES_Decipher(UINT * K1h32,UINT * K1l16, + UINT * K2h32,UINT * K2l16, + UINT * K3h32,UINT * K3l16, + DES_DATA * pData) +{ + DES_Decipher(K3h32,K3l16,pData); + DES_Cipher(K2h32,K2l16,pData); + DES_Decipher(K1h32,K1l16,pData); +} +/********************** + ECB mode +**********************/ +void DES_ECB_Cipher(DES_DATA * pData,UINT nLength,KEY_STRUCT Key) +{ + UINT Kh32[16],Kl16[16]; + UINT i; + DES_KS(Key,(int *)Kh32,(int *)Kl16); + for (i=0;i #include #include "tcrypt.h" +#include + +#include +#include +#include +#include /* * Need to kmalloc() memory for testing kmap(). @@ -57,13 +63,21 @@ #define MODE_ECB 1 #define MODE_CBC 0 +#ifdef CONFIG_SL2312_IPSEC +#define IPSEC_MAX_PACKET_LEN 2048 +static unsigned char *pkt; +#else +#define IPSEC_MAX_PACKET_LEN 2048 +static unsigned char *pkt; +#endif + static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; /* * Used by test_cipher_speed() */ static unsigned int sec; - +extern unsigned int crypto_done,crypto_go ; static int mode; static char *xbuf; static char *tvmem; @@ -74,8 +88,24 @@ "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL }; - -static void hexdump(unsigned char *buf, unsigned int len) +#if 0 +void HW_memcpy(char *to,char *from,unsigned long n) +{ + unsigned int i; + unsigned int p_to = __pa(to); + unsigned int p_from = __pa(from); + + consistent_sync(to,n,DMA_BIDIRECTIONAL); + consistent_sync(from,n,DMA_BIDIRECTIONAL); + writel(p_from,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x24); /* set source address */ + writel(p_to,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x28); /* set destination address */ + writel(n,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x2c); /* set byte count */ + writel(0x00000001,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20); + + while (readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20)); +} +#endif +void hexdump(unsigned char *buf, unsigned int len) { while (len--) printk("%02x", *buf++); @@ -83,7 +113,262 @@ printk("\n"); } -static void test_hash(char *algo, struct hash_testvec *template, +void test_digest(void) +{ + unsigned char alg[2][8] = {"md5","sha1"}; + // unsigned int mode = 0; + //unsigned char auth_key[64]; + unsigned int key_len=0 ; + struct crypto_tfm *tfm; + struct scatterlist sg[8]; + char *packet,*auth_key; //*p, + unsigned int i,k=0,algorithm_len; //j + char result[64], result_sw[64]; + + + + packet = kmalloc(IPSEC_MAX_PACKET_LEN,GFP_ATOMIC); + auth_key = kmalloc(64,GFP_ATOMIC); + if ((packet == NULL)||(auth_key == NULL)) + { + printk("memory allocation fail !\n"); + } + + /* init packet */ + for (i=0;icrt_u.digest.dit_setkey) { + crypto_digest_setkey (tfm, auth_key, + key_len); + } + crypto_digest_update (tfm, sg, 1); + crypto_digest_final (tfm, result); + crypto_go = 1; + //printk("crypto : "); + //hexdump (result, crypto_tfm_alg_digestsize (tfm)); + //printk("cryapi : "); + //hexdump (hash_tv[i].digest, crypto_tfm_alg_digestsize (tfm)); + + ipsec_sw_authentication(packet, i, auth_key, ipsec_get_auth_algorithm((unsigned char *)tfm->__crt_alg->cra_name,0), result_sw); + //printk("test 0x%x : %s\n", i, + // memcmp(result, result_sw, + // crypto_tfm_alg_digestsize(tfm)) ? "fail" : + // "pass"); + if(memcmp(result, result_sw, crypto_tfm_alg_digestsize(tfm))) + { + printk("test 0x%x \n",i); + printk("crypto : "); + hexdump (result, crypto_tfm_alg_digestsize (tfm)); + printk("crypsw : "); + hexdump (result_sw, crypto_tfm_alg_digestsize (tfm)); + } + + } + } + + //hmac + for(k=0;k<2;k++) + { + tfm = crypto_alloc_tfm(&alg[k][0], 0); + if (tfm == NULL) { + printk("failed to load transform for %s\n", &alg[k][0]); + return; + } + printk("\ntesting hmac_%s\n", &alg[k][0]); + //p = kmalloc(IPSEC_MAX_PACKET_LEN,GFP_ATOMIC); + //if (p == NULL) { + // printk("P failed to load transform.\n"); + // return; + //} + for (i=1;i<=algorithm_len;i++) + { + //memset(p, 0, IPSEC_MAX_PACKET_LEN); + memset(result, 0, sizeof (result)); + memset(result_sw, 0, sizeof (result_sw)); + + //memcpy(p, packet, i); + sg[0].page = virt_to_page(packet); + sg[0].offset = offset_in_page(packet); + sg[0].length = i; + + //for(j=0;j<64;j++) + //{ + key_len = 64; + crypto_hmac(tfm, auth_key, &key_len, sg, 1, result); + crypto_go = 1; + //printk("crypto : "); + //hexdump (result, crypto_tfm_alg_digestsize (tfm)); + //printk("cryapi : "); + //hexdump (hash_tv[i].digest, crypto_tfm_alg_digestsize (tfm)); + + ipsec_sw_authentication(packet, i, auth_key, ipsec_get_auth_algorithm((unsigned char *)tfm->__crt_alg->cra_name,1), result_sw); + //printk("test 0x%x : %s\n", i, + // memcmp(result, result_sw, + // crypto_tfm_alg_digestsize(tfm)) ? "fail" : + // "pass"); + if(memcmp(result, result_sw, crypto_tfm_alg_digestsize(tfm))) + { + printk("test hmac 0x%x \n",i); + printk("crypto : "); + hexdump (result, crypto_tfm_alg_digestsize (tfm)); + printk("crypsw : "); + hexdump (result_sw, crypto_tfm_alg_digestsize (tfm)); + } + //} + + } + } + + //kfree(p); + kfree(packet); + kfree(auth_key); + crypto_free_tfm (tfm); +} + +void test_crypto_cipher(void) +{ + struct crypto_tfm *tfm; + unsigned char algo[20][9] = {"des", "des", "des3_ede" , "des3_ede", "aes","aes","aes","aes","aes","aes" + ,"des","des","des3_ede","des3_ede","aes","aes","aes","aes","aes","aes"}; + unsigned int mode[20] ={MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC, + MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC,MODE_ECB,MODE_CBC}; + //unsigned int mode[20] ={MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC, + // MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC,MODE_CBC}; + unsigned int enc[20] ={ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT,ENCRYPT, + DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT,DECRYPT}; + unsigned int key_len[20] = {8,8,24,24,16,16,24,24,32,32,8,8,24,24,16,16,24,24,32,32}; + unsigned int iv_len[20] = {0,8,0,8,0,16,0,16,0,16,0,8,0,8,0,16,0,16,0,16}; + + unsigned char key[32]; + //unsigned int key_len = 16; + unsigned char iv[16]; + //unsigned char iv_len = 16; + struct scatterlist sg[8]; + unsigned char *q, *p; + unsigned int i,ret,j; + char e[11], m[4]; + + + + pkt = kmalloc(IPSEC_MAX_PACKET_LEN,GFP_ATOMIC); + for (i=0;icrt_u.digest.dit_setkey) { @@ -124,8 +418,8 @@ } crypto_digest_update(tfm, sg, 1); crypto_digest_final(tfm, result); - - hexdump(result, crypto_tfm_alg_digestsize(tfm)); +crypto_go = 1; +// hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? @@ -143,36 +437,43 @@ j++; printk("test %u:\n", j); memset(result, 0, 64); - + memset(&sg,0x00,8*sizeof(struct scatterlist)); + memset(&sg,0x00,8*sizeof(struct scatterlist)); temp = 0; for (k = 0; k < hash_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hash_tv[i].plaintext + temp, hash_tv[i].tap[k]); + + memcpy(p+temp,&xbuf[IDX[k]],hash_tv[i].tap[k]); temp += hash_tv[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - hash_tv[i].tap[k]); + sg[k].page = virt_to_page (p); + sg[k].offset = offset_in_page (p); + sg[k].length = hash_tv[i].tap[k]; + //sg_set_buf(&sg[k], &xbuf[IDX[k]], + // hash_tv[i].tap[k]); } crypto_digest_digest(tfm, sg, hash_tv[i].np, result); - - hexdump(result, crypto_tfm_alg_digestsize(tfm)); + crypto_go = 1; +// hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } } - + kfree(p); crypto_free_tfm(tfm); } #ifdef CONFIG_CRYPTO_HMAC -static void test_hmac(char *algo, struct hmac_testvec *template, +void test_hmac(char *algo, struct hmac_testvec *template, unsigned int tcount) { + char *p; unsigned int i, j, k, temp; struct scatterlist sg[8]; char result[64]; @@ -187,6 +488,13 @@ } printk("\ntesting hmac_%s\n", algo); + p = kmalloc(IPSEC_MAX_PACKET_LEN,GFP_ATOMIC); + if (p == NULL) { + printk("P failed to load transform.\n"); + return; + } + printk("\ntesting hmac_%s\n", algo); + tsize = sizeof(struct hmac_testvec); tsize *= tcount; @@ -202,13 +510,27 @@ for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, sizeof (result)); - + memset(&sg,0x00,8*sizeof(struct scatterlist)); + //klen = hmac_tv[i].ksize; + //sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize); + //p = hmac_tv[i].plaintext; + memcpy(p,hmac_tv[i].plaintext,hmac_tv[i].psize); + //printk("p = %x\n",p); klen = hmac_tv[i].ksize; - sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize); - + sg[0].page = virt_to_page(p); + sg[0].offset = offset_in_page(p); + sg[0].length = hmac_tv[i].psize; + crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result); - - hexdump(result, crypto_tfm_alg_digestsize(tfm)); + crypto_go = 1; + //hexdump(result, crypto_tfm_alg_digestsize(tfm)); + if(memcmp(result, hmac_tv[i].digest,crypto_tfm_alg_digestsize(tfm))) + { + printk("crypto : "); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("cryapi : "); + hexdump (hmac_tv[i].digest, crypto_tfm_alg_digestsize (tfm)); + } printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : @@ -218,29 +540,47 @@ printk("\ntesting hmac_%s across pages\n", algo); memset(xbuf, 0, XBUFSIZE); - + j = 0; for (i = 0; i < tcount; i++) { if (hmac_tv[i].np) { j++; printk("test %u:\n",j); memset(result, 0, 64); - + memset(&sg,0x00,8*sizeof(struct scatterlist)); temp = 0; klen = hmac_tv[i].ksize; for (k = 0; k < hmac_tv[i].np; k++) { memcpy(&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, hmac_tv[i].tap[k]); - temp += hmac_tv[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - hmac_tv[i].tap[k]); + //temp += hmac_tv[i].tap[k]; + //sg_set_buf(&sg[k], &xbuf[IDX[k]], + // hmac_tv[i].tap[k]); + memcpy(p+temp,&xbuf[IDX[k]],hmac_tv[i].tap[k]); + + sg[k].page = virt_to_page (p+temp); + sg[k].offset = offset_in_page (p+temp); + sg[k].length = hmac_tv[i].tap[k]; + temp += hmac_tv[i].tap[k]; } crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, result); - hexdump(result, crypto_tfm_alg_digestsize(tfm)); - + crypto_go = 1; + printk("crypto : "); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("cryapi : "); + hexdump (hmac_tv[i].digest, crypto_tfm_alg_digestsize (tfm)); + //hexdump(result, crypto_tfm_alg_digestsize(tfm)); + if(memcmp(result, hmac_tv[i].digest,crypto_tfm_alg_digestsize(tfm))) + { + printk("crypto : "); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("cryapi : "); + hexdump (hmac_tv[i].digest, crypto_tfm_alg_digestsize (tfm)); + } + printk("%s\n", memcmp(result, hmac_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? @@ -248,31 +588,33 @@ } } out: +kfree(p); crypto_free_tfm(tfm); } #endif /* CONFIG_CRYPTO_HMAC */ -static void test_cipher(char *algo, int mode, int enc, +void test_cipher(char *algo, int mode, int enc, struct cipher_testvec *template, unsigned int tcount) { unsigned int ret, i, j, k, temp; unsigned int tsize; - char *q; + char *p, *q; struct crypto_tfm *tfm; char *key; struct cipher_testvec *cipher_tv; struct scatterlist sg[8]; - const char *e, *m; + //const char *e, *m; + char e[11], m[4]; if (enc == ENCRYPT) - e = "encryption"; + strncpy(e, "encryption", 11); else - e = "decryption"; + strncpy(e, "decryption", 11); if (mode == MODE_ECB) - m = "ECB"; + strncpy(m, "ECB", 4); else - m = "CBC"; + strncpy(m, "CBC", 4); printk("\ntesting %s %s %s\n", algo, m, e); @@ -298,9 +640,16 @@ return; } + p = kmalloc(IPSEC_MAX_PACKET_LEN,GFP_DMA);//GFP_ATOMIC); + if (p == NULL) { + printk("P failed to load transform.\n"); + return; + } + j = 0; for (i = 0; i < tcount; i++) { if (!(cipher_tv[i].np)) { + memset(p,0,256); j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); @@ -318,8 +667,12 @@ goto out; } - sg_set_buf(&sg[0], cipher_tv[i].input, - cipher_tv[i].ilen); + //sg_set_buf(&sg[0], cipher_tv[i].input, + // cipher_tv[i].ilen); + memcpy(p,cipher_tv[i].input,cipher_tv[i].ilen); + sg[0].page = virt_to_page(p); + sg[0].offset = offset_in_page(p); + sg[0].length = cipher_tv[i].ilen; if (!mode) { crypto_cipher_set_iv(tfm, cipher_tv[i].iv, @@ -327,10 +680,16 @@ } if (enc) + { + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + crypto_go = 1; + } else + { ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); - + crypto_go = 1; + } if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); @@ -338,7 +697,7 @@ } q = kmap(sg[0].page) + sg[0].offset; - hexdump(q, cipher_tv[i].rlen); + printk("%s\n", memcmp(q, cipher_tv[i].result, @@ -352,6 +711,7 @@ j = 0; for (i = 0; i < tcount; i++) { if (cipher_tv[i].np) { + memset(p,0,256); j++; printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); @@ -374,9 +734,18 @@ memcpy(&xbuf[IDX[k]], cipher_tv[i].input + temp, cipher_tv[i].tap[k]); - temp += cipher_tv[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - cipher_tv[i].tap[k]); + + memcpy((p+temp),&xbuf[IDX[k]],cipher_tv[i].tap[k]); + consistent_sync(&p, cipher_tv[i].rlen, DMA_BIDIRECTIONAL); + printk("np %x : length : %x\n",k,cipher_tv[i].tap[k]); + hexdump((p+temp), cipher_tv[i].tap[k]); + //temp += cipher_tv[i].tap[k]; + //sg_set_buf(&sg[k], &xbuf[IDX[k]], + // cipher_tv[i].tap[k]); + sg[k].page = virt_to_page (p+temp); + sg[k].offset = offset_in_page (p+temp); + sg[k].length = cipher_tv[i].tap[k]; + temp += cipher_tv[i].tap[k]; } if (!mode) { @@ -385,9 +754,17 @@ } if (enc) + { + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + crypto_go = 1; + } else + { + ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); + crypto_go = 1; + } if (ret) { printk("%s () failed flags=%x\n", e, tfm->crt_flags); @@ -398,21 +775,26 @@ for (k = 0; k < cipher_tv[i].np; k++) { printk("page %u\n", k); q = kmap(sg[k].page) + sg[k].offset; - hexdump(q, cipher_tv[i].tap[k]); + consistent_sync(&q, cipher_tv[i].rlen, DMA_BIDIRECTIONAL); + printk("q : %x\n",q); + hexdump(q, cipher_tv[i].rlen); + hexdump(cipher_tv[i].result, cipher_tv[i].rlen); printk("%s\n", - memcmp(q, cipher_tv[i].result + temp, + memcmp(q , cipher_tv[i].result + temp, cipher_tv[i].tap[k]) ? "fail" : "pass"); + //hexdump(cipher_tv[i].result + temp, cipher_tv[i].tap[k]); temp += cipher_tv[i].tap[k]; } } } out: + kfree(p); crypto_free_tfm(tfm); } -static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p, +int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p, int blen, int sec) { struct scatterlist sg[1]; @@ -438,7 +820,7 @@ return 0; } -static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p, +int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p, int blen) { struct scatterlist sg[1]; @@ -490,7 +872,7 @@ return ret; } -static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec, +void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec, struct cipher_testvec *template, unsigned int tcount, struct cipher_speed *speed) { @@ -570,7 +952,7 @@ crypto_free_tfm(tfm); } -static void test_deflate(void) +void test_deflate(void) { unsigned int i; char result[COMP_BUF_SIZE]; @@ -649,7 +1031,7 @@ crypto_free_tfm(tfm); } -static void test_crc32c(void) +void test_crc32c(void) { #define NUMVEC 6 #define VECSIZE 40 @@ -689,7 +1071,10 @@ for (i = 0; i < NUMVEC; i++) { for (j = 0; j < VECSIZE; j++) test_vec[i][j] = ++b; - sg_set_buf(&sg[i], test_vec[i], VECSIZE); + //sg_set_buf(&sg[i], test_vec[i], VECSIZE); + sg[i].page = virt_to_page(test_vec[i]); + sg[i].offset = offset_in_page(test_vec[i]); + sg[i].length = VECSIZE; } seed = SEEDTESTVAL; @@ -747,7 +1132,7 @@ printk("crc32c test complete\n"); } -static void test_available(void) +void test_available(void) { char **name = check; @@ -759,8 +1144,9 @@ } } -static void do_test(void) +void do_test(void) { + mode = 997; switch (mode) { case 0: @@ -861,7 +1247,8 @@ break; case 1: - test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + test_crypto_cipher(); + //test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); break; case 2: @@ -878,6 +1265,7 @@ case 4: test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); + break; case 5: @@ -1047,6 +1435,7 @@ des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS, des3_ede_speed_template); + break; case 202: @@ -1082,6 +1471,58 @@ des_speed_template); break; + case 999: + test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + //DES + test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); + + //DES3_EDE + test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); + + //AES + test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + + + break; + case 998: + //test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + //test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + + break; + + case 997: + test_digest(); + test_crypto_cipher(); + test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + //DES + //test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + // test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + // test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + // test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); + + //DES3_EDE + //test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + // test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); + + //AES + //test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + //test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + + break; + case 1000: test_available(); break; @@ -1093,7 +1534,7 @@ } } -static int __init init(void) +int __init init(void) { tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); if (tvmem == NULL) diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/crypto/tcrypt.h linux-sl3516/crypto/tcrypt.h --- linux-2.6.15-armeb/crypto/tcrypt.h 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/crypto/tcrypt.h 2006-04-13 19:19:53.000000000 +0930 @@ -113,13 +113,10 @@ /* * MD5 test vectors from RFC1321 */ -#define MD5_TEST_VECTORS 7 +#define MD5_TEST_VECTORS 6 static struct hash_testvec md5_tv_template[] = { { - .digest = { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, - 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }, - }, { .plaintext = "a", .psize = 1, .digest = { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/Documentation/00-INDEX linux-sl3516/Documentation/00-INDEX --- linux-2.6.15-armeb/Documentation/00-INDEX 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/Documentation/00-INDEX 1970-01-01 09:30:00.000000000 +0930 @@ -1,302 +0,0 @@ - -This is a brief list of all the files in ./linux/Documentation and what -they contain. If you add a documentation file, please list it here in -alphabetical order as well, or risk being hunted down like a rabid dog. -Please try and keep the descriptions small enough to fit on one line. - Thanks -- Paul G. - -Following translations are available on the WWW: - - - Japanese, maintained by the JF Project (JF@linux.or.jp), at - http://www.linux.or.jp/JF/ - -00-INDEX - - this file. -BUG-HUNTING - - brute force method of doing binary search of patches to find bug. -Changes - - list of changes that break older software packages. -CodingStyle - - how the boss likes the C code in the kernel to look. -DMA-API.txt - - DMA API, pci_ API & extensions for non-consistent memory machines. -DMA-mapping.txt - - info for PCI drivers using DMA portably across all platforms. -DocBook/ - - directory with DocBook templates etc. for kernel documentation. -HOWTO - - The process and procedures of how to do Linux kernel development. -IO-mapping.txt - - how to access I/O mapped memory from within device drivers. -IPMI.txt - - info on Linux Intelligent Platform Management Interface (IPMI) Driver. -IRQ-affinity.txt - - how to select which CPU(s) handle which interrupt events on SMP. -ManagementStyle - - how to (attempt to) manage kernel hackers. -MSI-HOWTO.txt - - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ. -RCU/ - - directory with info on RCU (read-copy update). -README.DAC960 - - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux. -SAK.txt - - info on Secure Attention Keys. -SubmittingDrivers - - procedure to get a new driver source included into the kernel tree. -SubmittingPatches - - procedure to get a source patch included into the kernel tree. -VGA-softcursor.txt - - how to change your VGA cursor from a blinking underscore. -applying-patches.txt - - description of various trees and how to apply their patches. -arm/ - - directory with info about Linux on the ARM architecture. -basic_profiling.txt - - basic instructions for those who wants to profile Linux kernel. -binfmt_misc.txt - - info on the kernel support for extra binary formats. -block/ - - info on the Block I/O (BIO) layer. -cachetlb.txt - - describes the cache/TLB flushing interfaces Linux uses. -cciss.txt - - info, major/minor #'s for Compaq's SMART Array Controllers. -cdrom/ - - directory with information on the CD-ROM drivers that Linux has. -cli-sti-removal.txt - - cli()/sti() removal guide. -computone.txt - - info on Computone Intelliport II/Plus Multiport Serial Driver. -cpqarray.txt - - info on using Compaq's SMART2 Intelligent Disk Array Controllers. -cpu-freq/ - - info on CPU frequency and voltage scaling. -cris/ - - directory with info about Linux on CRIS architecture. -crypto/ - - directory with info on the Crypto API. -debugging-modules.txt - - some notes on debugging modules after Linux 2.6.3. -device-mapper/ - - directory with info on Device Mapper. -devices.txt - - plain ASCII listing of all the nodes in /dev/ with major minor #'s. -digiepca.txt - - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. -dnotify.txt - - info about directory notification in Linux. -driver-model/ - - directory with info about Linux driver model. -dvb/ - - info on Linux Digital Video Broadcast (DVB) subsystem. -early-userspace/ - - info about initramfs, klibc, and userspace early during boot. -eisa.txt - - info on EISA bus support. -exception.txt - - how Linux v2.2 handles exceptions without verify_area etc. -fb/ - - directory with info on the frame buffer graphics abstraction layer. -filesystems/ - - directory with info on the various filesystems that Linux supports. -firmware_class/ - - request_firmware() hotplug interface info. -floppy.txt - - notes and driver options for the floppy disk driver. -ftape.txt - - notes about the floppy tape device driver. -hayes-esp.txt - - info on using the Hayes ESP serial driver. -highuid.txt - - notes on the change from 16 bit to 32 bit user/group IDs. -hpet.txt - - High Precision Event Timer Driver for Linux. -hw_random.txt - - info on Linux support for random number generator in i8xx chipsets. -i2c/ - - directory with info about the I2C bus/protocol (2 wire, kHz speed). -i2o/ - - directory with info about the Linux I2O subsystem. -i386/ - - directory with info about Linux on Intel 32 bit architecture. -ia64/ - - directory with info about Linux on Intel 64 bit architecture. -ide.txt - - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS). -initrd.txt - - how to use the RAM disk as an initial/temporary root filesystem. -input/ - - info on Linux input device support. -io_ordering.txt - - info on ordering I/O writes to memory-mapped addresses. -ioctl-number.txt - - how to implement and register device/driver ioctl calls. -iostats.txt - - info on I/O statistics Linux kernel provides. -isapnp.txt - - info on Linux ISA Plug & Play support. -isdn/ - - directory with info on the Linux ISDN support, and supported cards. -java.txt - - info on the in-kernel binary support for Java(tm). -kbuild/ - - directory with info about the kernel build process. -kdumpt.txt - - mini HowTo on getting the crash dump code to work. -kernel-doc-nano-HOWTO.txt - - mini HowTo on generation and location of kernel documentation files. -kernel-docs.txt - - listing of various WWW + books that document kernel internals. -kernel-parameters.txt - - summary listing of command line / boot prompt args for the kernel. -kobject.txt - - info of the kobject infrastructure of the Linux kernel. -laptop-mode.txt - - How to conserve battery power using laptop-mode. -ldm.txt - - a brief description of LDM (Windows Dynamic Disks). -locks.txt - - info on file locking implementations, flock() vs. fcntl(), etc. -logo.gif - - Full colour GIF image of Linux logo (penguin). -logo.txt - - Info on creator of above logo & site to get additional images from. -m68k/ - - directory with info about Linux on Motorola 68k architecture. -magic-number.txt - - list of magic numbers used to mark/protect kernel data structures. -mandatory.txt - - info on the Linux implementation of Sys V mandatory file locking. -mca.txt - - info on supporting Micro Channel Architecture (e.g. PS/2) systems. -md.txt - - info on boot arguments for the multiple devices driver. -memory.txt - - info on typical Linux memory problems. -mips/ - - directory with info about Linux on MIPS architecture. -mono.txt - - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. -moxa-smartio - - info on installing/using Moxa multiport serial driver. -mtrr.txt - - how to use PPro Memory Type Range Registers to increase performance. -nbd.txt - - info on a TCP implementation of a network block device. -networking/ - - directory with info on various aspects of networking with Linux. -nfsroot.txt - - short guide on setting up a diskless box with NFS root filesystem. -nmi_watchdog.txt - - info on NMI watchdog for SMP systems. -numastat.txt - - info on how to read Numa policy hit/miss statistics in sysfs. -oops-tracing.txt - - how to decode those nasty internal kernel error dump messages. -paride.txt - - information about the parallel port IDE subsystem. -parisc/ - - directory with info on using Linux on PA-RISC architecture. -parport.txt - - how to use the parallel-port driver. -parport-lowlevel.txt - - description and usage of the low level parallel port functions. -pci.txt - - info on the PCI subsystem for device driver authors. -pm.txt - - info on Linux power management support. -pnp.txt - - Linux Plug and Play documentation. -power/ - - directory with info on Linux PCI power management. -powerpc/ - - directory with info on using Linux with the PowerPC. -preempt-locking.txt - - info on locking under a preemptive kernel. -ramdisk.txt - - short guide on how to set up and use the RAM disk. -riscom8.txt - - notes on using the RISCom/8 multi-port serial driver. -rocket.txt - - info on the Comtrol RocketPort multiport serial driver. -rpc-cache.txt - - introduction to the caching mechanisms in the sunrpc layer. -rtc.txt - - notes on how to use the Real Time Clock (aka CMOS clock) driver. -s390/ - - directory with info on using Linux on the IBM S390. -sched-coding.txt - - reference for various scheduler-related methods in the O(1) scheduler. -sched-design.txt - - goals, design and implementation of the Linux O(1) scheduler. -sched-domains.txt - - information on scheduling domains. -sched-stats.txt - - information on schedstats (Linux Scheduler Statistics). -scsi/ - - directory with info on Linux scsi support. -serial/ - - directory with info on the low level serial API. -serial-console.txt - - how to set up Linux with a serial line console as the default. -sgi-visws.txt - - short blurb on the SGI Visual Workstations. -sh/ - - directory with info on porting Linux to a new architecture. -smart-config.txt - - description of the Smart Config makefile feature. -smp.txt - - a few notes on symmetric multi-processing. -sonypi.txt - - info on Linux Sony Programmable I/O Device support. -sound/ - - directory with info on sound card support. -sparc/ - - directory with info on using Linux on Sparc architecture. -specialix.txt - - info on hardware/driver for specialix IO8+ multiport serial card. -spinlocks.txt - - info on using spinlocks to provide exclusive access in kernel. -stable_api_nonsense.txt - - info on why the kernel does not have a stable in-kernel api or abi. -stable_kernel_rules.txt - - rules and procedures for the -stable kernel releases. -stallion.txt - - info on using the Stallion multiport serial driver. -svga.txt - - short guide on selecting video modes at boot via VGA BIOS. -sx.txt - - info on the Specialix SX/SI multiport serial driver. -sysctl/ - - directory with info on the /proc/sys/* files. -sysrq.txt - - info on the magic SysRq key. -telephony/ - - directory with info on telephony (e.g. voice over IP) support. -time_interpolators.txt - - info on time interpolators. -tipar.txt - - information about Parallel link cable for Texas Instruments handhelds. -tty.txt - - guide to the locking policies of the tty layer. -unicode.txt - - info on the Unicode character/font mapping used in Linux. -uml/ - - directory with information about User Mode Linux. -usb/ - - directory with info regarding the Universal Serial Bus. -video4linux/ - - directory with info regarding video/TV/radio cards and linux. -vm/ - - directory with info on the Linux vm code. -voyager.txt - - guide to running Linux on the Voyager architecture. -watchdog/ - - how to auto-reboot Linux if it has "fallen and can't get up". ;-) -x86_64/ - - directory with info on Linux support for AMD x86-64 (Hammer) machines. -xterm-linux.xpm - - XPM image of penguin logo (see logo.txt) sitting on an xterm. -zorro.txt - - info on writing drivers for Zorro bus devices found on Amigas. diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/Documentation/BUG-HUNTING linux-sl3516/Documentation/BUG-HUNTING --- linux-2.6.15-armeb/Documentation/BUG-HUNTING 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/Documentation/BUG-HUNTING 1970-01-01 09:30:00.000000000 +0930 @@ -1,92 +0,0 @@ -[Sat Mar 2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm@sgi.com (Larry McVoy)] - -This is how to track down a bug if you know nothing about kernel hacking. -It's a brute force approach but it works pretty well. - -You need: - - . A reproducible bug - it has to happen predictably (sorry) - . All the kernel tar files from a revision that worked to the - revision that doesn't - -You will then do: - - . Rebuild a revision that you believe works, install, and verify that. - . Do a binary search over the kernels to figure out which one - introduced the bug. I.e., suppose 1.3.28 didn't have the bug, but - you know that 1.3.69 does. Pick a kernel in the middle and build - that, like 1.3.50. Build & test; if it works, pick the mid point - between .50 and .69, else the mid point between .28 and .50. - . You'll narrow it down to the kernel that introduced the bug. You - can probably do better than this but it gets tricky. - - . Narrow it down to a subdirectory - - - Copy kernel that works into "test". Let's say that 3.62 works, - but 3.63 doesn't. So you diff -r those two kernels and come - up with a list of directories that changed. For each of those - directories: - - Copy the non-working directory next to the working directory - as "dir.63". - One directory at time, try moving the working directory to - "dir.62" and mv dir.63 dir"time, try - - mv dir dir.62 - mv dir.63 dir - find dir -name '*.[oa]' -print | xargs rm -f - - And then rebuild and retest. Assuming that all related - changes were contained in the sub directory, this should - isolate the change to a directory. - - Problems: changes in header files may have occurred; I've - found in my case that they were self explanatory - you may - or may not want to give up when that happens. - - . Narrow it down to a file - - - You can apply the same technique to each file in the directory, - hoping that the changes in that file are self contained. - - . Narrow it down to a routine - - - You can take the old file and the new file and manually create - a merged file that has - - #ifdef VER62 - routine() - { - ... - } - #else - routine() - { - ... - } - #endif - - And then walk through that file, one routine at a time and - prefix it with - - #define VER62 - /* both routines here */ - #undef VER62 - - Then recompile, retest, move the ifdefs until you find the one - that makes the difference. - -Finally, you take all the info that you have, kernel revisions, bug -description, the extent to which you have narrowed it down, and pass -that off to whomever you believe is the maintainer of that section. -A post to linux.dev.kernel isn't such a bad idea if you've done some -work to narrow it down. - -If you get it down to a routine, you'll probably get a fix in 24 hours. - -My apologies to Linus and the other kernel hackers for describing this -brute force approach, it's hardly what a kernel hacker would do. However, -it does work and it lets non-hackers help fix bugs. And it is cool -because Linux snapshots will let you do this - something that you can't -do with vendor supplied releases. - diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/Documentation/Changes linux-sl3516/Documentation/Changes --- linux-2.6.15-armeb/Documentation/Changes 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/Documentation/Changes 1970-01-01 09:30:00.000000000 +0930 @@ -1,438 +0,0 @@ -Intro -===== - -This document is designed to provide a list of the minimum levels of -software necessary to run the 2.6 kernels, as well as provide brief -instructions regarding any other "Gotchas" users may encounter when -trying life on the Bleeding Edge. If upgrading from a pre-2.4.x -kernel, please consult the Changes file included with 2.4.x kernels for -additional information; most of that information will not be repeated -here. Basically, this document assumes that your system is already -functional and running at least 2.4.x kernels. - -This document is originally based on my "Changes" file for 2.0.x kernels -and therefore owes credit to the same people as that file (Jared Mauch, -Axel Boldt, Alessandro Sigala, and countless other users all over the -'net). - -The latest revision of this document, in various formats, can always -be found at . - -Feel free to translate this document. If you do so, please send me a -URL to your translation for inclusion in future revisions of this -document. - -Smotrite file , yavlyaushisya -russkim perevodom dannogo documenta. - -Visite para obtener la traducción -al español de este documento en varios formatos. - -Eine deutsche Version dieser Datei finden Sie unter -. - -Last updated: October 29th, 2002 - -Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu). - -Current Minimal Requirements -============================ - -Upgrade to at *least* these software revisions before thinking you've -encountered a bug! If you're unsure what version you're currently -running, the suggested command should tell you. - -Again, keep in mind that this list assumes you are already -functionally running a Linux 2.4 kernel. Also, not all tools are -necessary on all systems; obviously, if you don't have any ISDN -hardware, for example, you probably needn't concern yourself with -isdn4k-utils. - -o Gnu C 2.95.3 # gcc --version -o Gnu make 3.79.1 # make --version -o binutils 2.12 # ld -v -o util-linux 2.10o # fdformat --version -o module-init-tools 0.9.10 # depmod -V -o e2fsprogs 1.29 # tune2fs -o jfsutils 1.1.3 # fsck.jfs -V -o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs -o xfsprogs 2.6.0 # xfs_db -V -o pcmciautils 004 -o pcmcia-cs 3.1.21 # cardmgr -V -o quota-tools 3.09 # quota -V -o PPP 2.4.0 # pppd --version -o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version -o nfs-utils 1.0.5 # showmount --version -o procps 3.2.0 # ps --version -o oprofile 0.9 # oprofiled --version -o udev 071 # udevinfo -V - -Kernel compilation -================== - -GCC ---- - -The gcc version requirements may vary depending on the type of CPU in your -computer. The next paragraph applies to users of x86 CPUs, but not -necessarily to users of other CPUs. Users of other CPUs should obtain -information about their gcc version requirements from another source. - -The recommended compiler for the kernel is gcc 2.95.x (x >= 3), and it -should be used when you need absolute stability. You may use gcc 3.0.x -instead if you wish, although it may cause problems. Later versions of gcc -have not received much testing for Linux kernel compilation, and there are -almost certainly bugs (mainly, but not exclusively, in the kernel) that -will need to be fixed in order to use these compilers. In any case, using -pgcc instead of plain gcc is just asking for trouble. - -The Red Hat gcc 2.96 compiler subtree can also be used to build this tree. -You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build -the kernel correctly. - -In addition, please pay attention to compiler optimization. Anything -greater than -O2 may not be wise. Similarly, if you choose to use gcc-2.95.x -or derivatives, be sure not to use -fstrict-aliasing (which, depending on -your version of gcc 2.95.x, may necessitate using -fno-strict-aliasing). - -Make ----- - -You will need Gnu make 3.79.1 or later to build the kernel. - -Binutils --------- - -Linux on IA-32 has recently switched from using as86 to using gas for -assembling the 16-bit boot code, removing the need for as86 to compile -your kernel. This change does, however, mean that you need a recent -release of binutils. - -System utilities -================ - -Architectural changes ---------------------- - -DevFS has been obsoleted in favour of udev -(http://www.kernel.org/pub/linux/utils/kernel/hotplug/) - -32-bit UID support is now in place. Have fun! - -Linux documentation for functions is transitioning to inline -documentation via specially-formatted comments near their -definitions in the source. These comments can be combined with the -SGML templates in the Documentation/DocBook directory to make DocBook -files, which can then be converted by DocBook stylesheets to PostScript, -HTML, PDF files, and several other formats. In order to convert from -DocBook format to a format of your choice, you'll need to install Jade as -well as the desired DocBook stylesheets. - -Util-linux ----------- - -New versions of util-linux provide *fdisk support for larger disks, -support new options to mount, recognize more supported partition -types, have a fdformat which works with 2.4 kernels, and similar goodies. -You'll probably want to upgrade. - -Ksymoops --------- - -If the unthinkable happens and your kernel oopses, you may need the -ksymoops tool to decode it, but in most cases you don't. -In the 2.6 kernel it is generally preferred to build the kernel with -CONFIG_KALLSYMS so that it produces readable dumps that can be used as-is -(this also produces better output than ksymoops). -If for some reason your kernel is not build with CONFIG_KALLSYMS and -you have no way to rebuild and reproduce the Oops with that option, then -you can still decode that Oops with ksymoops. - -Module-Init-Tools ------------------ - -A new module loader is now in the kernel that requires module-init-tools -to use. It is backward compatible with the 2.4.x series kernels. - -Mkinitrd --------- - -These changes to the /lib/modules file tree layout also require that -mkinitrd be upgraded. - -E2fsprogs ---------- - -The latest version of e2fsprogs fixes several bugs in fsck and -debugfs. Obviously, it's a good idea to upgrade. - -JFSutils --------- - -The jfsutils package contains the utilities for the file system. -The following utilities are available: -o fsck.jfs - initiate replay of the transaction log, and check - and repair a JFS formatted partition. -o mkfs.jfs - create a JFS formatted partition. -o other file system utilities are also available in this package. - -Reiserfsprogs -------------- - -The reiserfsprogs package should be used for reiserfs-3.6.x -(Linux kernels 2.4.x). It is a combined package and contains working -versions of mkreiserfs, resize_reiserfs, debugreiserfs and -reiserfsck. These utils work on both i386 and alpha platforms. - -Xfsprogs --------- - -The latest version of xfsprogs contains mkfs.xfs, xfs_db, and the -xfs_repair utilities, among others, for the XFS filesystem. It is -architecture independent and any version from 2.0.0 onward should -work correctly with this version of the XFS kernel code (2.6.0 or -later is recommended, due to some significant improvements). - -PCMCIAutils ------------ - -PCMCIAutils replaces pcmcia-cs (see below). It properly sets up -PCMCIA sockets at system startup and loads the appropriate modules -for 16-bit PCMCIA devices if the kernel is modularized and the hotplug -subsystem is used. - -Pcmcia-cs ---------- - -PCMCIA (PC Card) support is now partially implemented in the main -kernel source. The "pcmciautils" package (see above) replaces pcmcia-cs -for newest kernels. - -Quota-tools ------------ - -Support for 32 bit uid's and gid's is required if you want to use -the newer version 2 quota format. Quota-tools version 3.07 and -newer has this support. Use the recommended version or newer -from the table above. - -Intel IA32 microcode --------------------- - -A driver has been added to allow updating of Intel IA32 microcode, -accessible as both a devfs regular file and as a normal (misc) -character device. If you are not using devfs you may need to: - -mkdir /dev/cpu -mknod /dev/cpu/microcode c 10 184 -chmod 0644 /dev/cpu/microcode - -as root before you can use this. You'll probably also want to -get the user-space microcode_ctl utility to use with this. - -Powertweak ----------- - -If you are running v0.1.17 or earlier, you should upgrade to -version v0.99.0 or higher. Running old versions may cause problems -with programs using shared memory. - -udev ----- -udev is a userspace application for populating /dev dynamically with -only entries for devices actually present. udev replaces devfs. - -FUSE ----- - -Needs libfuse 2.4.0 or later. Absolute minimum is 2.3.0 but mount -options 'direct_io' and 'kernel_cache' won't work. - -Networking -========== - -General changes ---------------- - -If you have advanced network configuration needs, you should probably -consider using the network tools from ip-route2. - -Packet Filter / NAT -------------------- -The packet filtering and NAT code uses the same tools like the previous 2.4.x -kernel series (iptables). It still includes backwards-compatibility modules -for 2.2.x-style ipchains and 2.0.x-style ipfwadm. - -PPP ---- - -The PPP driver has been restructured to support multilink and to -enable it to operate over diverse media layers. If you use PPP, -upgrade pppd to at least 2.4.0. - -If you are not using devfs, you must have the device file /dev/ppp -which can be made by: - -mknod /dev/ppp c 108 0 - -as root. - -If you use devfsd and build ppp support as modules, you will need -the following in your /etc/devfsd.conf file: - -LOOKUP PPP MODLOAD - -Isdn4k-utils ------------- - -Due to changes in the length of the phone number field, isdn4k-utils -needs to be recompiled or (preferably) upgraded. - -NFS-utils ---------- - -In 2.4 and earlier kernels, the nfs server needed to know about any -client that expected to be able to access files via NFS. This -information would be given to the kernel by "mountd" when the client -mounted the filesystem, or by "exportfs" at system startup. exportfs -would take information about active clients from /var/lib/nfs/rmtab. - -This approach is quite fragile as it depends on rmtab being correct -which is not always easy, particularly when trying to implement -fail-over. Even when the system is working well, rmtab suffers from -getting lots of old entries that never get removed. - -With 2.6 we have the option of having the kernel tell mountd when it -gets a request from an unknown host, and mountd can give appropriate -export information to the kernel. This removes the dependency on -rmtab and means that the kernel only needs to know about currently -active clients. - -To enable this new functionality, you need to: - - mount -t nfsd nfsd /proc/fs/nfs - -before running exportfs or mountd. It is recommended that all NFS -services be protected from the internet-at-large by a firewall where -that is possible. - -Getting updated software -======================== - -Kernel compilation -****************** - -gcc 2.95.3 ----------- -o - -Make ----- -o - -Binutils --------- -o - -System utilities -**************** - -Util-linux ----------- -o - -Ksymoops --------- -o - -Module-Init-Tools ------------------ -o - -Mkinitrd --------- -o - -E2fsprogs ---------- -o - -JFSutils --------- -o - -Reiserfsprogs -------------- -o - -Xfsprogs --------- -o - -Pcmciautils ------------ -o - -Pcmcia-cs ---------- -o - -Quota-tools ----------- -o - -DocBook Stylesheets -------------------- -o - -XMLTO XSLT Frontend -------------------- -o - -Intel P6 microcode ------------------- -o - -Powertweak ----------- -o - -udev ----- -o - -FUSE ----- -o - -Networking -********** - -PPP ---- -o - -Isdn4k-utils ------------- -o - -NFS-utils ---------- -o - -Iptables --------- -o - -Ip-route2 ---------- -o - -OProfile --------- -o - -NFS-Utils ---------- -o - diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/atm/idt77252.c linux-sl3516/drivers/atm/idt77252.c --- linux-2.6.15-armeb/drivers/atm/idt77252.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/atm/idt77252.c 2006-04-03 18:10:44.000000000 +0930 @@ -1,8 +1,8 @@ /******************************************************************* - * ident "$Id: idt77252.c,v 1.2 2001/11/11 08:13:54 ecd Exp $" + * ident "$Id: idt77252.c,v 1.1.1.1 2006/04/03 08:40:44 amos_lee Exp $" * - * $Author: ecd $ - * $Date: 2001/11/11 08:13:54 $ + * $Author: amos_lee $ + * $Date: 2006/04/03 08:40:44 $ * * Copyright (c) 2000 ATecoM GmbH * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/atm/idt77252.h linux-sl3516/drivers/atm/idt77252.h --- linux-2.6.15-armeb/drivers/atm/idt77252.h 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/atm/idt77252.h 2006-04-03 18:10:44.000000000 +0930 @@ -1,8 +1,8 @@ /******************************************************************* - * ident "$Id: idt77252.h,v 1.2 2001/11/11 08:13:54 ecd Exp $" + * ident "$Id: idt77252.h,v 1.1.1.1 2006/04/03 08:40:44 amos_lee Exp $" * - * $Author: ecd $ - * $Date: 2001/11/11 08:13:54 $ + * $Author: amos_lee $ + * $Date: 2006/04/03 08:40:44 $ * * Copyright (c) 2000 ATecoM GmbH * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/block/cryptoloop.c linux-sl3516/drivers/block/cryptoloop.c --- linux-2.6.15-armeb/drivers/block/cryptoloop.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/block/cryptoloop.c 2006-10-25 16:25:02.000000000 +0930 @@ -35,7 +35,9 @@ #define LOOP_IV_SECTOR_BITS 9 #define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS) - +#ifdef CONFIG_SL2312_IPSEC +extern unsigned long crypto_go; +#endif static int cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) { @@ -101,6 +103,7 @@ encdec_ecb_t encdecfunc; struct page *in_page, *out_page; unsigned in_offs, out_offs; + unsigned int ret; if (cmd == READ) { in_page = raw_page; @@ -127,7 +130,22 @@ sg_out.offset = out_offs; sg_out.length = sz; +#ifdef CONFIG_SL2312_IPSEC + ret = -1; + while (ret) + { + ret = encdecfunc(tfm, &sg_out, &sg_in, sz); + + if (ret) + { + msleep(1); + // printk("%s () failed flags=%x\n", __func__, tfm->crt_flags); + } + } + crypto_go = 1; +#else encdecfunc(tfm, &sg_out, &sg_in, sz); +#endif size -= sz; in_offs += sz; @@ -155,6 +173,7 @@ encdec_cbc_t encdecfunc; struct page *in_page, *out_page; unsigned in_offs, out_offs; + unsigned int ret; if (cmd == READ) { in_page = raw_page; @@ -183,7 +202,23 @@ sg_out.offset = out_offs; sg_out.length = sz; +#ifdef CONFIG_SL2312_IPSEC + ret = -1; + while (ret) + { + ret = encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); + + if (ret) + { + msleep(1); + // printk("%s () failed flags=%x\n", __func__, tfm->crt_flags); + } + } + crypto_go = 1; +#else encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); +#endif + IV++; size -= sz; diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/cyclades.c linux-sl3516/drivers/char/cyclades.c --- linux-2.6.15-armeb/drivers/char/cyclades.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/cyclades.c 2006-04-03 18:10:46.000000000 +0930 @@ -25,6 +25,9 @@ * This version supports shared IRQ's (only for PCI boards). * * $Log: cyclades.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:46 amos_lee + * initial + * * Prevent users from opening non-existing Z ports. * * Revision 2.3.2.8 2000/07/06 18:14:16 ivan diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/ftape/lowlevel/ftape-write.h linux-sl3516/drivers/char/ftape/lowlevel/ftape-write.h --- linux-2.6.15-armeb/drivers/char/ftape/lowlevel/ftape-write.h 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/ftape/lowlevel/ftape-write.h 2006-04-03 18:10:46.000000000 +0930 @@ -20,11 +20,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * - $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-write.h,v $ - $Author: claus $ + $Source: /home/cvs/gemini-2.6.15/drivers/char/ftape/lowlevel/ftape-write.h,v $ + $Author: amos_lee $ * - $Revision: 1.2 $ - $Date: 1997/10/05 19:18:30 $ + $Revision: 1.1.1.1 $ + $Date: 2006/04/03 08:40:46 $ $State: Exp $ * * This file contains the definitions for the write functions diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/gemini_cir.c linux-sl3516/drivers/char/gemini_cir.c --- linux-2.6.15-armeb/drivers/char/gemini_cir.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/gemini_cir.c 2006-06-08 17:02:27.000000000 +0930 @@ -0,0 +1,434 @@ +/* + * FILE NAME sl_cir.c + * + * BRIEF MODULE DESCRIPTION + * Driver for CIR device. + * + * Author: StorLink, Corp. + * Jason Lee + * + * Copyright 2005 StorLink, Corp. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMit8712D TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMit8712D TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, writ8712 to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//#define DEBUT_CIR 1 +#ifndef CIR_MINOR +#define CIR_MINOR 240 // Documents/devices.txt suggest to use 240~255 for local driver!! +#endif + +#ifndef IRQ_CIR +#define IRQ_CIR 25 +#endif + + +static int sl_cir_debug = 1 ; +#define DEB(x) if(sl_cir_debug>=1) x + +unsigned int data=0; +unsigned short data_ext=0; +wait_queue_head_t cir_wait_q; +extern void arch_power_off(char mode); + +static unsigned int cir_read_reg(unsigned int offset) +{ + unsigned int reg_val; + + reg_val = readl(CIR_BASE_ADDR + offset); + return (reg_val); +} + +static void cir_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask) +{ + unsigned int reg_val; + unsigned int *addr; + + reg_val = ( cir_read_reg(offset) & (~bit_mask) ) | (data & bit_mask); + addr = (unsigned int *)(CIR_BASE_ADDR + offset); + writel(reg_val,addr); + return; +} + +// set: 1-5 +// mode:0: input, 1: output +void set_sl_cir_set_baudrate(unsigned short baud) +{ + unsigned int tmp; + tmp = CIR_CTR_REG & 0x0000FFFE ; + tmp |= (baud*EXT_CLK)<<16; +// CIR_CTR_REG = tmp |BIT(0); +} + +void set_sl_cir_set_h_period(unsigned int period) +{ + unsigned int tmp; + if(period>16) + period = 16; + + tmp = CIR_CTR_REG & 0xFFFF0FFE ; + tmp |= (period-1)<<12; +// CIR_CTR_REG = tmp |BIT(0); +} + +void set_sl_cir_set_l_period(unsigned int period) +{ + unsigned int tmp; + if(period>16) + period = 16; + + tmp = CIR_CTR_REG & 0xFFFFF0FE ; + tmp |= (period-1)<<8; +// CIR_CTR_REG = tmp |BIT(0); +} + +void set_sl_cir_set_protocol(unsigned int protocol) +{ + unsigned int tmp; + + tmp = CIR_CTR_REG & ~(BIT(4)|BIT(1)) ; + tmp |= protocol ? BIT(4):0; +// CIR_CTR_REG = tmp |BIT(0); +} + +void set_sl_cir_set_demodula(unsigned int enable) +{ + +// cir_write_reg(CIR_STATUS_REG, enable?BIT(1):0, BIT(1)); +} + +void set_sl_cir_set_compare(unsigned int enable) +{ + +// cir_write_reg(CIR_STATUS_REG, enable?BIT(23):0, BIT(23)); +// cir_write_reg(CIR_CTR_REG, BIT(0), BIT(0)); +} + +void set_sl_cir_set_powerkey(unsigned int key,unsigned int key_ext) +{ +// unsigned int reg_v; +#if 0 + // clear initialize ok bit + reg_v = cir_read_reg(CIR_CTR_REG); + reg_v &= ~BIT(0); + cir_write_reg(CIR_CTR_REG,reg_v,BIT(0)); + + // set power key + cir_write_reg(CIR_PWR_REG,key,0xFFFFFFFF); + cir_write_reg(CIR_PWR_EXT_REG,key_ext,0x0000FFFF); + + // set initialize ok bit + reg_v = cir_read_reg(CIR_CTR_REG); + reg_v |= BIT(0); + cir_write_reg(CIR_CTR_REG,reg_v,BIT(0)); +#endif +} + +void cir_init(int mode) +{ + unsigned int baud; + unsigned int reg_v; + + if(mode==VCC_PROTOCOL) { // VCR-33 + /*=================== Set RX/TX baud rate ==================*/ + baud = VCC_BAUD*EXT_CLK ; + CIR_CTR_REG &= 0x0000FFE8 ; + CIR_CTR_REG |= (baud << 16) |BIT(4); + CIR_TX_CTR_REG = 0x0 ; + CIR_CTR_REG |= (baud << 16); + + + /*=================== Set Power key ==================*/ + CIR_PWR_REG = VCR_KEY_POWER; + CIR_PWR_EXT_REG = 0; + + /*=============== Set Carrier Frequency ==============*/ + CIR_TX_FEQ_REG = (unsigned int)(EXT_CLK/CARR_FREQ); + + CIR_CTR_REG &= 0xFFFF00FF; + CIR_CTR_REG |= (VCC_H_ACT_PER<<12)|(VCC_L_ACT_PER<<8); + + CIR_STATUS_REG &= 0xFFC0FFFF; + CIR_STATUS_REG |= VCC_DATA_LEN<<16 ; + + CIR_TX_CTR_REG &= 0xFFFF0000; // Set TX para + CIR_TX_CTR_REG |= (VCC_H_ACT_PER<<12)|(VCC_L_ACT_PER<<8)|(VCC_DATA_LEN); + + CIR_TX_FEQ_REG = (unsigned int)(EXT_CLK/CARR_FREQ); + + } + else if(mode==TV1_PROTOCOL) { // TV1-26 + /*=================== Set RX/TX baud rate ==================*/ + baud = TV1_BAUD*EXT_CLK ; + CIR_CTR_REG &= 0x0000FFE8 ; + CIR_CTR_REG |= (baud << 16) | BIT(4); + CIR_TX_CTR_REG = 0x0 ; + CIR_CTR_REG |= (baud << 16); + + /*=================== Set Power key ==================*/ + CIR_PWR_REG = TV1_KEY_POWER; + CIR_PWR_EXT_REG = TV1_KEY_POWER_EXT; + + /*=============== Set Carrier Frequency ==============*/ + CIR_TX_FEQ_REG = (unsigned int)(EXT_CLK/CARR_FREQ); + + CIR_CTR_REG &= 0xFFFF00FF; + CIR_CTR_REG |= (TV1_H_ACT_PER<<12)|(TV1_L_ACT_PER<<8); + + CIR_STATUS_REG &= 0xFFC0FFFF; + CIR_STATUS_REG |= TV1_DATA_LEN<<16 ; + + CIR_TX_CTR_REG &= 0xFFFF0000; // Set TX para + CIR_TX_CTR_REG |= (TV1_H_ACT_PER<<12)|(TV1_L_ACT_PER<<8)|(TV1_DATA_LEN); + + CIR_TX_FEQ_REG = (unsigned int)(EXT_CLK/CARR_FREQ); + } + + CIR_CTR_REG |= BIT(0); // Initial complete + CIR_STATUS_REG &= ~BIT(1); // Clear Interrupt + mdelay(10); + + reg_v = PWR_CTRL_REG ; + mdelay(10); + PWR_CTRL_REG = reg_v | BIT(2) |BIT(1); // Clear cir interrupt; + mdelay(10); + reg_v &= ~BIT(1); + reg_v |= BIT(0); + PWR_CTRL_REG = reg_v|BIT(2); // Power off machine because of first power on + + + +} + + +static int sl_cir_open(struct inode *inode, struct file *file) +{ + //if (request_irq(IRQ_CIR, cir_interrupt, SA_INTERRUPT, "cir", NULL)) + // printk("Error: Register IRQ for Storlink IR failed\n"); + + return 0; +} + + +static int sl_cir_release(struct inode *inode, struct file *file) +{ + //free_irq(IRQ_CIR,NULL); + return 0; +} + +static irqreturn_t cir_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + unsigned int addr,reg_v; +// unsigned int reg_v; + // Programming sequence: + // ¦pªG±µ¦¬ªø«×¤j©ó32bit,«h¥ýŪEXTEND register,¦A¨úDATA register + // ¥u­nŪDATA register,interrupt ´N³Q²M°£ + DEB(printk("CIR RX:0x")); + if(((CIR_STATUS_REG>>16)&0x00003F)>32) { + data_ext = CIR_RX_EXT_REG; + data = CIR_RX_REG; + DEB(printk("%08x%04x\n",data,data_ext)); + } + else { + data = CIR_RX_REG; + DEB(printk("%08x\n",data)); + } + //mdelay(10); + CIR_STATUS_REG &= ~BIT(1); + addr = IO_ADDRESS(SL2312_INTERRUPT_BASE); + reg_v = readl(addr+0x08); + reg_v |= BIT(IRQ_CIR); + writel(reg_v,addr+0x08); + wake_up_interruptible(&cir_wait_q); + + return IRQ_RETVAL(IRQ_HANDLED); +} + + +int sl_cir_int_wait (__u32 *data1,__u32 *data2,__u32 timeout) +{ + int ret=0; + + ret = interruptible_sleep_on_timeout(&cir_wait_q, timeout*HZ); + if(ret > 0){ + *data1 = data; + *data2 = data_ext; + } + else{ + *data1 = 0; + *data2 = 0; + } + return ret; +} + +static int sl_cir_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct cir_ioctl_data para; + struct cir_ioctl_data48 data48; + + DEB(printk("cir ioctl successly\n")); + + switch(cmd) { + case CIR_SET_BAUDRATE: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_baudrate(para.data); + break; + case CIR_SET_HIGH_PERIOD: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_h_period(para.data); + + break; + case CIR_SET_LOW_PERIOD: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_l_period(para.data); + break; + case CIR_SET_PROTOCOL: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_protocol(para.data); + break; + case CIR_SET_ENABLE_COMPARE: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_compare(para.data); + break; + case CIR_SET_ENABLE_DEMOD: + if (copy_from_user(¶, (struct cir_ioctl_data *)arg, sizeof(para))) + return -EFAULT; + set_sl_cir_set_demodula(para.data); + break; + case CIR_SET_POWER_KEY: + if (copy_from_user(&data48, (struct cir_ioctl_data48 *)arg, sizeof(data48))) + return -EFAULT; + + set_sl_cir_set_powerkey(data48.data,data48.data_ext); + break; + case CIR_GET_ENABLE_DEMOD: + + break; + case CIR_GET_DATA: + if (copy_from_user(&data48, (struct cir_ioctl_data48 *)arg, sizeof(data48))) + return -EFAULT; + data48.ret = OLD_DATA; + data48.data = data; + data48.data_ext = data_ext; + if (copy_to_user((struct cir_ioctl_data48 *)arg, &data48, sizeof(data48))) + return -EFAULT; + break; + case CIR_WAIT_INT_DATA: + if (copy_from_user(&data48, (struct cir_ioctl_data48 *)arg, sizeof(data48))) + return -EFAULT; + ret = sl_cir_int_wait(&data48.data,&data48.data_ext,data48.timeout); + data48.ret = (ret>0) ? NEW_RECEIVE:OLD_DATA; + if (copy_to_user((struct cir_ioctl_data48 *)arg, &data48, sizeof(data48))) + return -EFAULT; + break; + default: + return -1; + } + return 0; +} + + +static struct file_operations sl_cir_fops = +{ + .owner = THIS_MODULE, + .ioctl = sl_cir_ioctl, + .open = sl_cir_open, + .release = sl_cir_release, +}; + +/* include/linux/miscdevice.h */ +static struct miscdevice sl_cir_miscdev = +{ + CIR_MINOR, + "sl_cir", + &sl_cir_fops +}; + +int __init sl_cir_init(void) +{ +// unsigned int reg_v; + +// reg_v = cir_read_reg(CIR_IP_ID); + if((CIR_IP_ID&0xFFFFFF00)!=STORLINK_CIR_ID){ + printk("Storlink IR Module Not Found!!\n"); + return -ENODEV; // Storlink CIR not found!! + } + + misc_register(&sl_cir_miscdev); + printk("Storlink CIR Initialization\n"); + + if(CIR_STATUS_REG&BIT(2)) // First Power On + { + printk("Please reboot now."); + cir_init(TV1_PROTOCOL); + } + + // Clear INTERRUPT before request_irq +// reg_v = cir_read_reg(CIR_STATUS_REG); +// reg_v &= ~(BIT(0)|BIT(1)); +// cir_write_reg(CIR_STATUS_REG, reg_v, BIT(0)|BIT(1) ); + CIR_STATUS_REG &= ~(BIT(0)|BIT(1)); + + if (request_irq(IRQ_CIR, cir_interrupt, SA_INTERRUPT, "cir", NULL)) + printk("Error: Register IRQ for Storlink IR failed\n"); + + init_waitqueue_head(&cir_wait_q); + + return 0; +} + +void __exit sl_cir_exit(void) +{ + free_irq(IRQ_CIR,NULL); + misc_deregister(&sl_cir_miscdev); +} + +module_init(sl_cir_init); +module_exit(sl_cir_exit); + +MODULE_AUTHOR("Jason Lee "); +MODULE_DESCRIPTION("Gemini CIR driver"); +MODULE_LICENSE("GPL"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/gemini_gpio.c linux-sl3516/drivers/char/gemini_gpio.c --- linux-2.6.15-armeb/drivers/char/gemini_gpio.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/gemini_gpio.c 2007-04-25 15:55:34.000000000 +0930 @@ -0,0 +1,770 @@ +/* + * FILE NAME Gemini_gpio.c + * + * BRIEF MODULE DESCRIPTION + * API for gemini GPIO module + * Driver for gemini GPIO module + * + * Author: StorLink, Corp. + * Jason Lee + * + * Copyright 2005 StorLink, Corp. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMit8712D TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMit8712D TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, writ8712 to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GEMINI_GPIO_BASE1 SL2312_GPIO_BASE +#define GEMINI_GPIO_BASE2 SL2312_GPIO_BASE1 +#define GEMINI_GPIO_BASE3 SL2312_GPIO_BASE2 + +#define BANK1_BIT(__BIT__) (0+__BIT__) +#define BANK2_BIT(__BIT__) (32+__BIT__) +#define BANK3_BIT(__BIT__) (64+__BIT__) + +#define GPIO_SET 3 +#define MAX_GPIO_LINE 32*GPIO_SET + +wait_queue_head_t gemini_gpio_wait[MAX_GPIO_LINE]; + +enum GPIO_REG +{ + GPIO_DATA_OUT = 0x00, + GPIO_DATA_IN = 0x04, + GPIO_PIN_DIR = 0x08, + GPIO_BY_PASS = 0x0C, + GPIO_DATA_SET = 0x10, + GPIO_DATA_CLEAR = 0x14, + GPIO_PULL_ENABLE = 0x18, + GPIO_PULL_TYPE = 0x1C, + GPIO_INT_ENABLE = 0x20, + GPIO_INT_RAW_STATUS = 0x24, + GPIO_INT_MASK_STATUS = 0x28, + GPIO_INT_MASK = 0x2C, + GPIO_INT_CLEAR = 0x30, + GPIO_INT_TRIG = 0x34, + GPIO_INT_BOTH = 0x38, + GPIO_INT_POLAR = 0x3C +}; + +unsigned int regist_gpio_int0=0,regist_gpio_int1=0,regist_gpio_int2=0; +static int gemini_gpio_debug=0; +#define DEB(x) if (gemini_gpio_debug>=1) x + +struct gpio_irqaction { + void (*handler)(unsigned int); +}; + +struct gpio_irqaction irq_handle[MAX_GPIO_LINE]; + + +void gemini_gpio_access(unsigned char pin, unsigned char bit, unsigned char addr_offset) +{ + unsigned char set = pin >>5; // each GPIO set has 32 pins + unsigned int status,addr; + + if (set==0) + addr = IO_ADDRESS(GEMINI_GPIO_BASE1); + else if (set==1) + addr = IO_ADDRESS(GEMINI_GPIO_BASE2); + else + addr = IO_ADDRESS(GEMINI_GPIO_BASE3); + addr+=addr_offset; + status = readl(addr); + + status &= ~(1 << (pin %32)); + status |= (bit << (pin % 32)); + writel(status,addr); +} + +// set: 1-2 +// mode:0: input, 1: output +void set_gemini_gpio_io_mode(unsigned char pin, unsigned char mode) +{ + unsigned char set = pin >>5; // each GPIO set has 32 pins + unsigned int status,addr; + + if (set==0) + addr = IO_ADDRESS(GEMINI_GPIO_BASE1)+GPIO_PIN_DIR; + else if (set==1) + addr = IO_ADDRESS(GEMINI_GPIO_BASE2)+GPIO_PIN_DIR; + else + addr = IO_ADDRESS(GEMINI_GPIO_BASE3)+GPIO_PIN_DIR; + status = readl(addr); + + status &= ~(1 << (pin %32)); + status |= (mode << (pin % 32)); + writel(status,addr); +} + +// set: 1-2 +// high: 1:high, 0:low +void set_gemini_gpio_pin_status(unsigned char pin, unsigned char high) +{ + unsigned char set = pin >>5; // each GPIO set has 32 pins + unsigned int status,addr; + + if (set==0) + addr = IO_ADDRESS(GEMINI_GPIO_BASE1); + else if (set==1) + addr = IO_ADDRESS(GEMINI_GPIO_BASE2); + else + addr = IO_ADDRESS(GEMINI_GPIO_BASE3); + addr+=GPIO_DATA_OUT; + + status = readl(addr); + if (high==0) + status&=~(1 << (pin % 32)); + else + status|=(1 << (pin % 32)); + writel(status,addr); + + DEB(printk("set_gemini_gpio_pin_status: write 0x%X at 0x%X.\n",status,addr)); +} + +void set_gemini_gpio_fan_status(unsigned char pin, unsigned char value) +{ + unsigned int status,addr; + + addr=IO_ADDRESS(GEMINI_GPIO_BASE3); + addr+=GPIO_DATA_OUT; + + status = readl(addr); + status&=~(0x1F << 8); + status|=(value << 8); + writel(status,addr); + +// don't want to see that, by Freecom +// DEB(printk("set_gemini_gpio_fan_status: write 0x%X at 0x%X.\n",status,addr)); +} + +// set: 1-2 +// return: 1:high, 0:low +int get_gemini_gpio_pin_status(unsigned char pin) +{ + unsigned char set = pin >>5; // each GPIO set has 32 pins + unsigned int status,addr; + + if (set==0) + addr = IO_ADDRESS(GEMINI_GPIO_BASE1)+GPIO_DATA_IN; + else if (set==1) + addr = IO_ADDRESS(GEMINI_GPIO_BASE2)+GPIO_DATA_IN; + else + addr = IO_ADDRESS(GEMINI_GPIO_BASE3)+GPIO_DATA_IN; + + status = readl(addr); + + DEB(printk("get_gemini_gpio_pin_status pin %u - 0x%X - address: 0x%X.\n",pin,status,addr)); + + return (status&(1<<(pin % 32)))?1:0; +} + + +// wait interrupt event +int wait_gemini_gpio_pin_interrupt(struct gemini_gpio_ioctl_data *ioctl_data) +{ + + DEB(printk("wait GPIO_%d Interrupt\n",ioctl_data->pin)); + if(ioctl_data->use_default==1) + init_gpio_int(ioctl_data->pin, 0, 0, 0); + else + init_gpio_int(ioctl_data->pin, ioctl_data->trig_type, ioctl_data->trig_polar, \ + ioctl_data->trig_both); + + interruptible_sleep_on(&gemini_gpio_wait[ioctl_data->pin]); + return 0; +} + +void init_gpio_int(__u32 pin,__u8 trig_type,__u8 trig_polar,__u8 trig_both) +{ + unsigned int data =0,addr,base; + unsigned char set = pin >>5; + + if (set==0) + base = IO_ADDRESS(GEMINI_GPIO_BASE1); + else if (set==1) + base = IO_ADDRESS(GEMINI_GPIO_BASE2); + else + base = IO_ADDRESS(GEMINI_GPIO_BASE3); + + addr = base + GPIO_INT_TRIG ; + data = readl(addr); +// data &= ~(1<<(pin%32)) ; // edge trig + trig_type ? (data|=(1<<(pin%32))):(data &= ~(1<<(pin%32))); + writel(data,addr); + + addr = base + GPIO_INT_POLAR ; + data = readl(addr); +// data &= ~(1<<(pin%32)); // rising edge + trig_polar ? (data|=(1<<(pin%32))):(data &= ~(1<<(pin%32))); + writel(data,addr); + + addr = base + GPIO_INT_BOTH ; + data = readl(addr); +// data &= ~(1<<(pin%32)) ; // single edge + trig_both ? (data|=(1<<(pin%32))):(data &= ~(1<<(pin%32))); + writel(data,addr); + + addr = base + GPIO_INT_MASK ; + data = readl(addr); + data &= ~(1<<(pin%32)); // unmask + writel(data,addr); + + addr = base + GPIO_INT_CLEAR ; + data = readl(addr); + data |= 1<<(pin%32) ; // Clear interrupt before Enable it + writel(data,addr); + + addr = base + GPIO_INT_ENABLE ; + data = readl(addr); + data |= 1<<(pin%32) ; // Enable interrupt + writel(data,addr); + +} + +static irqreturn_t gpio_int1(void) +{ + unsigned int i,int_src,addr,data,base,int_status; + unsigned int mask_stat; + + base = IO_ADDRESS(GEMINI_GPIO_BASE1); + addr = base + GPIO_INT_RAW_STATUS ; + int_status = int_src = readl(addr); + + addr = base + GPIO_INT_MASK; + mask_stat = readl(addr); + + int_src &= ~mask_stat; // ignore INT that was masked + for(i=0;int_src;int_src>>=1,i++) { + if((int_src&(1))==0) + continue; + + addr = base + GPIO_INT_MASK ; + data = readl(addr); + data |= (1<>=1,i++) { + if((int_src&(1))==0) + continue; + + addr = base + GPIO_INT_MASK ; + data = readl(addr); + data |= (1<>=1,i++) { + if((int_src&(1))==0) + continue; + + addr = base + GPIO_INT_MASK ; + data = readl(addr); + data |= (1<= MAX_GPIO_LINE) + { + printk("gemini_gpio ioctl fail[pin > %d]\n",MAX_GPIO_LINE); + return -EFAULT; + } +// don't want to see that, by Freecom +// DEB(printk("gemini_gpio ioctl successfully\n")); + + switch(cmd) { + case GEMINI_SET_GPIO_PIN_DIR: // Set pin Direction + set_gemini_gpio_io_mode(ioctl_data.pin, ioctl_data.status); + break; + + case GEMINI_SET_GPIO_PIN_STATUS: // Set pin Status + set_gemini_gpio_pin_status(ioctl_data.pin, ioctl_data.status); + break; + + case GEMINI_GET_GPIO_PIN_STATUS: // Get pin Status + ioctl_data.status = get_gemini_gpio_pin_status(ioctl_data.pin); + if (copy_to_user((struct gemini_gpio_ioctl_data *)arg,&ioctl_data, sizeof(ioctl_data))) + return -EFAULT; + break; + + case GEMINI_WAIT_GPIO_PIN_INT: // Wait pin Interrupt + if (ioctl_data.pin<32) + { + if ((regist_gpio_int0 & (1< the pin number of gpio to regist interrupt */ +/* handler --> handle of interrupt service routine */ +/* level --> trigger type level/edge */ +/* high --> trigger mode high/low or rigsing/falling */ +/* both --> if edge trigger single/both edge */ +/* return: 0 if succeed */ +/* -EINVAL indicate this gpio was assigned to other module */ +/************************************************************************/ +int request_gpio_irq(int bit,void (*handler)(int),char level,char high,char both) +{ + if( (bit>=MAX_GPIO_LINE)||(bit<0) ) + return -EINVAL; + + if(bit<32){ + if(regist_gpio_int0&(1< pin number of gpio to release irq */ +/* return: None */ +/************************************************************************/ +int free_gpio_irq(int bit) +{ + unsigned int base,addr,data; + + if( (bit>=MAX_GPIO_LINE)||(bit<0) ) + return -EINVAL; + + if (bit<32) + base=IO_ADDRESS(GEMINI_GPIO_BASE1); + else if (bit<64) + base=IO_ADDRESS(GEMINI_GPIO_BASE2); + else + base=IO_ADDRESS(GEMINI_GPIO_BASE3); + + irq_handle[bit].handler = NULL; + + if(bit<32) + regist_gpio_int0 &= ~(1<=4*HZ) + { + INIT_WORK(&work_item,work_item_function,"DEFAULTS"); + } + else + { + INIT_WORK(&work_item,work_item_function,"REBOOT"); + } + + schedule_work(&work_item); + } +} + +static void irq_button_usb1_handler(int status) +{ + mdelay(50); + + DEB(printk("irq_button_usb1_handler. status: 0x%X.\n",get_gemini_gpio_pin_status(BANK3_BIT(16)))); + + if (get_gemini_gpio_pin_status(BANK3_BIT(16))==0) + { + INIT_WORK(&work_item,work_item_function,"UNPLUG USB1"); + schedule_work(&work_item); + } +} + +static void irq_button_usb2_handler(int status) +{ + mdelay(50); + + DEB(printk("irq_button_usb2_handler. status: 0x%X.\n",get_gemini_gpio_pin_status(BANK3_BIT(17)))); + + if (get_gemini_gpio_pin_status(BANK3_BIT(17))==0) + { + INIT_WORK(&work_item,work_item_function,"UNPLUG USB2"); + schedule_work(&work_item); + } +} + +static void irq_button_user_handler(int status) +{ + mdelay(50); + + DEB(printk("irq_button_user_handler. status: 0x%X.\n",get_gemini_gpio_pin_status(BANK3_BIT(18)))); + + if (get_gemini_gpio_pin_status(BANK3_BIT(18))==0) + { + INIT_WORK(&work_item,work_item_function,"USEREVENT"); + schedule_work(&work_item); + } +} + +static void irq_button_power_handler(int status) +{ + mdelay(50); + + DEB(printk("irq_button_power_handler. status: 0x%X.\n",get_gemini_gpio_pin_status(BANK3_BIT(19)))); + + if (get_gemini_gpio_pin_status(BANK3_BIT(19))==0) + { + INIT_WORK(&work_item,work_item_function,"SHUTDOWN"); + schedule_work(&work_item); + } +} + +int __init gemini_gpio_init(void) +{ + int i,ret=0; + + misc_register(&gemini_gpio_miscdev); + printk("Freecom/Gemini GPIO Init.\n"); + + for(i=0;i"); +MODULE_DESCRIPTION("Storlink GPIO driver"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/gemini_pwr.c linux-sl3516/drivers/char/gemini_pwr.c --- linux-2.6.15-armeb/drivers/char/gemini_pwr.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/gemini_pwr.c 2007-02-20 02:29:35.000000000 +1030 @@ -0,0 +1,376 @@ +/* + * FILE NAME gemini_pwr.c + * + * BRIEF MODULE DESCRIPTION + * Driver for Power control. + * + * Author: StorLink, Corp. + * Jason Lee + * + * Copyright 2005 StorLink, Corp. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMit8712D TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMit8712D TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, writ8712 to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PWR_MINOR +#define PWR_MINOR 241 // Documents/devices.txt suggest to use 240~255 for local driver!! +#endif + +#define GEMINI_PWR_IP_ID 0x00010500 + +#ifndef SL2312_POWER_CTRL_BASE +#define SL2312_POWER_CTRL_BASE 0x4B000000 +#endif + +#ifndef PWR_BASE_ADDR +#define PWR_BASE_ADDR IO_ADDRESS(SL2312_POWER_CTRL_BASE) +#endif +#define PWR_CTRL_ID *(unsigned int*)(PWR_BASE_ADDR+0x00) +#define PWR_CTRL_REG *(unsigned int*)(PWR_BASE_ADDR+0x04) +#define PWR_STATUS_REG *(unsigned int*)(PWR_BASE_ADDR+0x08) + +#define PWR_SHUTDOWN 0x01 + +#ifndef IRQ_PWC +#define IRQ_PWC 26 +#endif + + +#ifndef SL2312_GPIO_BASE +#define SL2312_GPIO_BASE 0x4D000000 +#endif +//#define SL2312_GPIO_BASE_ADDR IO_ADDRESS(SL2312_GPIO_BASE1) + +#define GPIO_LEVEL_TRIG 1 +#define GPIO_EDGE_TRIG 0 +#define GPIO_LOW_ACTIVE 1 +#define GPIO_HIGH_ACTIVE 0 +#define GPIO_FALL_ACTIVE 1 +#define GPIO_RISE_ACTIVE 0 +#define GPIO_BOTH_EDGE 1 +#define GPIO_SINGLE_EDGE 0 + +enum GPIO_REG +{ + GPIO_DATA_OUT = 0x00, + GPIO_DATA_IN = 0x04, + GPIO_PIN_DIR = 0x08, + GPIO_BY_PASS = 0x0C, + GPIO_DATA_SET = 0x10, + GPIO_DATA_CLEAR = 0x14, + GPIO_PULL_ENABLE = 0x18, + GPIO_PULL_TYPE = 0x1C, + GPIO_INT_ENABLE = 0x20, + GPIO_INT_RAW_STATUS = 0x24, + GPIO_INT_MASK_STATUS = 0x28, + GPIO_INT_MASK = 0x2C, + GPIO_INT_CLEAR = 0x30, + GPIO_INT_TRIG = 0x34, + GPIO_INT_BOTH = 0x38, + GPIO_INT_POLAR = 0x3C +}; +#define GPIO_FAC_DEF 18 +#define GPIO_FAC_PIN BIT((GPIO_FAC_DEF%32)) + +#if (GPIO_FAC_DEF > 31) +#define SL2312_GPIO_BASE_ADDR IO_ADDRESS(SL2312_GPIO_BASE1) +#else +#define SL2312_GPIO_BASE_ADDR IO_ADDRESS(SL2312_GPIO_BASE) +#endif +#define LATCH_TIME 5 +#define PUSH_VALUE 0 +unsigned int Action=0; + +static int gemini_pwr_debug = 0; +#define DEB(x) if(gemini_pwr_debug>=1) x +unsigned int pwr_src=0; + +wait_queue_head_t pwc_wait_q; + +static unsigned int pwr_read_reg(unsigned int offset) +{ + unsigned int reg_val; + + reg_val = readl(CIR_BASE_ADDR + offset); + return (reg_val); +} + +static void pwr_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask) +{ + unsigned int reg_val; + unsigned int *addr; + + reg_val = ( pwr_read_reg(offset) & (~bit_mask) ) | (data & bit_mask); + addr = (unsigned int *)(CIR_BASE_ADDR + offset); + writel(reg_val,addr); + return; +} + +static int gemini_pwr_open(struct inode *inode, struct file *file) +{ +// PWR_CTRL_REG |= BIT(1); +// if (request_irq(IRQ_PWC, pwr_interrupt, SA_INTERRUPT, "Power Control", NULL)) +// printk("Error: Register IRQ for Power control failed\n"); + + return 0; +} + +static int gemini_pwr_release(struct inode *inode, struct file *file) +{ + return 0; +} + + +// Interrupt handle +static irqreturn_t pwr_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + + unsigned int reg_v,addr; + // Get power interrupt source + mdelay(1); + pwr_src = PWR_STATUS_REG&0x70; + + + printk("Power event by "); + switch(pwr_src){ + case PWR_STAT_CIR: + CIR_STATUS_REG &= ~BIT(0); // Clear CIR interrupt indicator + printk("CIR...\n"); + break; + case PWR_STAT_RTC: + printk("RTC...\n"); + break; + case PWR_STAT_PUSH: + printk("Button...\n"); + break; + default: + printk("Unknow Source \n"); + } + + mdelay(1); + PWR_CTRL_REG |= BIT(2); + Action = POWEROFF; + + addr = IO_ADDRESS(SL2312_INTERRUPT_BASE); + reg_v = readl(addr+0x08); + reg_v |= BIT(IRQ_PWC); + writel(reg_v,addr+0x08); + wmb(); + + wake_up(&pwc_wait_q); + Action = POWEROFF; + return IRQ_RETVAL(IRQ_HANDLED); +} + +static void gpio_handle(int status) +{ + unsigned int int_src,addr,data,addr2; + unsigned char i=0; + + addr = SL2312_GPIO_BASE_ADDR + GPIO_INT_RAW_STATUS ; + + int_src = readl(addr); + if(int_src&GPIO_FAC_PIN){ + DEB(printk("Restore Factory Default\n")); + wake_up(&pwc_wait_q); + addr = SL2312_GPIO_BASE_ADDR + GPIO_INT_MASK ; + data = readl(addr); + data |= GPIO_FAC_PIN ; // mask INT + writel(data,addr); + addr = SL2312_GPIO_BASE_ADDR + GPIO_INT_CLEAR ; + data = readl(addr); + data |= GPIO_FAC_PIN ; // clear INT + writel(data,addr); + // count push time + addr = SL2312_GPIO_BASE_ADDR + GPIO_DATA_IN ; + for(i=0;i<=LATCH_TIME*10;i++){ + int_src = readl(addr); + + if((int_src & GPIO_FAC_PIN)==PUSH_VALUE) { + if((i%10)==0) + printk("\r%d seconds to restore default!!\r",LATCH_TIME-i/10); + + addr2 = SL2312_GPIO_BASE_ADDR + GPIO_INT_CLEAR ; + data = readl(addr2); + data |= GPIO_FAC_PIN ; // clear INT + writel(data,addr2); + } + else { + break; + } + mdelay(100); + } + if((i/10)<1){ + Action = SYSTEM_REBOOT; + wake_up(&pwc_wait_q); + printk("\nReboot\n"); + } + else if((i/10)"); +MODULE_DESCRIPTION("Gemini Power control driver"); +MODULE_LICENSE("GPL"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/it8712_gpio.c linux-sl3516/drivers/char/it8712_gpio.c --- linux-2.6.15-armeb/drivers/char/it8712_gpio.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/it8712_gpio.c 2006-06-06 16:06:53.000000000 +0930 @@ -0,0 +1,244 @@ +/* + * FILE NAME it8712_gpio.c + * + * BRIEF MODULE DESCRIPTION + * API for it8712 GPIO device. + * Driver for it8712 GPIO device. + * + * Author: StorLink, Corp. + * Andy Chang + * + * Copyright 2003 StorLink, Corp. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMit8712D TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMit8712D TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, writ8712 to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IT8712_SET_GPIO_PIN_IN 1 +#define IT8712_SET_GPIO_PIN_OUT 2 +#define IT8712_SET_GPIO_PIN_STATUS_LOW 3 +#define IT8712_SET_GPIO_PIN_STATUS_HIGH 4 +#define IT8712_GET_GPIO_PIN_STATUS 5 +#define LPC_BASE_ADDR IO_ADDRESS(IT8712_IO_BASE) + +extern int it8712_exist; + +#define MAX_GPIO_LINE 40 +#define inb_gpio(x) inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x) +#define outb_gpio(x, y) outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x) + +wait_queue_head_t it8712_gpio_wait[MAX_GPIO_LINE]; + +//static int it8712_gpio_debug=0; +//#define DEB(x) if (it8712_gpio_debug>=1) x + +// set: 1-5 +// mode:0: input, 1: output +void set_it8712_gpio_io_mode(unsigned char pin, unsigned char mode) +{ + unsigned char iomode; + unsigned char set = pin / 8; // each GPIO set has 8 pins + + iomode = LPCGetConfig(LDN_GPIO, 0xc8 + set); + iomode &= ~(1 << (pin % 8)); + iomode |= (mode << (pin % 8)); + LPCSetConfig(LDN_GPIO, 0xc8 + set, iomode); +} + +// set: 1-5 +// high: 1:high, 0:low +void set_it8712_gpio_pin_status(unsigned char pin, unsigned char high) +{ + unsigned char status; + unsigned char set = pin / 8; // each GPIO set has 8 pins + + status = inb_gpio(set); + status &= ~(1 << (pin % 8)); + status |= (high << (pin % 8)); + outb_gpio(set, status); +} + +// set: 1-5 +// return: 1:high, 0:low +int get_it8712_gpio_pin_status(unsigned char pin) +{ + unsigned char status; + unsigned char set = pin / 8; // each GPIO set has 8 pins + + status = inb_gpio(set); + if (status & (1 << (pin % 8))) + return 1; + return 0; +} + +static int it8712_gpio_open(struct inode *inode, struct file *file) +{ + unsigned int minor; + + minor = MINOR(inode->i_rdev); + if (minor != GPIO_MINOR) + return -ENODEV; + printk("it8712_gpio open\n"); + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + + +static int it8712_gpio_release(struct inode *inode, struct file *file) +{ + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + printk("it8712_gpio release\n"); + return 0; +} + + +static int it8712_gpio_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned char pin = (unsigned char) arg; + + if (pin >= MAX_GPIO_LINE) + { + printk("it8712_gpio ioctl fail\n"); + return -EFAULT; + } + printk("it8712_gpio ioctl successly\n"); + + switch(cmd) { + case IT8712_SET_GPIO_PIN_IN: + set_it8712_gpio_io_mode(pin, 0); + break; + + case IT8712_SET_GPIO_PIN_OUT: + set_it8712_gpio_io_mode(pin, 1); + break; + + case IT8712_SET_GPIO_PIN_STATUS_LOW: + set_it8712_gpio_pin_status(pin, 0); + break; + + case IT8712_SET_GPIO_PIN_STATUS_HIGH: + set_it8712_gpio_pin_status(pin, 1); + break; + + case IT8712_GET_GPIO_PIN_STATUS: + return get_it8712_gpio_pin_status(pin); + break; + + default: + return -ENOIOCTLCMD; + + } + return 0; +} + + +static struct file_operations it8712_gpio_fops = +{ + owner: THIS_MODULE, + ioctl: it8712_gpio_ioctl, + open: it8712_gpio_open, + release: it8712_gpio_release, +}; + +/* GPIO_MINOR in include/linux/miscdevice.h */ +static struct miscdevice it8712_gpio_miscdev = +{ + GPIO_MINOR, + "it8712_gpio", + &it8712_gpio_fops +}; + +int __init it8712_gpio_init(void) +{ + int i; + + misc_register(&it8712_gpio_miscdev); + + if (!it8712_exist) { + return -ENODEV; + } + printk("it8712_gpio init\n"); + + /* initialize registers */ + // switch all multi-function pins to GPIO + LPCSetConfig(LDN_GPIO, 0x25, 0xff); + LPCSetConfig(LDN_GPIO, 0x26, 0xff); + LPCSetConfig(LDN_GPIO, 0x27, 0xff); + LPCSetConfig(LDN_GPIO, 0x28, 0xff); + LPCSetConfig(LDN_GPIO, 0x29, 0xff); + + // set simple I/O base address + LPCSetConfig(LDN_GPIO, 0x62, IT8712_GPIO_BASE >> 8); + LPCSetConfig(LDN_GPIO, 0x63, (unsigned char) IT8712_GPIO_BASE >> 8); + + // select GPIO to simple I/O + LPCSetConfig(LDN_GPIO, 0xc0, 0xff); + LPCSetConfig(LDN_GPIO, 0xc1, 0xff); + LPCSetConfig(LDN_GPIO, 0xc2, 0xff); + LPCSetConfig(LDN_GPIO, 0xc3, 0xff); + LPCSetConfig(LDN_GPIO, 0xc4, 0xff); + + // enable internal pull-up + LPCSetConfig(LDN_GPIO, 0xb8, 0xff); + LPCSetConfig(LDN_GPIO, 0xb9, 0xff); + LPCSetConfig(LDN_GPIO, 0xba, 0xff); + LPCSetConfig(LDN_GPIO, 0xbb, 0xff); + LPCSetConfig(LDN_GPIO, 0xbc, 0xff); + + // set polarity to inverting +// LPCSetConfig(LDN_GPIO, 0xb0, 0xff); + + for (i = 0; i < MAX_GPIO_LINE; i++) { + init_waitqueue_head(&it8712_gpio_wait[i]); + } + return 0; +} + +void __exit it8712_gpio_exit(void) +{ + misc_deregister(&it8712_gpio_miscdev); +} + +module_init(it8712_gpio_init); +module_exit(it8712_gpio_exit); + +MODULE_LICENSE("GPL"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/Kconfig linux-sl3516/drivers/char/Kconfig --- linux-2.6.15-armeb/drivers/char/Kconfig 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/Kconfig 2006-04-03 18:10:45.000000000 +0930 @@ -78,6 +78,23 @@ Most people can say N here. +###### for Storlink SoC ###### +config IT8712_GPIO + bool "Support for IT8712 GPIO" + depends on SL2312_LPC + +config GEMINI_GPIO + bool "Support for GEMINI GPIO" + depends on ARCH_SL2312 + +config GEMINI_CIR + bool "Support for GEMINI CIR" + depends on ARCH_SL2312 + +config GEMINI_PWC + bool "Gemini Power Control" + depends on ARCH_SL2312 + config COMPUTONE tristate "Computone IntelliPort Plus serial support" depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP @@ -581,6 +598,12 @@ source "drivers/char/watchdog/Kconfig" +### for Storlink SoC ### +config SL2312_WATCHDOG + tristate "SL2312 hardware watchdog timer support" + depends on ARCH_SL2312 + help + config DS1620 tristate "NetWinder thermometer support" depends on ARCH_NETWINDER @@ -711,6 +734,11 @@ To compile this driver as a module, choose M here: the module will be called rtc. +###### for Storlink SoC ###### +config SL2312_RTC + tristate "Storlink Real Time Clock Support" + depends on ARCH_SL2312 + config SGI_DS1286 tristate "SGI DS1286 RTC support" depends on SGI_IP22 diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/Makefile linux-sl3516/drivers/char/Makefile --- linux-2.6.15-armeb/drivers/char/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/Makefile 2006-06-01 11:45:11.000000000 +0930 @@ -57,6 +57,15 @@ obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o + +### for Storlink SoC ### +obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o +obj-$(CONFIG_IT8712_GPIO) += it8712_gpio.o +obj-$(CONFIG_GEMINI_GPIO) += gemini_gpio.o +obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o +obj-$(CONFIG_GEMINI_CIR) += gemini_cir.o +obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o + obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/n_r3964.c linux-sl3516/drivers/char/n_r3964.c --- linux-2.6.15-armeb/drivers/char/n_r3964.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/n_r3964.c 2006-04-03 18:10:46.000000000 +0930 @@ -13,6 +13,9 @@ * L. Haag * * $Log: n_r3964.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:46 amos_lee + * initial + * * Revision 1.10 2001/03/18 13:02:24 dwmw2 * Fix timer usage, use spinlocks properly. * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/rio/rio_linux.c linux-sl3516/drivers/char/rio/rio_linux.c --- linux-2.6.15-armeb/drivers/char/rio/rio_linux.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/rio/rio_linux.c 2006-04-03 18:10:47.000000000 +0930 @@ -26,7 +26,10 @@ * USA. * * Revision history: - * $Log: rio.c,v $ + * $Log: rio_linux.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:47 amos_lee + * initial + * * Revision 1.1 1999/07/11 10:13:54 wolff * Initial revision * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/serial167.c linux-sl3516/drivers/char/serial167.c --- linux-2.6.15-armeb/drivers/char/serial167.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/serial167.c 2006-04-03 18:10:46.000000000 +0930 @@ -23,7 +23,10 @@ * * This version does not support shared irq's. * - * $Log: cyclades.c,v $ + * $Log: serial167.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:46 amos_lee + * initial + * * Revision 1.36.1.4 1995/03/29 06:14:14 bentson * disambiguate between Cyclom-16Y and Cyclom-32Ye; * diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/sl2312_rtc.c linux-sl3516/drivers/char/sl2312_rtc.c --- linux-2.6.15-armeb/drivers/char/sl2312_rtc.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/sl2312_rtc.c 2006-04-06 11:46:55.000000000 +0930 @@ -0,0 +1,503 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define RTC_VERSION "0.10" +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* missed irq timer active */ + +/* define EMAC base address */ +#define RTC_PHYSICAL_BASE_ADDR (SL2312_RTC_BASE) //0x25000000 +#define RTC_BASE_ADDR (IO_ADDRESS(RTC_PHYSICAL_BASE_ADDR)) +#define RTC_GLOBAL_BASE_ADDR (IO_ADDRESS(SL2312_GLOBAL_BASE)) + +#define RTC_READ(offset) readl(RTC_BASE_ADDR+offset) +#define RTC_WRITE(offset,data) writel(data,RTC_BASE_ADDR+offset) + +/***************************************/ +/* the offset address of RTC register */ +/***************************************/ +enum EMAC_REGISTER { + RTC_SECOND = 0x00, + RTC_MINUTE = 0x04, + RTC_HOUR = 0x08, + RTC_DAYS = 0x0c, + RTC_ALARM_SECOND= 0x10, + RTC_ALARM_MINUTE= 0x14, + RTC_ALARM_HOUR = 0x18, + RTC_RECORD = 0x1c, + RTC_CR = 0x20 +}; + + +/* + * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is + * protected by the big kernel lock. However, ioctl can still disable the timer + * in rtc_status and then with del_timer after the interrupt has read + * rtc_status but before mod_timer is called, which would then reenable the + * timer (but you would need to have an awful timing before you'd trip on it) + */ +static unsigned long rtc_status = 0; /* bitmapped status byte. */ +static unsigned long rtc_irq_data = 0; /* our output to the world */ + +static unsigned long epoch = 1970; /* year corresponding to 0x00 */ + +static const unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + +static struct fasync_struct *rtc_async_queue; + +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); + +static ssize_t rtc_read(struct file *file, char *buf, + size_t count, loff_t *ppos); + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static void rtc_sw_reset(void); + +static void get_rtc_time (struct rtc_time *rtc_tm); +static void get_rtc_alm_time (struct rtc_time *alm_tm); + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +void rtc_set_time_second(unsigned int second); +unsigned int rtc_get_time_second(void); + +static void rtc_sw_reset(void) +{ + unsigned int reg_val; + + reg_val = readl(RTC_GLOBAL_BASE_ADDR+0x10) | 0x00000400; + writel(reg_val,RTC_GLOBAL_BASE_ADDR+0x10); + return; +} + +static ssize_t rtc_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ +//#if !RTC_IRQ + return -EIO; +//#endif +} + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct rtc_time wtime; +// unsigned int i; + + switch (cmd) { + case RTC_ALM_READ: /* Read the present alarm time */ + { + return -EINVAL; +/* + get_rtc_alm_time(&wtime); + break; +*/ + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + return -EINVAL; +/* + unsigned char hrs, min, sec; + struct rtc_time alm_tm; + + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + hrs = alm_tm.tm_hour; + min = alm_tm.tm_min; + sec = alm_tm.tm_sec; + + if (hrs >= 24) + hrs = 0xff; + + if (min >= 60) + min = 0xff; + + if (sec >= 60) + sec = 0xff; + + spin_lock_irq(&rtc_lock); + RTC_WRITE(RTC_ALARM_HOUR,hrs); + RTC_WRITE(RTC_ALARM_MINUTE,min); + RTC_WRITE(RTC_ALARM_SECOND,sec); + spin_unlock_irq(&rtc_lock); + + return 0; +*/ + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + memset(&wtime, 0, sizeof(wtime)); + get_rtc_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_year; + unsigned int years; +// unsigned int days; + unsigned int rtc_record; + unsigned int rtc_sec,rtc_min,rtc_hour,rtc_day,total_sec; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + years = rtc_tm.tm_year + 1900; // add tm_year offset + mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm.tm_mday; + hrs = rtc_tm.tm_hour; + min = rtc_tm.tm_min; + sec = rtc_tm.tm_sec; + + printk("RTC_SET_TIME::%04d-%02d-%02d %02d:%02d:%02d\n", + years, mon, day, hrs, min, sec); + + if (years < epoch) + return -EINVAL; + if (years >= epoch + 178) + return -EINVAL; // because RtcDay overflow!! + + leap_year = ((!(years % 4) && (years % 100)) || !(years % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + + if (day > (days_in_mo[mon] + ((mon == 2) && leap_year))) + return -EINVAL; + + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + rtc_record = mktime(years,mon,day,hrs,min,sec); + rtc_record -= mktime(epoch, 1, 1, 0, 0, 0); + + spin_lock_irq(&rtc_lock); + rtc_day = RTC_READ(RTC_DAYS); + rtc_hour = RTC_READ(RTC_HOUR); + rtc_min = RTC_READ(RTC_MINUTE); + rtc_sec = RTC_READ(RTC_SECOND); + total_sec= rtc_day*86400 + rtc_hour*3600 + rtc_min*60 + rtc_sec; + + RTC_WRITE(RTC_RECORD,rtc_record-total_sec); + RTC_WRITE(RTC_CR,0x01); + spin_unlock_irq(&rtc_lock); + + return 0; + } + case RTC_EPOCH_READ: /* Read the epoch. */ + { + return put_user (epoch, (unsigned long *)arg); + } + case RTC_EPOCH_SET: /* Set the epoch. */ + { + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + epoch = arg; + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +/* We use rtc_lock to protect against concurrent opens. So the BKL is not + * needed here. Or anywhere else in this driver. */ +static int rtc_open(struct inode *inode, struct file *file) +{ + spin_lock_irq (&rtc_lock); + + if(rtc_status & RTC_IS_OPEN) + goto out_busy; + + rtc_status |= RTC_IS_OPEN; + + rtc_irq_data = 0; + spin_unlock_irq (&rtc_lock); + return 0; + +out_busy: + spin_unlock_irq (&rtc_lock); + return -EBUSY; +} + +static int rtc_fasync (int fd, struct file *filp, int on) + +{ + return fasync_helper (fd, filp, on, &rtc_async_queue); +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + + spin_lock_irq (&rtc_lock); + rtc_irq_data = 0; + spin_unlock_irq (&rtc_lock); + + /* No need for locking -- nobody else can do anything until this rmw is + * committed, and no timer is running. */ + rtc_status &= ~RTC_IS_OPEN; + return 0; +} + + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + read: rtc_read, + ioctl: rtc_ioctl, + open: rtc_open, + release: rtc_release, + fasync: rtc_fasync, +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &rtc_fops +}; + +extern int (*set_rtc)(void); + +static int sl2312_set_rtc(void) +{ + rtc_set_time_second(xtime.tv_sec); + return 1; +} + +static int __init rtc_init(void) +{ + + set_rtc = sl2312_set_rtc; + + misc_register(&rtc_dev); + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + + printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n"); + + RTC_WRITE(RTC_CR, 0x01); + + return 0; +} + +static void __exit rtc_exit (void) +{ + remove_proc_entry ("driver/rtc", NULL); + misc_deregister(&rtc_dev); +} + +module_init(rtc_init); +module_exit(rtc_exit); +//EXPORT_NO_SYMBOLS; + + +/* + * Info exported via "/proc/driver/rtc". + */ + +static int rtc_proc_output (char *buf) +{ +#define YN(bit) ((ctrl & bit) ? "yes" : "no") +#define NY(bit) ((ctrl & bit) ? "no" : "yes") + char *p; + struct rtc_time tm; + + p = buf; + + get_rtc_time(&tm); + + /* + * There is no way to tell if the luser has the RTC set for local + * time or for Universal Standard Time (GMT). Probably local though. + */ + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04lu\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + + get_rtc_alm_time(&tm); + + /* + * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will + * match any value for that particular field. Values that are + * greater than a valid time, but less than 0xc0 shouldn't appear. + */ + p += sprintf(p, "alarm\t\t: "); + if (tm.tm_hour <= 24) + p += sprintf(p, "%02d:", tm.tm_hour); + else + p += sprintf(p, "**:"); + + if (tm.tm_min <= 59) + p += sprintf(p, "%02d:", tm.tm_min); + else + p += sprintf(p, "**:"); + + if (tm.tm_sec <= 59) + p += sprintf(p, "%02d\n", tm.tm_sec); + else + p += sprintf(p, "**\n"); + + + return p - buf; +#undef YN +#undef NY +} + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = rtc_proc_output (page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + + +static void get_rtc_time(struct rtc_time *rtc_tm) +{ +// #if 0 + unsigned int days; + unsigned int months=0; + unsigned int years; + unsigned int hrs; + unsigned int min; + unsigned int sec; + unsigned int rtc_record; + unsigned int total_sec; + unsigned int leap_year; + unsigned int i; + + spin_lock_irq(&rtc_lock); + sec = RTC_READ(RTC_SECOND); + min = RTC_READ(RTC_MINUTE); + hrs = RTC_READ(RTC_HOUR); + days = RTC_READ(RTC_DAYS); + rtc_record = RTC_READ(RTC_RECORD); + spin_unlock_irq(&rtc_lock); + + total_sec = rtc_record + days*86400 + hrs*3600 + min*60 + sec; + + rtc_tm->tm_sec = total_sec % 60; + rtc_tm->tm_min = (total_sec/60) % 60; + rtc_tm->tm_hour = (total_sec/3600) % 24; + + years = epoch; + days = total_sec/86400; + while ( days > 365 ) { + leap_year = (!(years % 4) && (years % 100)) || !(years % 400); + days = days - 365 - leap_year; + years++; + } + leap_year = (!(years % 4) && (years+epoch % 100)) || !(years % 400); + + for (i=1;i<=12;i++) + { + if (days > (days_in_mo[i] + ((i == 2) && leap_year))) + { + days = days - (days_in_mo[i] + ((i == 2) && leap_year)); + } else { + months = i; + break; + } + } + + rtc_tm->tm_mday = days+1; + rtc_tm->tm_mon = months-1; + rtc_tm->tm_year = years-1900; +// #endif +} + +static void get_rtc_alm_time(struct rtc_time *alm_tm) +{ + + spin_lock_irq(&rtc_lock); + alm_tm->tm_sec = RTC_READ(RTC_ALARM_SECOND); + alm_tm->tm_min = RTC_READ(RTC_ALARM_MINUTE); + alm_tm->tm_hour = RTC_READ(RTC_ALARM_HOUR); + spin_unlock_irq(&rtc_lock); +} + +unsigned int rtc_get_time_second(void) +{ + unsigned int sec,min,hr,day,rtc_record; + unsigned int total_sec; + + spin_lock_irq(&rtc_lock); + sec = RTC_READ(RTC_SECOND); + min = RTC_READ(RTC_MINUTE); + hr = RTC_READ(RTC_HOUR); + day = RTC_READ(RTC_DAYS); + rtc_record = RTC_READ(RTC_RECORD); + spin_unlock_irq(&rtc_lock); + total_sec = rtc_record + day*86400 + hr*3600 + min*60 + sec; + return (total_sec); +} + +void rtc_set_time_second(unsigned int second) +{ + unsigned int sec,min,hr,day,rtc_record; + unsigned int total_sec; + + spin_lock_irq(&rtc_lock); + sec = RTC_READ(RTC_SECOND); + min = RTC_READ(RTC_MINUTE); + hr = RTC_READ(RTC_HOUR); + day = RTC_READ(RTC_DAYS); + spin_unlock_irq(&rtc_lock); + total_sec = day*86400 + hr*3600 + min*60 + sec; + rtc_record = second - total_sec; + RTC_WRITE(RTC_RECORD,rtc_record); + RTC_WRITE(RTC_CR,0x01); + + return ; +} + +MODULE_AUTHOR("Storlink"); +MODULE_LICENSE("GPL"); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/sl2312_wd.c linux-sl3516/drivers/char/sl2312_wd.c --- linux-2.6.15-armeb/drivers/char/sl2312_wd.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/char/sl2312_wd.c 2006-04-03 18:10:46.000000000 +0930 @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WATCHDOG_TEST 1 + +static int soft_margin = WATCHDOG_TIMEOUT_MARGIN; +static int open_state=WATCHDOG_DRIVER_CLOSE; +static int wd_expire=0; + +static void watchdog_disable(void) +{ + unsigned long wdcr; + + wdcr = *((unsigned long *)WATCHDOG_CR); + wdcr &= ~WATCHDOG_WDENABLE_MSK; + *((unsigned long *)WATCHDOG_CR) = wdcr; +} + +static void watchdog_enable(void) +{ + unsigned long wdcr; + + wdcr = *((unsigned long *)WATCHDOG_CR); + wdcr |= (WATCHDOG_WDENABLE_MSK|WATCHDOG_WDRST_MSK); +#ifdef WATCHDOG_TEST + wdcr |= WATCHDOG_WDINTR_MSK; + wdcr &= ~WATCHDOG_WDRST_MSK; +#endif + wdcr &= ~WATCHDOG_WDCLOCK_MSK; + *((unsigned long *)WATCHDOG_CR) = wdcr; +} + +#ifdef WATCHDOG_TEST +static irqreturn_t watchdog_fire(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int clear; + *((unsigned long *)WATCHDOG_CLEAR) = WATCHDOG_CLEAR_STATUS; + printk("Watchdog timeout, resetting system...\n"); + clear = __raw_readl(IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x0C); + clear &= 0x01; + __raw_writel(clear,IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x08); + wd_expire = 1; + return IRQ_HANDLED; +} + +#endif + +struct file_operations watchdog_fops = { + .owner= THIS_MODULE, + .write watchdog_write, + .read= watchdog_read, + .open= watchdog_open, + .release= watchdog_release, + .ioctl= watchdog_ioctl, +}; + +static int watchdog_open(struct inode *inode, struct file *filp) +{ + unsigned long timeout; + + printk("watchdog_open : \n"); + if(open_state == WATCHDOG_DRIVER_OPEN) + return -EBUSY; + + wd_expire = 0; +#ifdef WATCHDOG_TEST + printk("request watchdog irq %x \n", IRQ_WATCHDOG); + if(request_irq(IRQ_WATCHDOG,watchdog_fire,SA_INTERRUPT,"sl2312_wdt",NULL)) + { + printk(KERN_ERR "watchdog request interrupt %x fail \n", IRQ_WATCHDOG); + } + +#endif + watchdog_disable(); + timeout = WATCHDOG_TIMEOUT_SCALE * WATCHDOG_TIMEOUT_MARGIN; + *((unsigned long *)WATCHDOG_LOAD) = timeout; + *((unsigned long *)WATCHDOG_RESTART) = WATCHDOG_RESTART_VALUE; + watchdog_enable(); + + open_state = WATCHDOG_DRIVER_OPEN; + printk("watchdog_open complete : \n"); + return 0; +} + +static int watchdog_release(struct inode *inode, struct file *filp) +{ +#ifdef WATCHDOG_TEST + free_irq(IRQ_WATCHDOG, NULL); +#endif + open_state = WATCHDOG_DRIVER_CLOSE; + watchdog_disable(); + wd_expire = 0; + return 0; +} + +static ssize_t watchdog_read(struct file *filp, char *buf, size_t count, loff_t *off) +{ + int i; + unsigned long val; + + + for (i=0;i< count;i++) + { + if((i%4)==0) + val = *((unsigned long *)WATCHDOG_COUNTER); + buf[i] = (val & 0xFF); + val >>= 8; + } + return count; +} + +static ssize_t watchdog_write(struct file *filp, const char *buf, size_t len, loff_t *off) +{ + /* Can't seek (pwrite) on this device */ + if (off != &filp->f_pos) + return -ESPIPE; + + /* Refresh the timer. */ + if(len) + { + *((unsigned long *)WATCHDOG_RESTART) = WATCHDOG_RESTART_VALUE; + return 1; + } + return 0; + +} + +static int watchdog_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + int margin, timeout; + unsigned int wdcr; + +// printk("watchdog_ioctl cmd is %x \n", cmd); + switch(cmd) + { + default: + return -ENOTTY; + case WDIOC_KEEPALIVE: +// printk("WDIOC_KEEPALIVE : \n"); + *((unsigned long *)WATCHDOG_RESTART) = WATCHDOG_RESTART_VALUE; + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(margin, (int *)arg)) + return -EFAULT; + + /* Arbitrary, can't find the card's limits */ + if ((margin < 0) || (margin > 60)) + return -EINVAL; + soft_margin = margin; + timeout = WATCHDOG_TIMEOUT_SCALE * soft_margin; + *((unsigned long *)WATCHDOG_LOAD) = timeout; + *((unsigned long *)WATCHDOG_RESTART) = WATCHDOG_RESTART_VALUE; + + wdcr = *((unsigned long *)WATCHDOG_CR); + wdcr |= WATCHDOG_WDRST_MSK; + *((unsigned long *)WATCHDOG_CR) = wdcr; + + return put_user(soft_margin, (int *)arg); + + /* Fall */ + case WDIOC_GETTIMEOUT: + margin = *((unsigned long *)WATCHDOG_COUNTER) / WATCHDOG_TIMEOUT_SCALE ; + return put_user(margin, (int *)arg); + + case WDIOC_GETSTATUS: + if (wd_expire==1){ + wd_expire = 0; + return put_user(1, (int *)arg); + } + else + return put_user(0, (int *)arg); + } +} + +static struct miscdevice wd_dev= { + WATCHDOG_MINOR, + "watchog", + &watchdog_fops +}; + +static int __init watchdog_init(void) +{ + + int ret; + + ret = misc_register(&wd_dev); + printk(KERN_INFO "Watchdog Timer Initialized\n"); + return ret; +} + +module_init(watchdog_init); diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/char/sx.c linux-sl3516/drivers/char/sx.c --- linux-2.6.15-armeb/drivers/char/sx.c 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/char/sx.c 2006-04-03 18:10:46.000000000 +0930 @@ -33,6 +33,9 @@ * * Revision history: * $Log: sx.c,v $ + * Revision 1.1.1.1 2006/04/03 08:40:46 amos_lee + * initial + * * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff * - Fixed module and port counting * - Fixed signal handling diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/crypto/Kconfig linux-sl3516/drivers/crypto/Kconfig --- linux-2.6.15-armeb/drivers/crypto/Kconfig 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/crypto/Kconfig 2006-04-03 18:10:47.000000000 +0930 @@ -20,4 +20,11 @@ help Use VIA PadLock for AES algorithm. +config SL2312_IPSEC + tristate "Storlink H/W IPSec Acceleration Engine" + depends on CRYPTO + help + Storlink H/W crypto engine include MD5,SHA1,HMAC-MD5,HMAC-SHA1, + DES,3DES and AES. + endmenu diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/crypto/Makefile linux-sl3516/drivers/crypto/Makefile --- linux-2.6.15-armeb/drivers/crypto/Makefile 2006-01-03 13:51:10.000000000 +1030 +++ linux-sl3516/drivers/crypto/Makefile 2006-04-03 18:10:47.000000000 +0930 @@ -1,6 +1,8 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o +obj-$(CONFIG_SL2312_IPSEC) += sl2312_ipsec.o + padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o padlock-objs := padlock-generic.o $(padlock-objs-y) diff -BurN --ignore-matching-lines='$\(Header\|Id\|Source\|Revision\|Date\)\($\|:\)' linux-2.6.15-armeb/drivers/crypto/sl2312_ipsec.c linux-sl3516/drivers/crypto/sl2312_ipsec.c --- linux-2.6.15-armeb/drivers/crypto/sl2312_ipsec.c 1970-01-01 09:30:00.000000000 +0930 +++ linux-sl3516/drivers/crypto/sl2312_ipsec.c 2006-10-25 16:19:36.000000000 +0930 @@ -0,0 +1,3276 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +/***************************** + * const definition * + *****************************/ + +#define CONFIG_IPSEC_GEMINI + +/* define TX/RX descriptor parameter */ +#define TX_BUF_SIZE 2048 +#define TX_DESC_NUM 20 +#define TX_BUF_TOT_LEN (TX_BUF_SIZE * TX_DESC_NUM) +#define RX_BUF_SIZE 32768//2048 +#define RX_DESC_NUM 8 +#define RX_BUF_TOT_LEN (RX_BUF_SIZE * RX_DESC_NUM) + +/* define EMAC base address */ +#define IPSEC_PHYSICAL_BASE_ADDR (SL2312_SECURITY_BASE) //0x51000000 +#define IPSEC_BASE_ADDR (IO_ADDRESS(IPSEC_PHYSICAL_BASE_ADDR)) +#define IPSEC_GLOBAL_BASE_ADDR (IO_ADDRESS(SL2312_GLOBAL_BASE)) + +//#define IPSEC_IRQ 0x04 + +#define IPSEC_MAX_PACKET_LEN 32768//2048 + 256 + +#define APPEND_MODE 0 +#define CHECK_MODE 1 + +#define MIN_HW_CHECKSUM_LEN 60 + +/* memory management utility */ +#define DMA_MALLOC(size,handle) pci_alloc_consistent(NULL,size,handle) +#define DMA_MFREE(mem,size,handle) pci_free_consistent(NULL,size,mem,handle) + +#define ipsec_read_reg(offset) (readl(IPSEC_BASE_ADDR + offset)) +//#define ipsec_write_reg(offset,data,mask) writel( (ipsec_read_reg(offset)&(~mask)) |(data&mask),(IPSEC_BASE_ADDR+offset)) +#define ipsec_write_reg2(offset,data) writel(data,(unsigned int *)(IPSEC_BASE_ADDR + offset)) + +/* define owner bit */ +enum OWN_BIT { + CPU = 0, + DMA = 1 +}; + +typedef struct IPSEC_PACKET_S qhead; + +/***************************** + * Global Variable Declare * + *****************************/ +struct IPSEC_TEST_RESULT_S +{ + unsigned int auth_cmp_result; + unsigned int sw_pkt_len; + unsigned char sw_cipher[IPSEC_MAX_PACKET_LEN]; + unsigned int hw_pkt_len; + unsigned char hw_cipher[IPSEC_MAX_PACKET_LEN]; +} ipsec_result; + +static IPSEC_CIPHER_CBC_T cbc; +static IPSEC_CIPHER_ECB_T ecb; +static IPSEC_AUTH_T auth; +static IPSEC_AUTH_T fcs_auth; +static IPSEC_HMAC_AUTH_T auth_hmac; +static IPSEC_CBC_AUTH_T cbc_auth; +static IPSEC_ECB_AUTH_T ecb_auth; +static IPSEC_CBC_AUTH_HMAC_T cbc_auth_hmac; +static IPSEC_ECB_AUTH_HMAC_T ecb_auth_hmac; + +static IPSEC_DESCRIPTOR_T *rx_desc_index[RX_DESC_NUM]; +static unsigned int rx_index = 0; + + +static struct IPSEC_PACKET_S fcs_op; /* for tcp/ip checksum */ +//static unsigned char out_packet[2048]; /* for tcp/ip checksum */ + +//static unsigned short checksum; +static IPSEC_T *tp; +static unsigned int tx_desc_virtual_base = 0; +static unsigned int rx_desc_virtual_base = 0; +//static unsigned int tx_buf_virtual_base = 0; +//static unsigned int rx_buf_virtual_base = 0; +static qhead *ipsec_queue,dummy[3]; +//static spinlock_t ipsec_lock; +static spinlock_t ipsec_q_lock; +//static wait_queue_head_t ipsec_wait_q; +//static unsigned int fcs_data_len = 0; +static unsigned int wep_crc_ok = 0; +static unsigned int tkip_mic_ok = 0; +static unsigned int ccmp_mic_ok = 0; + +/************************************* + * Function Prototype * + *************************************/ +static void ipsec_fcs_init(void); +static void ipsec_hw_auth(unsigned char *ctrl_pkt,int ctrl_len,struct scatterlist *data_pkt, int data_len, unsigned int tqflag, + unsigned char *out_pkt,int *out_len); +static void ipsec_hw_cipher(unsigned char *ctrl_pkt,int ctrl_len,struct scatterlist *data_pkt, int data_len, unsigned int tqflag, + unsigned char *out_pkt,int *out_len); +static void ipsec_hw_fcs(unsigned char *ctrl_pkt,int ctrl_len,struct scatterlist *data_pkt, int data_len, unsigned int tqflag, + unsigned char *out_pkt,int *out_len); +static void ipsec_byte_change(unsigned char *in_key,unsigned int in_len,unsigned char *out_key,unsigned int *out_len); +static void ipsec_rx_packet(void); +static int ipsec_tx_packet(struct scatterlist *packet, int len, unsigned int tqflag); +static void ipsec_complete_tx_packet(void); +static irqreturn_t ipsec_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int ipsec_interrupt_polling(void); +static int ipsec_auth_and_cipher(struct IPSEC_PACKET_S *op); +static int ipsec_auth_or_cipher(struct IPSEC_PACKET_S *op); +static void ipsec_byte_change(unsigned char *in_key,unsigned int in_len,unsigned char *out_key,unsigned int *out_len); +static void ipsec_put_queue(qhead *q,struct IPSEC_PACKET_S *item); +static struct IPSEC_PACKET_S *ipsec_get_queue(qhead *q); + +/************************************************/ +/* function body */ +/************************************************/ +__inline__ unsigned int ipsec_get_time(void) +{ + return (readl(0xf2300000)); +} + +#if 0 +static unsigned int ipsec_read_reg(unsigned int offset) +{ + unsigned int reg_val; + + reg_val = readl(IPSEC_BASE_ADDR + offset); + return (reg_val); +} +#endif + +static void ipsec_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask) +{ + unsigned int reg_val; + unsigned int *addr; + + reg_val = ( ipsec_read_reg(offset) & (~bit_mask) ) | (data & bit_mask); + addr = (unsigned int *)(IPSEC_BASE_ADDR + offset); + writel(reg_val,addr); + return; +} + +void ipsec_sw_reset(void) +{ + unsigned int reg_val; + + reg_val = readl(IPSEC_GLOBAL_BASE_ADDR + 0x10) | 0x00000010; + writel(reg_val,IPSEC_GLOBAL_BASE_ADDR + 0x10); + return; +} + +//void hw_memcpy(char *to, char *from, unsigned long n) +//{ +// unsigned int i; +// unsigned int p_to = __pa(to); +// unsigned int p_from = __pa(from); +// +// consistent_sync(to,n,DMA_BIDIRECTIONAL); +// //consistent_sync(from,n,DMA_BIDIRECTIONAL); +// writel(p_from,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x24); /* set source address */ +// writel(p_to,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x28); /* set destination address */ +// writel(n,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x2c); /* set byte count */ +// wmb(); +// writel(0x00000001,IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20); +// +// while (readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+0x20)==0x00000001); +//} + +static void ipsec_put_queue(qhead *q,struct IPSEC_PACKET_S *i) +{ + unsigned long flags; + + spin_lock_irqsave(&ipsec_q_lock, flags); + + i->next = q->next; + i->prev = q; + q->next->prev = i; + q->next = i; + + spin_unlock_irqrestore(&ipsec_q_lock, flags); + return; +} + + + +static struct IPSEC_PACKET_S * ipsec_get_queue(qhead *q) +{ + struct IPSEC_PACKET_S *i; + unsigned long flags; + + if(q->prev == q) + { + return NULL; + } + + spin_lock_irqsave(&ipsec_q_lock, flags); + i = q->prev; + q->prev = i->prev; + i->prev->next = i->next; + + spin_unlock_irqrestore(&ipsec_q_lock, flags); + + i->next = i->prev = NULL; + return i; +} + + + +/***************************************************************************** + * Function : ipsec_crypto_hw_process + * Description : This function processes H/W authentication and cipher. + * Input : op_info - the authentication and cipher information for IPSec module. + * Output : none. + * Return : 0 - success, others - failure. + *****************************************************************************/ +int ipsec_crypto_hw_process(struct IPSEC_PACKET_S *op_info) +{ + IPSEC_DESCRIPTOR_T *rx_desc; + static unsigned int pid = 0; + + + op_info->process_id = (pid++) % 256; + + + + +#if (ZERO_COPY==1) + /* get rx descriptor for this operation */ + rx_desc = rx_desc_index[rx_index%RX_DESC_NUM]; + /* set receive buffer address for this operation */ +// consistent_sync(op_info->out_packet,op_info->pkt_len,PCI_DMA_TODEVICE); + rx_desc->buf_adr = __pa(op_info->out_packet); //virt_to_phys(op_info->out_packet); +// ipsec_write_reg(IPSEC_RXDMA_BUF_ADDR,rx_desc->buf_adr,0xffffffff); + ipsec_write_reg2(IPSEC_RXDMA_BUF_ADDR,rx_desc->buf_adr); + rx_index++; +#endif +// printk("%s : ipsec_put_queue op_info->process_id=%d pkt_len=%d\n",__func__,op_info->process_id,op_info->pkt_len); + ipsec_put_queue(ipsec_queue,op_info); + + if ((op_info->op_mode==ENC_AUTH) || (op_info->op_mode==AUTH_DEC)) + { + ipsec_auth_and_cipher(op_info); + } + else + { + ipsec_auth_or_cipher(op_info); + } + + return 0; +} + +static unsigned char iv[16]; +static unsigned char cipher_key[32]; +static unsigned char auth_key[64]; +static unsigned char auth_result[20]; + +/*======================================================================================================*/ +/* Generate random packet and do software/hardware authentication/encryption/decryption */ +/*======================================================================================================*/ +static int ipsec_auth_or_cipher(struct IPSEC_PACKET_S *op) +{ + unsigned int iv_size; + unsigned int tdflag=0; + unsigned int ctrl_pkt_len; + unsigned int cipher_key_size; + unsigned int auth_key_size; + unsigned int auth_result_len; + + if ( (op->op_mode == CIPHER_ENC) || (op->op_mode == CIPHER_DEC) ) /* Encryption & Decryption */ + { + if ((op->cipher_algorithm == CBC_DES) || (op->cipher_algorithm == CBC_3DES) || (op->cipher_algorithm == CBC_AES)) + { + memset(&cbc,0x00,sizeof(IPSEC_CIPHER_CBC_T)); + cbc.control.bits.op_mode = op->op_mode; /* cipher encryption */ + cbc.control.bits.cipher_algorithm = op->cipher_algorithm; /* DES-CBC mode */ + cbc.control.bits.process_id = op->process_id; /* set frame process id */ + cbc.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + cbc.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(cbc.cipher_key,cipher_key,cipher_key_size); + } + else + { + memset(&ecb,0x00,sizeof(IPSEC_CIPHER_ECB_T)); + ecb.control.bits.op_mode = op->op_mode; /* cipher encryption */ + ecb.control.bits.cipher_algorithm = op->cipher_algorithm; /* DES-CBC mode */ + ecb.control.bits.process_id = op->process_id; /* set frame process id */ + ecb.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + ecb.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(ecb.cipher_key,cipher_key,cipher_key_size); + } + } + + if (op->op_mode == AUTH) /* Authentication */ + { + if ((op->auth_algorithm == MD5) || (op->auth_algorithm == SHA1) ) + { + memset(&auth,0x00,sizeof(IPSEC_AUTH_T)); + auth.var.control.bits.op_mode = op->op_mode; /* authentication */ + auth.var.control.bits.auth_mode = op->auth_result_mode; /* append/check authentication result */ + auth.var.control.bits.auth_algorithm = op->auth_algorithm; /* MD5 */ + auth.var.control.bits.process_id = op->process_id; /* set frame process id */ + auth.var.auth.bits.auth_header_len = op->auth_header_len; + auth.var.auth.bits.auth_algorithm_len = op->auth_algorithm_len; + } +#if 1 + else if (op->auth_algorithm == FCS) + { + fcs_auth.var.control.bits.process_id = op->process_id; /* set frame process id */ + fcs_auth.var.auth.bits.auth_header_len = op->auth_header_len; + fcs_auth.var.auth.bits.auth_algorithm_len = op->auth_algorithm_len; +// fcs_auth.var.control.bits.auth_check_len = 4; /* 4-word to be checked or appended */ + ipsec_hw_fcs((unsigned char *)&fcs_auth,28, + op->in_packet,op->pkt_len,0x45, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + return 0; + } +#endif + else + { + memset(&auth_hmac,0x00,sizeof(IPSEC_HMAC_AUTH_T)); + auth_hmac.control.bits.op_mode = op->op_mode; /* authentication */ + auth_hmac.control.bits.auth_mode = op->auth_result_mode; /* append/check authentication result */ + auth_hmac.control.bits.auth_algorithm = op->auth_algorithm; /* MD5 */ + auth_hmac.control.bits.process_id = op->process_id; /* set frame process id */ + auth_hmac.auth.bits.auth_header_len = op->auth_header_len; + auth_hmac.auth.bits.auth_algorithm_len = op->auth_algorithm_len; + ipsec_byte_change(op->auth_key,op->auth_key_size,auth_key,&auth_key_size); + memcpy(auth_hmac.auth_key,auth_key,auth_key_size); + } + } + + switch (op->op_mode) + { + case CIPHER_ENC: + switch(op->cipher_algorithm) + { + case CBC_DES: + op->iv_size = 8; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; /* 1+2+8+10+20+40 */ +#else + tdflag = 0x1b; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_DES: +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; /* 1+2+10+20+40 */ +#else + tdflag = 0x13; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_3DES: + op->iv_size = 8; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); /* set IV */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; +#else + tdflag = 0x1b; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_3DES: +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; +#else + tdflag = 0x13; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_AES: + cbc.control.bits.aesnk = op->cipher_key_size/4; /* AES key size */ + op->iv_size = 16; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); /* set IV */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; +#else + tdflag = 0x1b; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_AES: + ecb.control.bits.aesnk = op->cipher_key_size/4; /* AES key size */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; +#else + tdflag = 0x13; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case CIPHER_DEC: + switch(op->cipher_algorithm) + { + case CBC_DES: + op->iv_size = 8; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); /* set IV */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; +#else + tdflag = 0x1b; +#endif + /* hardware decryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_DES: +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; +#else + tdflag = 0x13; +#endif + /* hardware decryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_3DES: + op->iv_size = 8; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); /* set IV */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; +#else + tdflag = 0x1b; +#endif + /* hardware decryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_3DES: +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; +#else + tdflag = 0x13; +#endif + /* hardware decryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_AES: + cbc.control.bits.aesnk = op->cipher_key_size/4; /* AES key size */ + op->iv_size = 16; + ipsec_byte_change(op->iv,op->iv_size,iv,&iv_size); + memcpy(cbc.cipher_iv,iv,iv_size); /* set IV */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7b; +#else + tdflag = 0x1b; +#endif + /* hardware decryption */ + ipsec_hw_cipher((unsigned char *)&cbc,sizeof(IPSEC_CIPHER_CBC_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_AES: + ecb.control.bits.aesnk = op->cipher_key_size/4; /* AES key size */ +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x73; +#else + tdflag = 0x13; +#endif + /* hardware encryption */ + ipsec_hw_cipher((unsigned char *)&ecb,sizeof(IPSEC_CIPHER_ECB_T), + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case AUTH: + switch (op->auth_algorithm) + { + case MD5: + if (op->auth_result_mode == APPEND_MODE) + { + ctrl_pkt_len = 8; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x05; +#else + tdflag = 0x05; +#endif + } + else + { + ipsec_result.sw_pkt_len = 16; + ipsec_byte_change(ipsec_result.sw_cipher,ipsec_result.sw_pkt_len,auth_result,&auth_result_len); + memcpy(auth.var.auth_check_val,auth_result,auth_result_len); + ctrl_pkt_len = 28; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x205; +#else + tdflag = 0x45; +#endif + } + + auth.var.control.bits.auth_check_len = 4; /* 4-word to be checked or appended */ + ipsec_hw_auth((unsigned char *)&auth,ctrl_pkt_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + if (op->auth_result_mode == APPEND_MODE) + { + ctrl_pkt_len = sizeof(IPSEC_AUTH_T) - 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x05; +#else + tdflag = 0x05; +#endif + } + else + { + ipsec_result.sw_pkt_len = 20; + ipsec_byte_change(ipsec_result.sw_cipher,ipsec_result.sw_pkt_len,auth_result,&auth_result_len); + memcpy(auth.var.auth_check_val,auth_result,auth_result_len); + ctrl_pkt_len = sizeof(IPSEC_AUTH_T); +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x205; +#else + tdflag = 0x45; +#endif + } + auth.var.control.bits.auth_check_len = 5; /* 6-word to be checked or appended */ + ipsec_hw_auth((unsigned char *)&auth,ctrl_pkt_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + if (op->auth_result_mode == APPEND_MODE) + { + ctrl_pkt_len = sizeof(IPSEC_HMAC_AUTH_T) - 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x185; /* 1+4+80+100 */ +#else + tdflag = 0x25; +#endif + } + else + { + ipsec_result.sw_pkt_len = 16; + ipsec_byte_change(ipsec_result.sw_cipher,ipsec_result.sw_pkt_len,auth_result,&auth_result_len); + memcpy(auth_hmac.auth_check_val,auth_result,auth_result_len); + ctrl_pkt_len = sizeof(IPSEC_HMAC_AUTH_T); +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x385; /* 1+4+80+100+200 */ +#else + tdflag = 0x65; +#endif + } + auth_hmac.control.bits.auth_check_len = 4; /* 4-word to be checked or appended */ + ipsec_hw_auth((unsigned char *)&auth_hmac,ctrl_pkt_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + if (op->auth_result_mode == APPEND_MODE) + { + ctrl_pkt_len = sizeof(IPSEC_HMAC_AUTH_T) - 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x185; /* 1+4+80+100 */ +#else + tdflag = 0x25; +#endif + } + else + { + ipsec_result.sw_pkt_len = 20; + ipsec_byte_change(ipsec_result.sw_cipher,ipsec_result.sw_pkt_len,auth_result,&auth_result_len); + memcpy(auth_hmac.auth_check_val,auth_result,auth_result_len); + ctrl_pkt_len = sizeof(IPSEC_HMAC_AUTH_T); +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x385; /* 1+4+80+100+200 */ +#else + tdflag = 0x65; +#endif + } + auth_hmac.control.bits.auth_check_len = 5; /* 6-word to be checked or appended */ + ipsec_hw_auth((unsigned char *)&auth_hmac,ctrl_pkt_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case FCS: +#if 0 + if (op->auth_result_mode == APPEND_MODE) + { + ctrl_pkt_len = 8; + tdflag = 0x05; + } + else + + { + ctrl_pkt_len = 28; + tdflag = 0x45; + } + + ipsec_hw_fcs((unsigned char *)&auth,ctrl_pkt_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); +#endif + ipsec_hw_fcs((unsigned char *)&fcs_auth,28, + op->in_packet,op->pkt_len,0x45, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + default: + break; + } + return (0); +} + + +/*======================================================================================================*/ +/* Generate random packet and do software/hardware authentication/encryption/decryption */ +/*======================================================================================================*/ +static int ipsec_auth_and_cipher(struct IPSEC_PACKET_S *op) +{ + unsigned char iv[16]; + unsigned int iv_size; + unsigned int tdflag=0; + unsigned char cipher_key[32]; + unsigned int cipher_key_size; + unsigned char auth_key[64]; + unsigned int auth_key_size; + unsigned int control_packet_len; + unsigned char auth_result[20]; + unsigned int auth_result_len; + + /* CBC mode */ + if ((op->cipher_algorithm == CBC_DES) || (op->cipher_algorithm == CBC_3DES) || (op->cipher_algorithm == CBC_AES)) + { + if ((op->auth_algorithm == MD5) || (op->auth_algorithm == SHA1)) + { + /* Authentication and Cipher CBC mode */ + memset(&cbc_auth,0x00,sizeof(IPSEC_CBC_AUTH_T)); + cbc_auth.control.bits.op_mode = op->op_mode; /* cipher encryption */ + cbc_auth.control.bits.cipher_algorithm = op->cipher_algorithm; /* cipher algorithm */ + cbc_auth.control.bits.process_id = op->process_id; /* set frame process id */ + cbc_auth.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + cbc_auth.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(cbc_auth.cipher_key,cipher_key,cipher_key_size); + cbc_auth.control.bits.auth_algorithm = op->auth_algorithm; /* authentication algorithm */ + cbc_auth.control.bits.auth_mode = op->auth_result_mode; /* append/check mode */ + cbc_auth.auth.bits.auth_header_len = op->auth_header_len; /* the header length to be skipped by the cipher */ + cbc_auth.auth.bits.auth_algorithm_len = op->auth_algorithm_len; /* the length of message body to be encrypted */ + } + else /* HMAC */ + { + /* Authentication HMAC mode and Cipher CBC mode */ + memset(&cbc_auth_hmac,0x00,sizeof(IPSEC_CBC_AUTH_HMAC_T)); + cbc_auth_hmac.control.bits.op_mode = op->op_mode; /* cipher encryption */ + cbc_auth_hmac.control.bits.cipher_algorithm = op->cipher_algorithm; /* cipher algorithm */ + cbc_auth_hmac.control.bits.process_id = op->process_id; /* set frame process id */ + cbc_auth_hmac.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + cbc_auth_hmac.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(cbc_auth_hmac.cipher_key,cipher_key,cipher_key_size); + cbc_auth_hmac.control.bits.auth_algorithm = op->auth_algorithm; /* authentication algorithm */ + cbc_auth_hmac.control.bits.auth_mode = op->auth_result_mode; /* append/check mode */ + cbc_auth_hmac.auth.bits.auth_header_len = op->auth_header_len; /* the header length to be skipped by the cipher */ + cbc_auth_hmac.auth.bits.auth_algorithm_len = op->auth_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->auth_key,op->auth_key_size,auth_key,&auth_key_size); + memcpy(cbc_auth_hmac.auth_key,auth_key,auth_key_size); + } + } + else /* ECB mode */ + { + if ((op->auth_algorithm == MD5) || (op->auth_algorithm == SHA1)) + { + /* Authentication and Cipher ECB mode */ + memset(&ecb_auth,0x00,sizeof(IPSEC_ECB_AUTH_T)); + ecb_auth.control.bits.op_mode = op->op_mode; /* cipher encryption */ + ecb_auth.control.bits.cipher_algorithm = op->cipher_algorithm; /* cipher algorithm */ + ecb_auth.control.bits.process_id = op->process_id; /* set frame process id */ + ecb_auth.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + ecb_auth.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(ecb_auth.cipher_key,cipher_key,cipher_key_size); + ecb_auth.control.bits.auth_algorithm = op->auth_algorithm; /* authentication algorithm */ + ecb_auth.control.bits.auth_mode = op->auth_result_mode; /* append/check mode */ + ecb_auth.auth.bits.auth_header_len = op->auth_header_len; /* the header length to be skipped by the cipher */ + ecb_auth.auth.bits.auth_algorithm_len = op->auth_algorithm_len; /* the length of message body to be encrypted */ + } + else /* HMAC */ + { + /* Authentication HMAC mode and Cipher ECB mode */ + memset(&ecb_auth_hmac,0x00,sizeof(IPSEC_ECB_AUTH_HMAC_T)); + ecb_auth_hmac.control.bits.op_mode = op->op_mode; /* cipher encryption */ + ecb_auth_hmac.control.bits.cipher_algorithm = op->cipher_algorithm; /* cipher algorithm */ + ecb_auth_hmac.control.bits.process_id = op->process_id; /* set frame process id */ + ecb_auth_hmac.cipher.bits.cipher_header_len = op->cipher_header_len; /* the header length to be skipped by the cipher */ + ecb_auth_hmac.cipher.bits.cipher_algorithm_len = op->cipher_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->cipher_key,op->cipher_key_size,cipher_key,&cipher_key_size); + memcpy(ecb_auth_hmac.cipher_key,cipher_key,cipher_key_size); + ecb_auth_hmac.control.bits.auth_algorithm = op->auth_algorithm; /* authentication algorithm */ + ecb_auth_hmac.control.bits.auth_mode = op->auth_result_mode; /* append/check mode */ + ecb_auth_hmac.auth.bits.auth_header_len = op->auth_header_len; /* the header length to be skipped by the cipher */ + ecb_auth_hmac.auth.bits.auth_algorithm_len = op->auth_algorithm_len; /* the length of message body to be encrypted */ + ipsec_byte_change(op->auth_key,op->auth_key_size,auth_key,&auth_key_size); + memcpy(ecb_auth_hmac.auth_key,auth_key,auth_key_size); + } + } + + switch (op->op_mode) + { + case ENC_AUTH: + switch(op->cipher_algorithm) + { + case CBC_DES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; /* 1+2+4+8+10+20+40+80+100 */ +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = 0; + cbc_auth_hmac.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; /* 1+2+4+8+10+20+40+80+100 */ +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = 0; + cbc_auth_hmac.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case ECB_DES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; /* 1+2+4+10+20+40+80+100 */ +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = 0; + ecb_auth_hmac.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; /* 1+2+4+10+20+40+80+100 */ +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = 0; + ecb_auth_hmac.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case CBC_3DES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40*/ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; /* 1+2+4+8+10+20+40+80+100 */ +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = 0; + cbc_auth_hmac.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = 0; + cbc_auth_hmac.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case ECB_3DES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40*/ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; /* 1+2+4+10+20+40+80+100*/ +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = 0; + ecb_auth_hmac.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = 0; + ecb_auth_hmac.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case CBC_AES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = op->cipher_key_size/4; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; /* 1+2+4+8+10+20+40+80+100 */ +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = op->cipher_key_size/4; + cbc_auth_hmac.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 16 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10 + 0x20; + control_packet_len = 124; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1ff; /* 1+2+4+8+10+20+40+80+100 */ +#else + tdflag = 0x3f; +#endif + /* IPSec Control Register */ + cbc_auth_hmac.control.bits.aesnk = op->cipher_key_size/4; + cbc_auth_hmac.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth_hmac.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case ECB_AES: + switch (op->auth_algorithm) + { + case MD5: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = op->cipher_key_size/4; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case SHA1: + //control_packet_len = 4 + 4 + 4 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = op->cipher_key_size/4; + ecb_auth.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_MD5: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; /* 1+2+4+10+20+40+80+100 */ +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = op->cipher_key_size/4; + ecb_auth_hmac.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case HMAC_SHA1: + //control_packet_len = 4 + 4 + 4 + 32 + 64; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10 + 0x20; + control_packet_len = 108; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x1f7; /* 1+2+4+10+20+40+80+100 */ +#else + tdflag = 0x37; +#endif + /* IPSec Control Register */ + ecb_auth_hmac.control.bits.aesnk = op->cipher_key_size/4; + ecb_auth_hmac.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth_hmac.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth_hmac,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + } + break; + + case AUTH_DEC: + switch (op->auth_algorithm) + { + case MD5: + switch(op->cipher_algorithm) + { + case CBC_DES: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_DES: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_3DES: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_3DES: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_AES: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = op->cipher_key_size/4; + cbc_auth.control.bits.auth_check_len = 4; + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_AES: + //control_packet_len = 4 + 4 + 4 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = op->cipher_key_size/4; + ecb_auth.control.bits.auth_check_len = 4; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],16,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + } + break; + + case SHA1: + switch(op->cipher_algorithm) + { + case CBC_DES: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_DES: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_3DES: + //control_packet_len = 4 + 4 + 4 + 16 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = 0; + cbc_auth.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,8,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(cbc_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&cbc_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case ECB_3DES: + //control_packet_len = 4 + 4 + 4 + 32; + //tdflag = 0x01 + 0x02 + 0x04 + 0x10; + control_packet_len = 44 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x77; /* 1+2+4+10+20+40 */ +#else + tdflag = 0x17; +#endif + /* IPSec Control Register */ + ecb_auth.control.bits.aesnk = 0; + ecb_auth.control.bits.auth_check_len = 5; + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); + memcpy(ecb_auth.auth_check_val,auth_result,auth_result_len); + control_packet_len = control_packet_len + 20; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = tdflag + 0x200; +#else + tdflag = tdflag + 0x40; +#endif + } + + ipsec_hw_cipher((unsigned char *)&ecb_auth,control_packet_len, + op->in_packet,op->pkt_len,tdflag, + ipsec_result.hw_cipher,&ipsec_result.hw_pkt_len); + break; + + case CBC_AES: + //control_packet_len = 4 + 4 + 4 + 16 + 32 ; + //tdflag = 0x01 + 0x02 + 0x04 + 0x08 + 0x10; + control_packet_len = 60 ; +#ifdef CONFIG_IPSEC_GEMINI + tdflag = 0x7f; /* 1+2+4+8+10+20+40 */ +#else + tdflag = 0x1f; +#endif + /* IPSec Control Register */ + cbc_auth.control.bits.aesnk = op->cipher_key_size/4; + cbc_auth.control.bits.auth_check_len = 5; + /* Cipher IV */ + ipsec_byte_change(op->iv,16,iv,&iv_size); + memcpy(cbc_auth.cipher_iv,iv,iv_size); + if (op->auth_result_mode == CHECK_MODE) + { + ipsec_byte_change(&ipsec_result.sw_cipher[op->pkt_len],20,auth_result,&auth_result_len); +