diff -urN linux/arch/arm/config.in new/arch/arm/config.in --- linux/arch/arm/config.in Tue Aug 10 17:24:24 1999 +++ new/arch/arm/config.in Fri Jul 16 17:12:05 1999 @@ -39,7 +39,8 @@ empeg CONFIG_SA1100_EMPEG \ Itsy CONFIG_SA1100_ITSY \ PLEB CONFIG_SA1100_PLEB \ - Victor CONFIG_SA1100_VICTOR" Brutus + Victor CONFIG_SA1100_VICTOR \ + Tifon CONFIG_SA1100_TIFON" Brutus fi if [ "$CONFIG_SA1100_EMPEG" = "y" ]; then @@ -56,6 +57,11 @@ define_bool CONFIG_ARCH_CO285 y fi +# Determine if machine has a sa1101 +if [ "$CONFIG_SA1100_TIFON" = "y" ]; then + define_bool CONFIG_SA1101 y +fi + # Select various configuration options depending on the machine type # Easy check for Acorn-style architectures if [ "$CONFIG_ARCH_ARC" = "y" -o \ @@ -144,6 +150,12 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_CPU_32" = "y" ]; then tristate 'RISC OS personality' CONFIG_ARTHUR +fi + +# Determine sa1101 parameters +if [ "$CONFIG_SA1101" = "y" ]; then + int 'sa1101 irq' SA1101_IRQ 1 + hex 'sa1101 base address' SA1101_BASE 0x10000000 fi tristate 'Parallel port support' CONFIG_PARPORT diff -urN linux/arch/arm/kernel/Makefile new/arch/arm/kernel/Makefile --- linux/arch/arm/kernel/Makefile Tue Aug 10 17:24:24 1999 +++ new/arch/arm/kernel/Makefile Fri Jul 16 16:56:11 1999 @@ -54,6 +54,14 @@ endif endif +ifdef CONFIG_SA1101 + O_OBJS += sidekick.o +endif + +ifdef CONFIG_SA1100_TIFON + O_OBJS += tifon.o +endif + ifdef CONFIG_LEDS OX_OBJS += leds-$(MACHINE).o endif diff -urN linux/arch/arm/kernel/entry-armv.S new/arch/arm/kernel/entry-armv.S --- linux/arch/arm/kernel/entry-armv.S Tue Aug 10 17:24:25 1999 +++ new/arch/arm/kernel/entry-armv.S Thu Jul 29 18:46:55 1999 @@ -63,6 +63,9 @@ #define OFF_CR_ALIGNMENT(x) cr_alignment - x +#define APA(x) 7 - x + + #ifdef IOC_BASE /* IOC / IOMD based hardware */ #include @@ -295,10 +298,17 @@ .endm #elif defined(CONFIG_ARCH_SA1100) - .macro disable_fiq .endm +#ifdef CONFIG_SA1101 +intstatclr0: .word io_p2v(_INTSTATCLR0) +intstatclr1: .word io_p2v(_INTSTATCLR1) +intenable0: .word io_p2v(_INTENABLE0) +intenable1: .word io_p2v(_INTENABLE1) +#endif + + .macro get_irqnr_and_base, irqnr, irqstat, base mov r4, #0xfa000000 @ ICIP = 0x90050000 ... add r4, r4, #0x00050000 @ mapped to 0xfa050000 @@ -306,12 +316,52 @@ ldr \irqnr, [r4, #4] @ ICMR ands \irqstat, \irqstat, \irqnr mov \irqnr, #0 - beq 2002f + beq 2005f 2001: tst \irqstat, #1 addeq \irqnr, \irqnr, #1 moveq \irqstat, \irqstat, lsr #1 beq 2001b -2002: @ Z set for 'no irq found' + +#ifdef CONFIG_SA1101 + @ if SA1101_IRQ is triggered the sa1101 is + @ scanned for the real interrupt, if none + @ is found we return SA1101_IRQ to signal + @ an error in the sa1101 (should never happen) + cmp \irqnr, #SA1101_IRQ + bne 2005f @ Z not set - OK + + @ check first bank (irq 32-63) + adr r4, intstatclr0 + ldr r4, [r4] + ldr \irqstat, [r4] + adr r4, intenable0 + ldr r4, [r4] + ldr \irqnr, [r4] + ands \irqstat, \irqstat, \irqnr + beq 2003f + mov \irqnr, #32 @ first bank +2002: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + beq 2002b + b 2005f @ Z not set - OK + @ check second bank (irq 64-95) +2003: adr r4, intstatclr1 + ldr r4, [r4] + ldr \irqstat, [r4] + adr r4, intenable1 + ldr r4, [r4] + ldr \irqnr, [r4] + ands \irqstat, \irqstat, \irqnr + moveq \irqnr, #SA1101_IRQ @ nothing on sa1101 + beq 2005f @ Z set - OK + mov \irqnr, #64 @ second bank +2004: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + beq 2004b +#endif +2005: @ Z set for 'no irq found' .endm .macro irq_prio_table diff -urN linux/arch/arm/kernel/head-armv.S new/arch/arm/kernel/head-armv.S --- linux/arch/arm/kernel/head-armv.S Tue Aug 10 17:24:25 1999 +++ new/arch/arm/kernel/head-armv.S Wed Jul 28 16:24:34 1999 @@ -8,6 +8,11 @@ #include #include +#ifdef CONFIG_SA1100_TIFON +#define CONFIG_DEBUG_LL + /* __entry must be visible for the build tools */ + .globl __tifon_entry +#endif .globl SYMBOL_NAME(swapper_pg_dir) .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 @@ -70,7 +75,7 @@ orr r0, r0, #0xc0 msr cpsr, r0 #endif - + #ifdef CONFIG_SA1100_VICTOR @ Copy cmdline to 0xc0000000 mov r1, #0xc0000000 @@ -82,6 +87,15 @@ bne 1b #endif +#ifdef CONFIG_SA1100_TIFON +__tifon_entry: + @ We begin with setting up memory timing cpu speed + @ since this is not currently done by the loader + @ to do this we need to turn off the mmu + + bl SYMBOL_NAME(setup_tifon) + +#endif @ Data cache might be active. @ Be sure to flush kernel binary out of the cache, @ whatever state it is, before it is turned off. @@ -123,23 +137,25 @@ * r1 = 9 -> SA1100 based system */ -__entry: teq r0, #0 @ check for illegal entry... - bne .Lerror @ loop indefinitely - cmp r1, #10 @ Unknown machine architecture +__entry: teq r0, #0 @ check for illegal entry... + bne .Lerror @ loop indefinitely + cmp r1, #10 @ Unknown machine architecture bge .Lerror + + /* First thing to do is to get the page tables set up so that we can call * the kernel in the correct place. This is relocatable code... * - Read processor ID register (CP#15, CR0). */ - mrc p15, 0, r9, c0, c0 @ get Processor ID + mrc p15, 0, r9, c0, c0 @ get Processor ID /* Values are: * XX01XXXX = ARMv4 architecture (StrongARM) * XX00XXXX = ARMv3 architecture * 4156061X = ARM 610 */ adr r10, .LCProcTypes -1: ldmia r10!, {r5, r6, r8} @ Get Set, Mask, MMU Flags - teq r5, #0 @ End of list? +1: ldmia r10!, {r5, r6, r8} @ Get Set, Mask, MMU Flags + teq r5, #0 @ End of list? beq .Lerror eor r5, r5, r9 tst r5, r6 @@ -185,6 +201,8 @@ add r3, r3, #1 << 20 teq r0, r2 bne 1b + + #ifdef CONFIG_ARCH_NETWINDER teq r1, #5 bne 1f @@ -215,7 +233,7 @@ @ The following should work on both v3 and v4 implementations @ mov lr, pc - mov pc, r10 @ Call processor flush (returns ctrl reg) + mov pc, r10 @ Call processor flush (returns ctrl reg) adr r5, __entry sub r10, r10, r5 @ Make r10 PIC ldr lr, .Lbranch @@ -298,9 +316,9 @@ .long 0 @ DEC EBSA285 as co-processor - .long 0x4000 @ Address of page tables (physical) - .long 0 @ Address of RAM - .long 0x42000000 @ I/O base address + .long 0x4000 @ Address of page tables (physical) + .long 0 @ Address of RAM + .long 0x42000000 @ I/O base address .long 0 @ SA1100 @@ -313,21 +331,21 @@ .long 0x41560600 .long 0xffffff00 .long 0x00000c12 - b .Larmv3_flush_early @ arm v3 flush & ctrl early setup + b .Larmv3_flush_early @ arm v3 flush & ctrl early setup mov pc, lr @ ARM7 .long 0x41007000 .long 0xfffff000 .long 0x00000c12 - b .Larmv3_flush_late @ arm v3 flush & ctrl late setup + b .Larmv3_flush_late @ arm v3 flush & ctrl late setup mov pc, lr @ ARM710 .long 0x41007000 - .long 0xfff8f000 @ arm710 processors are weird + .long 0xfff8f000 @ arm710 processors are weird .long 0x00000c12 - b .Larmv3_flush_late @ arm v3 flush & ctrl late setup + b .Larmv3_flush_late @ arm v3 flush & ctrl late setup mov pc, lr @ StrongARM @@ -349,54 +367,54 @@ .Larmv3_flush_early: mov r0, #0 - mcr p15, 0, r0, c7, c0 @ flush caches on v3 - mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register #ifdef CONFIG_ALIGNMENT_TRAP - mov r0, #0x3f @ ....S..DPWCAM + mov r0, #0x3f @ ....S..DPWCAM #else - mov r0, #0x3d @ ....S..DPWC.M + mov r0, #0x3d @ ....S..DPWC.M #endif orr r0, r0, #0x100 mov pc, lr .Larmv3_flush_late: mov r0, #0 - mcr p15, 0, r0, c7, c0 @ flush caches on v3 - mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register #ifdef CONFIG_ALIGNMENT_TRAP - mov r0, #0x7f @ ....S.LDPWCAM + mov r0, #0x7f @ ....S.LDPWCAM #else - mov r0, #0x7d @ ....S.LDPWC.M + mov r0, #0x7d @ ....S.LDPWC.M #endif orr r0, r0, #0x100 mov pc, lr .Larmv4_flush_early: mov r0, #0 - mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 - mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register - mrc p15, 0, r0, c1, c0 @ get control register v4 + mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 bic r0, r0, #0x0e00 bic r0, r0, #0x0002 #ifdef CONFIG_ALIGNMENT_TRAP - orr r0, r0, #0x003f @ I...S..DPWCAM + orr r0, r0, #0x003f @ I...S..DPWCAM #else - orr r0, r0, #0x003d @ I...S..DPWC.M + orr r0, r0, #0x003d @ I...S..DPWC.M #endif - orr r0, r0, #0x1100 @ v4 supports separate I cache + orr r0, r0, #0x1100 @ v4 supports separate I cache mov pc, lr -.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching +.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching mov pc, lr .LC0: .long SYMBOL_NAME(__entry) @@ -413,17 +431,17 @@ ldmia r4, {r3, r4, r5, r6, r7, r8, sp} @ Setup stack add r10, r10, r3 @ Add base back in mov fp, #0 -1: cmp r5, r7 @ Clear BSS +1: cmp r5, r7 @ Clear BSS strcc fp, [r5],#4 bcc 1b - bic r2, r0, #2 @ Clear 'A' bit - stmia r8, {r0, r2} @ Save control register values + bic r2, r0, #2 @ Clear 'A' bit + stmia r8, {r0, r2} @ Save control register values - str r1, [r4] @ Save machine type - str r9, [r6] @ Save processor ID + str r1, [r4] @ Save machine type + str r9, [r6] @ Save processor ID mov lr, pc - add pc, r10, #4 @ Call post-processor init + add pc, r10, #4 @ Call post-processor init mov fp, #0 b SYMBOL_NAME(start_kernel) @@ -626,5 +644,5 @@ .bss hexbuf: .space 16 - + #endif diff -urN linux/arch/arm/kernel/irq.c new/arch/arm/kernel/irq.c --- linux/arch/arm/kernel/irq.c Tue Aug 10 17:24:25 1999 +++ new/arch/arm/kernel/irq.c Fri Jul 30 11:47:04 1999 @@ -247,6 +247,7 @@ if (bh_active & bh_mask) do_bottom_half(); } + } #if defined(CONFIG_ARCH_ACORN) @@ -499,3 +500,4 @@ #endif init_dma(); } + diff -urN linux/arch/arm/kernel/setup.c new/arch/arm/kernel/setup.c --- linux/arch/arm/kernel/setup.c Tue Aug 10 17:24:25 1999 +++ new/arch/arm/kernel/setup.c Wed Jul 28 16:25:54 1999 @@ -139,6 +139,19 @@ { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL } }; + +#ifdef CONFIG_SA1101 + extern int setup_sa1101( void ); +#endif + +#ifdef CONFIG_SA1100_TIFON + +#define RAMDISK_START 0x1100004 +#define RAMDISK_SIZE 0x140000 + +#endif + + /* * From head-armv.S */ @@ -303,6 +316,9 @@ #endif setup_processor(); +#ifdef CONFIG_SA1101 + //setup_sa1101(); +#endif init_task.mm->start_code = TASK_SIZE; init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; @@ -440,6 +456,12 @@ setup_ram(1, 0, 0); setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); +#elif defined(CONFIG_SA1100_TIFON) + memory_end = 32*1024*1024; + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); + + setup_ram(1, 0, 0); + setup_initrd( 0xd0000000 + RAMDISK_START, RAMDISK_SIZE ); #elif defined(CONFIG_SA1100_VICTOR) memory_end = 4*1024*1024; ROOT_DEV = MKDEV( 60, 2 ); @@ -470,6 +492,7 @@ #ifdef CONFIG_NWFPE fpe_init(); #endif + /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, from, COMMAND_LINE_SIZE); diff -urN linux/arch/arm/kernel/sidekick.c new/arch/arm/kernel/sidekick.c --- linux/arch/arm/kernel/sidekick.c Thu Jan 1 01:00:00 1970 +++ new/arch/arm/kernel/sidekick.c Mon Jul 19 15:56:23 1999 @@ -0,0 +1,54 @@ +/* + * File: sidekick.c + * + * Routines for setting up the sa1101 + * + */ + +#include +#include +#include + + +#define val_at( x ) ( *(volatile long *)(x)) + +#define DELAY_FIRST 28 +#define DELAY_NEXT 28 +#define RECOVERY_TIME 6 + +#define BANK_SETUP ((DELAY_FIRST<<3)|(DELAY_NEXT<<8)|(RECOVERY_TIME<<13)) + +void setup_sa1101(void) +{ + + /* Set up SA1100 to support SA1100: + * SRAM-bank 2 is set to Flash-ROM type + * GPIO 21 & 22 is MBREQ and MBGNT + * GPIO 27 is 3.68 MHz osc. + */ + +#if (SA1101_BASE == 0x08000000 ) /* bank 1 */ + val_at(_MSC0) = (val_at(_MSC0) & 0x0000ffff ) | (BANK_SETUP << 16); +#elif (SA1101_BASE == 0x10000000 ) /* bank 2 */ + val_at(_MSC1) = (val_at(_MSC1) & 0xffff0000 ) | BANK_SETUP; +#elif (SA1101_BASE == 0x18000000 ) /* bank 3 */ + val_at(_MSC1) = (val_at(_MSC1) & 0x0000ffff ) | (BANK_SETUP << 16); +#endif + + val_at(_GPDR) |= 0x08200000; /* Outp. 27 CLK, 21 MBGNT*/ + val_at(_GPDR) &= ~0x00400000; /* Inp. 22 MBREQ */ + val_at(_GAFR) |= 0x08600000; /* GAFR 27 1,2 */ + val_at(_TUCR) |= 0x20000400; /* 3.68 Mhz MBRQ,GNT */ + + + do { /* Wait for sa1101 to wake up */ + val_at(_SKCR) = 0x19; + }while( val_at(_SKCR) == 0x00 ); + + udelay(1000); + + val_at(_SKCR) = 0x1b; /* enable sa1101 */ + val_at(_SKPCR) = 0x6; /* skpcr enable ints + ps2 */ + + printk("SA1101 initialized\n"); +} diff -urN linux/arch/arm/kernel/tifon.c new/arch/arm/kernel/tifon.c --- linux/arch/arm/kernel/tifon.c Thu Jan 1 01:00:00 1970 +++ new/arch/arm/kernel/tifon.c Mon Jul 19 15:58:54 1999 @@ -0,0 +1,135 @@ +/* + * tifon.c + * + * some initialization code for the Tifon + * that should have been done by the bootloader + * + * note that this is executed before the + * pagetables has been setup + * + */ + +#include +#include + +#define val_at( x ) ( *(volatile long *)(x)) + + +#define DRAM_DE 0x03 /* Bank enable */ +#define DRAM_DRAC 0x03 /* Row ad. bits */ +#define DRAM_CDB2 0x00 /* Clock divide */ +#define DRAM_TRP 0x02 /* RAS Precharge */ +#define DRAM_TRASR 0x03 /* Ras time during cas before ras refresh */ +#define DRAM_TDL 0x03 /* Data latch after cas high */ +#define DRAM_DRI 0x138 /* Dram refresh interval */ +#define DRAM_MDCAS0 0x3333330f +#define DRAM_MDCAS1 0x33333333 +#define DRAM_MDCAS2 0x33333333 + + +#define DRAM_CTL ((DRAM_DRI<<17)|(DRAM_TDL<<15)|(DRAM_TRASR<<11)|\ + (DRAM_TRP<<7)|(DRAM_CDB2<<6)|(DRAM_DRAC<<4)|DRAM_DE) + +#define DRAM_RMASK 0x00000030 + +unsigned long setup_dram(void) +{ + unsigned long mdcnfg = val_at(_MDCNFG); + val_at(_MDCNFG) = (DRAM_CTL & ~(DRAM_RMASK))|(mdcnfg & DRAM_RMASK); + mdcnfg = val_at(_MDCNFG); + + val_at(_MDCAS0) = DRAM_MDCAS0; + val_at(_MDCAS1) = DRAM_MDCAS1; + val_at(_MDCAS2) = DRAM_MDCAS2; + return(mdcnfg); +} + + +#define BSIO1 0x3 +#define BSA1 0x3 +#define BSM1 0x4 + +#define BSIO2 0x1 +#define BSA2 0x3 +#define BSM2 0x1 + +#define MECR_VAL (BSM2<<26)|(BSA2<<21)| \ + (BSIO2<<16)|(BSM1<<10)|(BSA1<<5)|(BSIO1) + +unsigned long setup_mecr(void) +{ + return (val_at(_MECR) = MECR_VAL ); +} + +#define RT0 0 +#define RBW0 0 +#define RDF0 11 +#define RDN0 11 +#define RRR0 2 + +#define RT1 0 +#define RBW1 0 +#define RDF1 11 +#define RDN1 11 +#define RRR1 2 + +#define RT2 0 +#define RBW2 0 +#define RDF2 28 +#define RDN2 28 +#define RRR2 6 + +#define RT3 0 +#define RBW3 0 +#define RDF3 2 +#define RDN3 2 +#define RRR3 1 + + + +#define MSC0_VAL (RRR1<<29)|(RDN1<<24)|(RDF1<<19)|(RBW1<<18)|(RT1<<16)| \ + (RRR0<<13)|(RDN0<<8)|(RDF0<<3)|(RBW0<<2)|(RT0) + +#define MSC1_VAL (RRR3<<29)|(RDN3<<24)|(RDF3<<19)|(RBW3<<18)|(RT3<<16)| \ + (RRR2<<13)|(RDN2<<8)|(RDF2<<3)|(RBW2<<2)|(RT2) + +unsigned long setup_msc0(void) +{ + return (val_at(_MSC0)=MSC0_VAL); +} + +unsigned long setup_msc1(void) +{ + return (val_at(_MSC1)=MSC1_VAL); +} + +#define PPCR_K_100MHz 0x3 +#define PPCR_K_116MHz 0x4 +#define PPCR_K_133MHz 0x5 +#define PPCR_K_148MHz 0x6 +#define PPCR_K_166MHz 0x7 +#define PPCR_K_176MHz 0x8 +#define PPCR_K_191MHz 0x9 +#define PPCR_K_206MHz 0xa +#define PPCR_K_221MHz 0xb +#define PPCR_K_236MHz 0xc +#define PPCR_K_250MHz 0xd +#define PPCR_K_265MHz 0xe + +int setup_speed(int speed) +{ + int oldspeed=val_at(_PPCR); + if( speed > 0x02 && speed < 0x0f ) + val_at(_PPCR) = speed; + return (oldspeed); +} + +void setup_tifon(void) +{ + setup_dram(); + setup_speed(PPCR_K_191MHz); + setup_mecr(); + setup_msc0(); + setup_msc1(); +} + diff -urN linux/arch/arm/mm/fault-common.c new/arch/arm/mm/fault-common.c --- linux/arch/arm/mm/fault-common.c Tue Aug 10 17:24:25 1999 +++ new/arch/arm/mm/fault-common.c Mon Jul 19 16:41:03 1999 @@ -162,7 +162,7 @@ * However we may loop indefinitely if there is a * true fault. */ - printk( "do_page_fault(): CPU bug: pc == lr: fault igno$ + printk( "do_page_fault(): CPU bug: pc == lr: fault ignored\n"); return; } tsk->tss.error_code = mode; diff -urN linux/arch/arm/mm/mm-armv.c new/arch/arm/mm/mm-armv.c --- linux/arch/arm/mm/mm-armv.c Sat May 8 20:06:57 1999 +++ new/arch/arm/mm/mm-armv.c Wed Jul 28 16:34:05 1999 @@ -29,7 +29,7 @@ { const struct mapping *mp; int i; - + for (i = 0, mp = mapping; i < SIZEOFMAP; i++, mp++) { unsigned long virtual, physical, length; int prot; diff -urN linux/arch/arm/mm/mm-sa1100.c new/arch/arm/mm/mm-sa1100.c --- linux/arch/arm/mm/mm-sa1100.c Tue Aug 10 17:24:25 1999 +++ new/arch/arm/mm/mm-sa1100.c Wed Jul 28 16:43:02 1999 @@ -15,6 +15,8 @@ #include #include +#include + #ifdef CONFIG_SA1100_VICTOR #define FLASH_MAPPING \ { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1 }, /* flash */ @@ -22,12 +24,24 @@ #include #define FLASH_MAPPING \ { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1 }, /* flash */ +#elif defined(CONFIG_SA1100_TIFON) /* We want continuous flash memory */ +#define FLASH_MAPPING\ + { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1 }, /* flash bank 1 */\ + { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1 }, /* flash bank 2 */ #else #define FLASH_MAPPING #endif +#ifdef CONFIG_SA1101 +#define SA1101_MAPPING\ + { io_p2v( SA1101_BASE ), SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1 }, +#else +#define SA1101_MAPPING +#endif + #define MAPPING \ + SA1101_MAPPING\ { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1 }, \ { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1 }, \ { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1 }, \ @@ -73,6 +87,14 @@ #define PAGES_IN_BANK_2 0 #define PAGES_IN_BANK_3 0 +#elif defined(CONFIG_SA1100_TIFON) + +/* Two banks with 16Mb in each */ +#define PAGES_IN_BANK_0 4096 +#define PAGES_IN_BANK_1 4096 +#define PAGES_IN_BANK_2 0 +#define PAGES_IN_BANK_3 0 + #else #error missing memory configuration #endif @@ -131,4 +153,5 @@ #endif /* macros not defined */ + diff -urN linux/arch/arm/special/Makefile new/arch/arm/special/Makefile --- linux/arch/arm/special/Makefile Tue Aug 10 17:24:25 1999 +++ new/arch/arm/special/Makefile Mon Jul 19 11:08:17 1999 @@ -23,7 +23,12 @@ KEYB_rpc := defkeymap-acorn.o KEYB_ebsa110 := KEYB_footbridge := defkeymap.o pc_keyb.o -KEYB_sa1100 := defkeymap-acorn.o keyb_brutus.o + +ifeq ($(CONFIG_SA1100_TIFON),y) + KEYB_sa1100 := defkeymap-tifon.o tifon_keyb.o +else + KEYB_sa1100 := defkeymap-acorn.o keyb_brutus.o +endif ifeq ($(MACHINE),arc) SOLD_$(CONFIG_SERIAL) += serial6850.o @@ -72,6 +77,12 @@ ifdef CONFIG_SA1100_VICTOR L_OBJS += audio-sa1100-ssp.o keyb_victor.o endif + +ifdef CONFIG_SA1100_TIFON + L_OBJS += audio-sa1100-mcp.o + LX_OBJS += mcp_common.o +endif + # Common dependencies diff -urN linux/arch/arm/special/audio-sa1100-mcp.c new/arch/arm/special/audio-sa1100-mcp.c --- linux/arch/arm/special/audio-sa1100-mcp.c Tue Aug 10 17:24:25 1999 +++ new/arch/arm/special/audio-sa1100-mcp.c Mon Aug 9 16:44:46 1999 @@ -1191,6 +1191,14 @@ audio_shared *shared, audio_io_dir io_dir) { +#ifdef CONFIG_SA1100_TIFON + // special tifon enable + GPDR |= 0x10; + GPCR = 0x10; + printk( "Audio hardware activated (GPDR=0x%x, GPSR=0x%x)\n", + GPDR, GPSR ); +#endif + /* initialize */ KOBJ_INIT(dev, audio_dev); diff -urN linux/arch/arm/special/defkeymap-tifon.c new/arch/arm/special/defkeymap-tifon.c --- linux/arch/arm/special/defkeymap-tifon.c Thu Jan 1 01:00:00 1970 +++ new/arch/arm/special/defkeymap-tifon.c Mon Jul 19 10:55:31 1999 @@ -0,0 +1,76 @@ + +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xfb6e, 0xf702, 0xf023, 0xf039, 0xf036, 0xf033, 0xf602, + 0xf07f, 0xf600, 0xf603, 0xf030, 0xf038, 0xf035, 0xf032, 0xf601, + 0xf700, 0xfb79, 0xf01b, 0xf02a, 0xf037, 0xf034, 0xf031, 0xf201, + 0xf02c, 0xf02e, 0xf040, 0xfb6d, 0xfb6c, 0xfb70, 0xf02b, 0xf02d, + 0xf03a, 0xf02f, 0xfb6e, 0xfb6b, 0xfb6f, 0xfb7a, 0xfb78, 0xfb63, + 0xfb76, 0xfb62, 0xfb6a, 0xfb69, 0xfb61, 0xfb73, 0xfb64, 0xfb66, + 0xfb67, 0xfb68, 0xfb75, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, + 0xfb79, 0xf020, 0xf009, 0xf03f, 0xf021, 0xf060, 0xf022, 0xf027, + 0xf0e5, 0xf03d, 0xf05f, 0xf03b, 0xf05c, 0xf20e, 0xfb75, 0xf0f6, + 0xf03e, 0xf05d, 0xf05b, 0xfb53, 0xf05e, 0xf07e, 0xf0e4, 0xf07c, + 0xf07d, 0xf07b, 0xf0a3, 0xf024, 0xf119, 0xf118, 0xf03c, 0xf028, + 0xf029, 0xf025, 0xf026, 0xf117, 0xf114, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +static u_short shift_map[NR_KEYS] = { + 0xf200, 0xfb4e, 0xf702, 0xf023, 0xf039, 0xf036, 0xf033, 0xf602, + 0xf07f, 0xf600, 0xf603, 0xf030, 0xf038, 0xf035, 0xf032, 0xf601, + 0xf700, 0xfb59, 0xf01b, 0xf02a, 0xf037, 0xf034, 0xf031, 0xf201, + 0xf02c, 0xf02e, 0xf040, 0xfb4d, 0xfb4c, 0xfb50, 0xf02b, 0xf02d, + 0xf03a, 0xf02f, 0xfb4e, 0xfb4b, 0xfb4f, 0xfb5a, 0xfb58, 0xfb43, + 0xfb56, 0xfb42, 0xfb4a, 0xfb49, 0xfb41, 0xfb53, 0xfb44, 0xfb46, + 0xfb47, 0xfb48, 0xfb55, 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, + 0xfb59, 0xf020, 0xf009, 0xf03f, 0xf021, 0xf060, 0xf022, 0xf027, + 0xf0c5, 0xf03d, 0xf05f, 0xf03b, 0xf05c, 0xf20e, 0xfb55, 0xf0d6, + 0xf03e, 0xf05d, 0xf05b, 0xfb73, 0xf05e, 0xf07e, 0xf0c4, 0xf07c, + 0xf07d, 0xf07b, 0xf0a3, 0xf024, 0xf119, 0xf118, 0xf03c, 0xf028, + 0xf029, 0xf025, 0xf026, 0xf117, 0xf114, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, 0 +}; + +unsigned int keymap_count = 2; + + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + 0 +}; + + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { +}; + +unsigned int accent_table_size = 0; diff -urN linux/arch/arm/special/defkeymap-tifon.map new/arch/arm/special/defkeymap-tifon.map --- linux/arch/arm/special/defkeymap-tifon.map Thu Jan 1 01:00:00 1970 +++ new/arch/arm/special/defkeymap-tifon.map Mon Jul 19 10:42:31 1999 @@ -0,0 +1,109 @@ +# Default tfon keymap. Uses no modifiers +# Written by: Stefan Hellkvist +# +# numerical mode +keycode 1 = n +keycode 2 = Control +keycode 3 = numbersign +keycode 4 = nine +keycode 5 = six +keycode 6 = three +keycode 7 = Right +keycode 8 = Delete +keycode 9 = Down +keycode 10 = Up +keycode 11 = zero +keycode 12 = eight +keycode 13 = five +keycode 14 = two +keycode 15 = Left +keycode 16 = Shift +keycode 17 = y +keycode 18 = Escape +keycode 19 = asterisk +keycode 20 = seven +keycode 21 = four +keycode 22 = one +# +# alpha mode +# +keycode 23 = Return +keycode 24 = comma +keycode 25 = period +keycode 26 = at +keycode 27 = m +keycode 28 = l +keycode 29 = p +keycode 30 = plus +keycode 31 = minus +keycode 32 = colon +keycode 33 = slash +keycode 34 = n +keycode 35 = k +keycode 36 = o +keycode 37 = z +keycode 38 = x +keycode 39 = c +keycode 40 = v +keycode 41 = b +keycode 42 = j +keycode 43 = i +keycode 44 = a +keycode 45 = s +keycode 46 = d +keycode 47 = f +keycode 48 = g +keycode 49 = h +keycode 50 = u +keycode 51 = q +keycode 52 = w +keycode 53 = e +keycode 54 = r +keycode 55 = t +keycode 56 = y +keycode 57 = space +# +# mouse mode +# +keycode 58 = Tab +keycode 59 = question +keycode 60 = exclam +keycode 61 = grave +keycode 62 = quotedbl +keycode 63 = apostrophe +keycode 64 = aring Aring +keycode 65 = equal +keycode 66 = underscore +keycode 67 = semicolon +keycode 68 = backslash +keycode 69 = Compose +keycode 70 = u +keycode 71 = odiaeresis Odiaeresis +keycode 72 = greater +keycode 73 = bracketright +keycode 74 = bracketleft +keycode 75 = S +keycode 76 = asciicircum +keycode 77 = asciitilde +keycode 78 = adiaeresis Adiaeresis +keycode 79 = bar +keycode 80 = braceright +keycode 81 = braceleft +keycode 82 = sterling +keycode 83 = dollar +keycode 84 = Next +keycode 85 = Prior +keycode 86 = less +keycode 87 = parenleft +keycode 88 = parenright +keycode 89 = percent +keycode 90 = ampersand +keycode 91 = Select +keycode 92 = Find + + + + + + + diff -urN linux/arch/arm/special/tifon_keyb.c new/arch/arm/special/tifon_keyb.c --- linux/arch/arm/special/tifon_keyb.c Thu Jan 1 01:00:00 1970 +++ new/arch/arm/special/tifon_keyb.c Mon Jul 19 17:16:15 1999 @@ -0,0 +1,440 @@ +/* + * linux/drivers/char/tfonkeyb.c + * + * Keyboard driver for tfon + * + * Author: Stefan Hellkvist + */ + +#define NEW_KEYBOARD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "tifon_keyb.h" + +#define DEBUG 1 + + +#ifndef Word +#define Word unsigned int +#endif + +#define N_COLS 3 +#define N_ROWS 6 +#define N_KEYS 55 + +// #define TIME_OUT (HZ / 4) /* 250 msec */ +#define TIME_OUT 1 /* really short time out :) */ + +#define KEY_PRESSED(row, col, bm) ((bm) & (0x0001 << ((col) * N_ROWS + (row)))) +#define IS_REAL_KEY(row, col) (!((row) % 2) && !((col) % 2)) +#define IS_REAL_COL(col) (!((col) % 2)) +#define IS_REAL_ROW(row) (!((row) % 2)) + +#define ENABLE_KEYB_IRQS() {int i; for(i=56; i<59; i++) enable_irq(i);} +#define DISABLE_KEYB_IRQS() {int i; for(i=56; i<59; i++) disable_irq(i);} + +static struct timer_list tfon_kbd_timer; +static int timer_started = 0; + +/* what is this used for? */ +unsigned char tfonkbd_sysrq_xlate[128]; + +static inline unsigned int read_keyb( void ); +static unsigned char translate_to_scancode( unsigned int state ); +extern void handle_scancode(unsigned char scancode); + +/* The mode the pad is in. This is also used by the touch pad driver */ +unsigned char stupidly_long_variable_name_for_shift_mode = ALPHA_MODE; + +/* The mapping to keycodes in the three modes */ +static unsigned char keys[3][N_KEYS] = { + { NO_KEY, CTRL_KEY, 3, 0, 4, 0, 5, 0, 6, 0, 0, + RIGHT_KEY, DELETE_KEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, + DOWN_KEY, UP_KEY, 11, 0, 12, 0, 13, 0, 14, 0, 0, + LEFT_KEY, SHIFT_KEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, + YES_KEY, ESCAPE_KEY, 19, 0, 20, 0, 21, 0, 22, 0, 0 }, + { NO_KEY, CTRL_KEY, 23, 24, 25, 26, 27, 28, 29, 0, 0, + RIGHT_KEY, DELETE_KEY, 30, 31, 32, 33, 34, 35, 36, 0, 0, + DOWN_KEY, UP_KEY, 37, 38, 39, 40, 41, 42, 43, 0, 0, + LEFT_KEY, SHIFT_KEY, 44, 45, 46, 47, 48, 49, 50, 0, 0, + YES_KEY, ESCAPE_KEY, 51, 52, 53, 54, 55, 56, 57, 0, 0 }, + { NO_KEY, CTRL_KEY, TAB_KEY, 59, 60, 61, 62, 63, 64, 0, 0, + RIGHT_KEY, DELETE_KEY, 65, 66, 67, 68, 69, 70, 71, 0, 0, + DOWN_KEY, UP_KEY, 72, 73, 74, 75, 76, 77, 78, 0, 0, + LEFT_KEY, SHIFT_KEY, 79, 80, 81, 82, 83, PGDN_KEY, PGUP_KEY, 0, 0, + YES_KEY, ESCAPE_KEY, 86, 87, 88, 89, 90, END_KEY, HOME_KEY, 0, 0 } +}; + + +/** + * timed_out + * Called after a short delay after the first interrupt of + * a keypress (the simulation of more keys than exists makes + * a simulated keypress consist of several real keypresses) + * This is where the actual reading and handling takes place + **/ +static void +timed_out( unsigned long ptr ) +{ + unsigned char scancode = translate_to_scancode( read_keyb() ); + +#ifdef DEBUG + printk( "tfonkeyb: Handling scancode: 0x%x\n", scancode ); +#endif + + handle_scancode(scancode); /* key goes down */ + /* handle_scancode(scancode | 0x80); */ /* key goes up again */ + timer_started = 0; + ENABLE_KEYB_IRQS(); +} + + +/** + * keyboard interrupt + * The handler for the sa1101 interrupt + * Note that it's only called on positive flanks (key pressed) + * I don't know if there is a way to get an interrupt on both + * flanks + **/ +static void +keyboard_interrupt( int irq, void *data, struct pt_regs *regs ) +{ + /* enques a timer to call timed_out after TIME_OUT jiffies + so that "simultaneous" keypresses can be detected + see page 149 in LDD for an example of enqueuing a timer */ + + printk( "keyboard_interrupt: irq = %d\n", irq ); + + DISABLE_KEYB_IRQS(); + if (!timer_started) + { + timer_started = 1; + init_timer( &tfon_kbd_timer ); + tfon_kbd_timer.function = timed_out; + tfon_kbd_timer.data = 0; + tfon_kbd_timer.expires = jiffies + TIME_OUT; + add_timer( &tfon_kbd_timer ); + } +} + + +/** + * issimulatedkeydown + * A simulated key is down if one of the alternatives below are true: + * 1) It's in a real column and the real key above and below are down + * 2) It's in a real row and real keys to the right and to the left are down + * 3) It's in a simulated column and row and all it's real key neighbours are + * down + **/ +static inline int +issimulatedkeydown( int row, int col, unsigned int bm ) +{ + /* If simulated key is in a real col then the key is "down" if + * the real keys above and below in the same col is down */ + if ( IS_REAL_COL( col ) ) + return KEY_PRESSED( (row - 1) >> 1, col >> 1, bm ) && + KEY_PRESSED( (row + 1) >> 1, col >> 1, bm ); + + /* If simulated key is in a real row then the key is "down" if + * the real keys to the right and to the left in the same row is down */ + if (IS_REAL_ROW(row)) + return KEY_PRESSED(row >> 1, (col - 1) >> 1, bm) && + KEY_PRESSED(row >> 1, (col + 1) >> 1, bm); + + /* It's a middle key. + * Middle keys are down if two real key neigbours form + * a diagonal across it */ + return (KEY_PRESSED((row - 1) >> 1, (col - 1) >> 1, bm) && + KEY_PRESSED((row + 1) >> 1, (col + 1) >> 1, bm)) || + (KEY_PRESSED((row - 1) >> 1, (col + 1) >> 1, bm) && + KEY_PRESSED((row + 1) >> 1, (col - 1) >> 1, bm)); +} + + +/** + * isrealkeydown + * A real key is down if the key is down and it's not part of a + * simulated keypress. + **/ +static inline int +isrealkeydown( int row, int col, unsigned int bm ) +{ + int rrow = row >> 1; + int rcol = col >> 1; + + return KEY_PRESSED(rrow, rcol, bm) && + (rrow == 0 || !KEY_PRESSED(rrow-1, rcol, bm)) && + (rrow == 2 || !KEY_PRESSED(rrow+1, rcol, bm)) && + (rcol == 0 || !KEY_PRESSED(rrow, rcol - 1, bm)) && + (rcol == 2 || !KEY_PRESSED(rrow, rcol + 1, bm)); +} + + +/** + * iskeydown + * Checks if a key is down in the simulated 10x5-keypad + * Args: row - The row to check + * col - The col to check + * bm - The bitmask as returned from read_keyb + * Returns: zero if not pressed, else non zero + **/ +static inline int +iskeydown( int row, int col, unsigned int bm ) +{ + if ( IS_REAL_KEY( row, col ) ) /* Is the key a real key? */ + return isrealkeydown( row, col, bm ); + return issimulatedkeydown( row, col, bm ); +} + + +#ifdef DEBUG + +static +void printKeypadStatus( unsigned int kpad ) +{ + int i, j; + printk( "tfonkeyb: keypad status is 0x%x\n", kpad ); + + for ( i = 0; i < N_ROWS; i++ ) + { + for ( j = 0; j < N_COLS; j++ ) + { + if ( kpad & ( 1 << ( i * N_COLS + j ) ) ) + printk( "X" ); + else + printk( "." ); + } + printk( "\n" ); + } + printk( "\n" ); +} + +#endif + + +/** + * read_keyb + * Reads the 6x3 keypad. No simulated key mambo-jumbo involved yet. + * Returns: a bit mask of which keys that are down, a 1 means key is down + * Bit mask format: + * | Column 2 | Column 1 | Column 0 | + * ____________________________________________________________________ + * | 31-18 unused |R5|R4|R3|R2|R1|R0|R5|R4|R3|R2|R1|RO|R5|R4|R3|R2|R1|R0| + * -------------------------------------------------------------------- + **/ +static inline unsigned int +read_keyb() +{ + unsigned int i, j, scancode = 0, bitindex = 0; + + // sa1101_keypad_test(); + + // DISABLE_KEYB_IRQS(); // disable interrupts since our reading will generate lots of'em + + for ( i = 0; i < N_ROWS; i++ ) + { + PXDWR = ~( 1 << i ); /* select which row to read */ + /* Must delay some here to allow value to propagate. How long? */ + udelay( 10 ); + for ( j = 0; j < N_COLS; j++ ) + { + unsigned ymask = ( 1 << j ); + // PYDWR = 0xfff8 | ymask; + // udelay( 5000 ); + if ( !( PYDRR & ymask ) ) /* read col j */ + { + scancode |= 1 << bitindex; +#ifdef DEBUG + printk( "Key down in row %d, column %d\n", i, j ); +#endif + } + bitindex++; + } + } + + +#ifdef DEBUG + printKeypadStatus( scancode ); +#endif + + PXDWR = 0; // set all X ports to output low again + PYDWR = 0xffff; // set all Y ports to input again + // ENABLE_KEYB_IRQS(); // enable interrupts again + return scancode; +} + + +/** + * translate_to_scancode + * Translates the keyboard state to a scancode + **/ +static unsigned char +translate_to_scancode( unsigned int state ) +{ + int i, j; + if ( state == 0 ) + return 0; + + for ( i = 0; i < 2 * N_ROWS - 1; i++ ) + for ( j = 0; j < 2 * N_COLS - 1; j++ ) + if ( iskeydown( i, j, state ) ) + { + if ( i == 10 ) /* is it a mode shift key? */ + /* yes, so set new mode */ + stupidly_long_variable_name_for_shift_mode = j >> 1; + + return (unsigned char) (i * (2 * N_COLS-1) + j + 1 ); + } + return 0; +} + + +/** + * tfonkbd_pretranslate + * Part of the interface to the keyboard driver + * Checks if a scancode is valid + **/ +int +tfonkbd_pretranslate( unsigned char scancode, char raw_mode ) +{ + if (scancode == 0) + return 0; + return 1; +} + + +/** + * tfonkbd_translate + * Part of the interface to the keyboard driver + * Translates the scancode to a keycode + **/ +int +kbd_drv_translate( unsigned char scancode, unsigned char *keycode, + char rawmode ) +{ + *keycode = keys[stupidly_long_variable_name_for_shift_mode][scancode & 0x7f]; + return 1; +} + + +/** + * tfonkbd_setkeycode + * Part of the interface to the keyboard driver + * Sets the keycode for a scancode. + * Note: The first 55 scancodes belongs to numerical mode, + * second 55 to alpha mode and the last 55 to mouse mode + **/ +int +tfonkbd_setkeycode( unsigned int scancode, unsigned int keycode ) +{ + if (scancode >= 3 * 55 || keycode > 92) + return -EINVAL; + keys[scancode / 55][scancode % 55] = keycode; + return 0; +} + + +/** + * tfonkbd_getkeycode + * Part of the interface to the keyboard driver + * Gets the keycode for a scancode + * Note: The first 55 scancodes belongs to numerical mode, + * second 55 to alpha mode and the last 55 to mouse mode + **/ +int +tfonkbd_getkeycode( unsigned int scancode ) +{ + return (scancode >= 3 * 55) ? -EINVAL : + keys[scancode / 55][scancode % 55]; +} + + +/** + * tfonkbd_init_hw + * Part of the interface to the keyboard driver + * Initializes the interrupt handling + **/ +void +kbd_drv_init(void) +{ + int irq; + + for ( irq = KPYIN0; irq <= KPYIN2; irq++ ) + { + if ( request_irq( irq, keyboard_interrupt, SA_INTERRUPT, "Keypad", NULL )) + { + printk(KERN_ERR "Can't get SA1101_IRQ (IRQ = %d).\n", irq); + return; + } + } + SKPCR &= ~0x40; + PYDWR = ~0; // set all Y ports to input + PXDWR = 0; // set all X ports to output low + printk( "Keypad driver initialized: INTPOL0 = 0x%x, SKPCR = 0x%x", INTPOL0, SKPCR ); +} + +/** + * tfonkbd_leds + * Part of the interface to the keyboard driver + * Does nothing yet since we don't have no leds + **/ +void +tfonkbd_leds( unsigned char leds ) +{ +} + + +/** + * tfonkbd_unexpected_up + * Part of the interface to the keyboard driver + * Haven't figured out what this does yet but I guess it doesn't apply + * to our touch pad + **/ +char +tfonkbd_unexpected_up( unsigned char keycode ) +{ + return 0200; +} + + + +/** + * kbd_disable_irq + * Part of the interface to the keyboard driver + * Should probably disable irq but that is not done yet + **/ +void +kbd_disable_irq( void ) +{ +} + + +/** + * kbd_enable_irq + * Part of the interface to the keyboard driver + * Should probably disable irq but that is not done yet + **/ +void +kbd_enable_irq( void ) +{ +} + diff -urN linux/arch/arm/special/tifon_keyb.h new/arch/arm/special/tifon_keyb.h --- linux/arch/arm/special/tifon_keyb.h Thu Jan 1 01:00:00 1970 +++ new/arch/arm/special/tifon_keyb.h Mon Jul 19 10:42:08 1999 @@ -0,0 +1,33 @@ +#ifndef TFONKEYB_H +#define TFONKEYB_H + +/* The mode the pad is in. This is also used by the touch pad driver */ +extern unsigned char stupidly_long_variable_name_for_shift_mode; + +/* the three modes of operation */ +#define NUM_MODE 0 +#define MOUSE_MODE 1 +#define ALPHA_MODE 2 + +/* some key definitions */ +#define NO_KEY 1 +#define YES_KEY 17 +#define CTRL_KEY 2 +#define RIGHT_KEY 7 +#define DELETE_KEY 8 +#define DOWN_KEY 9 +#define UP_KEY 10 +#define SHIFT_KEY 16 +#define ESCAPE_KEY 18 +#define LEFT_KEY 15 +#define RETURN_KEY 23 +#define SPACE_KEY 57 +#define TAB_KEY 58 +#define PGUP_KEY 85 +#define PGDN_KEY 84 +#define END_KEY 91 +#define HOME_KEY 92 + + + +#endif diff -urN linux/drivers/char/mem.c new/drivers/char/mem.c --- linux/drivers/char/mem.c Tue Aug 10 17:24:25 1999 +++ new/drivers/char/mem.c Mon Jul 12 14:59:18 1999 @@ -714,5 +714,18 @@ audio_sa1100_mcp_init(); } #endif +#ifdef CONFIG_SA1100_TIFON + { + extern int sa1100_mcp_common_init( void ); + extern int audio_sa1100_mcp_init( void ); + + sa1100_mcp_common_init(); + audio_sa1100_mcp_init(); + + /* add touchscreen driver */ + /* add touchpad driver */ + /* add button driver */ + } +#endif return 0; } diff -urN linux/drivers/char/serial_sa1100.c new/drivers/char/serial_sa1100.c --- linux/drivers/char/serial_sa1100.c Tue Aug 10 17:24:26 1999 +++ new/drivers/char/serial_sa1100.c Thu Jul 29 14:43:26 1999 @@ -160,6 +160,9 @@ #if defined( CONFIG_SA1100_BRUTUS ) { 0, BASE_BAUD, (unsigned long) &Ser1UTCR0, IRQ_Ser1UART, STD_COM_FLAGS }, { 0, BASE_BAUD, (unsigned long) &Ser3UTCR0, IRQ_Ser3UART, STD_COM_FLAGS } +#elif defined( CONFIG_SA1100_TIFON ) + { 0, BASE_BAUD, (unsigned long) &Ser1UTCR0, IRQ_Ser1UART, STD_COM_FLAGS }, + { 0, BASE_BAUD, (unsigned long) &Ser3UTCR0, IRQ_Ser3UART, STD_COM_FLAGS } #else { 0, BASE_BAUD, (unsigned long) &Ser3UTCR0, IRQ_Ser3UART, STD_COM_FLAGS }, { 0, BASE_BAUD, (unsigned long) &Ser1UTCR0, IRQ_Ser1UART, STD_COM_FLAGS } @@ -2361,6 +2364,11 @@ GPDR |= GPIO_GPIO14; GPDR &= ~GPIO_GPIO15; PPAR |= PPAR_UPR; +#elif defined( CONFIG_SA1100_TIFON ) + GAFR |= (GPIO_GPIO14 | GPIO_GPIO15); + GPDR |= GPIO_GPIO14; + GPDR &= ~GPIO_GPIO15; + PPAR |= PPAR_UPR; #else Ser1SDCR0 |= SDCR0_UART; #endif @@ -2392,6 +2400,7 @@ int i; struct serial_state * state; + printascii("in sa1100_rs_init\n"); init_bh(SERIAL_BH, do_serial_bh); timer_table[RS_TIMER].fn = rs_timer; timer_table[RS_TIMER].expires = 0; @@ -2646,7 +2655,7 @@ */ __initfunc(static int serial_console_setup(struct console *co, char *options)) { - + printascii("in serial_console_setup\n"); #if defined( CONFIG_SA1100_ARNOLD ) #warning("compiling for Arnold"); serial_echo_port= (unsigned long *)&Ser3UTCR0; @@ -2655,6 +2664,13 @@ serial_echo_port[UTCR1] = 0; /* 38400 baud */ serial_echo_port[UTCR2] = 0x5; serial_echo_port[UTCR3] = UTCR3_TXE; /* Turn on transmitter */ +#elif defined( CONFIG_SA1100_TIFON ) + serial_echo_port= (unsigned long *)&Ser3UTCR0; + serial_echo_port[UTCR3] = 0; /* Disable all interrupts for now */ + serial_echo_port[UTCR0] = 0x08; /* No parity, 8 bits, 1 stop */ + serial_echo_port[UTCR1] = 0; /* 9600 baud */ + serial_echo_port[UTCR2] = 0x17; + serial_echo_port[UTCR3] = UTCR3_TXE; /* Turn on transmitter */ #elif defined( CONFIG_SA1100_BRUTUS ) serial_echo_port = (unsigned long *)&Ser1UTCR0; /* set up for using alternate UART */ @@ -2805,7 +2821,11 @@ */ __initfunc (long serial_sa1100_console_init(long kmem_start, long kmem_end)) { + printascii("in serial_sa1100_console_init "); + printhex8(sercons.setup); + printascii("\n"); register_console(&sercons); + printascii("exit\n"); return kmem_start; } #endif diff -urN linux/drivers/net/smc9194.c new/drivers/net/smc9194.c --- linux/drivers/net/smc9194.c Thu Mar 11 01:51:35 1999 +++ new/drivers/net/smc9194.c Fri Jul 16 15:34:18 1999 @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ . smc9194.c - . This is a driver for SMC's 9000 series of Ethernet cards. + . This is a driver for SMC's 9000 series of Ethernet cards. . . Copyright (C) 1996 by Erik Stahlman . This software may be used and distributed according to the terms . of the GNU Public License, incorporated herein by reference. . - . "Features" of the SMC chip: - . 4608 byte packet memory. ( for the 91C92. Others have more ) + . "Features" of the SMC chip: + . 4608 byte packet memory. ( for the 91C92. Others have more ) . EEPROM for configuration . AUI/TP selection ( mine has 10Base2/10BaseT select ) . . Arguments: . io = for the base address - . irq = for the IRQ - . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 ) + . irq = for the IRQ + . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 ) . - . author: + . author: . Erik Stahlman ( erik@vt.edu ) - . + . . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) . . Sources: @@ -27,33 +27,33 @@ . o ( a LOT of advice from Becker as well ) . . History: - . 12/07/95 Erik Stahlman written, got receive/xmit handled + . 12/07/95 Erik Stahlman written, got receive/xmit handled . 01/03/96 Erik Stahlman worked out some bugs, actually usable!!! :-) - . 01/06/96 Erik Stahlman cleaned up some, better testing, etc + . 01/06/96 Erik Stahlman cleaned up some, better testing, etc . 01/29/96 Erik Stahlman fixed autoirq, added multicast . 02/01/96 Erik Stahlman 1. disabled all interrupts in smc_reset - . 2. got rid of post-decrementing bug -- UGH. + . 2. got rid of post-decrementing bug -- UGH. . 02/13/96 Erik Stahlman Tried to fix autoirq failure. Added more . descriptive error messages. . 02/15/96 Erik Stahlman Fixed typo that caused detection failure - . 02/23/96 Erik Stahlman Modified it to fit into kernel tree + . 02/23/96 Erik Stahlman Modified it to fit into kernel tree . Added support to change hardware address . Cleared stats on opens . 02/26/96 Erik Stahlman Trial support for Kernel 1.2.13 . Kludge for automatic IRQ detection - . 03/04/96 Erik Stahlman Fixed kernel 1.3.70 + - . Fixed bug reported by Gardner Buchanan in + . 03/04/96 Erik Stahlman Fixed kernel 1.3.70 + + . Fixed bug reported by Gardner Buchanan in . smc_enable, with outw instead of outb . 03/06/96 Erik Stahlman Added hardware multicast from Peter Cammaert ----------------------------------------------------------------------------*/ static const char *version = - "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; +"smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; #ifdef MODULE #include #include -#endif +#endif #include #include @@ -65,7 +65,7 @@ #include #include #include -#include +#include #include #include #include @@ -73,55 +73,196 @@ #include #include #include +#include #include "smc9194.h" + /*------------------------------------------------------------------------ - . - . Configuration options, for the experienced user to change. + . + . Configuration options, for the experienced user to change. . -------------------------------------------------------------------------*/ -/* - . this is for kernels > 1.2.70 + +/* PPP */ + +#define PCMCIA_IOBASE_V 0xe0000000 +#define PCMCIA_ATTRBASE_V 0xe8000000 +#define OSITECH_AUI_CTL 0x0c +#define OSITECH_PWRDOWN 0x0d +#define OSITECH_RESET 0x0e +#define OSITECH_ISR 0x0f +#define OSITECH_AUI_PWR 0x0c +#define OSITECH_RESET_ISR 0x0e + +#define OSI_AUI_PWR 0x40 +#define OSI_LAN_PWRDOWN 0x02 +#define OSI_MODEM_PWRDOWN 0x01 +#define OSI_LAN_RESET 0x02 +#define OSI_MODEM_RESET 0x01 + +#define ERICSSON + + + +/* + .the SMC9194 can be at any of the following port addresses. To change, + .for a slightly different card, you can add it to the array. Keep in + .mind that the array must end in zero. +*/ +static unsigned int smc_portlist[] = +/* { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, */ +{ 0x300,0, 0 }; +/* 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0}; */ + + +/* #define inb(adr) *(volatile unsigned char *)(PCMCIA_IOBASE_V+((adr))) + #define inw(adr) *(volatile unsigned short *)(PCMCIA_IOBASE_V+((adr))) + + #define outw(v,adr) *(volatile unsigned short *)(PCMCIA_IOBASE_V+((adr)))=v + #define outb(v,adr) *(volatile unsigned char *)(PCMCIA_IOBASE_V+((adr)))=v +*/ +#define SWAP(a) ((((a)&0xff00)>>8)|(((a)&0xff)<<8)) + +#define set_bits(v, p) outw(inw(p)|(v), (p)) +#define mask_bits(v, p) outw(inw(p)&(v), (p)) + + +/* Special function registers for Ositech cards */ +#define OSITECH_AUI_CTL 0x0c +#define OSITECH_PWRDOWN 0x0d +#define OSITECH_RESET 0x0e +#define OSITECH_ISR 0x0f +#define OSITECH_AUI_PWR 0x0c +#define OSITECH_RESET_ISR 0x0e + +#define OSI_AUI_PWR 0x40 +#define OSI_LAN_PWRDOWN 0x02 +#define OSI_MODEM_PWRDOWN 0x01 +#define OSI_LAN_RESET 0x02 +#define OSI_MODEM_RESET 0x01 +#define OSI_TECH 1 +#if 1 +static int pcmcia_attrbase=0; +static int pcmcia_manuid; +static int pcmcia_cardid; +#define PCMCIA_MANUID_OSITECH 0x140 +static void read_attr(void) +{ + // int ioaddr=smc_portlist[0]; + volatile unsigned char *attrib_space=(volatile unsigned char *)PCMCIA_ATTRBASE_V; + unsigned char buffer[256],*p; + int len; + while ( *attrib_space != 0xFF ) { /* Valid Tuple found */ + p=buffer; + *p++ = *attrib_space; attrib_space+=2; + *p++ = len = *attrib_space; attrib_space+=2; + while ( len > 0 ) { + *p++ = *attrib_space; + attrib_space+=2; + len--; + } + if( attrib_space > (volatile unsigned char *)(PCMCIA_ATTRBASE_V+0x8000)) + break; + + switch ( buffer[0] ) { + case 0x1a: /* Read Base offset */ + if ( buffer[1] == 5 ) { + pcmcia_attrbase = buffer[5]<<8 | buffer[4]; + } + break; + case 0x20: /* Manufactor id */ + if ( buffer[1] == 4 ) { + pcmcia_manuid= buffer[3]<<8 | buffer[2]; + pcmcia_cardid= buffer[5]<<8 | buffer[6]; + } + break; + } + } + if( pcmcia_manuid == PCMCIA_MANUID_OSITECH ) + pcmcia_attrbase=0x800; + else + pcmcia_attrbase=0x8000; +} +#endif + + + + + +static int pcmcia_enable_smc(void) +{ + short cor,chipid; + int ioaddr=smc_portlist[0]; + + + ioaddr=smc_portlist[0]; + // pcmcia_vddvpp( 5, 0); + udelay(1000); + + read_attr(); /* load base offset */ + + cor = *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase); + + *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase)=0x8080; + *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase)=0x8080; + udelay(1000); + + *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase)=0x4141; + *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase)=0x4141; + udelay(10000); + + *(volatile short *)(PCMCIA_ATTRBASE_V+pcmcia_attrbase+2)=0; + udelay(1000); + + if ( pcmcia_manuid == PCMCIA_MANUID_OSITECH ) + { + set_bits(0x300, (ioaddr + OSITECH_AUI_PWR)); + set_bits(0x300, (ioaddr + OSITECH_RESET_ISR)); + } + + SMC_SELECT_BANK( 3 ); + chipid = inw( ioaddr+REVISION); + printk("smc chip id/revision 0x%04x\n", (int) chipid&0xffff); + + return(chipid); +} + + + +/* + . this is for kernels > 1.2.70 */ -#define REALLY_NEW_KERNEL +#define REALLY_NEW_KERNEL #ifndef REALLY_NEW_KERNEL #define free_irq( x, y ) free_irq( x ) #define request_irq( x, y, z, u, v ) request_irq( x, y, z, u ) #endif /* - . Do you want to use this with old kernels. - . WARNING: this is not well tested. + . Do you want to use this with old kernels. + . WARNING: this is not well tested. #define SUPPORT_OLD_KERNEL */ /* . Do you want to use 32 bit xfers? This should work on all chips, as - . the chipset is designed to accommodate them. + . the chipset is designed to accommodate them. */ -#define USE_32_BIT 1 -/* - .the SMC9194 can be at any of the following port addresses. To change, - .for a slightly different card, you can add it to the array. Keep in - .mind that the array must end in zero. -*/ -static unsigned int smc_portlist[] __initdata = - { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, - 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0}; +/* #define USE_32_BIT 1 */ -/* - . Wait time for memory to be free. This probably shouldn't be - . tuned that much, as waiting for this means nothing else happens - . in the system +/* + . Wait time for memory to be free. This probably shouldn't be + . tuned that much, as waiting for this means nothing else happens + . in the system */ #define MEMORY_WAIT_TIME 16 /* . DEBUGGING LEVELS - . + . . 0 for normal operation . 1 for slightly more details . >2 for various levels of increasingly useless information @@ -131,13 +272,13 @@ #define SMC_DEBUG 0 #if (SMC_DEBUG > 2 ) -#define PRINTK3(x) printk x -#else -#define PRINTK3(x) +#define PRINTK3(x) printk x +#else +#define PRINTK3(x) #endif -#if SMC_DEBUG > 1 -#define PRINTK2(x) printk x +#if SMC_DEBUG > 1 +#define PRINTK2(x) printk x #else #define PRINTK2(x) #endif @@ -146,7 +287,7 @@ #define PRINTK(x) printk x #else #define PRINTK(x) -#endif +#endif /* the older versions of the kernel cannot support autoprobing */ @@ -157,53 +298,53 @@ /*------------------------------------------------------------------------ . - . The internal workings of the driver. If you are changing anything - . here with the SMC stuff, you should have the datasheet and known - . what you are doing. - . + . The internal workings of the driver. If you are changing anything + . here with the SMC stuff, you should have the datasheet and known + . what you are doing. + . -------------------------------------------------------------------------*/ #define CARDNAME "SMC9194" #ifdef SUPPORT_OLD_KERNEL char kernel_version[] = UTS_RELEASE; -#endif +#endif -/* store this information for the driver.. */ +/* store this information for the driver.. */ struct smc_local { - /* - these are things that the kernel wants me to keep, so users - can find out semi-useless statistics of how well the card is - performing - */ - struct net_device_stats stats; - - /* - If I have to wait until memory is available to send - a packet, I will store the skbuff here, until I get the - desired memory. Then, I'll send it out and free it. - */ - struct sk_buff * saved_skb; - - /* - . This keeps track of how many packets that I have - . sent out. When an TX_EMPTY interrupt comes, I know - . that all of these have been sent. - */ - int packets_waiting; + /* + these are things that the kernel wants me to keep, so users + can find out semi-useless statistics of how well the card is + performing + */ + struct enet_statistics stats; + + /* + If I have to wait until memory is available to send + a packet, I will store the skbuff here, until I get the + desired memory. Then, I'll send it out and free it. + */ + struct sk_buff * saved_skb; + + /* + . This keeps track of how many packets that I have + . sent out. When an TX_EMPTY interrupt comes, I know + . that all of these have been sent. + */ + int packets_waiting; }; /*----------------------------------------------------------------- . . The driver can be entered at any of the following entry points. - . + . .------------------------------------------------------------------ */ /* - . This is called by register_netdev(). It is responsible for - . checking the portlist for the SMC9000 series chipset. If it finds + . This is called by register_netdev(). It is responsible for + . checking the portlist for the SMC9000 series chipset. If it finds . one, then it will initialize the device, find the hardware information, - . and sets up the appropriate device parameters. + . and sets up the appropriate device parameters. . NOTE: Interrupts are *OFF* when this procedure is called. . . NB:This shouldn't be static since it is referred to externally. @@ -212,76 +353,76 @@ /* . The kernel calls this function when someone wants to use the device, - . typically 'ifconfig ethX up'. + . typically 'ifconfig ethX up'. */ static int smc_open(struct device *dev); /* . This is called by the kernel to send a packet out into the net. it's . responsible for doing a best-effort send, but if it's simply not possible - . to send it, the packet gets dropped. -*/ + . to send it, the packet gets dropped. +*/ static int smc_send_packet(struct sk_buff *skb, struct device *dev); -/* +/* . This is called by the kernel in response to 'ifconfig ethX down'. It - . is responsible for cleaning up everything that the open routine - . does, and maybe putting the card into a powerdown state. + . is responsible for cleaning up everything that the open routine + . does, and maybe putting the card into a powerdown state. */ static int smc_close(struct device *dev); /* - . This routine allows the proc file system to query the driver's - . statistics. + . This routine allows the proc file system to query the driver's + . statistics. */ -static struct net_device_stats * smc_query_statistics( struct device *dev); +static struct enet_statistics * smc_query_statistics( struct device *dev); /* - . Finally, a call to set promiscuous mode ( for TCPDUMP and related + . Finally, a call to set promiscuous mode ( for TCPDUMP and related . programs ) and multicast modes. */ #ifdef SUPPORT_OLD_KERNEL static void smc_set_multicast_list(struct device *dev, int num_addrs, - void *addrs); + void *addrs); #else static void smc_set_multicast_list(struct device *dev); -#endif +#endif /*--------------------------------------------------------------- - . - . Interrupt level calls.. + . + . Interrupt level calls.. . ----------------------------------------------------------------*/ /* - . Handles the actual interrupt + . Handles the actual interrupt */ #ifdef REALLY_NEW_KERNEL static void smc_interrupt(int irq, void *, struct pt_regs *regs); #else static void smc_interrupt(int irq, struct pt_regs *regs); -#endif +#endif /* . This is a separate procedure to handle the receipt of a packet, to - . leave the interrupt code looking slightly cleaner -*/ + . leave the interrupt code looking slightly cleaner +*/ inline static void smc_rcv( struct device *dev ); /* . This handles a TX interrupt, which is only called when an error - . relating to a packet is sent. + . relating to a packet is sent. */ inline static void smc_tx( struct device * dev ); /* ------------------------------------------------------------ - . + . . Internal routines . ------------------------------------------------------------ */ /* - . Test if a given location contains a chip, trying to cause as + . Test if a given location contains a chip, trying to cause as . little damage as possible if it's not a SMC chip. */ static int smc_probe( int ioaddr ); @@ -289,26 +430,26 @@ /* . this routine initializes the cards hardware, prints out the configuration . to the system log as well as the vanity message, and handles the setup - . of a device parameter. + . of a device parameter. . It will give an error if it can't initialize the card. */ -static int smc_initcard( struct device *, int ioaddr ); +static int smc_initcard( struct device *, int ioaddr ); /* . A rather simple routine to print out a packet for debugging purposes. -*/ -#if SMC_DEBUG > 2 +*/ +#if SMC_DEBUG > 2 static void print_packet( byte *, int ); -#endif +#endif #define tx_done(dev) 1 -/* this is called to actually send the packet to the chip */ +/* this is called to actually send the packet to the chip */ static void smc_hardware_send_packet( struct device * dev ); /* Since I am not sure if I will have enough room in the chip's ram - . to store the packet, I call this routine, which either sends it - . now, or generates an interrupt when the card is ready for the + . to store the packet, I call this routine, which either sends it + . now, or generates an interrupt when the card is ready for the . packet */ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device *dev ); @@ -328,7 +469,7 @@ #endif /* - this routine will set the hardware multicast table to the specified + this routine will set the hardware multicast table to the specified values given it by the higher level routines */ #ifndef SUPPORT_OLD_KERNEL @@ -338,201 +479,196 @@ #ifdef SUPPORT_OLD_KERNEL extern struct device *init_etherdev(struct device *dev, int sizeof_private, - unsigned long *mem_startp ); -#endif + unsigned long *mem_startp ); +#endif /* . Function: smc_reset( int ioaddr ) . Purpose: . This sets the SMC91xx chip to its normal state, hopefully from whatever - . mess that any other DOS driver has put it in. - . + . mess that any other DOS driver has put it in. + . . Maybe I should reset more registers to defaults in here? SOFTRESET should - . do that for me. - . + . do that for me. + . . Method: - . 1. send a SOFT RESET + . 1. send a SOFT RESET . 2. wait for it to finish . 3. enable autorelease mode . 4. reset the memory management unit . 5. clear all interrupts . -*/ -static void smc_reset( int ioaddr ) -{ - /* This resets the registers mostly to defaults, but doesn't - affect EEPROM. That seems unnecessary */ - SMC_SELECT_BANK( 0 ); - outw( RCR_SOFTRESET, ioaddr + RCR ); - +*/ +static void smc_reset( int ioaddr ) +{ + /* This resets the registers mostly to defaults, but doesn't + affect EEPROM. That seems unnecessary */ + SMC_SELECT_BANK( 0 ); + outw( RCR_SOFTRESET, ioaddr + RCR ); + /* this should pause enough for the chip to be happy */ - SMC_DELAY( ); + SMC_DELAY( ); - /* Set the transmit and receive configuration registers to + /* Set the transmit and receive configuration registers to default values */ - outw( RCR_CLEAR, ioaddr + RCR ); - outw( TCR_CLEAR, ioaddr + TCR ); + outw( RCR_CLEAR, ioaddr + RCR ); + outw( TCR_CLEAR, ioaddr + TCR ); /* set the control register to automatically - release successfully transmitted packets, to make the best + release successfully transmitted packets, to make the best use out of our limited memory */ - SMC_SELECT_BANK( 1 ); - outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL ); + SMC_SELECT_BANK( 1 ); + outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL ); /* Reset the MMU */ - SMC_SELECT_BANK( 2 ); - outw( MC_RESET, ioaddr + MMU_CMD ); + SMC_SELECT_BANK( 2 ); + outw( MC_RESET, ioaddr + MMU_CMD ); - /* Note: It doesn't seem that waiting for the MMU busy is needed here, + /* Note: It doesn't seem that waiting for the MMU busy is needed here, but this is a place where future chipsets _COULD_ break. Be wary of issuing another MMU command right after this */ - outb( 0, ioaddr + INT_MASK ); + outb( 0, ioaddr + INT_MASK ); } -/* +/* . Function: smc_enable . Purpose: let the chip talk to the outside work - . Method: + . Method: . 1. Enable the transmitter . 2. Enable the receiver . 3. Enable interrupts */ -static void smc_enable( int ioaddr ) +static void smc_enable( int ioaddr ) { - SMC_SELECT_BANK( 0 ); - /* see the header file for options in TCR/RCR NORMAL*/ - outw( TCR_NORMAL, ioaddr + TCR ); - outw( RCR_NORMAL, ioaddr + RCR ); - - /* now, enable interrupts */ - SMC_SELECT_BANK( 2 ); - outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK ); -} - + SMC_SELECT_BANK( 0 ); + /* see the header file for options in TCR/RCR NORMAL*/ + outw( TCR_NORMAL, ioaddr + TCR ); + outw( RCR_NORMAL, ioaddr + RCR ); + + /* now, enable interrupts */ + SMC_SELECT_BANK( 2 ); + outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK ); +} + /* . Function: smc_shutdown . Purpose: closes down the SMC91xxx chip. - . Method: + . Method: . 1. zero the interrupt mask . 2. clear the enable receive flag . 3. clear the enable xmit flags . - . TODO: + . TODO: . (1) maybe utilize power down mode. . Why not yet? Because while the chip will go into power down mode, . the manual says that it will wake up in response to any I/O requests . in the register space. Empirical results do not show this working. */ -static void smc_shutdown( int ioaddr ) +static void smc_shutdown( int ioaddr ) { - /* no more interrupts for me */ - SMC_SELECT_BANK( 2 ); - outb( 0, ioaddr + INT_MASK ); - - /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK( 0 ); - outb( RCR_CLEAR, ioaddr + RCR ); - outb( TCR_CLEAR, ioaddr + TCR ); -#if 0 - /* finally, shut the chip down */ - SMC_SELECT_BANK( 1 ); - outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL ); -#endif + /* no more interrupts for me */ + SMC_SELECT_BANK( 2 ); + outb( 0, ioaddr + INT_MASK ); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK( 0 ); + outb( RCR_CLEAR, ioaddr + RCR ); + outb( TCR_CLEAR, ioaddr + TCR ); } -#ifndef SUPPORT_OLD_KERNEL -/* +#ifndef SUPPORT_OLD_KERNEL +/* . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) . Purpose: . This sets the internal hardware table to filter out unwanted multicast - . packets before they take up memory. - . + . packets before they take up memory. + . . The SMC chip uses a hash table where the high 6 bits of the CRC of - . address are the offset into the table. If that bit is 1, then the + . address are the offset into the table. If that bit is 1, then the . multicast packet is accepted. Otherwise, it's dropped silently. - . + . . To use the 6 bits as an offset into the table, the high 3 bits are the . number of the 8 bit register, while the low 3 bits are the bit within . that register. . - . This routine is based very heavily on the one provided by Peter Cammaert. + . This routine is based very heavily on the one provided by Peter Cammaert. */ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) { - int i; - unsigned char multicast_table[ 8 ]; - struct dev_mc_list * cur_addr; - /* table for flipping the order of 3 bits */ - unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - - /* start with a table of all zeros: reject all */ - memset( multicast_table, 0, sizeof( multicast_table ) ); - - cur_addr = addrs; - for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { - int position; - - /* do we have a pointer here? */ - if ( !cur_addr ) - break; - /* make sure this is a multicast address - shouldn't this - be a given if we have it here ? */ - if ( !( *cur_addr->dmi_addr & 1 ) ) - continue; - - /* only use the low order bits */ - position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; - - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert3[position&7]] |= - (1<>3)&7]); - - } - /* now, the table can be loaded into the chipset */ - SMC_SELECT_BANK( 3 ); - - for ( i = 0; i < 8 ; i++ ) { - outb( multicast_table[i], ioaddr + MULTICAST1 + i ); - } + int i; + unsigned char multicast_table[ 8 ]; + struct dev_mc_list * cur_addr; + /* table for flipping the order of 3 bits */ + unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + /* start with a table of all zeros: reject all */ + memset( multicast_table, 0, sizeof( multicast_table ) ); + + cur_addr = addrs; + for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { + int position; + + /* do we have a pointer here? */ + if ( !cur_addr ) + break; + /* make sure this is a multicast address - shouldn't this + be a given if we have it here ? */ + if ( !( *cur_addr->dmi_addr & 1 ) ) + continue; + + /* only use the low order bits */ + position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert3[position&7]] |= + (1<>3)&7]); + + } + /* now, the table can be loaded into the chipset */ + SMC_SELECT_BANK( 3 ); + + for ( i = 0; i < 8 ; i++ ) { + outb( multicast_table[i], ioaddr + MULTICAST1 + i ); + } } /* Finds the CRC32 of a set of bytes. - Again, from Peter Cammaert's code. + Again, from Peter Cammaert's code. */ -static int crc32( char * s, int length ) { - /* indices */ - int perByte; - int perBit; - /* crc polynomial for Ethernet */ - const unsigned long poly = 0xedb88320; - /* crc value - preinitialized to all 1's */ - unsigned long crc_value = 0xffffffff; - - for ( perByte = 0; perByte < length; perByte ++ ) { - unsigned char c; - - c = *(s++); - for ( perBit = 0; perBit < 8; perBit++ ) { - crc_value = (crc_value>>1)^ - (((crc_value^c)&0x01)?poly:0); - c >>= 1; - } - } - return crc_value; -} - -#endif - - -/* - . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) - . Purpose: +static int crc32( char * s, int length ) { + /* indices */ + int perByte; + int perBit; + /* crc polynomial for Ethernet */ + const unsigned long poly = 0xedb88320; + /* crc value - preinitialized to all 1's */ + unsigned long crc_value = 0xffffffff; + + for ( perByte = 0; perByte < length; perByte ++ ) { + unsigned char c; + + c = *(s++); + for ( perBit = 0; perBit < 8; perBit++ ) { + crc_value = (crc_value>>1)^ + (((crc_value^c)&0x01)?poly:0); + c >>= 1; + } + } + return crc_value; +} + +#endif + + +/* + . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) + . Purpose: . Attempt to allocate memory for a packet, if chip-memory is not - . available, then tell the card to generate an interrupt when it + . available, then tell the card to generate an interrupt when it . is available. . . Algorithm: @@ -540,718 +676,773 @@ . o if the saved_skb is not currently null, then drop this packet . on the floor. This should never happen, because of TBUSY. . o if the saved_skb is null, then replace it with the current packet, - . o See if I can sending it now. + . o See if I can sending it now. . o (NO): Enable interrupts and let the interrupt handler deal with it. . o (YES):Send it now. */ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev ) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - unsigned short ioaddr = dev->base_addr; - word length; - unsigned short numPages; - word time_out; - - if ( lp->saved_skb) { - /* THIS SHOULD NEVER HAPPEN. */ - lp->stats.tx_aborted_errors++; - printk(CARDNAME": Bad Craziness - sent packet while busy.\n" ); - return 1; - } - lp->saved_skb = skb; - - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - /* - . the MMU wants the number of pages to be the number of 256 bytes - . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) - */ - numPages = length / 256; - - if (numPages > 7 ) { - printk(CARDNAME": Far too big packet error. \n"); - /* freeing the packet is a good thing here... but should - . any packets of this size get down here? */ - dev_kfree_skb (skb); - lp->saved_skb = NULL; - /* this IS an error, but, i don't want the skb saved */ - return 0; - } - /* either way, a packet is waiting now */ - lp->packets_waiting++; - - /* now, try to allocate the memory */ - SMC_SELECT_BANK( 2 ); - outw( MC_ALLOC | numPages, ioaddr + MMU_CMD ); - /* - . Performance Hack - . - . wait a short amount of time.. if I can send a packet now, I send - . it now. Otherwise, I enable an interrupt and wait for one to be - . available. - . - . I could have handled this a slightly different way, by checking to - . see if any memory was available in the FREE MEMORY register. However, - . either way, I need to generate an allocation, and the allocation works - . no matter what, so I saw no point in checking free memory. - */ - time_out = MEMORY_WAIT_TIME; - do { - word status; - - status = inb( ioaddr + INTERRUPT ); - if ( status & IM_ALLOC_INT ) { - /* acknowledge the interrupt */ - outb( IM_ALLOC_INT, ioaddr + INTERRUPT ); - break; - } - } while ( -- time_out ); - - if ( !time_out ) { - /* oh well, wait until the chip finds memory later */ - SMC_ENABLE_INT( IM_ALLOC_INT ); - PRINTK2((CARDNAME": memory allocation deferred. \n")); - /* it's deferred, but I'll handle it later */ - return 0; - } - /* or YES! I can send the packet now.. */ - smc_hardware_send_packet(dev); - - return 0; -} +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned short ioaddr = dev->base_addr; + word length; + unsigned short numPages; + word time_out; + + if ( lp->saved_skb) { + /* THIS SHOULD NEVER HAPPEN. */ + lp->stats.tx_aborted_errors++; + printk(CARDNAME": Bad Craziness - sent packet while busy.\n" ); + return 1; + } + lp->saved_skb = skb; + + length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + + /* + . the MMU wants the number of pages to be the number of 256 bytes + . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + */ + numPages = length / 256; + + if (numPages > 7 ) { + printk(CARDNAME": Far too big packet error. \n"); + /* freeing the packet is a good thing here... but should + . any packets of this size get down here? */ + dev_kfree_skb (skb); + lp->saved_skb = NULL; + /* this IS an error, but, i don't want the skb saved */ + return 0; + } + /* either way, a packet is waiting now */ + lp->packets_waiting++; + + /* now, try to allocate the memory */ + SMC_SELECT_BANK( 2 ); + outw( MC_ALLOC | numPages, ioaddr + MMU_CMD ); + /* + . Performance Hack + . + . wait a short amount of time.. if I can send a packet now, I send + . it now. Otherwise, I enable an interrupt and wait for one to be + . available. + . + . I could have handled this a slightly different way, by checking to + . see if any memory was available in the FREE MEMORY register. However, + . either way, I need to generate an allocation, and the allocation works + . no matter what, so I saw no point in checking free memory. + */ + time_out = MEMORY_WAIT_TIME; + + do { + //word status; + byte status; // changed by stefan + status = inb( ioaddr + INTERRUPT ); + if ( status & IM_ALLOC_INT ) { + /* acknowledge the interrupt */ + outb( IM_ALLOC_INT, ioaddr + INTERRUPT ); + break; + } + } while ( -- time_out ); + + + if ( !time_out ) { + /* oh well, wait until the chip finds memory later */ + SMC_ENABLE_INT( IM_ALLOC_INT ); + PRINTK2((CARDNAME": memory allocation deferred. \n")); + /* it's deferred, but I'll handle it later */ + return 0; + } + /* or YES! I can send the packet now.. */ + smc_hardware_send_packet(dev); + + return 0; +} /* . Function: smc_hardware_send_packet(struct device * ) - . Purpose: - . This sends the actual packet to the SMC9xxx chip. - . + . Purpose: + . This sends the actual packet to the SMC9xxx chip. + . . Algorithm: - . First, see if a saved_skb is available. + . First, see if a saved_skb is available. . ( this should NOT be called if there is no 'saved_skb' . Now, find the packet number that the chip allocated - . Point the data pointers at it in memory + . Point the data pointers at it in memory . Set the length word in the chip's memory . Dump the packet to chip memory . Check if a last byte is needed ( odd length packet ) - . if so, set the control flag right - . Tell the card to send it + . if so, set the control flag right + . Tell the card to send it . Enable the transmit interrupt, so I know if it failed . Free the kernel data if I actually sent it. */ -static void smc_hardware_send_packet( struct device * dev ) +static void smc_hardware_send_packet( struct device * dev ) { - struct smc_local *lp = (struct smc_local *)dev->priv; - byte packet_no; - struct sk_buff * skb = lp->saved_skb; - word length; - unsigned short ioaddr; - byte * buf; - - ioaddr = dev->base_addr; - - if ( !skb ) { - PRINTK((CARDNAME": In XMIT with no packet to send \n")); - return; - } - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - buf = skb->data; - - /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = inb( ioaddr + PNR_ARR + 1 ); - if ( packet_no & 0x80 ) { - /* or isn't there? BAD CHIP! */ - printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n"); - kfree(skb); - lp->saved_skb = NULL; - dev->tbusy = 0; - return; - } - - /* we have a packet address, so tell the card to use it */ - outb( packet_no, ioaddr + PNR_ARR ); + struct smc_local *lp = (struct smc_local *)dev->priv; + byte packet_no; + struct sk_buff * skb = lp->saved_skb; + word length; + unsigned short ioaddr; + byte * buf; + + + ioaddr = dev->base_addr; + + if ( !skb ) { + PRINTK((CARDNAME": In XMIT with no packet to send \n")); + return; + } + length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + buf = skb->data; + + /* If I get here, I _know_ there is a packet slot waiting for me */ + packet_no = inb( ioaddr + PNR_ARR + 1 ); /* INB WORKS ??????? */ + if ( packet_no & 0x80 ) { + /* or isn't there? BAD CHIP! */ + printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n"); + printk("smc91c94 hardware_send_packet %x FREE 0x%x\n", packet_no,(int) skb); + dev_kfree_skb(skb); + lp->saved_skb = NULL; + dev->tbusy = 0; + return; + } + /* we have a packet address, so tell the card to use it */ + outw( packet_no, ioaddr + PNR_ARR ); - /* point to the beginning of the packet */ - outw( PTR_AUTOINC , ioaddr + POINTER ); + /* point to the beginning of the packet */ + outw( PTR_AUTOINC , ioaddr + POINTER ); - PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length )); + PRINTK3((CARDNAME": Trying to xmit packet of length 0x%x\n", length )); #if SMC_DEBUG > 2 - print_packet( buf, length ); + print_packet( buf, length ); #endif - /* send the packet length ( +6 for status, length and ctl byte ) - and the status word ( set to zeros ) */ + /* send the packet length ( +6 for status, length and ctl byte ) + and the status word ( set to zeros ) */ #ifdef USE_32_BIT - outl( (length +6 ) << 16 , ioaddr + DATA_1 ); + outl( (length +6 ) << 16 , ioaddr + DATA_1 ); #else - outw( 0, ioaddr + DATA_1 ); - /* send the packet length ( +6 for status words, length, and ctl*/ - outb( (length+6) & 0xFF,ioaddr + DATA_1 ); - outb( (length+6) >> 8 , ioaddr + DATA_1 ); -#endif - - /* send the actual data - . I _think_ it's faster to send the longs first, and then - . mop up by sending the last word. It depends heavily - . on alignment, at least on the 486. Maybe it would be - . a good idea to check which is optimal? But that could take - . almost as much time as is saved? - */ -#ifdef USE_32_BIT - if ( length & 0x2 ) { - outsl(ioaddr + DATA_1, buf, length >> 2 ); - outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); - } - else - outsl(ioaddr + DATA_1, buf, length >> 2 ); + outw( 0, ioaddr + DATA_1 ); + /* send the packet length ( +6 for status words, length, and ctl*/ + outw( (length+6), ioaddr + DATA_1 ); + /* + outb( (length+6) & 0xFF,ioaddr + DATA_1 ); + outb( (length+6) >> 8 , ioaddr + DATA_1 ); + */ +#endif + + /* send the actual data + . I _think_ it's faster to send the longs first, and then + . mop up by sending the last word. It depends heavily + . on alignment, at least on the 486. Maybe it would be + . a good idea to check which is optimal? But that could take + . almost as much time as is saved? + */ +#ifdef USE_32_BIT + if ( length & 0x2 ) { + outsl(ioaddr + DATA_1, buf, length >> 2 ); + outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); + } + else + outsl(ioaddr + DATA_1, buf, length >> 2 ); #else - outsw(ioaddr + DATA_1 , buf, (length ) >> 1); + outsw(ioaddr + DATA_1 , buf, (length ) >> 1); #endif - /* Send the last byte, if there is one. */ + /* Send the last byte, if there is one. */ +#if 1 + /* The odd last byte, if there is one, goes in the control word. */ + outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1 ); +#else + if ( (length & 1) == 0 ) { + outw( 0, ioaddr + DATA_1 ); + } else { + outb( buf[length -1 ], ioaddr + DATA_1 ); + outb( 0x20, ioaddr + DATA_1); + } +#endif + /* enable the interrupts */ + SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) ); - if ( (length & 1) == 0 ) { - outw( 0, ioaddr + DATA_1 ); - } else { - outb( buf[length -1 ], ioaddr + DATA_1 ); - outb( 0x20, ioaddr + DATA_1); - } + /* and let the chipset deal with it */ + outw( MC_ENQUEUE , ioaddr + MMU_CMD ); + + PRINTK2((CARDNAME": Sent packet of length 0x%x \n",length)); - /* enable the interrupts */ - SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) ); - /* and let the chipset deal with it */ - outw( MC_ENQUEUE , ioaddr + MMU_CMD ); +#ifdef ARNOLD + PRINTK2((CARDNAME " GPLVL 0x%08x GPDR 0x%08x GAFR 0x%08x GEDR 0x%08x GFER 0x%08x \n", + *(volatile unsigned long *)GPLR, + *(volatile unsigned long *)GPDR, + *(volatile unsigned long *)GAFR, + *(volatile unsigned long *)GEDR, + *(volatile unsigned long *)GFER + )); +#endif - PRINTK2((CARDNAME": Sent packet of length %d \n",length)); + lp->saved_skb = NULL; - lp->saved_skb = NULL; - dev_kfree_skb (skb); + /* printk("smc91c94 hardware_send_packet FREE 0x%x\n", (int) skb); */ + dev_kfree_skb (skb); - dev->trans_start = jiffies; + dev->trans_start = jiffies; - /* we can send another packet */ - dev->tbusy = 0; + /* we can send another packet */ + dev->tbusy = 0; - return; + return; } /*------------------------------------------------------------------------- | - | smc_init( struct device * dev ) - | Input parameters: + | smc_init( struct device * dev ) + | Input parameters: | dev->base_addr == 0, try to find all possible locations | dev->base_addr == 1, return failure code | dev->base_addr == 2, always allocate space, and return success - | dev->base_addr == this is the address to check + | dev->base_addr == this is the address to check | - | Output: + | Output: | 0 --> there is a device - | anything else, error - | + | anything else, error + | --------------------------------------------------------------------------- -*/ -__initfunc(int smc_init(struct device *dev)) +*/ +int smc_init(struct device *dev) { - int i; - int base_addr = dev ? dev->base_addr : 0; - - /* try a specific location */ - if (base_addr > 0x1ff) { - int error; - error = smc_probe(base_addr); - if ( 0 == error ) { - return smc_initcard( dev, base_addr ); - } - return error; - } else { - if ( 0 != base_addr ) { - return -ENXIO; - } - } - - /* check every ethernet address */ - for (i = 0; smc_portlist[i]; i++) { - int ioaddr = smc_portlist[i]; - - /* check if the area is available */ - if (check_region( ioaddr , SMC_IO_EXTENT)) - continue; - - /* check this specific address */ - if ( smc_probe( ioaddr ) == 0) { - return smc_initcard( dev, ioaddr ); - } - } + int i; + int base_addr = dev ? dev->base_addr : 0; - /* couldn't find anything */ - return -ENODEV; + /* try a specific location */ + if (base_addr > 0x1ff) { + int error; + error = smc_probe(base_addr); + if ( 0 == error ) { + return smc_initcard( dev, base_addr ); + } + return error; + } else { + if ( 0 != base_addr ) { + return -ENXIO; + } + } + /*printk("Searching SMC91C94\n");*/ +#if 1 + /* check every ethernet address */ + for (i = 0; smc_portlist[i]; i++) { + int ioaddr = smc_portlist[i]; + + /* check if the area is available */ + if (check_region( ioaddr , SMC_IO_EXTENT)) + continue; + + /* check this specific address */ + if ( smc_probe( ioaddr ) == 0) { + return smc_initcard( dev, ioaddr ); + } + } +#endif + /* couldn't find anything */ + return -ENODEV; } #ifndef NO_AUTOPROBE /*---------------------------------------------------------------------- - . smc_findirq - . - . This routine has a simple purpose -- make the SMC chip generate an + . smc_findirq + . + . This routine has a simple purpose -- make the SMC chip generate an . interrupt, so an auto-detect routine can detect it, and find the IRQ, ------------------------------------------------------------------------ */ -__initfunc(int smc_findirq( int ioaddr )) +int smc_findirq( int ioaddr ) { - int timeout = 20; - - - /* I have to do a STI() here, because this is called from - a routine that does an CLI during this process, making it - rather difficult to get interrupts for auto detection */ - sti(); - - autoirq_setup( 0 ); - - /* - * What I try to do here is trigger an ALLOC_INT. This is done - * by allocating a small chunk of memory, which will give an interrupt - * when done. - */ - - - SMC_SELECT_BANK(2); - /* enable ALLOCation interrupts ONLY */ - outb( IM_ALLOC_INT, ioaddr + INT_MASK ); + int timeout = 20; - /* - . Allocate 512 bytes of memory. Note that the chip was just - . reset so all the memory is available - */ - outw( MC_ALLOC | 1, ioaddr + MMU_CMD ); - /* - . Wait until positive that the interrupt has been generated - */ - while ( timeout ) { - byte int_status; + /* I have to do a STI() here, because this is called from + a routine that does an CLI during this process, making it + rather difficult to get interrupts for auto detection */ + sti(); + + autoirq_setup( 0 ); + + /* + * What I try to do here is trigger an ALLOC_INT. This is done + * by allocating a small chunk of memory, which will give an interrupt + * when done. + */ + + + SMC_SELECT_BANK(2); + /* enable ALLOCation interrupts ONLY */ + outb( IM_ALLOC_INT, ioaddr + INT_MASK ); + + /* + . Allocate 512 bytes of memory. Note that the chip was just + . reset so all the memory is available + */ + outw( MC_ALLOC | 1, ioaddr + MMU_CMD ); + + /* + . Wait until positive that the interrupt has been generated + */ + while ( timeout ) { + byte int_status; + + int_status = inb( ioaddr + INTERRUPT ); + + if ( int_status & IM_ALLOC_INT ) + break; /* got the interrupt */ + timeout--; + } + /* there is really nothing that I can do here if timeout fails, + as autoirq_report will return a 0 anyway, which is what I + want in this case. Plus, the clean up is needed in both + cases. */ + + /* DELAY HERE! + On a fast machine, the status might change before the interrupt + is given to the processor. This means that the interrupt was + never detected, and autoirq_report fails to report anything. + This should fix autoirq_* problems. + */ + SMC_DELAY(); + SMC_DELAY(); + + /* and disable all interrupts again */ + outb( 0, ioaddr + INT_MASK ); + + /* clear hardware interrupts again, because that's how it + was when I was called... */ + cli(); - int_status = inb( ioaddr + INTERRUPT ); - - if ( int_status & IM_ALLOC_INT ) - break; /* got the interrupt */ - timeout--; - } - /* there is really nothing that I can do here if timeout fails, - as autoirq_report will return a 0 anyway, which is what I - want in this case. Plus, the clean up is needed in both - cases. */ - - /* DELAY HERE! - On a fast machine, the status might change before the interrupt - is given to the processor. This means that the interrupt was - never detected, and autoirq_report fails to report anything. - This should fix autoirq_* problems. - */ - SMC_DELAY(); - SMC_DELAY(); - - /* and disable all interrupts again */ - outb( 0, ioaddr + INT_MASK ); - - /* clear hardware interrupts again, because that's how it - was when I was called... */ - cli(); - - /* and return what I found */ - return autoirq_report( 0 ); + /* and return what I found */ + return autoirq_report( 0 ); } #endif - + /*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) - . - . Purpose: + . + . Purpose: . Tests to see if a given ioaddr points to an SMC9xxx chip. - . Returns a 0 on success - . + . Returns a 0 on success + . . Algorithm: . (1) see if the high byte of BANK_SELECT is 0x33 . (2) compare the ioaddr with the base register's address . (3) see if I recognize the chip ID in the appropriate register - . + . .--------------------------------------------------------------------- - */ + */ -__initfunc(static int smc_probe( int ioaddr )) +static int smc_probe( int ioaddr ) { - unsigned int bank; - word revision_register; - word base_address_register; - - /* First, see if the high byte is 0x33 */ - bank = inw( ioaddr + BANK_SELECT ); - if ( (bank & 0xFF00) != 0x3300 ) { - return -ENODEV; - } - /* The above MIGHT indicate a device, but I need to write to further - test this. */ - outw( 0x0, ioaddr + BANK_SELECT ); - bank = inw( ioaddr + BANK_SELECT ); - if ( (bank & 0xFF00 ) != 0x3300 ) { - return -ENODEV; - } - /* well, we've already written once, so hopefully another time won't - hurt. This time, I need to switch the bank register to bank 1, - so I can access the base address register */ - SMC_SELECT_BANK(1); - base_address_register = inw( ioaddr + BASE ); - if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) { - printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)." - "Probably not a SMC chip\n", - ioaddr, base_address_register >> 3 & 0x3E0 ); - /* well, the base address register didn't match. Must not have - been a SMC chip after all. */ - return -ENODEV; - } - - /* check if the revision register is something that I recognize. - These might need to be added to later, as future revisions - could be added. */ - SMC_SELECT_BANK(3); - revision_register = inw( ioaddr + REVISION ); - if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) { - /* I don't recognize this chip, so... */ - printk(CARDNAME ": IO %x: Unrecognized revision register:" - " %x, Contact author. \n", ioaddr, revision_register ); - - return -ENODEV; - } - - /* at this point I'll assume that the chip is an SMC9xxx. - It might be prudent to check a listing of MAC addresses - against the hardware address, or do some other tests. */ - return 0; + unsigned int bank; + word revision_register; + word base_address_register; + + if(( pcmcia_enable_smc() & 0xff00) != 0x3300 ) + return -ENODEV; + + /* First, see if the high byte is 0x33 */ + bank = inw( ioaddr + BANK_SELECT ); + if ( (bank & 0xFF00) != 0x3300 ) { + return -ENODEV; + } + /* The above MIGHT indicate a device, but I need to write to further + test this. */ + outw( 0x0, ioaddr + BANK_SELECT ); + bank = inw( ioaddr + BANK_SELECT ); + if ( (bank & 0xFF00 ) != 0x3300 ) { + return -ENODEV; + } + /* well, we've already written once, so hopefully another time won't + hurt. This time, I need to switch the bank register to bank 1, + so I can access the base address register */ + SMC_SELECT_BANK(1); + base_address_register = inw( ioaddr + BASE ); + + if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) { + printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)." + "Probably not a SMC chip\n", + ioaddr, base_address_register >> 3 & 0x3E0 ); + /* well, the base address register didn't match. Must not have + been a SMC chip after all. */ + return -ENODEV; + } + + /* check if the revision register is something that I recognize. + These might need to be added to later, as future revisions + could be added. */ + SMC_SELECT_BANK(3); + revision_register = inw( ioaddr + REVISION ); + if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) { + /* I don't recognize this chip, so... */ + printk(CARDNAME ": IO %x: Unrecognized revision register:" + " %x, Contact author. \n", ioaddr, revision_register ); + + return -ENODEV; + } + + /* at this point I'll assume that the chip is an SMC9xxx. + It might be prudent to check a listing of MAC addresses + against the hardware address, or do some other tests. */ + return 0; } /*--------------------------------------------------------------- - . Here I do typical initialization tasks. - . + . Here I do typical initialization tasks. + . . o Initialize the structure if needed . o print out my vanity message if not done so already . o print out what type of hardware is detected . o print out the ethernet address - . o find the IRQ - . o set up my private data + . o find the IRQ + . o set up my private data . o configure the dev structure with my subroutines . o actually GRAB the irq. - . o GRAB the region + . o GRAB the region .----------------------------------------------------------------- */ -__initfunc(static int smc_initcard(struct device *dev, int ioaddr)) +static int smc_initcard(struct device *dev, int ioaddr) { - int i; + int i; - static unsigned version_printed = 0; + static unsigned version_printed = 0; - /* registers */ - word revision_register; - word configuration_register; - word memory_info_register; - word memory_cfg_register; + /* registers */ + word revision_register; + word configuration_register; + word memory_info_register; + word memory_cfg_register; - const char * version_string; - const char * if_string; - int memory; + const char * version_string; + const char * if_string; + int memory; + // int if_port; - int irqval; + int irqval; - /* see if I need to initialize the ethernet card structure */ - if (dev == NULL) { + /* see if I need to initialize the ethernet card structure */ + if (dev == NULL) { #ifdef SUPPORT_OLD_KERNEL #ifndef MODULE -/* note: the old module interface does not support this call */ - dev = init_etherdev( 0, sizeof( struct smc_local ), 0 ); -#endif + /* note: the old module interface does not support this call */ + dev = init_etherdev( 0, sizeof( struct smc_local ), 0 ); +#endif #else - dev = init_etherdev(0, 0); -#endif - if (dev == NULL) - return -ENOMEM; - } - - if (version_printed++ == 0) - printk("%s", version); - - /* fill in some of the fields */ - dev->base_addr = ioaddr; - - /* - . Get the MAC address ( bank 1, regs 4 - 9 ) - */ - SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) { - word address; - - address = inw( ioaddr + ADDR0 + i ); - dev->dev_addr[ i + 1] = address >> 8; - dev->dev_addr[ i ] = address & 0xFF; - } - - /* get the memory information */ - - SMC_SELECT_BANK( 0 ); - memory_info_register = inw( ioaddr + MIR ); - memory_cfg_register = inw( ioaddr + MCR ); - memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */ - memory *= 256 * ( memory_info_register & 0xFF ); - - /* - Now, I want to find out more about the chip. This is sort of - redundant, but it's cleaner to have it in both, rather than having - one VERY long probe procedure. - */ - SMC_SELECT_BANK(3); - revision_register = inw( ioaddr + REVISION ); - version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ]; - if ( !version_string ) { - /* I shouldn't get here because this call was done before.... */ - return -ENODEV; - } - - /* is it using AUI or 10BaseT ? */ - if ( dev->if_port == 0 ) { - SMC_SELECT_BANK(1); - configuration_register = inw( ioaddr + CONFIG ); - if ( configuration_register & CFG_AUI_SELECT ) - dev->if_port = 2; - else - dev->if_port = 1; - } - if_string = interfaces[ dev->if_port - 1 ]; - - /* now, reset the chip, and put it into a known state */ - smc_reset( ioaddr ); - - /* - . If dev->irq is 0, then the device has to be banged on to see - . what the IRQ is. - . - . This banging doesn't always detect the IRQ, for unknown reasons. - . a workaround is to reset the chip and try again. - . - . Interestingly, the DOS packet driver *SETS* the IRQ on the card to - . be what is requested on the command line. I don't do that, mostly - . because the card that I have uses a non-standard method of accessing - . the IRQs, and because this _should_ work in most configurations. - . - . Specifying an IRQ is done with the assumption that the user knows - . what (s)he is doing. No checking is done!!!! - . - */ -#ifndef NO_AUTOPROBE - if ( dev->irq < 2 ) { - int trials; - - trials = 3; - while ( trials-- ) { - dev->irq = smc_findirq( ioaddr ); - if ( dev->irq ) - break; - /* kick the card and try again */ - smc_reset( ioaddr ); - } - } - if (dev->irq == 0 ) { - printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n"); - return -ENODEV; - } + dev = init_etherdev(0, 0); +#endif + if (dev == NULL) + return -ENOMEM; + } + + if (version_printed++ == 0) + printk("%s", version); + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + + /* + . Get the MAC address ( bank 1, regs 4 - 9 ) + */ + SMC_SELECT_BANK( 1 ); + // HACK ! IP -addr fixed and wrong ?? + { + volatile char *attrib_space=(volatile char *)PCMCIA_ATTRBASE_V; + char buffer[256],*p; + int len; + while ( *attrib_space != 0xFF ) { /* Valid Tuple found */ + p=buffer; + *p++ = *attrib_space; attrib_space+=2; + *p++ = len = *attrib_space; attrib_space+=2; + while ( len > 0 ) { + *p++ = *attrib_space; + attrib_space+=2; + len--; + } + switch ( buffer[0] ) { + case 0x15: /* Vendor ID */ + for(len=4;len < buffer[1];len++ ) { + if ( buffer[len] != 0 ) + printk("%c",buffer[len]); + else{ + printk(" "); + } + } + + break; + case 0x22: + if ( buffer[1]!= 8 ) break; + if ( buffer[2]!= 4 ) break; + if ( buffer[3]!= 6 ) break; /* 6 Byte */ + + outw( (buffer[5])<<8|buffer[4], ioaddr + ADDR0 + 0 ); + outw( (buffer[7])<<8|buffer[6], ioaddr + ADDR0 + 2 ); + outw( (buffer[9])<<8|buffer[8], ioaddr + ADDR0 + 4 ); + break; + } + } + } + printk("\n"); + for ( i = 0; i < 6; i += 2 ) { + word address; + + address = inw( ioaddr + ADDR0 + i ); + dev->dev_addr[ i + 1] = address >> 8; + dev->dev_addr[ i ] = address & 0xFF; + } + + /* get the memory information */ + + SMC_SELECT_BANK( 0 ); + memory_info_register = inw( ioaddr + MIR ); + memory_cfg_register = inw( ioaddr + MCR ); + memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */ + memory *= 256 * ( memory_info_register & 0xFF ); + + /* + Now, I want to find out more about the chip. This is sort of + redundant, but it's cleaner to have it in both, rather than having + one VERY long probe procedure. + */ + SMC_SELECT_BANK(3); + revision_register = inw( ioaddr + REVISION ); + version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ]; + if ( !version_string ) { + /* I shouldn't get here because this call was done before.... */ + return -ENODEV; + } + + /* is it using AUI or 10BaseT ? */ + if ( dev->if_port == 0 ) { + SMC_SELECT_BANK(1); + configuration_register = inw( ioaddr + CONFIG ); + if ( configuration_register & CFG_AUI_SELECT ) + dev->if_port = 2; + else + dev->if_port = 1; + } + if_string = interfaces[ dev->if_port - 1 ]; +#define CFG_16BIT 0x0080 + + /* now, reset the chip, and put it into a known state */ + smc_reset( ioaddr ); + + /* + . If dev->irq is 0, then the device has to be banged on to see + . what the IRQ is. + . + . This banging doesn't always detect the IRQ, for unknown reasons. + . a workaround is to reset the chip and try again. + . + . Interestingly, the DOS packet driver *SETS* the IRQ on the card to + . be what is requested on the command line. I don't do that, mostly + . because the card that I have uses a non-standard method of accessing + . the IRQs, and because this _should_ work in most configurations. + . + . Specifying an IRQ is done with the assumption that the user knows + . what (s)he is doing. No checking is done!!!! + . + */ +#ifndef ERICSSON + dev->irq = 1; #else - if (dev->irq == 0 ) { - printk(CARDNAME - ": Autoprobing IRQs is not supported for old kernels.\n"); - return -ENODEV; - } + dev->irq = 89; #endif - if (dev->irq == 2) { - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - * or don't know which one to set. - */ - dev->irq = 9; - } - /* now, print out the card info, in a short format.. */ - - printk(CARDNAME ": %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", - version_string, revision_register & 0xF, ioaddr, dev->irq, - if_string, memory ); - /* - . Print the Ethernet address - */ - printk("ADDR: "); - for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i] ); - printk("%2.2x \n", dev->dev_addr[5] ); - - - /* Initialize the private structure. */ - if (dev->priv == NULL) { - dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - } - /* set the private data to zero by default */ - memset(dev->priv, 0, sizeof(struct smc_local)); - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - /* Grab the IRQ */ - irqval = request_irq(dev->irq, &smc_interrupt, 0, CARDNAME, dev); - if (irqval) { - printk(CARDNAME": unable to get IRQ %d (irqval=%d).\n", - dev->irq, irqval); - return -EAGAIN; - } - - /* Grab the region so that no one else tries to probe our ioports. */ - request_region(ioaddr, SMC_IO_EXTENT, CARDNAME); - - dev->open = smc_open; - dev->stop = smc_close; - dev->hard_start_xmit = smc_send_packet; - dev->get_stats = smc_query_statistics; + /* now, print out the card info, in a short format.. */ + + printk(CARDNAME ": %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", + version_string, revision_register & 0xF, ioaddr, dev->irq, + if_string, memory ); + /* + . Print the Ethernet address + */ + printk("ADDR: "); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i] ); + printk("%2.2x \n", dev->dev_addr[5] ); + + + /* Initialize the private structure. */ + if (dev->priv == NULL) { + dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + } + /* set the private data to zero by default */ + memset(dev->priv, 0, sizeof(struct smc_local)); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + /* Grab the region so that no one else tries to probe our ioports. */ + request_region(ioaddr, SMC_IO_EXTENT, CARDNAME); + + dev->open = smc_open; + dev->stop = smc_close; + dev->hard_start_xmit = smc_send_packet; + dev->get_stats = smc_query_statistics; #ifdef HAVE_MULTICAST - dev->set_multicast_list = &smc_set_multicast_list; + dev->set_multicast_list = &smc_set_multicast_list; #endif + /* Grab the IRQ */ + // irq2dev_map[dev->irq] = dev; + + /* SA1100 specific patch Keith 19.5.99 */ - return 0; + SMC_SELECT_BANK( 2 ); + outb( 0, ioaddr + INT_MASK ); + + //irqval = request_irq(dev->irq, &smc_interrupt, 0, CARDNAME, dev); + // uncomented by Stefan, replaced with line below + irqval = request_irq(dev->irq, &smc_interrupt, SA_INTERRUPT, CARDNAME, dev); + + if (irqval) { + printk(CARDNAME": unable to get IRQ %d (irqval=%d).\n", + dev->irq, irqval); + return -EAGAIN; + } + + outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK ); + /*printk(CARDNAME": GPIO LVL 0x%08x\n", *(volatile unsigned long *)GPLR );*/ + + + return 0; } #if SMC_DEBUG > 2 -static void print_packet( byte * buf, int length ) -{ -#if 0 - int i; - int remainder; - int lines; - - printk("Packet of length %d \n", length ); - lines = length / 16; - remainder = length % 16; - - for ( i = 0; i < lines ; i ++ ) { - int cur; - - for ( cur = 0; cur < 8; cur ++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printk("%02x%02x ", a, b ); - } - printk("\n"); - } - for ( i = 0; i < remainder/2 ; i++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printk("%02x%02x ", a, b ); - } - printk("\n"); +static void print_packet( byte * buf, int length ) +{ +#if 1 + int i; + int remainder; + int lines; + + printk("Packet of length %d \n", length ); + lines = length / 16; + remainder = length % 16; + + for ( i = 0; i < lines ; i ++ ) { + int cur; + + for ( cur = 0; cur < 8; cur ++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + printk("%02x%02x ", a, b ); + } + printk("\n"); + } + for ( i = 0; i < remainder/2 ; i++ ) { + byte a, b; + + a = *(buf ++ ); + b = *(buf ++ ); + printk("%02x%02x ", a, b ); + } + printk("\n"); #endif } -#endif +#endif /* * Open and Initialize the board - * + * * Set up everything, reset the card, etc .. * */ static int smc_open(struct device *dev) { - int ioaddr = dev->base_addr; + int ioaddr = dev->base_addr; - int i; /* used to set hw ethernet address */ + int i; /* used to set hw ethernet address */ - /* clear out all the junk that was put here before... */ - memset(dev->priv, 0, sizeof(struct smc_local)); + /* clear out all the junk that was put here before... */ + memset(dev->priv, 0, sizeof(struct smc_local)); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; #ifdef MODULE - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; #endif - /* reset the hardware */ - - smc_reset( ioaddr ); - smc_enable( ioaddr ); + /* reset the hardware */ - /* Select which interface to use */ + smc_reset( ioaddr ); + smc_enable( ioaddr ); - SMC_SELECT_BANK( 1 ); - if ( dev->if_port == 1 ) { - outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT, - ioaddr + CONFIG ); - } - else if ( dev->if_port == 2 ) { - outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT, - ioaddr + CONFIG ); - } - - /* - According to Becker, I have to set the hardware address - at this point, because the (l)user can set it with an - ioctl. Easily done... - */ - SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) { - word address; - - address = dev->dev_addr[ i + 1 ] << 8 ; - address |= dev->dev_addr[ i ]; - outw( address, ioaddr + ADDR0 + i ); - } - return 0; + /* Select which interface to use */ + + SMC_SELECT_BANK( 1 ); + if ( dev->if_port == 1 ) { + outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT, + ioaddr + CONFIG ); + } + else if ( dev->if_port == 2 ) { + outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT, + ioaddr + CONFIG ); + } + + /* + According to Becker, I have to set the hardware address + at this point, because the (l)user can set it with an + ioctl. Easily done... + */ + SMC_SELECT_BANK( 1 ); + for ( i = 0; i < 6; i += 2 ) { + word address; + + address = dev->dev_addr[ i + 1 ] << 8 ; + address |= dev->dev_addr[ i ]; + outw( address, ioaddr + ADDR0 + i ); + } + return 0; } /*-------------------------------------------------------- . Called by the kernel to send a packet out into the void - . of the net. This routine is largely based on - . skeleton.c, from Becker. + . of the net. This routine is largely based on + . skeleton.c, from Becker. .-------------------------------------------------------- */ static int smc_send_packet(struct sk_buff *skb, struct device *dev) { - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n", - tx_done(dev) ? "IRQ conflict" : - "network cable problem"); - /* "kick" the adaptor */ - smc_reset( dev->base_addr ); - smc_enable( dev->base_addr ); - - dev->tbusy = 0; - dev->trans_start = jiffies; - /* clear anything saved */ - ((struct smc_local *)dev->priv)->saved_skb = NULL; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n"); - dev_kfree_skb (skb); - } else { - /* Well, I want to send the packet.. but I don't know - if I can send it right now... */ - return smc_wait_to_send_packet( skb, dev ); - } - return 0; + if (dev->tbusy) { + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5) + return 1; + printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n", + tx_done(dev) ? "IRQ conflict" : + "network cable problem"); + /* "kick" the adaptor */ + smc_reset( dev->base_addr ); + smc_enable( dev->base_addr ); + + dev->tbusy = 0; + dev->trans_start = jiffies; + /* clear anything saved */ + ((struct smc_local *)dev->priv)->saved_skb = NULL; + } + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n"); + dev_kfree_skb (skb); + } else { + /* Well, I want to send the packet.. but I don't know + if I can send it right now... */ + return smc_wait_to_send_packet( skb, dev ); + } + return 0; } /*-------------------------------------------------------------------- @@ -1261,145 +1452,151 @@ . . So: . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge + . branch off into routines to handle each case, and acknowledge . each to the interrupt register - . and finally restore state. - . + . and finally restore state. + . ---------------------------------------------------------------------*/ + #ifdef REALLY_NEW_KERNEL static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -#else -static void smc_interrupt(int irq, struct pt_regs * regs) -#endif +#else + static void smc_interrupt(int irq, struct pt_regs * regs) +#endif { - struct device *dev = dev_id; - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - - byte status; - word card_stats; - byte mask; - int timeout; - /* state registers */ - word saved_bank; - word saved_pointer; - - - - PRINTK3((CARDNAME": SMC interrupt started \n")); - - if (dev == NULL) { - printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n", - irq); - return; - } - -/* will Linux let this happen ?? If not, this costs some speed */ - if ( dev->interrupt ) { - printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n"); - return; - } - - dev->interrupt = 1; - - saved_bank = inw( ioaddr + BANK_SELECT ); - - SMC_SELECT_BANK(2); - saved_pointer = inw( ioaddr + POINTER ); - - mask = inb( ioaddr + INT_MASK ); - /* clear all interrupts */ - outb( 0, ioaddr + INT_MASK ); - - - /* set a timeout value, so I don't stay here forever */ - timeout = 4; - - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); - do { - /* read the status flag, and mask it */ - status = inb( ioaddr + INTERRUPT ) & mask; - if (!status ) - break; - - PRINTK3((KERN_WARNING CARDNAME - ": Handling interrupt status %x \n", status )); - - if (status & IM_RCV_INT) { - /* Got a packet(s). */ - PRINTK2((KERN_WARNING CARDNAME - ": Receive Interrupt\n")); - smc_rcv(dev); - } else if (status & IM_TX_INT ) { - PRINTK2((KERN_WARNING CARDNAME - ": TX ERROR handled\n")); - smc_tx(dev); - outb(IM_TX_INT, ioaddr + INTERRUPT ); - } else if (status & IM_TX_EMPTY_INT ) { - /* update stats */ - SMC_SELECT_BANK( 0 ); - card_stats = inw( ioaddr + COUNTER ); - /* single collisions */ - lp->stats.collisions += card_stats & 0xF; - card_stats >>= 4; - /* multiple collisions */ - lp->stats.collisions += card_stats & 0xF; - - /* these are for when linux supports these statistics */ -#if 0 - card_stats >>= 4; - /* deferred */ - card_stats >>= 4; - /* excess deferred */ -#endif - SMC_SELECT_BANK( 2 ); - PRINTK2((KERN_WARNING CARDNAME - ": TX_BUFFER_EMPTY handled\n")); - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); - mask &= ~IM_TX_EMPTY_INT; - lp->stats.tx_packets += lp->packets_waiting; - lp->packets_waiting = 0; - - } else if (status & IM_ALLOC_INT ) { - PRINTK2((KERN_DEBUG CARDNAME - ": Allocation interrupt \n")); - /* clear this interrupt so it doesn't happen again */ - mask &= ~IM_ALLOC_INT; - - smc_hardware_send_packet( dev ); - - /* enable xmit interrupts based on this */ - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); - - /* and let the card send more packets to me */ - mark_bh( NET_BH ); - - PRINTK2((CARDNAME": Handoff done successfully.\n")); - } else if (status & IM_RX_OVRN_INT ) { - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); - } else if (status & IM_EPH_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); - } else if (status & IM_ERCV_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); - outb( IM_ERCV_INT, ioaddr + INTERRUPT ); - } - } while ( timeout -- ); - - - /* restore state register */ - SMC_SELECT_BANK( 2 ); - outb( mask, ioaddr + INT_MASK ); - - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); - outw( saved_pointer, ioaddr + POINTER ); - - SMC_SELECT_BANK( saved_bank ); - - dev->interrupt = 0; - PRINTK3((CARDNAME ": Interrupt done\n")); - return; + struct device *dev = dev_id; + int ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + + byte status; + word card_stats; + byte mask; + int timeout; + /* state registers */ + word saved_bank; + word saved_pointer; + + + PRINTK3((CARDNAME": SMC interrupt started \n")); + + if (dev == NULL) { + printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n", + irq); + /* disable_irq( irq); */ /* Wichtig sonst immer und immer wieder ! */ + return; + } + + /* will Linux let this happen ?? If not, this costs some speed */ + if ( dev->interrupt ) { + printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n"); + return; + } + + dev->interrupt = 1; + + saved_bank = inw( ioaddr + BANK_SELECT ); + + SMC_SELECT_BANK(2); + saved_pointer = inw( ioaddr + POINTER ); + + mask = inb( ioaddr + INT_MASK ); + /* clear all interrupts */ + outb( 0, ioaddr + INT_MASK ); + + + /* set a timeout value, so I don't stay here forever */ + timeout = 4; + + PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); + do { + /* read the status flag, and mask it */ + status = inb( ioaddr + INTERRUPT ) & mask; + if (!status ) + break; + + PRINTK3((KERN_WARNING CARDNAME + ": Handling interrupt status %x \n", status )); + + if (status & IM_RCV_INT) { + /* Got a packet(s). */ + PRINTK2((KERN_WARNING CARDNAME + ": Receive Interrupt\n")); + smc_rcv(dev); + } else if (status & IM_TX_INT ) { + PRINTK2((KERN_WARNING CARDNAME + ": TX ERROR handled\n")); + smc_tx(dev); + outb(IM_TX_INT, ioaddr + INTERRUPT ); + } else if (status & IM_TX_EMPTY_INT ) { + /* update stats */ + SMC_SELECT_BANK( 0 ); + card_stats = inw( ioaddr + COUNTER ); + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + + /* these are for when linux supports these statistics */ + SMC_SELECT_BANK( 2 ); + PRINTK2((KERN_WARNING CARDNAME + ": TX_BUFFER_EMPTY handled\n")); + outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); + mask &= ~IM_TX_EMPTY_INT; + lp->stats.tx_packets += lp->packets_waiting; + lp->packets_waiting = 0; + + } else if (status & IM_ALLOC_INT ) { + PRINTK2((KERN_DEBUG CARDNAME + ": Allocation interrupt \n")); + /* clear this interrupt so it doesn't happen again */ + mask &= ~IM_ALLOC_INT; + + smc_hardware_send_packet( dev ); + + /* enable xmit interrupts based on this */ + mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); + + /* and let the card send more packets to me */ + mark_bh( NET_BH ); + + PRINTK2((CARDNAME": Handoff done successfully.\n")); + } else if (status & IM_RX_OVRN_INT ) { + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); + } else if (status & IM_EPH_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); + } else if (status & IM_ERCV_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); + outb( IM_ERCV_INT, ioaddr + INTERRUPT ); + } + } while ( timeout -- ); + +#if 1 + if ( pcmcia_manuid == PCMCIA_MANUID_OSITECH ) + { /* Retrigger interrupt if needed */ + mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR); + set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR); + } +#endif + +#ifdef ARNOLD + /* restore state register */ + *(volatile unsigned long *)GEDR |= 2; +#endif + + SMC_SELECT_BANK( 2 ); + outb( mask, ioaddr + INT_MASK ); + + PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); + outw( saved_pointer, ioaddr + POINTER ); + + SMC_SELECT_BANK( saved_bank ); + + dev->interrupt = 0; + PRINTK3((CARDNAME ": Interrupt done\n")); + return; } /*------------------------------------------------------------- @@ -1408,207 +1605,214 @@ . . There is ( at least ) a packet waiting to be read from . chip-memory. - . - . o Read the status - . o If an error, record it - . o otherwise, read in the packet + . + . o Read the status + . o If an error, record it + . o otherwise, read in the packet -------------------------------------------------------------- */ -static void smc_rcv(struct device *dev) +void smc_rcv(struct device *dev) { - struct smc_local *lp = (struct smc_local *)dev->priv; - int ioaddr = dev->base_addr; - int packet_number; - word status; - word packet_length; - - /* assume bank 2 */ - - packet_number = inw( ioaddr + FIFO_PORTS ); - - if ( packet_number & FP_RXEMPTY ) { - /* we got called , but nothing was on the FIFO */ - PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n")); - /* don't need to restore anything */ - return; - } - - /* start reading from the start of the packet */ - outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER ); + struct smc_local *lp = (struct smc_local *)dev->priv; + int ioaddr = dev->base_addr; + int packet_number; + word status; + word packet_length; + + /* assume bank 2 */ + + packet_number = inw( ioaddr + FIFO_PORTS ); + + if ( packet_number & FP_RXEMPTY ) { + /* we got called , but nothing was on the FIFO */ + PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n")); + /* don't need to restore anything */ + return; + } + + /* start reading from the start of the packet */ + outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER ); + + /* First two words are status and packet_length */ + status = inw( ioaddr + DATA_1 ); + packet_length = inw( ioaddr + DATA_1 ); + + packet_length &= 0x07ff; /* mask off top bits */ + + PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length )); + /* + . the packet length contains 3 extra words : + . status, length, and a extra word with an odd byte . + */ +#if 1 +#define RS_ODDFRAME 0x1000 - /* First two words are status and packet_length */ - status = inw( ioaddr + DATA_1 ); - packet_length = inw( ioaddr + DATA_1 ); - - packet_length &= 0x07ff; /* mask off top bits */ - - PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length )); - /* - . the packet length contains 3 extra words : - . status, length, and an extra word with an odd byte . - */ - packet_length -= 6; - - if ( !(status & RS_ERRORS ) ){ - /* do stuff to make a new packet */ - struct sk_buff * skb; - byte * data; - - /* read one extra byte */ - if ( status & RS_ODDFRAME ) - packet_length++; - - /* set multicast stats */ - if ( status & RS_MULTICAST ) - lp->stats.multicast++; + packet_length -= (status & RS_ODDFRAME ? 5 : 6); +#else + packet_length -= 6; +#endif + if ( !(status & RS_ERRORS ) ){ + /* do stuff to make a new packet */ + struct sk_buff * skb; + byte * data; + + /* read one extra byte */ + if ( status & RS_ODDFRAME ) + packet_length++; + + /* set multicast stats */ + if ( status & RS_MULTICAST ) + lp->stats.multicast++; #ifdef SUPPORT_OLD_KERNEL - skb = alloc_skb( packet_length + 5, GFP_ATOMIC ); -#else - skb = dev_alloc_skb( packet_length + 5); + skb = alloc_skb( packet_length + 5, GFP_ATOMIC ); +#else + skb = dev_alloc_skb( packet_length + 5); #endif - if ( skb == NULL ) { - printk(KERN_NOTICE CARDNAME - ": Low memory, packet dropped.\n"); - lp->stats.rx_dropped++; - } - - /* - ! This should work without alignment, but it could be - ! in the worse case - */ + if ( skb == NULL ) { + printk(KERN_NOTICE CARDNAME + ": Low memory, packet dropped.\n"); + lp->stats.rx_dropped++; + } + + /* + ! This should work without alignment, but it could be + ! in the worse case + */ #ifndef SUPPORT_OLD_KERNEL - /* TODO: Should I use 32bit alignment here ? */ - skb_reserve( skb, 2 ); /* 16 bit alignment */ + /* TODO: Should I use 32bit alignment here ? */ + skb_reserve( skb, 2 ); /* 16 bit alignment */ #endif - skb->dev = dev; + skb->dev = dev; #ifdef SUPPORT_OLD_KERNEL - skb->len = packet_length; - data = skb->data; + skb->len = packet_length; + data = skb->data; #else - data = skb_put( skb, packet_length); + data = skb_put( skb, packet_length); #endif -#ifdef USE_32_BIT - /* QUESTION: Like in the TX routine, do I want - to send the DWORDs or the bytes first, or some - mixture. A mixture might improve already slow PIO - performance */ - PRINTK3((" Reading %d dwords (and %d bytes) \n", - packet_length >> 2, packet_length & 3 )); - insl(ioaddr + DATA_1 , data, packet_length >> 2 ); - /* read the left over bytes */ - insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC), - packet_length & 0x3 ); + +#ifdef USE_32_BIT + /* QUESTION: Like in the TX routine, do I want + to send the DWORDs or the bytes first, or some + mixture. A mixture might improve already slow PIO + performance */ + PRINTK3((" Reading %d dwords (and %d bytes) \n", + packet_length >> 2, packet_length & 3 )); + insl(ioaddr + DATA_1 , data, packet_length >> 2 ); + /* read the left over bytes */ + insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC), + packet_length & 0x3 ); +#else + PRINTK3((" Reading %d words and %d byte(s) \n", (packet_length >> 1), packet_length & 1 )); +#if 1 + insw(ioaddr + DATA_1 , data, (packet_length + 1 ) >> 1); #else - PRINTK3((" Reading %d words and %d byte(s) \n", - (packet_length >> 1 ), packet_length & 1 ); - if ( packet_length & 1 ) - *(data++) = inb( ioaddr + DATA_1 ); - insw(ioaddr + DATA_1 , data, (packet_length + 1 ) >> 1); - if ( packet_length & 1 ) { - data += packet_length & ~1; - *((data++) = inb( ioaddr + DATA_1 ); - } + if ( packet_length & 1 ) + *(data++) = inb( ioaddr + DATA_1 ); + insw(ioaddr + DATA_1 , data, (packet_length + 1 ) >> 1); + if ( packet_length & 1 ) { + data += packet_length & ~1; + *(data++) = inb( ioaddr + DATA_1 ); + } #endif -#if SMC_DEBUG > 2 - print_packet( data, packet_length ); +#endif + +#if SMC_DEBUG > 2 + print_packet( data, packet_length ); #endif #ifndef SUPPORT_OLD_KERNEL - skb->protocol = eth_type_trans(skb, dev ); + skb->protocol = eth_type_trans(skb, dev ); #endif - netif_rx(skb); - lp->stats.rx_packets++; - } else { - /* error ... */ - lp->stats.rx_errors++; - - if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++; - if ( status & (RS_TOOSHORT | RS_TOOLONG ) ) - lp->stats.rx_length_errors++; - if ( status & RS_BADCRC) lp->stats.rx_crc_errors++; - } - /* error or good, tell the card to get rid of this packet */ - outw( MC_RELEASE, ioaddr + MMU_CMD ); + netif_rx(skb); + lp->stats.rx_packets++; + } else { + /* error ... */ + lp->stats.rx_errors++; + + if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++; + if ( status & (RS_TOOSHORT | RS_TOOLONG ) ) + lp->stats.rx_length_errors++; + if ( status & RS_BADCRC) lp->stats.rx_crc_errors++; + } + /* error or good, tell the card to get rid of this packet */ + outw( MC_RELEASE, ioaddr + MMU_CMD ); - return; + return; } -/************************************************************************* +/************************************************************************* . smc_tx - . + . . Purpose: Handle a transmit error message. This will only be called - . when an error, because of the AUTO_RELEASE mode. - . + . when an error, because of the AUTO_RELEASE mode. + . . Algorithm: . Save pointer and packet no . Get the packet no from the top of the queue . check if it's valid ( if not, is this an error??? ) - . read the status word + . read the status word . record the error . ( resend? Not really, since we don't want old packets around ) - . Restore saved values - ************************************************************************/ -static void smc_tx( struct device * dev ) + . Restore saved values + ************************************************************************/ +static void smc_tx( struct device * dev ) { - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - byte saved_packet; - byte packet_no; - word tx_status; - - - /* assume bank 2 */ - - saved_packet = inb( ioaddr + PNR_ARR ); - packet_no = inw( ioaddr + FIFO_PORTS ); - packet_no &= 0x7F; - - /* select this as the packet to read from */ - outb( packet_no, ioaddr + PNR_ARR ); - - /* read the first word from this packet */ - outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER ); - - tx_status = inw( ioaddr + DATA_1 ); - PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status )); - - lp->stats.tx_errors++; - if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++; - if ( tx_status & TS_LATCOL ) { - printk(KERN_DEBUG CARDNAME - ": Late collision occurred on last xmit.\n"); - lp->stats.tx_window_errors++; - } -#if 0 - if ( tx_status & TS_16COL ) { ... } -#endif - - if ( tx_status & TS_SUCCESS ) { - printk(CARDNAME": Successful packet caused interrupt \n"); - } - /* re-enable transmit */ - SMC_SELECT_BANK( 0 ); - outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR ); - - /* kill the packet */ - SMC_SELECT_BANK( 2 ); - outw( MC_FREEPKT, ioaddr + MMU_CMD ); - - /* one less packet waiting for me */ - lp->packets_waiting--; - - outb( saved_packet, ioaddr + PNR_ARR ); - return; + int ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + byte saved_packet; + byte packet_no; + word tx_status; + + + /* assume bank 2 */ + + saved_packet = inb( ioaddr + PNR_ARR ); + packet_no = inw( ioaddr + FIFO_PORTS ); + packet_no &= 0x7F; + + /* select this as the packet to read from */ + outb( packet_no, ioaddr + PNR_ARR ); + + /* read the first word from this packet */ + outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER ); + + tx_status = inw( ioaddr + DATA_1 ); + PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status )); + + lp->stats.tx_errors++; + if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++; + if ( tx_status & TS_LATCOL ) { + printk(KERN_DEBUG CARDNAME + ": Late collision occurred on last xmit.\n"); + lp->stats.tx_window_errors++; + } + + if ( tx_status & TS_SUCCESS ) { + printk(CARDNAME": Successful packet caused interrupt \n"); + } + /* re-enable transmit */ + SMC_SELECT_BANK( 0 ); + outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR ); + + /* kill the packet */ + SMC_SELECT_BANK( 2 ); + outw( MC_FREEPKT, ioaddr + MMU_CMD ); + + /* one less packet waiting for me */ + lp->packets_waiting--; + + outb( saved_packet, ioaddr + PNR_ARR ); + return; } /*---------------------------------------------------- . smc_close - . + . . this makes the board clean up everything that it can . and not talk to the outside world. Caused by . an 'ifconfig ethX down' @@ -1616,157 +1820,155 @@ -----------------------------------------------------*/ static int smc_close(struct device *dev) { - dev->tbusy = 1; - dev->start = 0; + dev->tbusy = 1; + dev->start = 0; - /* clear everything */ - smc_shutdown( dev->base_addr ); + /* clear everything */ + smc_shutdown( dev->base_addr ); - /* Update the statistics here. */ + /* Update the statistics here. */ #ifdef MODULE - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #endif - return 0; + return 0; } /*------------------------------------------------------------ - . Get the current statistics. - . This may be called with the card open or closed. + . Get the current statistics. + . This may be called with the card open or closed. .-------------------------------------------------------------*/ -static struct net_device_stats* smc_query_statistics(struct device *dev) { - struct smc_local *lp = (struct smc_local *)dev->priv; +static struct enet_statistics * smc_query_statistics(struct device *dev) { + struct smc_local *lp = (struct smc_local *)dev->priv; - return &lp->stats; + return &lp->stats; } /*----------------------------------------------------------- . smc_set_multicast_list - . + . . This routine will, depending on the values passed to it, - . either make it accept multicast packets, go into + . either make it accept multicast packets, go into . promiscuous mode ( for TCPDUMP and cousins ) or accept - . a select set of multicast packets + . a select set of multicast packets */ #ifdef SUPPORT_OLD_KERNEL -static void smc_set_multicast_list( struct device * dev, - int num_addrs, void * addrs ) +static void smc_set_multicast_list( struct device * dev, + int num_addrs, void * addrs ) #else -static void smc_set_multicast_list(struct device *dev) -#endif + static void smc_set_multicast_list(struct device *dev) +#endif { - short ioaddr = dev->base_addr; + short ioaddr = dev->base_addr; - SMC_SELECT_BANK(0); + SMC_SELECT_BANK(0); #ifdef SUPPORT_OLD_KERNEL - if ( num_addrs < 0 ) + if ( num_addrs < 0 ) #else - if ( dev->flags & IFF_PROMISC ) -#endif - outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR ); - -/* BUG? I never disable promiscuous mode if multicasting was turned on. - Now, I turn off promiscuous mode, but I don't do anything to multicasting - when promiscuous mode is turned on. -*/ - - /* Here, I am setting this to accept all multicast packets. - I don't need to zero the multicast table, because the flag is - checked before the table is - */ -#ifdef SUPPORT_OLD_KERNEL - else if ( num_addrs > 20 ) /* arbitrary constant */ + if ( dev->flags & IFF_PROMISC ) +#endif + outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR ); + + /* BUG? I never disable promiscuous mode if multicasting was turned on. + Now, I turn off promiscuous mode, but I don't do anything to multicasting + when promiscuous mode is turned on. + */ + + /* Here, I am setting this to accept all multicast packets. + I don't need to zero the multicast table, because the flag is + checked before the table is + */ +#ifdef SUPPORT_OLD_KERNEL + else if ( num_addrs > 20 ) /* arbitrary constant */ #else - else if (dev->flags & IFF_ALLMULTI) -#endif - outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR ); - - /* We just get all multicast packets even if we only want them - . from one source. This will be changed at some future - . point. */ + else if (dev->flags & IFF_ALLMULTI) +#endif + outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR ); + + /* We just get all multicast packets even if we only want them + . from one source. This will be changed at some future + . point. */ #ifdef SUPPORT_OLD_KERNEL - else if (num_addrs > 0 ) { -/* the old kernel support will not have hardware multicast support. It would - involve more kludges, and make the multicast setting code even worse. - Instead, just use the ALMUL method. This is reasonable, considering that - it is seldom used -*/ - outw( inw( ioaddr + RCR ) & ~RCR_PROMISC, ioaddr + RCR ); - outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR ); - } + else if (num_addrs > 0 ) { + /* the old kernel support will not have hardware multicast support. It would + involve more kludges, and make the multicast setting code even worse. + Instead, just use the ALMUL method. This is reasonable, considering that + it is seldom used + */ + outw( inw( ioaddr + RCR ) & ~RCR_PROMISC, ioaddr + RCR ); + outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR ); + } #else - else if (dev->mc_count ) { - /* support hardware multicasting */ - - /* be sure I get rid of flags I might have set */ - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), - ioaddr + RCR ); - /* NOTE: this has to set the bank, so make sure it is the - last thing called. The bank is set to zero at the top */ - smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); - } -#endif - else { - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), - ioaddr + RCR ); - - /* - since I'm disabling all multicast entirely, I need to - clear the multicast list - */ - SMC_SELECT_BANK( 3 ); - outw( 0, ioaddr + MULTICAST1 ); - outw( 0, ioaddr + MULTICAST2 ); - outw( 0, ioaddr + MULTICAST3 ); - outw( 0, ioaddr + MULTICAST4 ); - } + else if (dev->mc_count ) { + /* support hardware multicasting */ + + /* be sure I get rid of flags I might have set */ + outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), + ioaddr + RCR ); + /* NOTE: this has to set the bank, so make sure it is the + last thing called. The bank is set to zero at the top */ + smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); + } +#endif + else { + outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), + ioaddr + RCR ); + + /* + since I'm disabling all multicast entirely, I need to + clear the multicast list + */ + SMC_SELECT_BANK( 3 ); + outw( 0, ioaddr + MULTICAST1 ); + outw( 0, ioaddr + MULTICAST2 ); + outw( 0, ioaddr + MULTICAST3 ); + outw( 0, ioaddr + MULTICAST4 ); + } } #ifdef MODULE static char devicename[9] = { 0, }; static struct device devSMC9194 = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, /* I/O address, IRQ */ - 0, 0, 0, NULL, smc_init }; + devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0x300, 1, /* I/O address, IRQ */ + 0, 0, 0, NULL, smc_init }; int io = 0; int irq = 0; int ifport = 0; -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(ifport, "i"); - int init_module(void) { - int result; + int result; - if (io == 0) - printk(KERN_WARNING - CARDNAME": You shouldn't use auto-probing with insmod!\n" ); - - /* copy the parameters from insmod into the device structure */ - devSMC9194.base_addr = io; - devSMC9194.irq = irq; - devSMC9194.if_port = ifport; - if ((result = register_netdev(&devSMC9194)) != 0) - return result; + if (io == 0) + printk(KERN_WARNING + CARDNAME": You shouldn't use auto-probing with insmod!\n" ); + + /* copy the parameters from insmod into the device structure */ + devSMC9194.base_addr = io; + devSMC9194.irq = irq; + devSMC9194.if_port = ifport; + if ((result = register_netdev(&devSMC9194)) != 0) + return result; - return 0; + return 0; } void cleanup_module(void) { - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - unregister_netdev(&devSMC9194); + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + unregister_netdev(&devSMC9194); - free_irq(devSMC9194.irq, &devSMC9194); - release_region(devSMC9194.base_addr, SMC_IO_EXTENT); + free_irq(devSMC9194.irq, NULL ); + irq2dev_map[devSMC9194.irq] = NULL; + release_region(devSMC9194.base_addr, SMC_IO_EXTENT); - if (devSMC9194.priv) - kfree_s(devSMC9194.priv, sizeof(struct smc_local)); + if (devSMC9194.priv) + kfree_s(devSMC9194.priv, sizeof(struct smc_local)); } #endif /* MODULE */ + diff -urN linux/drivers/video/sa1100fb.c new/drivers/video/sa1100fb.c --- linux/drivers/video/sa1100fb.c Tue Aug 10 17:24:26 1999 +++ new/drivers/video/sa1100fb.c Mon Jul 19 12:18:27 1999 @@ -79,7 +79,7 @@ #define MAX_SCREEN_SIZE_H 320 #define MAX_SCREEN_SIZE_V 240 -#elif defined(CONFIG_SA1100_TIFONE) +#elif defined(CONFIG_SA1100_TIFON) #define MAX_BITS_PER_PIXEL 4 #define MAX_SCREEN_SIZE_H 640 @@ -629,20 +629,20 @@ init_var.green = init_var.red; init_var.blue = init_var.red; init_var.sync = 0; -#elif defined(CONFIG_SA1100_TIFONE) +#elif defined(CONFIG_SA1100_TIFON) init_var.red.length = 4; init_var.green = init_var.red; init_var.blue = init_var.red; init_var.grayscale = 1; - init_var.pixclock; = 150000; - init_var.left_margin; = 20; - init_var.right_margin; = 256; - init_var.upper_margin; = 0; - init_var.lower_margin; = 0; - init_var.hsync_len; = 2; - init_var.vsync_len; = 1; - init_var.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_AC; - init_var.vmode; = 0; + init_var.pixclock = 150000; + init_var.left_margin = 20; + init_var.right_margin = 256; + init_var.upper_margin = 0; + init_var.lower_margin = 0; + init_var.hsync_len = 2; + init_var.vsync_len = 1; + init_var.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT; + init_var.vmode = 0; #endif current_par.montype = -1; @@ -753,8 +753,8 @@ LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); lcd_shadow.lccr3 = LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44); -#elif defined(CONFIG_SA1100_TIFONE) - DPRINTK("Configuring TIFONE LCD\n"); +#elif defined(CONFIG_SA1100_TIFON) + DPRINTK("Configuring TIFON LCD\n"); lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + LCCR0_BigEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + @@ -770,10 +770,13 @@ lcd_shadow.lccr3 = LCCR3_PixClkDiv( 31 ) + LCCR3_ACBsDiv( 512 ) + LCCR3_ACBsCnt(0) + + LCCR3_HorSnchH + LCCR3_VrtSnchH; + /* ((current_var.sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HorSnchH : LCCR3_HorSnchL) + ((current_var.sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); + */ #endif /* Restore status of interrupts */ @@ -832,7 +835,7 @@ #if defined(CONFIG_SA1100_PENNY) FpgaLcdCS1 = 0x000; /* LCD Backlight to 0% */ FpgaPortI &= ~LCD_ON; /* Turn off LCD Backlight */ -#elif defined(CONFIG_SA1100_TIFONE) +#elif defined(CONFIG_SA1100_TIFON) GPCR = GPCR | GPIO_GPIO(24); /* turn off display */ #endif @@ -878,7 +881,7 @@ #if defined(CONFIG_SA1100_PENNY) FpgaLcdCS1 = 0x0FF; /* LCD Backlight to 100% */ FpgaPortI |= LCD_ON; /* Turn on LCD Backlight */ -#elif defined(CONFIG_SA1100_TIFONE) +#elif defined(CONFIG_SA1100_TIFON) GPSR = GPSR | GPIO_GPIO(24); /* turn on display */ #endif current_par.controller_state = LCD_MODE_ENABLED; @@ -976,7 +979,7 @@ #if defined(CONFIG_SA1100_PENNY) GPDR |= GPIO_GPDR_GFX; /* GPIO Data Direction register for LCD data bits 8-11 */ GAFR |= GPIO_GAFR_GFX; /* GPIO Alternate Function register for LCD data bits 8-11 */ -#elif defined(CONFIG_SA1100_TIFONE) +#elif defined(CONFIG_SA1100_TIFON) GPDR = GPDR | GPIO_GPIO(24); /* set GPIO24 to output */ #endif diff -urN linux/include/asm-arm/arch-sa1100/SA-1101.h new/include/asm-arm/arch-sa1100/SA-1101.h --- linux/include/asm-arm/arch-sa1100/SA-1101.h Thu Jan 1 01:00:00 1970 +++ new/include/asm-arm/arch-sa1100/SA-1101.h Thu Jul 29 16:53:07 1999 @@ -0,0 +1,913 @@ +/* + * SA-1101.h + * + * Copyright (c) Peter Danielsson 1999 + * + * Definition of constants related to the sa1101 + * support chip for the sa1100 + * + */ + +/* Be sure that virtual mapping is defined right */ +#ifndef __ASM_ARCH_HARDWARE_H +#error You must include hardware.h not SA-1100.h +#endif + + +#ifndef SA1101_BASE +#error You must define SA-1101 base address +#endif + +#ifndef LANGUAGE +#define LANGUAGE C +#endif /* !defined (LANGUAGE) */ + +#ifndef VirtAdd +#define VirtAdd(PhAdd) (PhAdd) +#endif /* !defined (VirtAdd) */ + +#include +#include + +#define C 0 +#define Assembly 1 + +/* + * Memory map + */ + +#define __SHMEM_CONTROL0 0x00000000 +#define __SYSTEM_CONTROL1 0x00000400 +#define __ARBITER 0x00020000 +#define __SYSTEM_CONTROL2 0x00040000 +#define __SYSTEM_CONTROL3 0x00060000 +#define __PARALLEL_PORT 0x00080000 +#define __VIDMEM_CONTORL 0x00100000 +#define __UPDATE_FIFO 0x00120000 +#define __SHMEM_CONTROL1 0x00140000 +#define __INTERRUPT_CONTROL 0x00160000 +#define __USB_CONTROL 0x00180000 +#define __TRACK_INTERFACE 0x001a0000 +#define __MOUSE_INTERFACE 0x001b0000 +#define __KEYPAD_INTERFACE 0x001c0000 +#define __PCMCIA_INTERFACE 0x001e0000 +#define __VGA_CONTROL 0x00200000 +#define __GPIO_INTERFACE 0x00300000 + +/* + * Macro that calculates real address for registers in the SA-1101 + */ + +#define _SA1101( x ) ((x) + SA1101_BASE) + +/* + * Interface and shared memory controller registers + * + * Registers + * SKCR SA-1101 control register (read/write) + * SMCR Shared Memory Controller Register + * SNPR Snoop Register + */ + +#define _SKCR _SA1101( 0x00000000 ) /* SA-1101 Control Reg. */ +#define _SMCR _SA1101( 0x00140000 ) /* Shared Mem. Control Reg. */ +#define _SNPR _SA1101( 0x00140400 ) /* Snoop Reg. */ + +#if LANGUAGE == C +#define SKCR (*((volatile Word *) VirtAdd (_SKCR))) +#define SMCR (*((volatile Word *) VirtAdd (_SMCR))) +#define SNPR (*((volatile Word *) VirtAdd (_SNPR))) + +#define SKCR_PLLEn 0x0001 /* Enable On-Chip PLL */ +#define SKCR_BCLKEn 0x0002 /* Enables BCLK */ +#define SKCR_Sleep 0x0004 /* Sleep Mode */ +#define SKCR_IRefEn 0x0008 /* DAC Iref input enable */ +#define SKCR_VCOON 0x0010 /* VCO bias */ +#define SKCR_ScanTestEn 0x0020 /* Enables scan test */ +#define SKCR_ClockTestEn 0x0040 /* Enables clock test */ + +#define SMCR_DCAC Fld(2,0) /* Number of column address bits */ +#define SMCR_DRAC Fld(2,2) /* Number of row address bits */ +#define SMCR_ArbiterBias 0x0008 /* favor video or USB */ +#define SMCR_TopVidMem Fld(4,5) /* Top 4 bits of vidmem addr. */ + +#define SMCR_ColAdrBits( x ) /* col. addr bits 8..11 */ \ + (( (x) - 8 ) << FShft (SMCR_DCAC)) +#define SMCR_RowAdrBits( x ) /* row addr bits 9..12 */\ + (( (x) - 9 ) << FShft (SMCR_DRAC) + +#define SNPR_VFBstart Fld(12,0) /* Video frame buffer addr */ +#define SNPR_VFBsize Fld(11,12) /* Video frame buffer size */ +#define SNPR_WholeBank (1 << 23) /* Whole bank bit */ +#define SNPR_BankSelect Fld(2,27) /* Bank select */ +#define SNPR_SnoopEn (1 << 31) /* Enable snoop operation */ + +#define SNPR_Set_VFBsize( x ) /* set frame buffer size (in kb) */ \ + ( (x) << FShft (SNPR_VFBsize)) +#define SNPR_Select_Bank(x) /* select bank 0 or 1 */ \ + (( (x) + 1 ) << FShft (SNPR_BankSelect )) + +#endif /* LANGUAGE == C */ + +/* + * Video Memory Controller + * + * Registers + * VMCCR Configuration register + * VMCAR VMC address register + * VMCDR VMC data register + * + */ + +#define _VMCCR _SA1101( 0x00100000 ) /* Configuration register */ +#define _VMCAR _SA1101( 0x00101000 ) /* VMC address register */ +#define _VMCDR _SA1101( 0x00101400 ) /* VMC data register */ + +#if LANGUAGE == C +#define VMCCR (*((volatile Word *) VirtAdd (_VMCCR))) +#define VMCAR (*((volatile Word *) VirtAdd (_VMCAR))) +#define VMCDR (*((volatile Word *) VirtAdd (_VMCDR))) + +#define VMCCR_RefreshEn 0x0000 /* Enable memory refresh */ +#define VMCCR_Config 0x0001 /* DRAM size */ +#define VMCCR_RefPeriod Fld(2,3) /* Refresh period */ +#define VMCCR_StaleDataWait Fld(4,5) /* Stale FIFO data timeout counter */ +#define VMCCR_SleepState (1<<9) /* State of interface pins in sleep*/ +#define VMCCR_RefTest (1<<10) /* refresh test */ +#define VMCCR_RefLow Fld(6,11) /* refresh low counter */ +#define VMCCR_RefHigh Fld(7,17) /* refresh high counter */ +#define VMCCR_SDTCTest Fld(7,24) /* stale data timeout counter */ +#define VMCCR_ForceSelfRef (1<<31) /* Force self refresh */ + +#endif LANGUAGE == C + + +/* Update FIFO + * + * Registers + * UFCR Update FIFO Control Register + * UFSR Update FIFO Status Register + * UFLVLR update FIFO level register + * UFDR update FIFO data register + */ + +#define _UFCR _SA1101(0x00120000) /* Update FIFO Control Reg. */ +#define _UFSR _SA1101(0x00120400) /* Update FIFO Status Reg. */ +#define _UFLVLR _SA1101(0x00120800) /* Update FIFO level reg. */ +#define _UFDR _SA1101(0x00120c00) /* Update FIFO data reg. */ + +#if LANGUAGE == C + +#define UFCR (*((volatile Word *) VirtAdd (_UFCR))) +#define UFSR (*((volatile Word *) VirtAdd (_UFSR))) +#define UFLVLR (*((volatile Word *) VirtAdd (_UFLVLR))) +#define UFDR (*((volatile Word *) VirtAdd (_UFDR))) + + +#define UFCR_FifoThreshhold Fld(7,0) /* Level for FifoGTn flag */ + +#define UFSR_FifoGTnFlag 0x01 /* FifoGTn flag */#define UFSR_FifoEmpty 0x80 /* FIFO is empty */ + +#endif /* LANGUAGE == C */ + +/* System Controller + * + * Registers + * SKPCR Power Control Register + * SKCDR Clock Divider Register + * DACDR1 DAC1 Data register + * DACDR2 DAC2 Data register + */ + +#define _SKPCR _SA1101(0x00000400) +#define _SKCDR _SA1101(0x00040000) +#define _DACDR1 _SA1101(0x00060000) +#define _DACDR2 _SA1101(0x00060400) + +#if LANGUAGE == C +#define SKPCR (*((volatile Word *) VirtAdd (_SKPCR))) +#define SKCDR (*((volatile Word *) VirtAdd (_SKCDR))) +#define DACDR1 (*((volatile Word *) VirtAdd (_DACDR1))) +#define DACDR2 (*((volatile Word *) VirtAdd (_DACDR2))) + +#define SKPCR_UCLKEn 0x01 /* USB Enable */ +#define SKPCR_PCLKEn 0x02 /* PS/2 Enable */ +#define SKPCR_ICLKEn 0x04 /* Interrupt Controller Enable */ +#define SKPCR_VCLKEn 0x08 /* Video Controller Enable */ +#define SKPCR_PICLKEn 0x10 /* parallel port Enable */ +#define SKPCR_DCLKEn 0x20 /* DACs Enable */ +#define SKPCR_nKPADEn 0x40 /* Multiplexer */ + +#define SKCDR_PLLMul Fld(7,0) /* PLL Multiplier */ +#define SKCDR_VCLKEn Fld(2,7) /* Video controller clock divider */ +#define SKDCR_BCLKEn (1<<9) /* BCLK Divider */ +#define SKDCR_UTESTCLKEn (1<<10) /* Route USB clock during test mode */ +#define SKDCR_DivRValue Fld(6,11) /* Input clock divider for PLL */ +#define SKDCR_DivNValue Fld(5,17) /* Output clock divider for PLL */ +#define SKDCR_PLLRSH Fld(3,22) /* PLL bandwidth control */ +#define SKDCR_ChargePump (1<<25) /* Charge pump control */ +#define SKDCR_ClkTestMode (1<<26) /* Clock output test mode */ +#define SKDCR_ClkTestEn (1<<27) /* Test clock generator */ +#define SKDCR_ClkJitterCntl Fld(3,28) /* video clock jitter compensation */ + +#define DACDR_DACCount Fld(8,0) /* Count value */ +#define DACDR1_DACCount DACDR_DACCount +#define DACDR2_DACCount DACDR_DACCount + +#endif /* LANGUAGE == C */ + +/* + * Parallel Port Interface + * + * Registers + * IEEE_Config IEEE mode selection and programmable attributes + * IEEE_Control Controls the states of IEEE port control outputs + * IEEE_Data Forward transfer data register + * IEEE_Addr Forward transfer address register + * IEEE_Status Port IO signal status register + * IEEE_IntStatus Port interrupts status register + * IEEE_FifoLevels Rx and Tx FIFO interupt generation levels + * IEEE_InitTime Forward timeout counter initial value + * IEEE_TimerStatus Forward timeout counter current value + * IEEE_FifoReset Reset forward transfer FIFO + * IEEE_ReloadValue Counter reload value + * IEEE_TestControl Control testmode + * IEEE_TestDataIn Test data register + * IEEE_TestDataInEn Enable test data + * IEEE_TestCtrlIn Test control signals + * IEEE_TestCtrlInEn Enable test control signals + * IEEE_TestDataStat Current data bus value + * + */ + +/* + * The control registers are defined as offsets from a base address + */ + +#define _IEEE( x ) _SA1101( (x) + __PARALLEL_PORT ) + +#define _IEEE_Config _IEEE( 0x0000 ) +#define _IEEE_Control _IEEE( 0x0400 ) +#define _IEEE_Data _IEEE( 0x4000 ) +#define _IEEE_Addr _IEEE( 0x0800 ) +#define _IEEE_Status _IEEE( 0x0c00 ) +#define _IEEE_IntStatus _IEEE( 0x1000 ) +#define _IEEE_FifoLevels _IEEE( 0x1400 ) +#define _IEEE_InitTime _IEEE( 0x1800 ) +#define _IEEE_TimerStatus _IEEE( 0x1c00 ) +#define _IEEE_FifoReset _IEEE( 0x2000 ) +#define _IEEE_ReloadValue _IEEE( 0x3c00 ) +#define _IEEE_TestControl _IEEE( 0x2400 ) +#define _IEEE_TestDataIn _IEEE( 0x2800 ) +#define _IEEE_TestDataInEn _IEEE( 0x2c00 ) +#define _IEEE_TestCtrlIn _IEEE( 0x3000 ) +#define _IEEE_TestCtrlInEn _IEEE( 0x3400 ) +#define _IEEE_TestDataStat _IEEE( 0x3800 ) + + +#if LANGUAGE == C +#define IEEE_Config (*((volatile Word *) VirtAdd (_IEEE_Config))) +#define IEEE_Control (*((volatile Word *) VirtAdd (_IEEE_Control))) +#define IEEE_Data (*((volatile Word *) VirtAdd (_IEEE_Data))) +#define IEEE_Addr (*((volatile Word *) VirtAdd (_IEEE_Addr))) +#define IEEE_Status (*((volatile Word *) VirtAdd (_IEEE_Status))) +#define IEEE_IntStatus (*((volatile Word *) VirtAdd (_IEEE_IntStatus))) +#define IEEE_FifoLevels (*((volatile Word *) VirtAdd (_IEEE_FifoLevels))) +#define IEEE_InitTime (*((volatile Word *) VirtAdd (_IEEE_InitTime))) +#define IEEE_TimerStatus (*((volatile Word *) VirtAdd (_IEEE_TimerStatus))) +#define IEEE_FifoReset (*((volatile Word *) VirtAdd (_IEEE_FifoReset))) +#define IEEE_ReloadValue (*((volatile Word *) VirtAdd (_IEEE_ReloadValue))) +#define IEEE_TestControl (*((volatile Word *) VirtAdd (_IEEE_TestControl))) +#define IEEE_TestDataIn (*((volatile Word *) VirtAdd (_IEEE_TestDataIn))) +#define IEEE_TestDataInEn (*((volatile Word *) VirtAdd (_IEEE_TestDataInEn))) +#define IEEE_TestCtrlIn (*((volatile Word *) VirtAdd (_IEEE_TestCtrlIn))) +#define IEEE_TestCtrlInEn (*((volatile Word *) VirtAdd (_IEEE_TestCtrlInEn))) +#define IEEE_TestDataStat (*((volatile Word *) VirtAdd (_IEEE_TestDataStat))) + + +#define IEEE_Config_M Fld(3,0) /* Mode select */ +#define IEEE_Config_D 0x04 /* FIFO access enable */ +#define IEEE_Config_B 0x08 /* 9-bit word enable */ +#define IEEE_Config_T 0x10 /* Data transfer enable */ +#define IEEE_Config_A 0x20 /* Data transfer direction */ +#define IEEE_Config_E 0x40 /* Timer enable */ +#define IEEE_Control_A 0x08 /* AutoFd output */ +#define IEEE_Control_E 0x04 /* Selectin output */ +#define IEEE_Control_T 0x02 /* Strobe output */ +#define IEEE_Control_I 0x01 /* Port init output */ +#define IEEE_Data_C (1<<31) /* Byte count */ +#define IEEE_Data_Db Fld(9,16) /* Data byte 2 */ +#define IEEE_Data_Da Fld(9,0) /* Data byte 1 */ +#define IEEE_Addr_A Fld(8,0) /* forward address transfer byte */ +#define IEEE_Status_A 0x0100 /* nAutoFd port output status */ +#define IEEE_Status_E 0x0080 /* nSelectIn port output status */ +#define IEEE_Status_T 0x0040 /* nStrobe port output status */ +#define IEEE_Status_I 0x0020 /* nInit port output status */ +#define IEEE_Status_B 0x0010 /* Busy port inout status */ +#define IEEE_Status_S 0x0008 /* Select port input status */ +#define IEEE_Status_K 0x0004 /* nAck port input status */ +#define IEEE_Status_F 0x0002 /* nFault port input status */ +#define IEEE_Status_R 0x0001 /* pError port input status */ + +#define IEEE_IntStatus_IntReqDat 0x0100 +#define IEEE_IntStatus_IntReqEmp 0x0080 +#define IEEE_IntStatus_IntReqInt 0x0040 +#define IEEE_IntStatus_IntReqRav 0x0020 +#define IEEE_IntStatus_IntReqTim 0x0010 +#define IEEE_IntStatus_RevAddrComp 0x0008 +#define IEEE_IntStatus_RevDataComp 0x0004 +#define IEEE_IntStatus_FwdAddrComp 0x0002 +#define IEEE_IntStatus_FwdDataComp 0x0001 +#define IEEE_FifoLevels_RevFifoLevel 2 +#define IEEE_FifoLevels_FwdFifoLevel 1 +#define IEEE_InitTime_TimValInit Fld(22,0) +#define IEEE_TimerStatus_TimValStat Fld(22,0) +#define IEEE_ReloadValue_Reload Fld(4,0) + +#define IEEE_TestControl_RegClk 0x04 +#define IEEE_TestControl_ClockSelect Fld(2,1) +#define IEEE_TestControl_TimerTestModeEn 0x01 +#define IEEE_TestCtrlIn_PError 0x10 +#define IEEE_TestCtrlIn_nFault 0x08 +#define IEEE_TestCtrlIn_nAck 0x04 +#define IEEE_TestCtrlIn_PSel 0x02 +#define IEEE_TestCtrlIn_Busy 0x01 + +#endif /* LANGUAGE == C */ + +/* + * VGA Controller + * + * Registers + * VideoControl Video Control Register + * VgaTiming0 VGA Timing Register 0 + * VgaTiming1 VGA Timing Register 1 + * VgaTiming2 VGA Timing Register 2 + * VgaTiming3 VGA Timing Register 3 + * VgaBorder VGA Border Color Register + * VgaDBAR VGADMA Base Address Register + * VgaDCAR VGADMA Channel Current Address Register + * VgaStatus VGA Status Register + * VgaInterruptMask VGA Interrupt Mask Register + * VgaPalette VGA Palette Registers + * DacControl DAC Control Register + * VgaTest VGA Controller Test Register + */ + +#define _VGA( x ) _SA1101( ( x ) + __VGA_CONTROL ) + +#define _VideoControl _VGA( 0x0000 ) +#define _VgaTiming0 _VGA( 0x0400 ) +#define _VgaTiming1 _VGA( 0x0800 ) +#define _VgaTiming2 _VGA( 0x0c00 ) +#define _VgaTiming3 _VGA( 0x1000 ) +#define _VgaBorder _VGA( 0x1400 ) +#define _VgaDBAR _VGA( 0x1800 ) +#define _VgaDCAR _VGA( 0x1c00 ) +#define _VgaStatus _VGA( 0x2000 ) +#define _VgaInterruptMask _VGA( 0x2400 ) +#define _VgaPalette _VGA( 0x40000 ) +#define _DacControl _VGA( 0x3000 ) +#define _VgaTest _VGA( 0x2c00 ) + +#if (LANGUAGE == C) +#define VideoControl (*((volatile Word *) VirtAdd (_VideoControl))) +#define VgaTiming0 (*((volatile Word *) VirtAdd (_VgaTiming0))) +#define VgaTiming1 (*((volatile Word *) VirtAdd (_VgaTiming1))) +#define VgaTiming2 (*((volatile Word *) VirtAdd (_VgaTiming2))) +#define VgaTiming3 (*((volatile Word *) VirtAdd (_VgaTiming3))) +#define VgaBorder (*((volatile Word *) VirtAdd (_VgaBorder))) +#define VgaDBAR (*((volatile Word *) VirtAdd (_VgaDBAR))) +#define VgaDCAR (*((volatile Word *) VirtAdd (_VgaDCAR))) +#define VgaStatus (*((volatile Word *) VirtAdd (_VgaStatus))) +#define VgaInterruptMask (*((volatile Word *) VirtAdd (_VgaInterruptMask))) +#define VgaPalette (*((volatile Word *) VirtAdd (_VgaPalette))) +#define DacControl (*((volatile Word *) VirtAdd (_DacControl)) +#define VgaTest (*((volatile Word *) VirtAdd (_VgaTest))) + +#define VideoControl_VgaEn 0x00000000 +#define VideoControl_BGR 0x00000001 +#define VideoControl_VCompVal Fld(2,2) +#define VideoControl_VgaReq Fld(4,4) +#define VideoControl_VBurstL Fld(4,8) +#define VideoControl_VMode (1<<12) +#define VideoControl_PalRead (1<<13) + +#define VgaTiming0_PPL Fld(6,2) +#define VgaTiming0_HSW Fld(8,8) +#define VgaTiming0_HFP Fld(8,16) +#define VgaTiming0_HBP Fld(8,24) + +#define VgaTiming1_LPS Fld(10,0) +#define VgaTiming1_VSW Fld(6,10) +#define VgaTiming1_VFP Fld(8,16) +#define VgaTiming1_VBP Fld(8,24) + +#define VgaTiming2_IVS 0x01 +#define VgaTiming2_IHS 0x02 +#define VgaTiming2_CVS 0x04 +#define VgaTiming2_CHS 0x08 + +#define VgaTiming3_HBS Fld(8,0) +#define VgaTiming3_HBE Fld(8,8) +#define VgaTiming3_VBS Fld(8,16) +#define VgaTiming3_VBE Fld(8,24) + +#define VgaBorder_BCOL Fld(24,0) + +#define VgaStatus_VFUF 0x01 +#define VgaStatus_VNext 0x02 +#define VgaStatus_VComp 0x04 + +#define VgaInterruptMask_VFUFMask 0x00 +#define VgaInterruptMask_VNextMask 0x01 +#define VgaInterruptMask_VCompMask 0x02 + +#define VgaPalette_R Fld(8,0) +#define VgaPalette_G Fld(8,8) +#define VgaPalette_B Fld(8,16) + +#define DacControl_DACON 0x0001 +#define DacControl_COMPON 0x0002 +#define DacControl_PEDON 0x0004 +#define DacControl_RTrim Fld(5,4) +#define DacControl_GTrim Fld(5,9) +#define DacControl_BTrim Fld(5,14) + +#define VgaTest_TDAC 0x00 +#define VgaTest_Datatest Fld(4,1) +#define VgaTest_DACTESTDAC 0x10 +#define VgaTest_DACTESTOUT Fld(3,5) + +#endif /* LANGUAGE == C */ + +/* + * USB Host Interface Controller + * + * Registers + * Revision + * Control + * CommandStatus + * InterruptStatus + * InterruptEnable + * HCCA + * PeriodCurrentED + * ControlHeadED + * BulkHeadED + * BulkCurrentED + * DoneHead + * FmInterval + * FmRemaining + * FmNumber + * PeriodicStart + * LSThreshold + * RhDescriptorA + * RhDescriptorB + * RhStatus + * RhPortStatus + * USBStatus + * USBReset + * USTAR + * USWER + * USRFR + * USNFR + * USTCSR + * USSR + * + */ + +#define _USB( x ) _SA1101( ( x ) + __USB_CONTROL ) + + +#define _Revision _USB( 0x0000 ) +#define _Control _USB( 0x0888 ) +#define _CommandStatus _USB( 0x0c00 ) +#define _InterruptStatus _USB( 0x1000 ) +#define _InterruptEnable _USB( 0x1400 ) +#define _HCCA _USB( 0x1800 ) +#define _PeriodCurrentED _USB( 0x1c00 ) +#define _ControlHeadED _USB( 0x2000 ) +#define _BulkHeadED _USB( 0x2800 ) +#define _BulkCurrentED _USB( 0x2c00 ) +#define _DoneHead _USB( 0x3000 ) +#define _FmInterval _USB( 0x3400 ) +#define _FmRemaining _USB( 0x3800 ) +#define _FmNumber _USB( 0x3c00 ) +#define _PeriodicStart _USB( 0x4000 ) +#define _LSThreshold _USB( 0x4400 ) +#define _RhDescriptorA _USB( 0x4800 ) +#define _RhDescriptorB _USB( 0x4c00 ) +#define _RhStatus _USB( 0x5000 ) +#define _RhPortStatus _USB( 0x5400 ) +#define _USBStatus _USB( 0x11800 ) +#define _USBReset _USB( 0x11c00 ) + +#define _USTAR _USB( 0x10400 ) +#define _USWER _USB( 0x10800 ) +#define _USRFR _USB( 0x10c00 ) +#define _USNFR _USB( 0x11000 ) +#define _USTCSR _USB( 0x11400 ) +#define _USSR _USB( 0x11800 ) + + +#if (LANGUAGE == C) + +#define Revision (*((volatile Word *) VirtAdd (_Revision))) +#define Control (*((volatile Word *) VirtAdd (_Control))) +#define CommandStatus (*((volatile Word *) VirtAdd (_CommandStatus))) +#define InterruptStatus (*((volatile Word *) VirtAdd (_InterruptStatus))) +#define InterruptEnable (*((volatile Word *) VirtAdd (_InterruptEnable))) +#define HCCA (*((volatile Word *) VirtAdd (_HCCA))) +#define PeriodCurrentED (*((volatile Word *) VirtAdd (_PeriodCurrentED))) +#define ControlHeadED (*((volatile Word *) VirtAdd (_ControlHeadED))) +#define BulkHeadED (*((volatile Word *) VirtAdd (_BulkHeadED))) +#define BulkCurrentED (*((volatile Word *) VirtAdd (_BulkCurrentED))) +#define DoneHead (*((volatile Word *) VirtAdd (_DoneHead))) +#define FmInterval (*((volatile Word *) VirtAdd (_FmInterval))) +#define FmRemaining (*((volatile Word *) VirtAdd (_FmRemaining))) +#define FmNumber (*((volatile Word *) VirtAdd (_FmNumber))) +#define PeriodicStart (*((volatile Word *) VirtAdd (_PeriodicStart))) +#define LSThreshold (*((volatile Word *) VirtAdd (_LSThreshold))) +#define RhDescriptorA (*((volatile Word *) VirtAdd (_RhDescriptorA))) +#define RhDescriptorB (*((volatile Word *) VirtAdd (_RhDescriptorB))) +#define RhStatus (*((volatile Word *) VirtAdd (_RhStatus))) +#define RhPortStatus (*((volatile Word *) VirtAdd (_RhPortStatus))) +#define USBStatus (*((volatile Word *) VirtAdd (_USBStatus))) +#define USBReset (*((volatile Word *) VirtAdd (_USBReset))) +#define USTAR (*((volatile Word *) VirtAdd (_USTAR))) +#define USWER (*((volatile Word *) VirtAdd (_USWER))) +#define USRFR (*((volatile Word *) VirtAdd (_USRFR))) +#define USNFR (*((volatile Word *) VirtAdd (_USNFR))) +#define USTCSR (*((volatile Word *) VirtAdd (_USTCSR))) +#define USSR (*((volatile Word *) VirtAdd (_USSR))) + + +#define USBStatus_IrqHciRmtWkp (1<<7) +#define USBStatus_IrqHciBuffAcc (1<<8) +#define USBStatus_nIrqHciM (1<<9) +#define USBStatus_nHciMFClr (1<<10) + +#define USBReset_ForceIfReset 0x01 +#define USBReset_ForceHcReset 0x02 +#define USBReset_ClkGenReset 0x04 + +#define USTCR_RdBstCntrl Fld(3,0) +#define USTCR_ByteEnable Fld(4,3) +#define USTCR_WriteEn (1<<7) +#define USTCR_FifoCir (1<<8) +#define USTCR_TestXferSel (1<<9) +#define USTCR_FifoCirAtEnd (1<<10) +#define USTCR_nSimScaleDownClk (1<<11) + +#define USSR_nAppMDEmpty 0x01 +#define USSR_nAppMDFirst 0x02 +#define USSR_nAppMDLast 0x04 +#define USSR_nAppMDFull 0x08 +#define USSR_nAppMAFull 0x10 +#define USSR_XferReq 0x20 +#define USSR_XferEnd 0x40 + +#endif /* LANGUAGE == C */ + + +/* + * Interrupt Controller + * + * Registers + * INTTEST0 Test register 0 + * INTTEST1 Test register 1 + * INTENABLE0 Interrupt Enable register 0 + * INTENABLE1 Interrupt Enable register 1 + * INTPOL0 Interrupt Polarity selection 0 + * INTPOL1 Interrupt Polarity selection 1 + * INTTSTSEL Interrupt source selection + * INTSTATCLR0 Interrupt Status 0 + * INTSTATCLR1 Interrupt Status 1 + * INTSET0 Interrupt Set 0 + * INTSET1 Interrupt Set 1 + */ + +#define _INT( x ) _SA1101( ( x ) + __INTERRUPT_CONTROL) + +#define _INTTEST0 _INT( 0x1000 ) +#define _INTTEST1 _INT( 0x1400 ) +#define _INTENABLE0 _INT( 0x2000 ) +#define _INTENABLE1 _INT( 0x2400 ) +#define _INTPOL0 _INT( 0x3000 ) +#define _INTPOL1 _INT( 0x3400 ) +#define _INTTSTSEL _INT( 0x5000 ) +#define _INTSTATCLR0 _INT( 0x6000 ) +#define _INTSTATCLR1 _INT( 0x6400 ) +#define _INTSET0 _INT( 0x7000 ) +#define _INTSET1 _INT( 0x7400 ) + +#if ( LANGUAGE == C ) +#define INTTEST0 (*((volatile Word *) VirtAdd (_INTTEST0))) +#define INTTEST1 (*((volatile Word *) VirtAdd (_INTTEST1))) +#define INTENABLE0 (*((volatile Word *) VirtAdd (_INTENABLE0))) +#define INTENABLE1 (*((volatile Word *) VirtAdd (_INTENABLE1))) +#define INTPOL0 (*((volatile Word *) VirtAdd (_INTPOL0))) +#define INTPOL1 (*((volatile Word *) VirtAdd (_INTPOL1))) +#define INTTSTSEL (*((volatile Word *) VirtAdd (_INTTSTSEL))) +#define INTSTATCLR0 (*((volatile Word *) VirtAdd (_INTSTATCLR0))) +#define INTSTATCLR1 (*((volatile Word *) VirtAdd (_INTSTATCLR1))) +#define INTSET0 (*((volatile Word *) VirtAdd (_INTSET0))) +#define INTSET1 (*((volatile Word *) VirtAdd (_INTSET1))) + +#endif /* LANGUAGE == C */ + +/* + * PS/2 Trackpad and Mouse Interfaces + * + * Registers (prefix kbd applies to trackpad interface, mse to mouse) + * KBDCR Control Register + * KBDSTAT Status Register + * KBDDATA Transmit/Receive Data register + * KBDCLKDIV Clock Division Register + * KBDPRECNT Clock Precount Register + * KBDTEST1 Test register 1 + * KBDTEST2 Test register 2 + * KBDTEST3 Test register 3 + * KBDTEST4 Test register 4 + * MSECR + * MSESTAT + * MSEDATA + * MSECLKDIV + * MSEPRECNT + * MSETEST1 + * MSETEST2 + * MSETEST3 + * MSETEST4 + * + */ + +#define _KBD( x ) _SA1101( ( x ) + __TRACK_INTERFACE ) +#define _MSE( x ) _SA1101( ( x ) + __MOUSE_INTERFACE ) + +#define _KBDCR _KBD( 0x0000 ) +#define _KBDSTAT _KBD( 0x0400 ) +#define _KBDDATA _KBD( 0x0800 ) +#define _KBDCLKDIV _KBD( 0x0c00 ) +#define _KBDPRECNT _KBD( 0x1000 ) +#define _KBDTEST1 _KBD( 0x2000 ) +#define _KBDTEST2 _KBD( 0x2400 ) +#define _KBDTEST3 _KBD( 0x2800 ) +#define _KBDTEST4 _KBD( 0x2c00 ) +#define _MSECR _MSE( 0x0000 ) +#define _MSESTAT _MSE( 0x0400 ) +#define _MSEDATA _MSE( 0x0800 ) +#define _MSECLKDIV _MSE( 0x0c00 ) +#define _MSEPRECNT _MSE( 0x1000 ) +#define _MSETEST1 _MSE( 0x2000 ) +#define _MSETEST2 _MSE( 0x2400 ) +#define _MSETEST3 _MSE( 0x2800 ) +#define _MSETEST4 _MSE( 0x2c00 ) + +#if ( LANGUAGE == C ) + +#define KBDCR (*((volatile Word *) VirtAdd (_KBDCR))) +#define KBDSTAT (*((volatile Word *) VirtAdd (_KBDSTAT))) +#define KBDDATA (*((volatile Word *) VirtAdd (_KBDDATA))) +#define KBDCLKDIV (*((volatile Word *) VirtAdd (_KBDCLKDIV))) +#define KBDPRECNT (*((volatile Word *) VirtAdd (_KBDPRECNT))) +#define KBDTEST1 (*((volatile Word *) VirtAdd (_KBDTEST1))) +#define KBDTEST2 (*((volatile Word *) VirtAdd (_KBDTEST2))) +#define KBDTEST3 (*((volatile Word *) VirtAdd (_KBDTEST3))) +#define KBDTEST4 (*((volatile Word *) VirtAdd (_KBDTEST4))) +#define MSECR (*((volatile Word *) VirtAdd (_MSECR))) +#define MSESTAT (*((volatile Word *) VirtAdd (_MSESTAT))) +#define MSEDATA (*((volatile Word *) VirtAdd (_MSEDATA))) +#define MSECLKDIV (*((volatile Word *) VirtAdd (_MSECLKDIV))) +#define MSEPRECNT (*((volatile Word *) VirtAdd (_MSEPRECNT))) +#define MSETEST1 (*((volatile Word *) VirtAdd (_MSETEST1))) +#define MSETEST2 (*((volatile Word *) VirtAdd (_MSETEST2))) +#define MSETEST3 (*((volatile Word *) VirtAdd (_MSETEST3))) +#define MSETEST4 (*((volatile Word *) VirtAdd (_MSETEST4))) + + +#define KBDCR_ENA 0x08 +#define KBDCR_FKD 0x02 +#define KBDCR_FKC 0x01 + +#define KBDSTAT_TXE 0x80 +#define KBDSTAT_TXB 0x40 +#define KBDSTAT_RXF 0x20 +#define KBDSTAT_RXB 0x10 +#define KBDSTAT_ENA 0x08 +#define KBDSTAT_RXP 0x04 +#define KBDSTAT_KBD 0x02 +#define KBDSTAT_KBC 0x01 + +#define KBDCLKDIV_DivVal Fld(4,0) + +#define MSECR_ENA 0x08 +#define MSECR_FKD 0x02 +#define MSECR_FKC 0x01 + +#define MSESTAT_TXE 0x80 +#define MSESTAT_TXB 0x40 +#define MSESTAT_RXF 0x20 +#define MSESTAT_RXB 0x10 +#define MSESTAT_ENA 0x08 +#define MSESTAT_RXP 0x04 +#define MSESTAT_MSD 0x02 +#define MSESTAT_MSC 0x01 + +#define MSECLKDIV_DivVal Fld(4,0) + +#define KBDTEST1_CD 0x80 +#define KBDTEST1_RC1 0x40 +#define KBDTEST1_MC 0x20 +#define KBDTEST1_C Fld(2,3) +#define KBDTEST1_T2 0x40 +#define KBDTEST1_T1 0x20 +#define KBDTEST1_T0 0x10 +#define KBDTEST2_TICBnRES 0x08 +#define KBDTEST2_RKC 0x04 +#define KBDTEST2_RKD 0x02 +#define KBDTEST2_SEL 0x01 +#define KBDTEST3_ms_16 0x80 +#define KBDTEST3_us_64 0x40 +#define KBDTEST3_us_16 0x20 +#define KBDTEST3_DIV8 0x10 +#define KBDTEST3_DIn 0x08 +#define KBDTEST3_CIn 0x04 +#define KBDTEST3_KD 0x02 +#define KBDTEST3_KC 0x01 +#define KBDTEST4_BC12 0x80 +#define KBDTEST4_BC11 0x40 +#define KBDTEST4_TRES 0x20 +#define KBDTEST4_CLKOE 0x10 +#define KBDTEST4_CRES 0x08 +#define KBDTEST4_RXB 0x04 +#define KBDTEST4_TXB 0x02 +#define KBDTEST4_SRX 0x01 + +#define MSETEST1_CD 0x80 +#define MSETEST1_RC1 0x40 +#define MSETEST1_MC 0x20 +#define MSETEST1_C Fld(2,3) +#define MSETEST1_T2 0x40 +#define MSETEST1_T1 0x20 +#define MSETEST1_T0 0x10 +#define MSETEST2_TICBnRES 0x08 +#define MSETEST2_RKC 0x04 +#define MSETEST2_RKD 0x02 +#define MSETEST2_SEL 0x01 +#define MSETEST3_ms_16 0x80 +#define MSETEST3_us_64 0x40 +#define MSETEST3_us_16 0x20 +#define MSETEST3_DIV8 0x10 +#define MSETEST3_DIn 0x08 +#define MSETEST3_CIn 0x04 +#define MSETEST3_KD 0x02 +#define MSETEST3_KC 0x01 +#define MSETEST4_BC12 0x80 +#define MSETEST4_BC11 0x40 +#define MSETEST4_TRES 0x20 +#define MSETEST4_CLKOE 0x10 +#define MSETEST4_CRES 0x08 +#define MSETEST4_RXB 0x04 +#define MSETEST4_TXB 0x02 +#define MSETEST4_SRX 0x01 + +#endif /* LANGUAGE == C */ + + +/* + * General-Purpose I/O Interface + * + * Registers + * PADWR Port A Data Write Register + * PBDWR Port B Data Write Register + * PADRR Port A Data Read Register + * PBDRR Port B Data Read Register + * PADDR Port A Data Direction Register + * PBDDR Port B Data Direction Register + * PASSR Port A Sleep State Register + * PBSSR Port B Sleep State Register + * + */ + +#define _PIO( x ) _SA1101( ( x ) + __GPIO_INTERFACE ) + +#define _PADWR _PIO( 0x0000 ) +#define _PBDWR _PIO( 0x0400 ) +#define _PADRR _PIO( 0x0000 ) +#define _PBDRR _PIO( 0x0400 ) +#define _PADDR _PIO( 0x0800 ) +#define _PBDDR _PIO( 0x0c00 ) +#define _PASSR _PIO( 0x1000 ) +#define _PBSSR _PIO( 0x1400 ) + + +#if ( LANGUAGE == C ) + + +#define PADWR (*((volatile Word *) VirtAdd (_PADWR))) +#define PBDWR (*((volatile Word *) VirtAdd (_PBDWR))) +#define PADRR (*((volatile Word *) VirtAdd (_PADRR))) +#define PBDRR (*((volatile Word *) VirtAdd (_PBDRR))) +#define PADDR (*((volatile Word *) VirtAdd (_PADDR))) +#define PBDDR (*((volatile Word *) VirtAdd (_PBDDR))) +#define PASSR (*((volatile Word *) VirtAdd (_PASSR))) +#define PBSSR (*((volatile Word *) VirtAdd (_PBSSR))) + +#endif + + + +/* + * Keypad Interface + * + * Registers + * PXDWR + * PXDRR + * PYDWR + * PYDRR + * + */ + +#define _KEYPAD( x ) _SA1101( ( x ) + __KEYPAD_INTERFACE ) + +#define _PXDWR _KEYPAD( 0x0000 ) +#define _PXDRR _KEYPAD( 0x0000 ) +#define _PYDWR _KEYPAD( 0x0400 ) +#define _PYDRR _KEYPAD( 0x0400 ) + +#if ( LANGUAGE == C ) + + +#define PXDWR (*((volatile Word *) VirtAdd (_PXDWR))) +#define PXDRR (*((volatile Word *) VirtAdd (_PXDRR))) +#define PYDWR (*((volatile Word *) VirtAdd (_PYDWR))) +#define PYDRR (*((volatile Word *) VirtAdd (_PYDRR))) + +#endif + + + +/* + * PCMCIA Interface + * + * Registers + * PCSR Status Register + * PCCR Control Register + * PCSSR Sleep State Register + * + */ + +#define _CARD( x ) _SA1101( ( x ) + __PCMCIA_INTERFACE ) + +#define _PCSR _CARD( 0x0000 ) +#define _PCCR _CARD( 0x0400 ) +#define _PCSSR _CARD( 0x0800 ) + +#if ( LANGUAGE == C ) +#define PCSR (*((volatile Word *) VirtAdd (_PCSR))) +#define PCCR (*((volatile Word *) VirtAdd (_PCCR))) +#define PCSSR (*((volatile Word *) VirtAdd (_PCSSR))) + +#define PCSR_S0_ready 0x0001 +#define PCSR_S1_ready 0x0002 +#define PCSR_S0_detected 0x0004 +#define PCSR_S1_detected 0x0008 +#define PCSR_S0_VS1 0x0010 +#define PCSR_S0_VS2 0x0020 +#define PCSR_S1_VS1 0x0040 +#define PCSR_S1_VS2 0x0080 +#define PCSR_S0_WP 0x0100 +#define PCSR_S1_WP 0x0200 +#define PCSR_S0_BVD1_nSTSCHG 0x0400 +#define PCSR_S0_BVD2_nSPKR 0x0800 +#define PCSR_S1_BVD1_nSTSCHG 0x1000 +#define PCSR_S1_BVD2_nSPKR 0x2000 + +#define PCCR_S0_VPP0 0x0001 +#define PCCR_S0_VPP1 0x0002 +#define PCCR_S0_VCC0 0x0004 +#define PCCR_S0_VCC1 0x0008 +#define PCCR_S1_VPP0 0x0010 +#define PCCR_S1_VPP1 0x0020 +#define PCCR_S1_VCC0 0x0040 +#define PCCR_S1_VCC1 0x0080 +#define PCCR_S0_reset 0x0100 +#define PCCR_S1_reset 0x0200 +#define PCCR_S0_float 0x0400 +#define PCCR_S1_float 0x0800 + +#define PCSSR_S0_VCC0 0x0001 +#define PCSSR_S0_VCC1 0x0002 +#define PCSSR_S0_VPP0 0x0004 +#define PCSSR_S0_VPP1 0x0008 +#define PCSSR_S0_control 0x0010 +#define PCSSR_S1_VCC0 0x0020 +#define PCSSR_S1_VCC1 0x0040 +#define PCSSR_S1_VPP0 0x0080 +#define PCSSR_S1_VPP1 0x0100 +#define PCSSR_S1_control 0x0200 + +#endif + +#undef C +#undef Assembly diff -urN linux/include/asm-arm/arch-sa1100/hardware.h new/include/asm-arm/arch-sa1100/hardware.h --- linux/include/asm-arm/arch-sa1100/hardware.h Tue Aug 10 17:24:26 1999 +++ new/include/asm-arm/arch-sa1100/hardware.h Thu Jul 29 17:18:35 1999 @@ -47,12 +47,41 @@ #define PIO_START 0x80000000 +#ifdef CONFIG_SA1101 + +/* + * We have mapped the sa1101 depending + * on the value of SA1101_BASE + * so we also need to redefine the macros + * io_p2v and io_v2p + * + * SA1101_BASE virtual address + * 0x08000000 0xd9000000 bank2 + * 0x10000000 0xda000000 bank3 + * 0x18000000 0xdb000000 bank4 + * + */ + +#define io_p2v( x ) \ + (((x) & 0x00ffffff) | \ + (((x) & 0x38000000)>>VIO_SHIFT ) | \ + (((x) & 0x80000000)>>2 ) | 0xd8000000) + +#define io_v2p( x ) \ + (((x) & 0x00ffffff) | \ + (((x) & 0x20000000)<<2) | \ + (((x) & 0x07000000)<>VIO_SHIFT)) + VIO_BASE ) #define io_v2p( x ) \ ( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))<need_resched = 1; + printascii("everything up and running\n"); cpu_idle(NULL); } diff -urN linux/kernel/printk.c new/kernel/printk.c --- linux/kernel/printk.c Sat Mar 6 23:37:10 1999 +++ new/kernel/printk.c Thu Jul 29 14:42:01 1999 @@ -330,6 +330,9 @@ * that registers here. */ if (preferred_console < 0) { + printascii("console->setup: "); + printhex8(console->setup); + printascii("\n"); if (console->index < 0) console->index = 0; if (console->setup == NULL || @@ -369,9 +372,11 @@ * preferred driver at the head of the list. */ if ((console->flags & CON_CONSDEV) || console_drivers == NULL) { + printascii("c\n"); console->next = console_drivers; console_drivers = console; } else { + printascii("d\n"); console->next = console_drivers->next; console_drivers->next = console; } diff -urN linux/mm/slab.c new/mm/slab.c --- linux/mm/slab.c Tue Aug 10 17:24:17 1999 +++ new/mm/slab.c Wed Jul 28 18:10:05 1999 @@ -408,7 +408,7 @@ #define kmem_slab_diff(a,b) (kmem_slab_offset(a) - kmem_slab_offset(b)) #define kmem_cache_offset(x) ((unsigned long)&((kmem_cache_t *)0)->x) #define kmem_cache_diff(a,b) (kmem_cache_offset(a) - kmem_cache_offset(b)) - + /* Sanity checks... */ if (kmem_cache_diff(c_firstp, c_magic) != kmem_slab_diff(s_nextp, s_magic) || kmem_cache_diff(c_firstp, c_inuse) != kmem_slab_diff(s_nextp, s_inuse) || @@ -434,7 +434,7 @@ size += (L1_CACHE_BYTES-1); size &= ~(L1_CACHE_BYTES-1); cache_cache.c_offset = size-sizeof(kmem_bufctl_t); - + i = (PAGE_SIZE<