Update of /cvsroot/linux-vax/kernel-2.4/arch/cris/drivers/lpslave In directory usw-pr-cvs1:/tmp/cvs-serv13825/cris/drivers/lpslave Added Files: Makefile bintocarr.pl e100lpslave.README e100lpslave.S e100lpslave.h e100lpslaveld e100lpslavenet.c Log Message: synch 2.4.15 commit 29 --- NEW FILE --- # # Makefile for parallel port slave drivers # O_TARGET := lpslavedrivers.o obj-y = e100lpslavenet.o e100lpslave_code.o include $(TOPDIR)/Rules.make e100lpslave_code.o: e100lpslave.o e100lpslaveld $(CROSS_COMPILE)ld -qmagic -Te100lpslaveld e100lpslave.o -o e100lpslave $(CROSS_COMPILE)objcopy -O binary --remove-section=.data --remove-section=.bss e100lpslave e100lpslave.text $(CROSS_COMPILE)objcopy -O binary --remove-section=.text --remove-section=.bss e100lpslave e100lpslave.data cat e100lpslave.text e100lpslave.data |\ ./bintocarr.pl e100lpslaveprog |\ $(CC) $(CFLAGS) -pipe -o e100lpslave_code.o -c -x c - ls -l e100lpslave.text e100lpslave.data rm -f e100lpslave e100lpslave.text e100lpslave.data --- NEW FILE --- #!/usr/bin/perl -w # $Id: bintocarr.pl,v 1.1 2002/04/09 17:03:15 atp Exp $ # Copy of mkjulbin.pl made by Olof # convert a binary stdin to a C-file containing a char array of the input # first argument is the symbol name $symbol = shift @ARGV; print "#include <linux/init.h>\n\n"; #print "unsigned char $symbol", "[] __initdata = {\n"; print "unsigned char $symbol", "[] = {\n"; my $char; $bcount = 0; while(read STDIN, $char, 1) { printf("0x%x, ", ord($char)); $bcount++; if(!($bcount % 16)) { print "\n"; } } print "\n};\n"; $lensymb = ("_" . ($symbol . "_length")); print "__asm__(\"\\t.globl $lensymb\\n$lensymb = $bcount\\n\");\n"; --- NEW FILE --- ***** MODIFICATIONS To use a 5600 as a slave device it has to somewhat modified. This has to be done on a 5600 (art no 16144 R2) to automatically set it to parallel port boot mode: 1) Close to the LPT1 connector there are two resistors, between the "Pulse" inductor and the LS245. The one closest to the LS245 is a 4k7 pull up (R105). Remove it. 2) Between the other "Pulse" inductor and Etrax there is a black 5-pin inverter (D15). Short connectors 2 and 3 with a solder blob. ***** PINOUT To use this driver use cables connected like this: DSUB25-Male DSUB25Male 1 10 2-9 2-9 10 1 11 14 12 18 13 NC 14 11 15 NC 16 NC 17 NC 18 12 19 NC 20-25 20-25 Thus the cables are symmetrical with most cables straight through, some crossed (1-10, 11-14 and 12-18) and some Not connected (NC 13,15,16,17 and 19). ******* Only for reference To ease the use of flat-cable connectors, here are the notes of wich wires to cross and cut with pin 1 being cable 1: Cross: 1 19 2 21 10 23 Cut: 4 6 8 12 25 jon...@ax... --- NEW FILE --- ;; $Id: e100lpslave.S,v 1.1 2002/04/09 17:03:15 atp Exp $ ;; ;; Etrax100 slave network<->parport forwarder ;; ;; Copyright (c) 1999 Bjorn Wesen, Axis Communications AB ;; ;; We got 784 bytes (par loader size) to do DMA forwarding ;; between DMA0/1 (ethernet) and DMA3/4 (par port 0 RX/1 TX) ;; #include <linux/config.h> #if 0 #define ASSEMBLER_MACROS_ONLY #endif #include <asm/sv_addr_ag.h> #define BUFSIZE 0x600 ;; R_IRQ_READ2 #define DMA1EOPBIT 3 #define DMA0EOPBIT 1 #define DMA3EOPBIT 7 #define DMA4DESCBIT 8 ;; R_IRQ_READ0 #define PAR0ECPCMDBIT 11 ;; get host CMDs #include "e100lpslave.h" start: ;; disable interrupts. we are not going to use them at all. di ;; setup DMA connections and port configuration movu.w 0x84, r0 ; DMA2/3/4/5 to par ports move.d r0, [R_GEN_CONFIG] ;; setup port PA dirs and turn on the LED to show were alive movu.w 0x0cfb, r0 ; PA2-PA3 out, PA2 inactive move.d r0, [R_PORT_PA_SET] ;; enable MDIO output pin moveq IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable), r0 move.d r0, [R_NETWORK_MGM_CTRL] ;; accept broadcast frames, and enable station address 0 moveq IO_STATE(R_NETWORK_REC_CONFIG, broadcast, receive) | \ IO_STATE(R_NETWORK_REC_CONFIG, ma0, enable), r0 move.d r0, [R_NETWORK_REC_CONFIG] ;; use MII CLK mode, and enable the controller moveq IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | \ IO_STATE(R_NETWORK_GEN_CONFIG, enable, on), r0 move.d r0, [R_NETWORK_GEN_CONFIG] move.d IO_STATE(R_PAR0_CONFIG, ioe, noninv) | \ IO_STATE(R_PAR0_CONFIG, iseli, noninv) | \ IO_STATE(R_PAR0_CONFIG, iautofd, noninv) | \ IO_STATE(R_PAR0_CONFIG, istrb, noninv) | \ IO_STATE(R_PAR0_CONFIG, iinit, noninv) | \ IO_STATE(R_PAR0_CONFIG, iperr, noninv) | \ IO_STATE(R_PAR0_CONFIG, iack, noninv) | \ IO_STATE(R_PAR0_CONFIG, ibusy, noninv) | \ IO_STATE(R_PAR0_CONFIG, ifault, noninv) | \ IO_STATE(R_PAR0_CONFIG, isel, noninv) | \ IO_STATE(R_PAR0_CONFIG, dma, enable) | \ IO_STATE(R_PAR0_CONFIG, rle_in, disable) | \ IO_STATE(R_PAR0_CONFIG, rle_out, disable) | \ IO_STATE(R_PAR0_CONFIG, enable, on) | \ IO_STATE(R_PAR0_CONFIG, force, on) | \ IO_STATE(R_PAR0_CONFIG, mode, ecp_rev), r0 ; Reverse ECP - PAR0 is RX move.d r0, [R_PAR0_CONFIG] move.d IO_STATE(R_PAR1_CONFIG, ioe, noninv) | \ IO_STATE(R_PAR1_CONFIG, iseli, noninv) | \ IO_STATE(R_PAR1_CONFIG, iautofd, noninv) | \ IO_STATE(R_PAR1_CONFIG, istrb, noninv) | \ IO_STATE(R_PAR1_CONFIG, iinit, noninv) | \ IO_STATE(R_PAR1_CONFIG, iperr, inv) | \ IO_STATE(R_PAR1_CONFIG, iack, noninv) | \ IO_STATE(R_PAR1_CONFIG, ibusy, noninv) | \ IO_STATE(R_PAR1_CONFIG, ifault, noninv) | \ IO_STATE(R_PAR1_CONFIG, isel, noninv) | \ IO_STATE(R_PAR1_CONFIG, dma, enable) | \ IO_STATE(R_PAR1_CONFIG, rle_in, disable) | \ IO_STATE(R_PAR1_CONFIG, rle_out, disable) | \ IO_STATE(R_PAR1_CONFIG, enable, on) | \ IO_STATE(R_PAR1_CONFIG, force, on) | \ IO_STATE(R_PAR1_CONFIG, mode, ecp_fwd), r0 ; Forward ECP - PAR1 is TX move.d r0, [R_PAR1_CONFIG] moveq IO_FIELD(R_PAR1_DELAY, setup, 0), r0 ; setup time of value * 160 + 20 == 20 ns move.d r0, [R_PAR1_DELAY] ;; we got four descriptors, that can be active at the same time: ;; 1) from network ;; 2) to parport ;; 3) from parport ;; 4) to network ;; ;; we got four buffers, each can hold a max packet (we use 1536 bytes) ;; buffers 1 and 2 are used from network to parport, while ;; buffers 3 and 4 are used from parport to network. ;; ;; a double buffering scheme is used, so that new data can be read ;; into a buffer pair while the last data is written out from the ;; last buffer. if the read buffer is done before the write buffer, ;; the reading will halt until the writing is done, at which point ;; writing starts from the newly read and reading can start with ;; the newly written. ;; move.d R_DMA_CH0_FIRST, r1 ; we use this as base for subsequent DMA ops moveq IO_STATE(R_DMA_CH1_CMD, cmd, start), r6 move.d FN1desc, r7 move.d R_IRQ_READ0, r9 ;; start receiving from network jsr startdmaFPTN jsr startdmaFNTP ;; ------------------- MAIN LOOP ;; IRQ bits: parport rcv is par0_ecp_cmd, then dma3_eop ;; network rcv is dma1_eop ;; parport tx is dma4_desc ;; network tx is dma0_eop mainloop: ;; ------- first handle the parport -> network link ;; check if we got something from the parport move.d [r9], r0 ; r0 <- *R_IRQ_READ0 btstq PAR0ECPCMDBIT, r0 bpl noparecp nop ;; ack it by reading PAR0_STATUS_DATA move.d [R_PAR0_STATUS_DATA], r0 ;; trigger EOP on DMA3 (par0 incoming channel) moveq IO_STATE(R_SET_EOP, ch3_eop, set), r0 move.d r0, [R_SET_EOP] noparecp: ;; if we simultaneously have parport rx EOP and ;; network TX eop, we can swap buffers and start a new RX/TX move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0 btstq DMA3EOPBIT, r0 ; check parport rx bpl noswap1 btstq DMA0EOPBIT, r0 ; check network tx bpl noswap1 nop ;; prepare to swap buffer ptrs (FN3b <-> TN4b) move.d [r4 = r7 + 56], r0; FP3b move.d [r3 = r7 + 72], r2; TN4b ;; but first check if this was a Host Command Packet move.d [r0], r5 ; r5 <- first 4 bytes in PAR-received packet bne handle_command ; if non-zero, it was a host command addq 4, r0 ; skip command (in delay slot - handle_command requires this) move.d r0, [r3] ; write to To Network descriptor subq 4, r2 ; undo the skipping done last swap move.d r2, [r4] ; write to From Parport descriptor ;; clear the interrupts moveq IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do), r0 move.b r0, [r1 + (R_DMA_CH0_CLR_INTR - R_DMA_CH0_FIRST)] move.b r0, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)] ;; copy received length to outgoing network length move.w [r7 + 60], r0 ; FPhlen subq 4, r0 ; skip command move.w r0, [r7 + 64] ; TN4desc ;; restart DMAs jsr startdmaFPTN #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS #if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK) ;; Turn off the LED signaling an outgoing network packet movu.b [LEDOff], r0 #elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY) ;; Light the LED signaling an outgoing network packet movu.b [LEDAmber], r0 #else #error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY" #endif move.b r0, [R_PORT_PA_DATA] move.d 0x00011000, r0 move.d r0,[LEDCount] #endif noswap1: ;; ----- now check the network -> parport link ;; if we simultaneously have network rx EOP and ;; parport TX desc, we can swap buffers and start a new RX/TX move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0 btstq DMA1EOPBIT, r0 ; check network rx bpl noswap2 btstq DMA4DESCBIT, r0 ; check parport tx bpl noswap2 nop ;; prepare to swap buffer ptrs (FP1b <-> TP2b) move.d [r4 = r7 + 8], r0; FN1b move.d [r3 = r7 + 24], r2; TP2b move.d r0, [r3] ; write to To Parport descriptor move.d r2, [r4] ; write to From Network descriptor ;; clear the interrupts moveq IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) | \ IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do), r0 move.b r0, [r1 + (R_DMA_CH1_CLR_INTR - R_DMA_CH0_FIRST)] move.b r0, [r1 + (R_DMA_CH4_CLR_INTR - R_DMA_CH0_FIRST)] ;; copy received network length to outgoing parport length move.w [r7 + 12], r0 ; FNhlen move.w r0, [r7 + 16] ; TP2desc ;; restart DMAs jsr startdmaFNTP #if 0 #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS ;; Light the LED signaling an incoming networkpacket movu.b 0xFB, r0 move.b r0, [R_PORT_PA_DATA] move.d 0x00010000, r0 move.d r0,[LEDCount] #endif #endif noswap2: #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS ;; Count down LED counter, and turn off the network LED if required move.d [LEDCount], r0 beq mainloop nop subq 1, r0 move.d r0, [LEDCount] bne mainloop nop #if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK) ;; Light the network LED , and start over the main loop movu.b [LEDAmber], r0 #elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY) ;; Turn off the network LED, and start over the main loop movu.b [LEDOff], r0 #else #error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY" #endif move.b r0, [R_PORT_PA_DATA] #endif ba mainloop nop ;; --- some useful subroutines. handle_command: ;; handle command. we also need to clear the PAR0 RX EOP IRQ, and ;; restart the PAR0 dma. command is in R5, packet after cmd is in R0 moveq IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do), r2 move.b r2, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)] cmpq HOST_CMD_SETMAC, r5 bne no_setmac nop ;; copy station address (6 bytes) from packet to hardware move.d [r0+], r2 move.d R_NETWORK_SA_0, r3 move.d r2, [r3] move.w [r0], r2 move.w r2, [r3 + 4] no_setmac: move noswap1, SRP ba startdmaFP nop ;; start DMAs, from parport and to network startdmaFPTN: ;; start transmitting to the network (CH0) move.d TN4desc, r8 move.d r8, [r1] ; TN4desc -> FIRST0 move.b r6, [r1 + (R_DMA_CH0_CMD - R_DMA_CH0_FIRST)] ; start -> CMD0 startdmaFP: ;; start receiving from parport (CH3) move.d FP3desc, r8 move.d r8, [r1 + (R_DMA_CH3_FIRST - R_DMA_CH0_FIRST)] ; FP3desc -> FIRST3 move.b r6, [r1 + (R_DMA_CH3_CMD - R_DMA_CH0_FIRST)] ; start -> CMD3 ret nop ;; start DMAs, from network and to parport startdmaFNTP: ;; start transmitting to the parport (CH4) move.d TP2desc, r8 move.d r8, [r1 + (R_DMA_CH4_FIRST - R_DMA_CH0_FIRST)] ; TP2desc -> FIRST4 move.b r6, [r1 + (R_DMA_CH4_CMD - R_DMA_CH0_FIRST)] ; start -> CMD4 ;; start receiving from network (CH1) (r7 already contains FN1desc) move.d r7, [r1 + (R_DMA_CH1_FIRST - R_DMA_CH0_FIRST)] ; FN1desc -> FIRST1 move.b r6, [r1 + (R_DMA_CH1_CMD - R_DMA_CH0_FIRST)] ; start -> CMD1 ret nop ;; --- DMA descriptors - each descriptor is 4 longwords (16 bytes) ;; DONT MOVE THESE AROUND. Due to the as/ld "hole-in-the-head", ;; we cant write stuff like (TP2b - TP2desc) but the offsets ;; have to be hardcoded. .data ;; 0 from network FN1desc: .word BUFSIZE ; sw_len .word 0x0001 ; ctrl, d_eol is only flag we need .dword 0 ; next FN1b: .dword buffers ; buffer 1 8 .word 0 ; hw_len .word 0 ; status ;; 16 to parport TP2desc: .word 2 ; sw_len, filled in by code .word 0x0004 ; ctrl, d_wait because ecp cmd in next .dword TP2desc2 ; next TP2b: .dword buffers + BUFSIZE ; buffer 2 24 .word 0 ; hw_len .word 0 ; status ;; 32 to parport second descriptor, for the ECP command TP2desc2: .word 0x0001 ; sw_len, 1 byte (ecp command) .word 0x0019 ; ctrl, d_ecp | d_eol | d_int .dword 0 ; next .dword TP2desc2 ; buffer, dont care .word 0 ; hw_len .word 0 ; status ;; 48 from parport FP3desc: .word BUFSIZE ; sw_len .word 0x0001 ; ctrl, d_eol is only flag we need .dword 0 ; next FP3b: .dword buffers + BUFSIZE * 2 ; 56 buffer 3 FPhlen: .word 0 ; 60 hw_len .word 0 ; status ;; 64 to network TN4desc: .word 2 ; sw_len, filled in by code .word 0x0007 ; ctrl, d_eop | d_eol | d_wait .dword 0 ; next TN4b: .dword buffers + BUFSIZE * 3 + 4 ; 72 buffer 4 (the +4 is to offset the anti-skipping) .word 0 ; hw_len .word 0 ; status #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS LEDCount: .dword 0 LEDOff: .word 0xff LEDGreen: .word 0xfb LEDRed: .word 0xf7 LEDAmber: .word 0xf3 LED: .word 0xf7 #endif ;; after the prog we put the buffers. not in the asm program, we just use ;; the address generated buffers: ;; END --- NEW FILE --- #define HOST_CMD_SENDPACK 0 #define HOST_CMD_SETMAC 1 --- NEW FILE --- MEMORY { cache : ORIGIN = 0x380000f0, LENGTH = 784 } SECTIONS { .text : { *(.text) } > cache .data : { *(.data) *(COMMON) } > cache .bss : { *(.bss) } > cache } --- NEW FILE --- /* $Id: e100lpslavenet.c,v 1.1 2002/04/09 17:03:15 atp Exp $ * * e100lpslavenet.c: A network driver for the ETRAX 100LX slave controller. * * Copyright (c) 1998-2001 Axis Communications AB. * * The outline of this driver comes from skeleton.c. * * $Log: e100lpslavenet.c,v $ * Revision 1.1 2002/04/09 17:03:15 atp * synch 2.4.15 commit 29 * * Revision 1.4 2001/06/21 16:55:26 olof * Minimized par port setup time to gain bandwidth * * Revision 1.3 2001/06/21 15:49:02 olof * Removed setting of default MAC address * * Revision 1.2 2001/06/11 15:39:52 olof [...996 lines suppressed...] } #endif /* ETHDEBUG */ static struct net_device dev_etrax_slave_ethernet; static int etrax_init_module(void) { struct net_device *d = &dev_etrax_slave_ethernet; d->init = etrax_ethernet_lpslave_init; if(register_netdev(d) == 0) return 0; else return -ENODEV; } module_init(etrax_init_module); |