LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Syscall auditing and seccomp for PPC32.
From: David Woodhouse @ 2005-05-08 15:07 UTC (permalink / raw)
  To: paulus, benh; +Cc: linuxppc-dev

For information (and feedback) only. Do not apply; it's already in 
    rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git

Why _is_ do_syscall_trace() exported, anyway?

Index: arch/ppc/Kconfig
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/arch/ppc/Kconfig  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/arch/ppc/Kconfig  (mode:100644)
@@ -1083,6 +1083,23 @@
 
 source kernel/power/Kconfig
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 config ISA_DMA_API
Index: arch/ppc/kernel/entry.S
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/arch/ppc/kernel/entry.S  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/arch/ppc/kernel/entry.S  (mode:100644)
@@ -202,7 +202,7 @@
 	rlwinm	r11,r11,0,~_TIFL_FORCE_NOERROR
 	stw	r11,TI_LOCAL_FLAGS(r10)
 	lwz	r11,TI_FLAGS(r10)
-	andi.	r11,r11,_TIF_SYSCALL_TRACE
+	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
 	cmplwi	0,r0,NR_syscalls
@@ -237,7 +237,7 @@
 	SYNC
 	MTMSRD(r10)
 	lwz	r9,TI_FLAGS(r12)
-	andi.	r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
 	bne-	syscall_exit_work
 syscall_exit_cont:
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -277,7 +277,8 @@
 	SAVE_NVGPRS(r1)
 	li	r0,0xc00
 	stw	r0,TRAP(r1)
-	bl	do_syscall_trace
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_syscall_trace_enter
 	lwz	r0,GPR0(r1)	/* Restore original registers */
 	lwz	r3,GPR3(r1)
 	lwz	r4,GPR4(r1)
@@ -291,7 +292,7 @@
 syscall_exit_work:
 	stw	r6,RESULT(r1)	/* Save result */
 	stw	r3,GPR3(r1)	/* Update return value */
-	andi.	r0,r9,_TIF_SYSCALL_TRACE
+	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
 	beq	5f
 	ori	r10,r10,MSR_EE
 	SYNC
@@ -303,7 +304,8 @@
 	li	r4,0xc00
 	stw	r4,TRAP(r1)
 4:
-	bl	do_syscall_trace
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_syscall_trace_leave
 	REST_NVGPRS(r1)
 2:
 	lwz	r3,GPR3(r1)
@@ -627,8 +629,8 @@
 	subi	r1,r3,STACK_FRAME_OVERHEAD
 	rlwinm	r12,r1,0,0,18	/* current_thread_info() */
 	lwz	r9,TI_FLAGS(r12)
-	andi.	r0,r9,_TIF_SYSCALL_TRACE
-	bnel-	do_syscall_trace
+	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
+	bnel-	do_syscall_trace_leave
 	/* fall through */
 
 	.globl	ret_from_except_full
Index: arch/ppc/kernel/ppc_ksyms.c
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/arch/ppc/kernel/ppc_ksyms.c  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/arch/ppc/kernel/ppc_ksyms.c  (mode:100644)
@@ -55,7 +55,6 @@
 #define EXPORT_SYMTAB_STROPS
 
 extern void transfer_to_handler(void);
-extern void do_syscall_trace(void);
 extern void do_IRQ(struct pt_regs *regs);
 extern void MachineCheckException(struct pt_regs *regs);
 extern void AlignmentException(struct pt_regs *regs);
@@ -74,7 +73,6 @@
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(do_signal);
-EXPORT_SYMBOL(do_syscall_trace);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(MachineCheckException);
Index: arch/ppc/kernel/ptrace.c
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/arch/ppc/kernel/ptrace.c  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/arch/ppc/kernel/ptrace.c  (mode:100644)
@@ -27,6 +27,9 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/seccomp.h>
+#include <linux/audit.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -455,11 +458,10 @@
 	return ret;
 }
 
-void do_syscall_trace(void)
+static void do_syscall_trace(void)
 {
-        if (!test_thread_flag(TIF_SYSCALL_TRACE)
-	    || !(current->ptrace & PT_PTRACED))
-		return;
+	/* the 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
 	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 				 ? 0x80 : 0));
 
@@ -473,3 +475,33 @@
 		current->exit_code = 0;
 	}
 }
+
+void do_syscall_trace_enter(struct pt_regs *regs)
+{
+	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	    && (current->ptrace & PT_PTRACED))
+		do_syscall_trace();
+
+	if (unlikely(current->audit_context))
+		audit_syscall_entry(current, AUDIT_ARCH_PPC,
+				    regs->gpr[0],
+				    regs->gpr[3], regs->gpr[4],
+				    regs->gpr[5], regs->gpr[6]);
+}
+
+void do_syscall_trace_leave(struct pt_regs *regs)
+{
+	secure_computing(regs->gpr[0]);
+
+	if (unlikely(current->audit_context))
+		audit_syscall_exit(current,
+				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+				   regs->result);
+
+	if ((test_thread_flag(TIF_SYSCALL_TRACE))
+	    && (current->ptrace & PT_PTRACED))
+		do_syscall_trace();
+}
+
+EXPORT_SYMBOL(do_syscall_trace_enter);
+EXPORT_SYMBOL(do_syscall_trace_leave);
Index: include/asm-ppc/thread_info.h
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/include/asm-ppc/thread_info.h  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/include/asm-ppc/thread_info.h  (mode:100644)
@@ -77,12 +77,19 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
+#define TIF_SECCOMP             7      /* secure computing */
+
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_SYSCALL_AUDIT      (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP            (1<<TIF_SECCOMP)
+
+#define _TIF_SYSCALL_T_OR_A     (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 /*
  * Non racy (local) flags bit numbers
Index: init/Kconfig
===================================================================
--- 6cdd9771bd9a56de1b0246a330ccd916ecdb1d41/init/Kconfig  (mode:100644)
+++ 27383b18b9f62d3c4f1b5dd9f3daeffb10416c15/init/Kconfig  (mode:100644)
@@ -173,7 +173,7 @@
 
 config AUDITSYSCALL
 	bool "Enable system-call auditing support"
-	depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
+	depends on AUDIT && (X86 || PPC || PPC64 || ARCH_S390 || IA64 || UML)
 	default y if SECURITY_SELINUX
 	help
 	  Enable low-overhead system-call auditing infrastructure that

-- 
dwmw2

^ permalink raw reply

* Re: Laptop sleep & current "git" tree
From: John Steele Scott @ 2005-05-08 22:35 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: debian-powerpc
In-Reply-To: <20050508113925.36f9989f@jack.colino.net>

[-- Attachment #1: Type: text/plain, Size: 818 bytes --]

Colin Leroy <colin@colino.net> writes:
> On 08 May 2005 at 14h05, John Steele Scott wrote:
>> I finally tried this today, using 2.6.12-rc4, which has this patch.
>> Without USB devices attached, it's okay, but with my USB hub
>> attached, I get a (reproducable) panic in echi_hcd on the way to
>> sleep.
>> 
>> I took a photo of the panic and enhanced it for readability, it's at
>> <http://www.toojays.net/portal/Members/toojays/ibook-g4-sleep-crash-2.6.12-rc4.jpg>.
>
> linux-usb-devel may be interested. (I don't have an usb hub so can't
> test it)

I forwarded the bug report to linux-usb-devel as per Colin's suggestion, and
David Brownell has fixed it. His post, which includes the patch, can be found
at <http://marc.theaimsgroup.com/?l=linux-usb-devel&m=111558764113428&w=2>

cheers,

John

[-- Attachment #2: Type: application/pgp-signature, Size: 282 bytes --]

^ permalink raw reply

* RE: Network Setup - HOW TO
From: Atit_Shah @ 2005-05-09  5:46 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

My company uses the 172.19.x.x IP addresses, I want a PC with
192.168.x.x IP address to access the company network via a router. I
have a router running Linux and having 2 Ethernet ports. I configured
the systems in the following 2 ways:

1. Eth0 (LAN port) - 172.19.56.218=20
   Eth1 (WAN port) - 172.19.56.219
   Single System   - 192.168.100.10 - IP Address
			   172.19.56.218  - Gateway
			   172.19.56.218  - DNS

2. Eth0 (LAN port) - 192.168.100.20=20
   Eth1 (WAN port) - 172.19.56.219
   Single System   - 192.168.100.10 - IP Address
			   192.168.100.20 - Gateway
			   192.168.100.20 - DNS
	  =09
But I am not able to ping from the router to my single system in either
way.
How should I configure router to make this possible for the 2 networks
to communicate?=20

The second question is how to run DHCP on my router so it can receive a
dynamic IP and assign dynamic IP when I power my router?=20

Atit


-----Original Message-----
From: Grant Likely [mailto:glikely@gmail.com]=20
Sent: Friday, May 06, 2005 8:59 PM
To: Atit_Shah
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: Network Setup - HOW TO

On 5/5/05, Atit_Shah <Atit_Shah@satyam.com> wrote:
> Hi all,
>=20
>         I have a custom board designed to function as a router. It has
2
> Ethernet ports. Eth1 is a WAN port and Eth0 is a LAN port. This is
what
> I wish to do:
> 1. connect the board/router to my company network
> 2. connect a normal system running windows or linux to the router
> 3. I should be able to ping or browse the net using the normal system
> via the router through the company network.
>=20
> I have connect the normal network cable (not a cross wire cable)
between
> the router and the company network. The router does not seem to get a
> dynamic IP. Why and What should I do for it to get one?
Are you running a dhcp client?  Let's see the log output
>=20
> I connect a system to eth0 again with a normal network cable (not a
> cross wire cable) but the system does not seem to get an IP assigned
> even when I run the dhcp server on my router....used udhcpd command.
Why
> and how can I get it up?
What do you see on the wire?  Bring up Ethereal to capture traffic.

>=20
> Appreciate a response on this....
Not enough information.  Include output logs please.



DISCLAIMER:
This email (including any attachments) is intended for the sole use of =
the intended recipient/s and may contain material that is CONFIDENTIAL =
AND PRIVATE COMPANY INFORMATION. Any review or reliance by others or =
copying or distribution or forwarding of any or all of the contents in =
this message is STRICTLY PROHIBITED. If you are not the intended =
recipient, please contact the sender by email and delete all copies; =
your cooperation in this regard is appreciated.

^ permalink raw reply

* Re: [PATCH] 8xx: fix usage of pinned 8Mbyte TLB entries
From: Pantelis Antoniou @ 2005-05-09  6:09 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20050507140527.GC16996@logos.cnet>

Marcelo Tosatti wrote:
>>NO.  Just leave that code alone.  I don't understand why you think
>>doing this will have any effect on the system operation.  If you are
>>able to run a system without creating these tables, then the pinned
>>TLBs must be working.  If pinned TLBs weren't working, the kernel
>>would crash.
> 
> 
> I just booted a kernel with 4kb PTE mappings at KERNELBASE and
> the pinned TLB was not trashed.
> 
> So, I was talking nonsense. :)
> 
> The only problem are DMA users who dont use dma_alloc_coherent API. 
> 
> 
> 

Perhaps I'm jumping in too late, but in my 8xx trees all my drivers
use the correct API. So this will not be a problem after we fix the
drivers :)

Regards

Pantelis

^ permalink raw reply

* Re: Laptop sleep & current "git" tree
From: Colin Leroy @ 2005-05-09  6:35 UTC (permalink / raw)
  To: John Steele Scott; +Cc: linuxppc-dev, debian-powerpc
In-Reply-To: <8764xtxs61.fsf@toojays.net>

On Mon, 09 May 2005 08:05:18 +0930
John Steele Scott <toojays@toojays.net> wrote:

> I forwarded the bug report to linux-usb-devel as per Colin's
> suggestion, and David Brownell has fixed it. His post, which includes
> the patch, can be found at
> <http://marc.theaimsgroup.com/?l=linux-usb-devel&m=111558764113428&w=2>

Great! Do you know if he plans pushing it to 2.6.12 quickly? 

-- 
Colin

^ permalink raw reply

* Re: Network Setup - HOW TO
From: Grant Likely @ 2005-05-09  6:36 UTC (permalink / raw)
  To: Atit_Shah; +Cc: linuxppc-embedded
In-Reply-To: <D8595042F3765A4285B848A78A2C2ED102779F@bsdmsg002.corp.satyam.ad>

On 5/8/05, Atit_Shah <Atit_Shah@satyam.com> wrote:
> My company uses the 172.19.x.x IP addresses, I want a PC with
> 192.168.x.x IP address to access the company network via a router. I
> have a router running Linux and having 2 Ethernet ports. I configured
> the systems in the following 2 ways:
So, two subnets:
Eth0 on subnet 192.168.0.0/255.255.0.0
Eth1 on subnet 172.19.0.0/255.255.0.0

>=20
> 1. Eth0 (LAN port) - 172.19.56.218
>    Eth1 (WAN port) - 172.19.56.219
>    Single System   - 192.168.100.10 - IP Address
>                            172.19.56.218  - Gateway
>                            172.19.56.218  - DNS
This is wrong.  IP address for Eth0 must be on the 192.168.0.0/16 subnet

>=20
> 2. Eth0 (LAN port) - 192.168.100.20
>    Eth1 (WAN port) - 172.19.56.219
>    Single System   - 192.168.100.10 - IP Address
>                            192.168.100.20 - Gateway
>                            192.168.100.20 - DNS
This is correct, but the DNS server does not have to be your router.

>=20
> But I am not able to ping from the router to my single system in either
> way.
> How should I configure router to make this possible for the 2 networks
> to communicate?
Is you netmask set right?  Does /sbin/route show sane IP routes?  What
do you see on the wire? (Use Ethereal on a third computer).  If you
cannot ping then you've got a fundamental flaw in your configurations.
 Get this working before worrying about DHCP or routing.

>=20
> The second question is how to run DHCP on my router so it can receive a
> dynamic IP and assign dynamic IP when I power my router?
You need to run both dhcpd and dhcpcd.  dhcpd to assign IP to your
client.  dhcpcd to get an IP from the network.

It sounds like you need to brush up on your IP networking knowledge w/
linux.  Go look at the howtos on www.tldp.org.  Specifically on
networking and DHCP.  You should get this stuff working on a regular
PC w/ 2 network cards running linux first before trying to get it
going on your embedded board.

Also, as I asked before, please include relevant output logs with your
posts and I strongly recommend sniffing the Ethernet traffic with a
tool like Ethereal.

g.

^ permalink raw reply

* Linuxppc-embedded Digest, montavista
From: Gopala Krishnam Raju @ 2005-05-09  7:28 UTC (permalink / raw)
  To: linuxppc-embedded

hello Linux gurus

I have created a boot image for montavista doing the following way.

1. I did make mrproper.

2. Then make xconfig.

3. Selected the target architecture.

4. saved the configuration file and then

5. I have said make dep.  There was no errors it compiled well.

6. I ran make bzImage to get the bzImage.  It also went well without any =
errors.

7. got the bzImage in /linux..../arch/i386/boot/.  then i have copied =
this to /boot.

8. Made necessary changes in the grub.conf.

	but while booting i am getting an error saying that vfs: kernal panic.
	any ideas regarding this.

	i also tried with make modules. =20

	that also went well. but after starting with the new kernel it is =
giving error vfs: kernal panic.

	target and host are both platforms.=20

Regards

GGKRAJU

^ permalink raw reply

* RE: Linuxppc-embedded Digest, montavista
From: Gopala Krishnam Raju @ 2005-05-09 10:13 UTC (permalink / raw)
  To: Vijesh VH; +Cc: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1622 bytes --]

Hello vijesh
 
that i could not make i am getting error for that so i am using the base os initrd i.e fedora core 3 initrd
 
Regards
 
GGKRAJU

-----Original Message-----
From: Vijesh VH [mailto:vijesh.vh@gmail.com]
Sent: Monday, May 09, 2005 3:14 PM
To: Gopala Krishnam Raju
Subject: Re: Linuxppc-embedded Digest, montavista


Hello Raju,
You have to create Initrd using initrd command and do necessary changes in the grub and in /boot folder

Regards
Vijesh.. 


On 5/9/05, Gopala Krishnam Raju < graju@facetime.com> wrote: 

hello Linux gurus

I have created a boot image for montavista doing the following way.

1. I did make mrproper.

2. Then make xconfig.

3. Selected the target architecture.

4. saved the configuration file and then 

5. I have said make dep.  There was no errors it compiled well.

6. I ran make bzImage to get the bzImage.  It also went well without any errors.

7. got the bzImage in /linux..../arch/i386/boot/.  then i have copied this to /boot. 

8. Made necessary changes in the grub.conf.

        but while booting i am getting an error saying that vfs: kernal panic.
        any ideas regarding this.

        i also tried with make modules. 

        that also went well. but after starting with the new kernel it is giving error vfs: kernal panic.

        target and host are both platforms.

Regards

GGKRAJU
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded





-- 
Thanks and Regards,
Vijesh V H 


[-- Attachment #2: Type: text/html, Size: 3568 bytes --]

^ permalink raw reply

* Writing a small test program - a bit off topic
From: Peter Asemann @ 2005-05-09  9:58 UTC (permalink / raw)
  To: linuxppc-embedded

Hi there!

I *hope* this mail isn't very off topic. In principle it probably is, 
but I don't know a mailing list which is about writing test programs to 
test processors in order to debug a hardware to get linux running. Plus, 
I suppose there are people out there who could help me. So I hope you 
won't stone me for this post.

Whatever:
I have to write some test program for a mpc875 processor. It should run 
in the processor cache as the memory of the hardware doesn't work for 
hardware-problem-reasons.

I set up the memory mapping of the IMMR of the processor with the 
debugger (BDM4GDB) so the IMMR is at 0xff000000.
Then I want to change the state of two leds. This can be done by writing 
some values into some memory-mapped MPC registers (PEDAT / PEDIR) which 
reside at IMMR + 0xac8 / 0xad8.

I wrote a C program to do that; As there is no OS I think I can just try 
to write to memory locations directly:

#define CONFIG_8xx

int main(void){
long* a;
long* b;
a = (long*)0xff000ac8;
*a = 0x00001800;
b = (long*)0xff000ad8;
*b = 0x00001800;
}

Actually, if I compile it (using Denx ELDK 3.1) with

ppc-linux-gcc -static led.c -o led

the resulting program is 477K big.
On the other hand, if I do

ppc-linux-as -mcom led.s
and
ppc-linux-as -mcom led.s -o led.bin

the resulting program is 439 byte big.

Now, my questions are: Will the 439 byte program faciliated this way do 
what I want? Did I make some fatal newbie mistakes? Does somebody know 
how to upload code to the mpc instruction cache and execute it?

Thanks for reading,

Peter Asemann

^ permalink raw reply

* RE: Linuxppc-embedded Digest, montavista
From: Gopala Krishnam Raju @ 2005-05-09 10:36 UTC (permalink / raw)
  To: Vijesh VH; +Cc: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 2204 bytes --]

Hello Vijesh
 
both the target and the host are the same. Then also i am getting the same problem
 
Regards
 
GGKRAJU

-----Original Message-----
From: Vijesh VH [mailto:vijesh.vh@gmail.com]
Sent: Monday, May 09, 2005 3:50 PM
To: Gopala Krishnam Raju
Subject: Re: Linuxppc-embedded Digest, montavista


raju,

     if you use that you will get that error only. you have create it for your specified target. (if your target and host is not same)


On 5/9/05, Gopala Krishnam Raju < graju@facetime.com> wrote: 

Hello vijesh
 
that i could not make i am getting error for that so i am using the base os initrd i.e fedora core 3 initrd
 
Regards
 
GGKRAJU


-----Original Message-----
From: Vijesh VH [mailto: vijesh.vh@gmail.com]
Sent: Monday, May 09, 2005 3:14 PM
To: Gopala Krishnam Raju
Subject: Re: Linuxppc-embedded Digest, montavista


Hello Raju,
You have to create Initrd using initrd command and do necessary changes in the grub and in /boot folder

Regards
Vijesh.. 


On 5/9/05, Gopala Krishnam Raju < graju@facetime.com> wrote: 

hello Linux gurus

I have created a boot image for montavista doing the following way.

1. I did make mrproper.

2. Then make xconfig.

3. Selected the target architecture.

4. saved the configuration file and then 

5. I have said make dep.  There was no errors it compiled well.

6. I ran make bzImage to get the bzImage.  It also went well without any errors.

7. got the bzImage in /linux..../arch/i386/boot/.  then i have copied this to /boot. 

8. Made necessary changes in the grub.conf.

        but while booting i am getting an error saying that vfs: kernal panic.
        any ideas regarding this.

        i also tried with make modules. 

        that also went well. but after starting with the new kernel it is giving error vfs: kernal panic.

        target and host are both platforms.

Regards

GGKRAJU
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded





-- 
Thanks and Regards,
Vijesh V H 




-- 
Thanks and Regards,
Vijesh V H 


[-- Attachment #2: Type: text/html, Size: 5761 bytes --]

^ permalink raw reply

* Re: 824x sandpoint and 2.6.x
From: Sam Song @ 2005-05-09 11:53 UTC (permalink / raw)
  To: Mark A. Greer; +Cc: linuxppc-embedded
In-Reply-To: <42718380.3050902@mvista.com>

Hi Mark,

It booted finally although something more need to
fix later. It truned out to be the problem of
UART init part.

"Mark A. Greer" <mgreer@mvista.com> wrote:

> Here is the output of a 7457 sandpoint on a very old
> root filesystem.
> Output for any other processor will be the same.

Thanks so much,

Sam

_________________________________________________________
Do You Yahoo!?
150万曲MP3疯狂搜,带您闯入音乐殿堂
http://music.yisou.com/
美女明星应有尽有,搜遍美图、艳图和酷图
http://image.yisou.com
1G就是1000兆,雅虎电邮自助扩容!
http://cn.rd.yahoo.com/mail_cn/tag/1g/*http://cn.mail.yahoo.com/event/mail_1g/

^ permalink raw reply

* [HEADS UP]  Freescale Ethernet combined driver
From: Pantelis Antoniou @ 2005-05-09 11:44 UTC (permalink / raw)
  To: Dan Malek, Kumar Gala, Eugene Surovegin, Vitaly Bordug, Tom Rini,
	Marcelo Tosatti, Jason McMullan, linuxppc-embedded

Hi

A patch containing a combined Freescale Ethernet driver for the
PQI/PQII, will follow. The patch is against 2.6.11.7 since my git-foo
is at bit weak.

Note that it's not a superset of all the FEC/FCC drivers floating
around; it's geared to be the base of the final community developed driver.

Let's talk about it...

Regards

Pantelis

^ permalink raw reply

* [PATCH  01/04] Freescale Ethernet combined driver
From: Pantelis Antoniou @ 2005-05-09 11:44 UTC (permalink / raw)
  To: Dan Malek, Kumar Gala, Eugene Surovegin, Vitaly Bordug, Tom Rini,
	Marcelo Tosatti, Jason McMullan, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 275 bytes --]

Hi

The following patch is a combined FCC/FEC ethernet driver
for the Freescale line of PowerQUICCs.

FECs on 8xx and FCCs on 82xx are supported.

This part of the patch contains makefiles and friends.

Regards

Pantelis

Signed-off-by: Pantelis Antoniou <panto@intracom.gr>

[-- Attachment #2: fs_enet-01.patch --]
[-- Type: text/x-patch, Size: 1319 bytes --]

--- linux-2.6.11.7-fs_enet.orig/drivers/net/Kconfig
+++ linux-2.6.11.7-fs_enet/drivers/net/Kconfig
@@ -1810,6 +1810,7 @@ config NE_H8300
 	  controller on the Renesas H8/300 processor.
 
 source "drivers/net/fec_8xx/Kconfig"
+source "drivers/net/fs_enet/Kconfig"
 
 endmenu
 
--- linux-2.6.11.7-fs_enet.orig/drivers/net/Makefile
+++ linux-2.6.11.7-fs_enet/drivers/net/Makefile
@@ -182,6 +182,7 @@ obj-$(CONFIG_IBMVETH) += ibmveth.o
 obj-$(CONFIG_S2IO) += s2io.o
 obj-$(CONFIG_SMC91X) += smc91x.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
+obj-$(CONFIG_FS_ENET) += fs_enet/
 
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_NET_FC) += fc/
@@ -197,3 +198,6 @@ obj-$(CONFIG_IRDA) += irda/
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+
+obj-$(CONFIG_FS_ENET) += fs_enet/ mii.o
+
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/Kconfig
@@ -0,0 +1,4 @@
+config FS_ENET
+	tristate "Freescale Ethernet Driver"
+	depends on NET_ETHERNET && (8xx || 8260)
+	select MII
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+
+obj-$(CONFIG_FS_ENET) += fs_enet.o
+
+obj-$(CONFIG_8xx) += mac-fec.o
+obj-$(CONFIG_8260) += mac-fcc.o
+
+fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o

^ permalink raw reply

* [PATCH  02/04] Freescale Ethernet combined driver
From: Pantelis Antoniou @ 2005-05-09 11:44 UTC (permalink / raw)
  To: Dan Malek, Kumar Gala, Eugene Surovegin, Vitaly Bordug, Tom Rini,
	Marcelo Tosatti, Jason McMullan, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 269 bytes --]

Hi

The following patch is a combined FCC/FEC ethernet driver
for the Freescale line of PowerQUICCs.

FECs on 8xx and FCCs on 82xx are supported.

This part of the patch contains the core driver.

Regards

Pantelis

Signed-off-by: Pantelis Antoniou <panto@intracom.gr>

[-- Attachment #2: fs_enet-02.patch --]
[-- Type: text/x-patch, Size: 51099 bytes --]

--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/fs_enet-main.c
@@ -0,0 +1,1161 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+static char version[] __devinitdata =
+    DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
+MODULE_DESCRIPTION("Freescale Ethernet Driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(fs_enet_debug, "i");
+MODULE_PARM_DESC(fs_enet_debug,
+		 "Freescale bitmapped debugging message enable value");
+
+int fs_enet_debug = -1;		/* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
+
+static void fs_set_multicast_list(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct dev_mc_list *pmc;
+
+	if ((dev->flags & IFF_PROMISC) == 0) {
+		(*fep->ops->set_multicast_start)(dev);
+		for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+			(*fep->ops->set_multicast_one)(dev, pmc->dmi_addr);
+		(*fep->ops->set_multicast_finish)(dev);
+	} else
+		(*fep->ops->set_promiscuous_mode)(dev);
+}
+
+static int fs_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct sockaddr *mac = addr;
+	int i;
+
+	/* Get pointer to SCC area in parameter RAM. */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = mac->sa_data[i];
+
+	(*fep->ops->set_mac_address)(dev);
+	return 0;
+}
+
+void fs_restart(struct net_device *dev, int duplex, int speed)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	(*fep->ops->restart)(dev, duplex, speed);
+	spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+void fs_stop(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	(*fep->ops->stop)(dev);
+	spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+/* common receive function */
+static int fs_enet_rx_common(struct net_device *dev, int *budget)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	cbd_t *bdp;
+	struct sk_buff *skb, *skbn, *skbt;
+	int received = 0;
+	__u16 pkt_len, sc;
+	int curidx;
+	int rx_work_limit = 0;	/* pacify gcc */
+
+	if (fpi->use_napi) {
+		rx_work_limit = min(dev->quota, *budget);
+
+		if (!netif_running(dev))
+			return 0;
+	}
+
+	/*
+	 * First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = fep->cur_rx;
+
+	/* clear RX status bits for napi*/
+	if (fpi->use_napi)
+		(*fep->ops->napi_clear_rx_event)(dev);
+
+	while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+		curidx = bdp - fep->rx_bd_base;
+
+		/*
+		 * Since we have allocated space to hold a complete frame,
+		 * the last indicator should be set.
+		 */
+		if ((sc & BD_ENET_RX_LAST) == 0)
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s rcv is not +last\n",
+			       dev->name);
+
+		/*
+		 * Check for errors. 
+		 */
+		if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+			  BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			fep->stats.rx_errors++;
+			/* Frame too long or too short. */
+			if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+				fep->stats.rx_length_errors++;
+			/* Frame alignment */
+			if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+				fep->stats.rx_frame_errors++;
+			/* CRC Error */
+			if (sc & BD_ENET_RX_CR)
+				fep->stats.rx_crc_errors++;
+			/* FIFO overrun */
+			if (sc & BD_ENET_RX_OV)
+				fep->stats.rx_crc_errors++;
+
+			skbn = fep->rx_skbuff[curidx];
+			BUG_ON(skbn == NULL);
+
+		} else {
+
+			/* napi, got packet but no quota */
+			if (fpi->use_napi && --rx_work_limit < 0)
+				break;
+
+			skb = fep->rx_skbuff[curidx];
+			BUG_ON(skb == NULL);
+
+			/*
+			 * Process the incoming frame.
+			 */
+			fep->stats.rx_packets++;
+			pkt_len = CBDR_DATLEN(bdp) - 4;	/* remove CRC */
+			fep->stats.rx_bytes += pkt_len + 4;
+
+			if (pkt_len <= fpi->rx_copybreak) {
+				/* +2 to make IP header L1 cache aligned */
+				skbn = dev_alloc_skb(pkt_len + 2);
+				if (skbn != NULL) {
+					skb_reserve(skbn, 2);	/* align IP header */
+					memcpy(skbn->data, skb->data, pkt_len);
+					/* swap */
+					skbt = skb;
+					skb = skbn;
+					skbn = skbt;
+				}
+			} else
+				skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+			if (skbn != NULL) {
+				skb->dev = dev;
+				skb_put(skb, pkt_len);	/* Make room */
+				skb->protocol = eth_type_trans(skb, dev);
+				received++;
+				if (!fpi->use_napi)
+					netif_rx(skb);
+				else
+					netif_receive_skb(skb);
+			} else {
+				printk(KERN_WARNING DRV_MODULE_NAME
+				       ": %s Memory squeeze, dropping packet.\n",
+				       dev->name);
+				fep->stats.rx_dropped++;
+				skbn = skb;
+			}
+		}
+
+		fep->rx_skbuff[curidx] = skbn;
+		CBDW_BUFADDR(bdp, fs_dma_from(fep, skbn->data,
+			     L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)));
+		CBDW_DATLEN(bdp, 0);
+		CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+		/*
+		 * Update BD pointer to next entry. 
+		 */
+		if ((sc & BD_ENET_RX_WRAP) == 0)
+			bdp++;
+		else
+			bdp = fep->rx_bd_base;
+
+		(*fep->ops->rx_bd_done)(dev);
+	}
+
+	fep->cur_rx = bdp;
+
+	if (fpi->use_napi) {
+		dev->quota -= received;
+		*budget -= received;
+
+		if (rx_work_limit < 0)
+			return 1;	/* not done */
+
+		/* done */
+		netif_rx_complete(dev);
+
+		(*fep->ops->napi_enable_rx)(dev);
+	}
+
+	return 0;
+}
+
+static void fs_enet_tx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	struct sk_buff *skb;
+	int dirtyidx, do_wake, do_restart;
+	__u16 sc;
+
+	spin_lock(&fep->lock);
+	bdp = fep->dirty_tx;
+
+	do_wake = do_restart = 0;
+	while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
+
+		dirtyidx = bdp - fep->tx_bd_base;
+
+		if (fep->tx_free == fep->tx_ring)
+			break;
+
+		skb = fep->tx_skbuff[dirtyidx];
+
+		/*
+		 * Check for errors. 
+		 */
+		if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+			  BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
+
+			if (sc & BD_ENET_TX_HB)	/* No heartbeat */
+				fep->stats.tx_heartbeat_errors++;
+			if (sc & BD_ENET_TX_LC)	/* Late collision */
+				fep->stats.tx_window_errors++;
+			if (sc & BD_ENET_TX_RL)	/* Retrans limit */
+				fep->stats.tx_aborted_errors++;
+			if (sc & BD_ENET_TX_UN)	/* Underrun */
+				fep->stats.tx_fifo_errors++;
+			if (sc & BD_ENET_TX_CSL)	/* Carrier lost */
+				fep->stats.tx_carrier_errors++;
+
+			if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+				fep->stats.tx_errors++;
+				do_restart = 1;
+			}
+		} else
+			fep->stats.tx_packets++;
+
+		if (sc & BD_ENET_TX_READY)
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s HEY! Enet xmit interrupt and TX_READY.\n",
+			       dev->name);
+
+		/*
+		 * Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (sc & BD_ENET_TX_DEF)
+			fep->stats.collisions++;
+
+		/*
+		 * Free the sk buffer associated with this last transmit. 
+		 */
+		dev_kfree_skb_irq(skb);
+		fep->tx_skbuff[dirtyidx] = NULL;
+
+		/*
+		 * Update pointer to next buffer descriptor to be transmitted. 
+		 */
+		if ((sc & BD_ENET_TX_WRAP) == 0)
+			bdp++;
+		else
+			bdp = fep->tx_bd_base;
+
+		/*
+		 * Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (!fep->tx_free++)
+			do_wake = 1;
+	}
+
+	fep->dirty_tx = bdp;
+
+	if (do_restart)
+		(*fep->ops->tx_restart)(dev);
+
+	spin_unlock(&fep->lock);
+
+	if (do_wake && netif_queue_stopped(dev))
+		netif_wake_queue(dev);
+}
+
+/*
+ * The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static irqreturn_t
+fs_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+	__u32 int_events;
+	__u32 int_clr_events;
+
+	if (unlikely(dev == NULL))
+		return IRQ_NONE;
+
+	fep = netdev_priv(dev);
+	fpi = fep->fpi;
+
+	/*
+	 * Get the interrupt events that caused us to be here.
+	 */
+	while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) {
+
+		int_clr_events = int_events;
+		if (fpi->use_napi)
+			int_clr_events &= ~fep->ev_napi_rx;
+
+		(*fep->ops->clear_int_events)(dev, int_clr_events);
+
+		if ((int_events & fep->ev_err) != 0)
+			(*fep->ops->ev_error)(dev, int_events);
+
+		if ((int_events & fep->ev_rx) != 0) {
+			if (!fpi->use_napi)
+				fs_enet_rx_common(dev, NULL);
+			else {
+				if (netif_rx_schedule_prep(dev)) {
+					(*fep->ops->napi_disable_rx)(dev);
+					__netif_rx_schedule(dev);
+				} else {
+					printk(KERN_ERR DRV_MODULE_NAME
+					       ": %s driver bug! interrupt while in poll!\n",
+					       dev->name);
+					(*fep->ops->napi_disable_rx)(dev);
+				}
+			}
+		}
+
+		if ((int_events & fep->ev_tx) != 0)
+			fs_enet_tx(dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void fs_init_bds(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	struct sk_buff *skb;
+	int i;
+
+	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+	fep->tx_free = fep->tx_ring;
+	fep->cur_rx = fep->rx_bd_base;
+
+	/*
+	 * Reset SKB receive buffers 
+	 */
+	for (i = 0; i < fep->rx_ring; i++) {
+		if ((skb = fep->rx_skbuff[i]) == NULL)
+			continue;
+		fep->rx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
+
+	/*
+	 * Initialize the receive buffer descriptors. 
+	 */
+	for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
+		skb = dev_alloc_skb(ENET_RX_FRSIZE);
+		if (skb == NULL) {
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s Memory squeeze, unable to allocate skb\n",
+			       dev->name);
+			fep->stats.rx_dropped++;
+			break;
+		}
+		fep->rx_skbuff[i] = skb;
+		skb->dev = dev;
+		CBDW_BUFADDR(bdp,
+			fs_dma_from(fep, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)));
+		CBDW_DATLEN(bdp, 0);	/* zero */
+		CBDW_SC(bdp, BD_ENET_RX_EMPTY |
+			((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
+	}
+	/*
+	 * if we failed, fillup remainder 
+	 */
+	for (; i < fep->rx_ring; i++, bdp++) {
+		fep->rx_skbuff[i] = NULL;
+		CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
+	}
+
+	/*
+	 * Reset SKB transmit buffers.  
+	 */
+	for (i = 0; i < fep->tx_ring; i++) {
+		if ((skb = fep->tx_skbuff[i]) == NULL)
+			continue;
+		fep->tx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
+
+	/*
+	 * ...and the same for transmit.  
+	 */
+	for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
+		fep->tx_skbuff[i] = NULL;
+		CBDW_BUFADDR(bdp, virt_to_bus(NULL));
+		CBDW_DATLEN(bdp, 0);
+		CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
+	}
+}
+
+void fs_cleanup_bds(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct sk_buff *skb;
+	int i;
+
+	/*
+	 * Reset SKB transmit buffers.  
+	 */
+	for (i = 0; i < fep->tx_ring; i++) {
+		if ((skb = fep->tx_skbuff[i]) == NULL)
+			continue;
+		fep->tx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
+
+	/*
+	 * Reset SKB receive buffers 
+	 */
+	for (i = 0; i < fep->rx_ring; i++) {
+		if ((skb = fep->rx_skbuff[i]) == NULL)
+			continue;
+		fep->rx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
+}
+
+/**********************************************************************************/
+
+static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	int curidx;
+	__u16 sc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->tx_lock, flags);
+
+	/*
+	 * Fill in a Tx ring entry 
+	 */
+	bdp = fep->cur_tx;
+
+	if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+		/*
+		 * Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since the tx queue should be stopped.
+		 */
+		printk(KERN_WARNING DRV_MODULE_NAME
+		       ": %s tx queue full!.\n", dev->name);
+		return 1;
+	}
+
+	curidx = bdp - fep->tx_bd_base;
+	/*
+	 * Clear all of the status flags. 
+	 */
+	CBDC_SC(bdp, BD_ENET_TX_STATS);
+
+	/*
+	 * Save skb pointer. 
+	 */
+	fep->tx_skbuff[curidx] = skb;
+
+	fep->stats.tx_bytes += skb->len;
+
+	/*
+	 * Push the data cache so the CPM does not get stale memory data. 
+	 */
+	CBDW_BUFADDR(bdp, fs_dma_to(fep, skb->data, skb->len));
+	CBDW_DATLEN(bdp, skb->len);
+
+	dev->trans_start = jiffies;
+
+	/*
+	 * If this was the last BD in the ring, start at the beginning again. 
+	 */
+	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
+		fep->cur_tx++;
+	else
+		fep->cur_tx = fep->tx_bd_base;
+
+	if (!--fep->tx_free)
+		netif_stop_queue(dev);
+
+	/* Trigger transmission start */
+	sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |
+	     BD_ENET_TX_LAST | BD_ENET_TX_TC;
+
+	/* note that while FEC does not have this bit
+	 * it marks it as available for software use
+	 * yay for hw reuse :) */
+	if (skb->len <= 60)
+		sc |= BD_ENET_TX_PAD;
+	CBDS_SC(bdp, sc);
+
+	(*fep->ops->tx_kickstart)(dev);
+
+	spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+	return 0;
+}
+
+static int fs_request_irq(struct net_device *dev, int irq, const char *name,
+		irqreturn_t (*irqf)(int irq, void *dev_id, struct pt_regs *regs))
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	(*fep->ops->pre_request_irq)(dev, irq);
+	return request_irq(irq, irqf, 0, name, dev);
+}
+
+static void fs_free_irq(struct net_device *dev, int irq)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	free_irq(irq, dev);
+	(*fep->ops->post_free_irq)(dev, irq);
+}
+
+/**********************************************************************************/
+
+/* This interrupt occurs when the PHY detects a link change. */
+static irqreturn_t
+fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+
+	if (unlikely(dev == NULL))
+		return IRQ_NONE;
+
+	fep = netdev_priv(dev);
+	fpi = fep->fpi;
+
+	/*
+	 * Acknowledge the interrupt if possible. If we have not
+	 * found the PHY yet we can't process or acknowledge the
+	 * interrupt now. Instead we ignore this interrupt for now,
+	 * which we can do since it is edge triggered. It will be
+	 * acknowledged later by fs_enet_open().
+	 */
+	if (!fep->phy)
+		return IRQ_NONE;
+
+	fs_mii_ack_int(dev);
+	fs_mii_link_status_change_check(dev, 0);
+
+	return IRQ_HANDLED;
+}
+
+static void fs_timeout(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->stats.tx_errors++;
+
+	if (fep->tx_free)
+		netif_wake_queue(dev);
+
+	/* check link status again */
+	fs_mii_link_status_change_check(dev, 0);
+}
+
+static int fs_enet_open(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	int r;
+
+	/* Install our interrupt handler. */
+	r = fs_request_irq(dev, fpi->fs_irq, "fs_enet-mac", fs_enet_interrupt);
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s Could not allocate FEC IRQ!", dev->name);
+		return -EINVAL;
+	}
+
+	/* Install our phy interrupt handler */
+	if (fpi->phy_irq != -1) {
+
+		r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
+		if (r != 0) {
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s Could not allocate PHY IRQ!", dev->name);
+			fs_free_irq(dev, fpi->fs_irq);
+			return -EINVAL;
+		}
+	}
+
+	fs_mii_startup(dev);
+	netif_carrier_off(dev);
+	fs_mii_link_status_change_check(dev, 1);
+
+	return 0;
+}
+
+static int fs_enet_close(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	unsigned long flags;
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	fs_mii_shutdown(dev);
+
+	spin_lock_irqsave(&fep->lock, flags);
+	(*fep->ops->stop)(dev);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	/* release any irqs */
+	if (fpi->phy_irq != -1)
+		fs_free_irq(dev, fpi->phy_irq);
+	fs_free_irq(dev, fpi->fs_irq);
+
+	return 0;
+}
+
+static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return &fep->stats;
+}
+
+static int fs_enet_poll(struct net_device *dev, int *budget)
+{
+	return fs_enet_rx_common(dev, budget);
+}
+
+/*************************************************************************/
+
+static void fs_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_MODULE_NAME);
+	strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int fs_get_regs_len(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	return (*fep->ops->get_regs_len)(dev);
+}
+
+static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			 void *p)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int r, len;
+
+	len = regs->len;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	r = (*fep->ops->get_regs)(dev, p, &len);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	if (r == 0)
+		regs->version = 0;
+}
+
+static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = mii_ethtool_gset(&fep->mii_if, cmd);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	return rc;
+}
+
+static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = mii_ethtool_sset(&fep->mii_if, cmd);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	return rc;
+}
+
+static int fs_nway_reset(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return mii_nway_restart(&fep->mii_if);
+}
+
+static __u32 fs_get_msglevel(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return fep->msg_enable;
+}
+
+static void fs_set_msglevel(struct net_device *dev, __u32 value)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fep->msg_enable = value;
+}
+
+static struct ethtool_ops fs_ethtool_ops = {
+	.get_drvinfo = fs_get_drvinfo,
+	.get_regs_len = fs_get_regs_len,
+	.get_settings = fs_get_settings,
+	.set_settings = fs_set_settings,
+	.nway_reset = fs_nway_reset,
+	.get_link = ethtool_op_get_link,
+	.get_msglevel = fs_get_msglevel,
+	.set_msglevel = fs_set_msglevel,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,	/* local! */
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_regs = fs_get_regs,
+};
+
+static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
+	unsigned long flags;
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+	spin_unlock_irqrestore(&fep->lock, flags);
+	return rc;
+}
+
+extern int fs_mii_connect(struct net_device *dev);
+extern void fs_mii_disconnect(struct net_device *dev);
+
+static struct net_device *fs_init_instance(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		struct device *dev,
+#endif
+		const struct fs_platform_info *fpi)
+{
+	struct net_device *ndev = NULL;
+	struct fs_enet_private *fep = NULL;
+	int privsize, i, r, err = 0, registered = 0;
+
+	/* guard */
+	if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
+		return ERR_PTR(-EINVAL);
+
+	privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
+			    (fpi->rx_ring + fpi->tx_ring));
+
+	ndev = alloc_etherdev(privsize);
+	if (!ndev) {
+		err = -ENOMEM;
+		goto err;
+	}
+	SET_MODULE_OWNER(ndev);
+
+	fep = netdev_priv(ndev);
+	memset(fep, 0, privsize);	/* clear everything */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	fep->dev = dev;
+	dev_set_drvdata(dev, ndev);
+#endif
+	fep->fpi = fpi;
+
+#ifdef CONFIG_8xx
+	if (fs_get_fec_index(fpi->fs_no) >= 0)
+		fep->ops = &fs_fec_ops;
+#endif
+
+#ifdef CONFIG_8260
+	if (fs_get_fcc_index(fpi->fs_no) >= 0)
+		fep->ops = &fs_fcc_ops;
+#endif
+
+#if 0
+	if (fs_get_scc_index(fpi->fs_no) >= 0)
+		fep->ops = &fs_scc_ops;
+#endif
+	if (fep->ops == NULL) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s No matching ops found (%d).\n",
+		       ndev->name, fpi->fs_no);
+		err = -EINVAL;
+		goto err;
+	}
+
+	r = (*fep->ops->setup_data)(ndev);
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s setup_data failed\n",
+		       ndev->name);
+		err = r;
+		goto err;
+	}
+
+	/* point rx_skbuff, tx_skbuff */
+	fep->rx_skbuff = (struct sk_buff **)&fep[1];
+	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+	/* init locks */
+	spin_lock_init(&fep->lock);
+	spin_lock_init(&fep->tx_lock);
+
+	/*
+	 * Set the Ethernet address. 
+	 */
+	for (i = 0; i < 6; i++)
+		ndev->dev_addr[i] = fpi->macaddr[i];
+
+	fep->ring_base = fs_alloc_coherent(fep,
+					    (fpi->tx_ring + fpi->rx_ring) *
+					    sizeof(cbd_t), &fep->ring_mem_addr,
+					    GFP_KERNEL);
+	if (fep->ring_base == NULL) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s dma alloc failed.\n", ndev->name);
+		err = -ENOMEM;
+		goto err;
+	}
+
+	/*
+	 * Set receive and transmit descriptor base.
+	 */
+	fep->rx_bd_base = fep->ring_base;
+	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+	/* initialize ring size variables */
+	fep->tx_ring = fpi->tx_ring;
+	fep->rx_ring = fpi->rx_ring;
+
+	/*
+	 * The FEC Ethernet specific entries in the device structure. 
+	 */
+	ndev->open = fs_enet_open;
+	ndev->hard_start_xmit = fs_enet_start_xmit;
+	ndev->tx_timeout = fs_timeout;
+	ndev->watchdog_timeo = 2 * HZ;
+	ndev->stop = fs_enet_close;
+	ndev->get_stats = fs_enet_get_stats;
+	ndev->set_multicast_list = fs_set_multicast_list;
+	ndev->set_mac_address = fs_set_mac_address;
+	if (fpi->use_napi) {
+		ndev->poll = fs_enet_poll;
+		ndev->weight = fpi->napi_weight;
+	}
+	ndev->ethtool_ops = &fs_ethtool_ops;
+	ndev->do_ioctl = fs_ioctl;
+
+	init_timer(&fep->phy_timer_list);
+
+	netif_carrier_off(ndev);
+
+	err = register_netdev(ndev);
+	if (err != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s register_netdev failed.\n", ndev->name);
+		goto err;
+	}
+	registered = 1;
+
+	err = fs_mii_connect(ndev);
+	if (err != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s fs_mii_connect failed.\n", ndev->name);
+		goto err;
+	}
+
+	return ndev;
+
+      err:
+	if (ndev != NULL) {
+
+		if (registered)
+			unregister_netdev(ndev);
+
+		if (fep != NULL) {
+			if (fep->ring_base)
+				fs_free_coherent(fep,
+					(fpi->tx_ring + fpi->rx_ring)
+						* sizeof(cbd_t),
+					fep->ring_base,
+					fep->ring_mem_addr);
+
+			(*fep->ops->cleanup_data)(ndev);
+		}
+
+		free_netdev(ndev);
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	dev_set_drvdata(dev, NULL);
+#endif
+
+	return ERR_PTR(err);
+}
+
+static int fs_cleanup_instance(struct net_device *ndev)
+{
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct device *dev;
+#endif
+
+	if (ndev == NULL)
+		return -EINVAL;
+
+	fep = netdev_priv(ndev);
+	if (fep == NULL)
+		return -EINVAL;
+
+	fpi = fep->fpi;
+
+	fs_mii_disconnect(ndev);
+
+	unregister_netdev(ndev);
+
+	fs_free_coherent(fep, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+			  fep->ring_base, fep->ring_mem_addr);
+
+	/* reset it */
+	(*fep->ops->cleanup_data)(ndev);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	dev = fep->dev;
+	if (dev != NULL) {
+		dev_set_drvdata(dev, NULL);
+		fep->dev = NULL;
+	}
+#endif
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+/**************************************************************************************/
+
+/* handy pointer to the immap */
+void *fs_enet_immap = NULL;
+
+static int setup_immap(void)
+{
+	phys_addr_t paddr = 0;
+	unsigned long size = 0;
+
+#ifdef CONFIG_8xx
+	paddr = IMAP_ADDR;
+	size = 0x10000;	/* map 64K */
+#endif
+#ifdef CONFIG_8260
+	paddr = CPM_MAP_ADDR;
+	size = 0x40000;	/* map 256 K */
+#endif
+	fs_enet_immap = ioremap(paddr, size);
+	if (fs_enet_immap == NULL)
+		return -EBADF;	/* XXX ahem; maybe just BUG_ON? */
+
+	return 0;
+}
+
+static void cleanup_immap(void)
+{
+	if (fs_enet_immap != NULL) {
+		iounmap(fs_enet_immap);
+		fs_enet_immap = NULL;
+	}
+}
+
+/**************************************************************************************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+static int __devinit fs_enet_probe(struct device *dev)
+{
+	struct net_device *ndev;
+
+	ndev = fs_init_instance(dev, dev->platform_data);
+	if (IS_ERR(ndev))
+		return PTR_ERR(ndev);
+	return 0;
+}
+
+static int fs_enet_remove(struct device *dev)
+{
+	return fs_cleanup_instance(dev_get_drvdata(dev));
+}
+
+static struct device_driver fs_enet_driver = {
+	.name	  	= FS_ENET_NAME,
+	.bus		= &platform_bus_type,
+	.probe		= fs_enet_probe,
+	.remove		= fs_enet_remove,
+#ifdef CONFIG_PM
+/*	.suspend	= fs_enet_suspend,	TODO */
+/*	.resume		= fs_enet_resume,	TODO */
+#endif
+};
+
+static int __init fs_init(void)
+{
+	int r;
+
+	printk(KERN_INFO
+			"%s", version);
+
+	r = setup_immap();
+	if (r != 0)
+		return r;
+
+	r = driver_register(&fs_enet_driver);
+	if (r != 0) {
+		cleanup_immap();
+		return r;
+	}
+
+	return 0;
+}
+
+static void __exit fs_cleanup(void)
+{
+	driver_unregister(&fs_enet_driver);
+	cleanup_immap();
+}
+
+#else
+
+int fs_enet_init_one(const struct fs_platform_info *fpi,
+		     struct net_device **ndevp)
+{
+	struct net_device *ndev;
+
+	ndev = fs_init_instance(fpi);
+	if (IS_ERR(ndev))
+		return PTR_ERR(ndev);
+	*ndevp = ndev;
+	return 0;
+}
+
+int fs_enet_cleanup_one(struct net_device *ndev)
+{
+	return fs_cleanup_instance(ndev);
+}
+
+static int __init fs_init(void)
+{
+	int r;
+
+	printk(KERN_INFO
+			"%s", version);
+
+	r = setup_immap();
+	if (r != 0)
+		return r;
+
+	r =  fs_enet_platform_init();
+	if (r != 0) {
+		cleanup_immap();
+		return r;
+	}
+
+	return 0;
+}
+
+static void __exit fs_cleanup(void)
+{
+	fs_enet_platform_cleanup();
+	cleanup_immap();
+}
+
+#endif
+
+/**************************************************************************************/
+
+module_init(fs_init);
+module_exit(fs_cleanup);
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/fs_enet-mii.c
@@ -0,0 +1,434 @@
+/*
+ * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/*
+ * Generic PHY support.
+ * Should work for all PHYs, but link change is detected by polling
+ */
+
+static void generic_timer_callback(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->phy_timer_list.expires = jiffies + HZ / 2;
+
+	add_timer(&fep->phy_timer_list);
+
+	fs_mii_link_status_change_check(dev, 0);
+}
+
+static void generic_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->phy_timer_list.expires = jiffies + HZ / 2;	/* every 500ms */
+	fep->phy_timer_list.data = (unsigned long)dev;
+	fep->phy_timer_list.function = generic_timer_callback;
+	add_timer(&fep->phy_timer_list);
+}
+
+static void generic_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	del_timer_sync(&fep->phy_timer_list);
+}
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9161 is used on the NETTA board			     */
+
+/* register definitions */
+
+#define MII_DM9161_ACR		16	/* Aux. Config Register         */
+#define MII_DM9161_ACSR		17	/* Aux. Config/Status Register  */
+#define MII_DM9161_10TCSR	18	/* 10BaseT Config/Status Reg.   */
+#define MII_DM9161_INTR		21	/* Interrupt Register           */
+#define MII_DM9161_RECR		22	/* Receive Error Counter Reg.   */
+#define MII_DM9161_DISCR	23	/* Disconnect Counter Register  */
+
+static void dm9161_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
+}
+
+static void dm9161_ack_int(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
+}
+
+static void dm9161_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
+}
+
+/**********************************************************************************/
+
+static const struct phy_info phy_info[] = {
+	{
+		.id = 0x00181b88,
+		.name = "DM9161",
+		.startup = dm9161_startup,
+		.ack_int = dm9161_ack_int,
+		.shutdown = dm9161_shutdown,
+	}, {
+		.id = 0,
+		.name = "GENERIC",
+		.startup = generic_startup,
+		.shutdown = generic_shutdown,
+	},
+};
+
+/**********************************************************************************/
+
+static int phy_id_detect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	int i, r, start, end, phytype, physubtype;
+	const struct phy_info *phy;
+	int phy_hwid, phy_id;
+
+	phy_hwid = -1;
+	fep->phy = NULL;
+
+	/* auto-detect? */
+	if (fpi->phy_addr == -1) {
+		start = 0;
+		end = 32;
+	} else {		/* direct */
+		start = fpi->phy_addr;
+		end = start + 1;
+	}
+
+	for (phy_id = start; phy_id < end; phy_id++) {
+		r = fs_mii_read(dev, phy_id, MII_PHYSID1);
+		if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
+			continue;
+		r = fs_mii_read(dev, phy_id, MII_PHYSID2);
+		if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
+			continue;
+		phy_hwid = (phytype << 16) | physubtype;
+		if (phy_hwid != -1)
+			break;
+	}
+
+	if (phy_hwid == -1) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s No PHY detected!\n", dev->name);
+		return -1;
+	}
+
+	for (i = 0, phy = phy_info; i < sizeof(phy_info) / sizeof(phy_info[0]);
+	     i++, phy++)
+		if (phy->id == (phy_hwid >> 4) || phy->id == 0)
+			break;
+
+	if (i >= sizeof(phy_info) / sizeof(phy_info[0])) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s PHY id 0x%08x is not supported!\n",
+		       dev->name, phy_hwid);
+		return -1;
+	}
+
+	fep->phy = phy;
+
+	printk(KERN_INFO DRV_MODULE_NAME
+	       ": %s Phy @ 0x%x, type %s (0x%08x)\n",
+	       dev->name, phy_id, fep->phy->name, phy_hwid);
+
+	return phy_id;
+}
+
+void fs_mii_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy == NULL)
+		return;
+
+	if (fep->phy->startup == NULL)
+		return;
+
+	(*fep->phy->startup) (dev);
+}
+
+void fs_mii_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy == NULL)
+		return;
+
+	if (fep->phy->shutdown == NULL)
+		return;
+
+	(*fep->phy->shutdown) (dev);
+}
+
+void fs_mii_ack_int(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy == NULL)
+		return;
+
+	if (fep->phy->ack_int == NULL)
+		return;
+
+	(*fep->phy->ack_int) (dev);
+}
+
+/* helper function */
+static int mii_negotiated(struct mii_if_info *mii)
+{
+	int advert, lpa, val;
+
+	if (!mii_link_ok(mii))
+		return 0;
+
+	val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
+	if ((val & BMSR_ANEGCOMPLETE) == 0)
+		return 0;
+
+	advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
+	lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
+
+	return mii_nway_result(advert & lpa);
+}
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned int media;
+
+	if (mii_check_media(&fep->mii_if, netif_msg_link(fep), init_media) == 0)
+		return;
+
+	media = mii_negotiated(&fep->mii_if);
+
+	if (netif_carrier_ok(dev)) {
+		fs_restart(dev, !!(media & ADVERTISE_FULL),
+			    (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ?
+			    100 : 10);
+
+		netif_start_queue(dev);
+	} else {
+		netif_stop_queue(dev);
+
+		fs_stop(dev);
+
+	}
+}
+
+/**********************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&bus->mii_lock, flags);
+	ret = (*bus->mii_read)(bus, phy_id, location);
+	spin_unlock_irqrestore(&bus->mii_lock, flags);
+
+	return ret;
+}
+
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bus->mii_lock, flags);
+	(*bus->mii_write)(bus, phy_id, location, value);
+	spin_unlock_irqrestore(&bus->mii_lock, flags);
+}
+
+/*****************************************************************************/
+
+/* list of all registered mii buses */
+static LIST_HEAD(fs_mii_bus_list);
+
+static struct fs_enet_mii_bus *lookup_bus(int method, int id)
+{
+	struct list_head *ptr;
+	struct fs_enet_mii_bus *bus;
+
+	list_for_each(ptr, &fs_mii_bus_list) {
+		bus = list_entry(ptr, struct fs_enet_mii_bus, list);
+		if (bus->bus_info->method == method &&
+			bus->bus_info->id == id)
+			return bus;
+	}
+	return NULL;
+}
+
+static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
+{
+	struct fs_enet_mii_bus *bus;
+	int ret = 0;
+
+	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+	if (bus == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	memset(bus, 0, sizeof(*bus));
+	spin_lock_init(&bus->mii_lock);
+	bus->bus_info = bi;
+	bus->refs = 0;
+
+	/* perform initialization */
+	switch (bi->method) {
+
+		case fsmii_fixed:
+			ret = fs_mii_fixed_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+
+		case fsmii_bitbang:
+			ret = fs_mii_bitbang_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+#ifdef CONFIG_8xx
+		case fsmii_fec:
+			ret = fs_mii_fec_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+#endif
+		default:
+			ret = -EINVAL;
+			goto err;
+	}
+
+	list_add(&bus->list, &fs_mii_bus_list);
+
+	return bus;
+
+err:
+	if (bus)
+		kfree(bus);
+	return ERR_PTR(ret);
+}
+
+static void destroy_bus(struct fs_enet_mii_bus *bus)
+{
+	/* remove from bus list */
+	list_del(&bus->list);
+
+	/* nothing more needed */
+	kfree(bus);
+}
+
+int fs_mii_connect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	struct fs_enet_mii_bus *bus = NULL;
+
+	/* check method validity */
+	switch (fpi->bus_info->method) {
+		case fsmii_fixed:
+		case fsmii_bitbang:
+			break;
+#ifdef CONFIG_8xx
+		case fsmii_fec:
+			break;
+#endif
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s Unknown MII bus method (%d)!\n",
+			       dev->name, fpi->bus_info->method);
+			return -EINVAL; 
+	}
+
+	bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
+
+	/* if not found create new bus */
+	if (bus == NULL) {
+		bus = create_bus(fpi->bus_info);
+		if (IS_ERR(bus)) {
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s MII bus creation failure!\n", dev->name);
+			return PTR_ERR(bus);
+		}
+	}
+
+	bus->refs++;
+
+	fep->mii_bus = bus;
+
+	fep->mii_if.dev = dev;
+	fep->mii_if.phy_id_mask = 0x1f;
+	fep->mii_if.reg_num_mask = 0x1f;
+	fep->mii_if.mdio_read = fs_mii_read;
+	fep->mii_if.mdio_write = fs_mii_write;
+	fep->mii_if.phy_id = phy_id_detect(dev);
+
+	return 0;
+}
+
+void fs_mii_disconnect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = NULL;
+
+	bus = fep->mii_bus;
+	fep->mii_bus = NULL;
+
+	if (--bus->refs <= 0)
+		destroy_bus(bus);
+}
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/fs_enet.h
@@ -0,0 +1,378 @@
+#ifndef FEC_8XX_H
+#define FEC_8XX_H
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/list.h>
+
+#include <linux/fs_enet_pd.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <asm/dma-mapping.h>
+#endif
+
+#ifdef CONFIG_8xx
+#include <asm/commproc.h>
+#endif
+
+#ifdef CONFIG_8260
+#include <asm/cpm2.h>
+#endif
+
+/* hw driver ops */
+struct fs_ops {
+	int (*setup_data)(struct net_device *dev);
+	void (*cleanup_data)(struct net_device *dev);
+	void (*set_promiscuous_mode)(struct net_device *dev);
+	void (*set_multicast_start)(struct net_device *dev);
+	void (*set_multicast_one)(struct net_device *dev, const __u8 *mac);
+	void (*set_multicast_finish)(struct net_device *dev);
+	void (*set_mac_address)(struct net_device *dev);
+	void (*restart)(struct net_device *dev, int duplex, int speed);
+	void (*stop)(struct net_device *dev);
+	void (*pre_request_irq)(struct net_device *dev, int irq);
+	void (*post_free_irq)(struct net_device *dev, int irq);
+	void (*napi_clear_rx_event)(struct net_device *dev);
+	void (*napi_enable_rx)(struct net_device *dev);
+	void (*napi_disable_rx)(struct net_device *dev);
+	void (*rx_bd_done)(struct net_device *dev);
+	void (*tx_kickstart)(struct net_device *dev);
+	__u32 (*get_int_events)(struct net_device *dev);
+	void (*clear_int_events)(struct net_device *dev, __u32 int_events);
+	void (*ev_error)(struct net_device *dev, __u32 int_events);
+	int (*get_regs)(struct net_device *dev, void *p, int *sizep);
+	int (*get_regs_len)(struct net_device *dev);
+	void (*tx_restart)(struct net_device *dev);
+};
+
+#define MII_ADVERTISE_HALF	(ADVERTISE_100HALF | \
+				 ADVERTISE_10HALF | ADVERTISE_CSMA)
+#define MII_ADVERTISE_ALL	(ADVERTISE_100FULL | \
+				 ADVERTISE_10FULL | MII_ADVERTISE_HALF)
+
+/* values for MII phy_status */
+
+#define PHY_CONF_ANE	0x0001	/* 1 auto-negotiation enabled     */
+#define PHY_CONF_LOOP	0x0002	/* 1 loopback mode enabled        */
+#define PHY_CONF_SPMASK	0x00f0	/* mask for speed                 */
+#define PHY_CONF_10HDX	0x0010	/* 10 Mbit half duplex supported  */
+#define PHY_CONF_10FDX	0x0020	/* 10 Mbit full duplex supported  */
+#define PHY_CONF_100HDX	0x0040	/* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX	0x0080	/* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK	0x0100	/* 1 up - 0 down                  */
+#define PHY_STAT_FAULT	0x0200	/* 1 remote fault                 */
+#define PHY_STAT_ANC	0x0400	/* 1 auto-negotiation complete    */
+#define PHY_STAT_SPMASK	0xf000	/* mask for speed                 */
+#define PHY_STAT_10HDX	0x1000	/* 10 Mbit half duplex selected   */
+#define PHY_STAT_10FDX	0x2000	/* 10 Mbit full duplex selected   */
+#define PHY_STAT_100HDX	0x4000	/* 100 Mbit half duplex selected  */
+#define PHY_STAT_100FDX	0x8000	/* 100 Mbit full duplex selected  */
+
+struct phy_info {
+	unsigned int id;
+	const char *name;
+	void (*startup) (struct net_device * dev);
+	void (*shutdown) (struct net_device * dev);
+	void (*ack_int) (struct net_device * dev);
+};
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define MAX_MTU 1508		/* Allow fullsized pppoe packets over VLAN */
+#define MIN_MTU 46		/* this is data size */
+#define CRC_LEN 4
+
+#define PKT_MAXBUF_SIZE		(MAX_MTU+ETH_HLEN+CRC_LEN)
+#define PKT_MINBUF_SIZE		(MIN_MTU+ETH_HLEN+CRC_LEN)
+
+/* Must be a multiple of 4 */
+#define PKT_MAXBLR_SIZE		((PKT_MAXBUF_SIZE+3) & ~3)
+/* This is needed so that invalidate_xxx wont invalidate too much */
+#define ENET_RX_FRSIZE		L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+
+struct fs_enet_mii_bus {
+	struct list_head list;
+	spinlock_t mii_lock;
+	const struct fs_mii_bus_info *bus_info;
+	int refs;
+
+	int (*mii_read)(struct fs_enet_mii_bus *bus,
+			int phy_id, int location);
+
+	void (*mii_write)(struct fs_enet_mii_bus *bus,
+			int phy_id, int location, int value);
+
+	union {
+		struct {
+			unsigned int mii_speed;
+			void *fsp;
+		} fec;
+
+		struct {
+			/* note that the actual port size may */
+			/* be different; cpm(s) handle it OK  */
+			__u8 mdio_msk;
+			__u8 *mdio_dir;
+			__u8 *mdio_dat;
+			__u8 mdc_msk;
+			__u8 *mdc_dir;
+			__u8 *mdc_dat;
+		} bitbang;
+
+		struct {
+			__u16 lpa;
+		} fixed;
+	};
+};
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+#ifdef CONFIG_8xx
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
+#endif
+
+struct fs_enet_private {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct device *dev;	/* pointer back to the device (must be initialized first) */
+#endif
+	spinlock_t lock;	/* during all ops except TX pckt processing */
+	spinlock_t tx_lock;	/* during fs_start_xmit and fs_tx         */
+	const struct fs_platform_info *fpi;
+	const struct fs_ops *ops;
+	int rx_ring, tx_ring;
+	dma_addr_t ring_mem_addr;
+	void *ring_base;
+	struct sk_buff **rx_skbuff;
+	struct sk_buff **tx_skbuff;
+	cbd_t *rx_bd_base;	/* Address of Rx and Tx buffers.    */
+	cbd_t *tx_bd_base;
+	cbd_t *dirty_tx;	/* ring entries to be free()ed.     */
+	cbd_t *cur_rx;
+	cbd_t *cur_tx;
+	int tx_free;
+	struct net_device_stats stats;
+	struct timer_list phy_timer_list;
+	const struct phy_info *phy;
+	__u32 msg_enable;
+	struct mii_if_info mii_if;
+	struct fs_enet_mii_bus *mii_bus;
+
+	/* event masks */
+	__u32 ev_napi_rx;	/* mask of NAPI rx events */
+	__u32 ev_rx;		/* rx event mask          */
+	__u32 ev_tx;		/* tx event mask          */
+	__u32 ev_err;		/* error event mask       */
+
+	__u16 bd_rx_empty;	/* mask of BD rx empty	  */
+	__u16 bd_rx_err;	/* mask of BD rx errors   */
+
+	union {
+		struct {
+			int idx;		/* FEC1 = 0, FEC2 = 1  */
+			void *fsp;		/* hw registers        */
+			__u32 hthi, htlo;	/* state for multicast */
+		} fec;
+
+		struct {
+			int idx;		/* FCC1-3 = 0-2	       */
+			void *fccp;		/* hw registers	       */
+			void *ep;		/* parameter ram       */
+			void *fcccp;		/* hw registers cont.  */
+			__u32 gaddrh, gaddrl;	/* group address       */
+		} fcc;
+	};
+};
+
+/***************************************************************************/
+
+void fs_restart(struct net_device *dev, int duplex, int speed);
+void fs_stop(struct net_device *dev);
+
+/***************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location);
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
+
+void fs_mii_startup(struct net_device *dev);
+void fs_mii_shutdown(struct net_device *dev);
+void fs_mii_ack_int(struct net_device *dev);
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+
+void fs_init_bds(struct net_device *dev);
+void fs_cleanup_bds(struct net_device *dev);
+
+/***************************************************************************/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+int fs_enet_init_one(const struct fs_platform_info *fpi,
+		     struct net_device **devp);
+int fs_enet_cleanup_one(struct net_device *dev);
+
+#endif
+
+/***************************************************************************/
+
+#define DRV_MODULE_NAME		"fs_enet"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"0.1"
+#define DRV_MODULE_RELDATE	"May 6, 2005"
+
+/***************************************************************************/
+
+int fs_enet_platform_init(void);
+void fs_enet_platform_cleanup(void);
+
+/***************************************************************************/
+
+/* buffer descriptor access macros */
+
+/* FEC access macros */
+#if defined(CONFIG_8xx)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __cbd_out32(addr, x)	__raw_writel(x, addr)
+#define __cbd_out16(addr, x)	__raw_writew(x, addr)
+#define __cbd_in32(addr)	__raw_readl(addr)
+#define __cbd_in16(addr)	__raw_readw(addr)
+#else
+/* for others play it safe */
+#define __cbd_out32(addr, x)	out_be32(addr, x)
+#define __cbd_out16(addr, x)	out_be16(addr, x)
+#define __cbd_in32(addr)	in_be32(addr)
+#define __cbd_in16(addr)	in_be16(addr)
+#endif
+
+/* write */
+#define CBDW_SC(_cbd, _sc) 		__cbd_out16(&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen)	__cbd_out16(&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr)	__cbd_out32(&(_cbd)->cbd_bufaddr, (_bufaddr))
+
+/* read */
+#define CBDR_SC(_cbd) 			__cbd_in16(&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd)		__cbd_in16(&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd)		__cbd_in32(&(_cbd)->cbd_bufaddr)
+
+/* set bits */
+#define CBDS_SC(_cbd, _sc) 		CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
+
+/* clear bits */
+#define CBDC_SC(_cbd, _sc) 		CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc))
+
+/***************************************************************************/
+
+/* kernel compatibility shim */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+static inline void *
+fs_alloc_coherent(struct fs_enet_private *fep, size_t size,
+		   dma_addr_t *dma_handle, int gfp)
+{
+	return dma_alloc_coherent(fep->dev, size, dma_handle, gfp);
+}
+
+static inline void
+fs_free_coherent(struct fs_enet_private *fep, size_t size,
+		  void *vaddr, dma_addr_t dma_handle)
+{
+	dma_free_coherent(fep->dev, size, vaddr, dma_handle);
+}
+
+static inline dma_addr_t
+fs_dma_to(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	return dma_map_single(fep->dev, ptr, size, DMA_TO_DEVICE);
+}
+
+static inline dma_addr_t
+fs_dma_from(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	return dma_map_single(fep->dev, ptr, size, DMA_FROM_DEVICE);
+}
+
+#else
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+
+static inline void *
+fs_alloc_coherent(struct fs_enet_private *fep, size_t size,
+		   dma_addr_t *dma_handle, int gfp)
+{
+	return consistent_alloc(gfp, size, dma_handle);
+}
+
+static inline void
+fs_free_coherent(struct fs_enet_private *fep, size_t size,
+		  void *vaddr, dma_addr_t dma_handle)
+{
+	consistent_free(vaddr);
+}
+
+static inline dma_addr_t
+fs_dma_to(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	consistent_sync(ptr, size, PCI_DMA_TODEVICE);
+	return (dma_addr_t)__pa(ptr);
+}
+
+static inline dma_addr_t
+fs_dma_from(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	consistent_sync(ptr, size, PCI_DMA_FROMDEVICE);
+	return (dma_addr_t)__pa(ptr);
+}
+
+#else
+
+static inline void *
+fs_alloc_coherent(struct fs_enet_private *fep, size_t size,
+		   dma_addr_t *dma_handle, int gfp)
+{
+	void *vaddr;
+
+	vaddr = kmalloc(size, gfp);
+	if (vaddr != NULL)
+		*dma_handle = __pa(vaddr);
+	return vaddr;
+}
+
+static inline void
+fs_free_coherent(struct fs_enet_private *fep, size_t size,
+		  void *vaddr, dma_addr_t dma_handle)
+{
+	kfree(vaddr);
+}
+
+static inline dma_addr_t
+fs_dma_to(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	return (dma_addr_t)__pa(ptr);
+}
+
+static inline dma_addr_t
+fs_dma_from(struct fs_enet_private *fep, void *ptr, size_t size)
+{
+	return (dma_addr_t)__pa(ptr);
+}
+
+#endif
+
+#endif
+
+/*******************************************************************/
+
+extern const struct fs_ops fs_fec_ops;
+extern const struct fs_ops fs_fcc_ops;
+
+/*******************************************************************/
+
+/* handy pointer to the immap */
+extern void *fs_enet_immap;
+
+/*******************************************************************/
+
+#endif
--- /dev/null
+++ linux-2.6.11.7-fs_enet/include/linux/fs_enet_pd.h
@@ -0,0 +1,96 @@
+#ifndef FS_ENET_PD_H
+#define FS_ENET_PD_H
+
+#include <asm/types.h>
+
+#define FS_ENET_NAME	"fs_enet"
+
+enum fs_id {
+	fsid_fec1,
+	fsid_fec2,
+	fsid_fcc1,
+	fsid_fcc2,
+	fsid_fcc3,
+	fsid_scc1,
+	fsid_scc2,
+	fsid_scc3,
+	fsid_scc4,
+};
+
+#define FS_MAX_INDEX	9
+
+static inline int fs_get_fec_index(enum fs_id id)
+{
+	if (id >= fsid_fec1 && id <= fsid_fec2)
+		return id - fsid_fec1;
+	return -1;
+}
+
+static inline int fs_get_fcc_index(enum fs_id id)
+{
+	if (id >= fsid_fcc1 && id <= fsid_fcc3)
+		return id - fsid_fcc1;
+	return -1;
+}
+
+static inline int fs_get_scc_index(enum fs_id id)
+{
+	if (id >= fsid_scc1 && id <= fsid_scc4)
+		return id - fsid_scc1;
+	return -1;
+}
+
+enum fs_mii_method {
+	fsmii_fixed,
+	fsmii_fec,
+	fsmii_bitbang,
+};
+
+enum fs_ioport {
+	fsiop_porta,
+	fsiop_portb,
+	fsiop_portc,
+	fsiop_portd,
+	fsiop_porte,
+};
+
+struct fs_mii_bus_info {
+	int method;		/* mii method                  */
+	int id;			/* the id of the mii_bus       */
+	union {
+		struct {
+			int duplex;
+			int speed;
+		} fixed;
+
+		struct {
+			/* nothing */
+		} fec;
+
+		struct {
+			int mdio_port;	/* port & bit for MDIO */
+			int mdio_bit;
+			int mdc_port;	/* port & bit for MDC  */
+			int mdc_bit;
+			int delay;	/* delay in us         */
+		} bitbang;
+	} i;
+};
+
+struct fs_platform_info {
+	int fs_no;		/* controller index            */
+	int fs_irq;		/* the irq for the controller  */
+				/* (or -1 for default)         */
+	int phy_addr;		/* the phy address (-1 no phy) */
+	int phy_irq;		/* the phy irq (if it exists)  */
+
+	const struct fs_mii_bus_info *bus_info;
+
+	int rx_ring, tx_ring;	/* number of buffers on rx     */
+	__u8 macaddr[6];	/* mac address                 */
+	int rx_copybreak;	/* limit we copy small frames  */
+	int use_napi;		/* use NAPI                    */
+	int napi_weight;	/* NAPI weight                 */
+};
+
+#endif

^ permalink raw reply

* [PATCH  03/04] Freescale Ethernet combined driver
From: Pantelis Antoniou @ 2005-05-09 11:45 UTC (permalink / raw)
  To: Dan Malek, Kumar Gala, Eugene Surovegin, Vitaly Bordug, Tom Rini,
	Marcelo Tosatti, Jason McMullan, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 283 bytes --]

Hi

The following patch is a combined FCC/FEC ethernet driver
for the Freescale line of PowerQUICCs.

FECs on 8xx and FCCs on 82xx are supported.

This part of the patch contains the mac drivers
for FEC & FCC.

Regards

Pantelis

Signed-off-by: Pantelis Antoniou <panto@intracom.gr>

[-- Attachment #2: fs_enet-03.patch --]
[-- Type: text/x-patch, Size: 29971 bytes --]

--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/mac-fcc.c
@@ -0,0 +1,508 @@
+/*
+ * FCC driver for Motorola MPC8xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/* FCC access macros */
+
+/* be safe version */
+#if 1
+#define __fcc_out32(addr, x)	out_be32((unsigned *)addr, x)
+#define __fcc_out16(addr, x)	out_be16((unsigned short *)addr, x)
+#define __fcc_out8(addr, x)	out_8((unsigned char *)addr, x)
+#define __fcc_in32(addr)	in_be32((unsigned *)addr)
+#define __fcc_in16(addr)	in_be16((unsigned short *)addr)
+#define __fcc_in8(addr)		in_8((unsigned char *)addr)
+#else
+#define __fcc_out32(addr, x)	__raw_writel(x, addr)
+#define __fcc_out16(addr, x)	__raw_writew(x, addr)
+#define __fcc_out8(addr, x)	__raw_writeb(x, addr)
+#define __fcc_in32(addr)	__raw_readl(addr)
+#define __fcc_in16(addr)	__raw_readw(addr)
+#define __fcc_in8(addr)		__raw_readb(addr)
+#endif
+
+/* parameter space */
+
+/* write, read, set bits, clear bits */
+#define W32(_p, _m, _v)	__fcc_out32(&(_p)->_m, (_v))
+#define R32(_p, _m)	__fcc_in32(&(_p)->_m)
+#define S32(_p, _m, _v)	W32(_p, _m, R32(_p, _m) | (_v))
+#define C32(_p, _m, _v)	W32(_p, _m, R32(_p, _m) & ~(_v))
+
+#define W16(_p, _m, _v)	__fcc_out16(&(_p)->_m, (_v))
+#define R16(_p, _m)	__fcc_in16(&(_p)->_m)
+#define S16(_p, _m, _v)	W16(_p, _m, R16(_p, _m) | (_v))
+#define C16(_p, _m, _v)	W16(_p, _m, R16(_p, _m) & ~(_v))
+
+#define W8(_p, _m, _v)	__fcc_out8(&(_p)->_m, (_v))
+#define R8(_p, _m)	__fcc_in8(&(_p)->_m)
+#define S8(_p, _m, _v)	W8(_p, _m, R8(_p, _m) | (_v))
+#define C8(_p, _m, _v)	W8(_p, _m, R8(_p, _m) & ~(_v))
+
+/*************************************************/
+
+#define FCC_MAX_MULTICAST_ADDRS	64
+
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end		0
+
+#define MAX_CR_CMD_LOOPS	10000
+
+static inline int fcc_cr_cmd(struct fs_enet_private *fep, __u32 mcn, __u32 op)
+{
+	cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+	cpm_cpm2_t *cpmp = &immap->im_cpm;
+	__u32 pg, sbc, v;
+
+	pg = CPM_CR_FCC1_PAGE + fep->fcc.idx;
+	sbc = CPM_CR_FCC1_SBLOCK + fep->fcc.idx;
+	v = mk_cr_cmd(pg, sbc, mcn, op);
+	W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
+	while ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) != 0)
+		;
+
+	return 0;
+}
+
+#define FCC_NAPI_RX_EVENT_MSK	(FCC_ENET_RXF | FCC_ENET_RXB)
+#define FCC_RX_EVENT		(FCC_ENET_RXF)
+#define FCC_TX_EVENT		(FCC_ENET_TXB)
+#define FCC_ERR_EVENT_MSK	(FCC_ENET_TXE | FCC_ENET_BSY)
+
+static int setup_data(struct net_device *dev)
+{
+	cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
+	if ((unsigned int)fep->fcc.idx >= 3)	/* max 3 FCCs */
+		return -EINVAL;
+
+	fep->fcc.fccp = &immap->im_fcc[fep->fcc.idx];
+	fep->fcc.ep = &immap->im_dprambase[PROFF_FCC1 + fep->fcc.idx * 0x100];
+	fep->fcc.fcccp = &immap->im_fcc_c[fep->fcc.idx];
+
+	fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
+	fep->ev_rx = FCC_RX_EVENT;
+	fep->ev_tx = FCC_TX_EVENT;
+	fep->ev_err = FCC_ERR_EVENT_MSK;
+
+	return 0;
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	S32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_enet_t *ep = fep->fcc.ep;
+
+	W32(ep, fen_gaddrh, 0);
+	W32(ep, fen_gaddrl, 0);
+}
+
+static void set_multicast_one(struct net_device *dev, const __u8 *mac)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_enet_t *ep = fep->fcc.ep;
+	__u16 taddrh, taddrm, taddrl;
+
+	taddrh = ((__u16)mac[5] << 8) | mac[4];
+	taddrm = ((__u16)mac[3] << 8) | mac[2];
+	taddrl = ((__u16)mac[1] << 8) | mac[0];
+
+	W16(ep, fen_taddrh, taddrh);
+	W16(ep, fen_taddrm, taddrm);
+	W16(ep, fen_taddrl, taddrl);
+	fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR);
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+	fcc_enet_t *ep = fep->fcc.ep;
+
+	/* clear promiscuous always */
+	C32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+
+	/* if all multi or too many multicasts; just enable all */
+	if ((dev->flags & IFF_ALLMULTI) != 0 ||
+	    dev->mc_count > FCC_MAX_MULTICAST_ADDRS) {
+
+		W32(ep, fen_gaddrh, 0xffffffff);
+		W32(ep, fen_gaddrl, 0xffffffff);
+	}
+
+	/* read back */
+	fep->fcc.gaddrh = R32(ep, fen_gaddrh);
+	fep->fcc.gaddrl = R32(ep, fen_gaddrl);
+}
+
+static void set_mac_address(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_enet_t *ep = fep->fcc.ep;
+	__u16 paddrh, paddrm, paddrl;
+	const unsigned char *mac = dev->dev_addr;
+
+	paddrh = ((__u16)mac[5] << 8) | mac[4];
+	paddrm = ((__u16)mac[3] << 8) | mac[2];
+	paddrl = ((__u16)mac[1] << 8) | mac[0];
+
+	W16(ep, fen_paddrh, paddrh);
+	W16(ep, fen_paddrm, paddrm);
+	W16(ep, fen_paddrl, paddrl);
+}
+
+static void restart(struct net_device *dev, int duplex, int speed)
+{
+	cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+	fcc_enet_t *ep = fep->fcc.ep;
+	__u16 paddrh, paddrm, paddrl;
+	__u16 mem_addr;
+	const unsigned char *mac;
+	int i;
+
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+	/* clear everything (slow & steady does it) */
+	for (i = 0; i < sizeof(*ep); i++)
+		__fcc_out8((char *)ep + i, 0);
+
+	/* point to bds */
+	W32(ep, fen_genfcc.fcc_rbase, iopa((__u32)fep->rx_bd_base));
+	W32(ep, fen_genfcc.fcc_tbase, iopa((__u32)fep->tx_bd_base));
+
+	/* Set maximum bytes per receive buffer.
+	 * It must be a multiple of 32.
+	 */
+	W16(ep, fen_genfcc.fcc_mrblr, PKT_MAXBLR_SIZE);
+
+	W32(ep, fen_genfcc.fcc_rstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+	W32(ep, fen_genfcc.fcc_tstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+
+	/* Allocate space in the reserved FCC area of DPRAM for the
+	 * internal buffers.  No one uses this space (yet), so we
+	 * can do this.  Later, we will add resource management for
+	 * this area.
+	 */
+	mem_addr = CPM_FCC_SPECIAL_BASE + fep->fcc.idx * 128;
+	W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
+	W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
+	W16(ep, fen_padptr, mem_addr + 64);
+	for (i = 64; i < 128; i++)
+		__fcc_out8(immap->im_dprambase + mem_addr + i, 0x88);
+
+	W32(ep, fen_genfcc.fcc_rbptr, 0);
+	W32(ep, fen_genfcc.fcc_tbptr, 0);
+	W32(ep, fen_genfcc.fcc_rcrc, 0);
+	W32(ep, fen_genfcc.fcc_tcrc, 0);
+	W32(ep, fen_genfcc.fcc_res1, 0);
+	W32(ep, fen_genfcc.fcc_res2, 0);
+
+	/* no CAM */
+	W32(ep, fen_camptr, 0);
+
+	/* Set CRC preset and mask */
+	W32(ep, fen_cmask, 0xdebb20e3);
+	W32(ep, fen_cpres, 0xffffffff);
+
+	W32(ep, fen_crcec, 0);		/* CRC Error counter       */
+	W32(ep, fen_alec, 0);		/* alignment error counter */
+	W32(ep, fen_disfc, 0);		/* discard frame counter   */
+	W16(ep, fen_retlim, 15);	/* Retry limit threshold   */
+	W16(ep, fen_pper, 0);		/* Normal persistence      */
+
+	/* set group address */
+	W32(ep, fen_gaddrh, fep->fcc.gaddrh);
+	W32(ep, fen_gaddrl, fep->fcc.gaddrh);
+
+	/* Clear hash filter tables */
+	W32(ep, fen_iaddrh, 0);
+	W32(ep, fen_iaddrl, 0);
+
+	/* Clear the Out-of-sequence TxBD  */
+	W16(ep, fen_tfcstat, 0);
+	W16(ep ,fen_tfclen, 0);
+	W32(ep, fen_tfcptr, 0);
+
+	W16(ep, fen_mflr, PKT_MAXBUF_SIZE);   /* maximum frame length register */
+	W16(ep, fen_minflr, PKT_MINBUF_SIZE); /* minimum frame length register */
+
+	/* set address */
+	mac = dev->dev_addr;
+	paddrh = ((__u16)mac[5] << 8) | mac[4];
+	paddrm = ((__u16)mac[3] << 8) | mac[2];
+	paddrl = ((__u16)mac[1] << 8) | mac[0];
+
+	W16(ep, fen_paddrh, paddrh);
+	W16(ep, fen_paddrm, paddrm);
+	W16(ep, fen_paddrl, paddrl);
+
+	W16(ep, fen_taddrh, 0);
+	W16(ep, fen_taddrm, 0);
+	W16(ep, fen_taddrl, 0);
+
+	W16(ep, fen_maxd1, 1520);	/* maximum DMA1 length */
+	W16(ep, fen_maxd2, 1520);	/* maximum DMA2 length */
+
+	/* Clear stat counters, in case we ever enable RMON */
+	W32(ep, fen_octc, 0);
+	W32(ep, fen_colc, 0);
+	W32(ep, fen_broc, 0);
+	W32(ep, fen_mulc, 0);
+	W32(ep, fen_uspc, 0);
+	W32(ep, fen_frgc, 0);
+	W32(ep, fen_ospc, 0);
+	W32(ep, fen_jbrc, 0);
+	W32(ep, fen_p64c, 0);
+	W32(ep, fen_p65c, 0);
+	W32(ep, fen_p128c, 0);
+	W32(ep, fen_p256c, 0);
+	W32(ep, fen_p512c, 0);
+	W32(ep, fen_p1024c, 0);
+
+	W16(ep, fen_rfthr, 0);	/* Suggested by manual */
+	W16(ep, fen_rfcnt, 0);
+	W16(ep, fen_cftype, 0);
+
+	fs_init_bds(dev);
+
+	fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX);
+
+	W16(ep, fen_genfcc.fcc_mrblr, PKT_MAXBLR_SIZE);
+
+	/* clear events */
+	W16(fccp, fcc_fcce, 0xffff);
+
+	/* Enable interrupts we wish to service */
+	W16(fccp, fcc_fccm, FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+	/* Set GFMR to enable Ethernet operating mode */
+	W32(fccp, fcc_gfmr, FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+	/* set sync/delimiters */
+	W16(fccp, fcc_fdsr, 0xd555);
+
+	W32(fccp, fcc_fpsmr, FCC_PSMR_ENCRC | FCC_PSMR_RMII);
+
+	/* adjust to duplex mode */
+	if (duplex)
+		S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+	else
+		C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+
+	S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+static void stop(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	/* stop ethernet */
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+	/* clear events */
+	W16(fccp, fcc_fcce, 0xffff);
+
+	/* clear interrupt mask */
+	W16(fccp, fcc_fccm, 0);
+
+	fs_cleanup_bds(dev);
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void post_free_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void napi_clear_rx_event(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static __u32 get_int_events(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	return (__u32)R16(fccp, fcc_fcce);
+}
+
+static void clear_int_events(struct net_device *dev, __u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	W16(fccp, fcc_fcce, int_events & 0xffff);
+}
+
+static void ev_error(struct net_device *dev, __u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	(void)fep;
+	printk(KERN_WARNING DRV_MODULE_NAME
+	       ": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t))
+		return -EINVAL;
+
+	memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
+	p = (char *)p + sizeof(fcc_t);
+
+	memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
+	p = (char *)p + sizeof(fcc_c_t);
+
+	memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
+
+	return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+	return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t);
+}
+
+/* Some transmit errors cause the transmitter to shut
+ * down.  We now issue a restart transmit.  Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.  Also, To workaround 8260 device erratum 
+ * CPM37, we must disable and then re-enable the transmitter
+ * following a Late Collision, Underrun, or Retry Limit error.
+ */
+void tx_restart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+	udelay(10);
+	S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+
+	fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX);
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fcc_ops = {
+	.setup_data		= setup_data,
+	.cleanup_data		= cleanup_data,
+	.set_promiscuous_mode	= set_promiscuous_mode,
+	.set_multicast_start	= set_multicast_start,
+	.set_multicast_one	= set_multicast_one,
+	.set_multicast_finish	= set_multicast_finish,
+	.set_mac_address	= set_mac_address,
+	.restart		= restart,
+	.stop			= stop,
+	.pre_request_irq	= pre_request_irq,
+	.post_free_irq		= post_free_irq,
+	.napi_clear_rx_event	= napi_clear_rx_event,
+	.napi_enable_rx		= napi_enable_rx,
+	.napi_disable_rx	= napi_disable_rx,
+	.rx_bd_done		= rx_bd_done,
+	.tx_kickstart		= tx_kickstart,
+	.get_int_events		= get_int_events,
+	.clear_int_events	= clear_int_events,
+	.ev_error		= ev_error,
+	.get_regs		= get_regs,
+	.get_regs_len		= get_regs_len,
+	.tx_restart		= tx_restart,
+};
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/mac-fec.c
@@ -0,0 +1,633 @@
+/*
+ * Freescale Ethernet controllers
+ *
+ * Copyright (c) 2005 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * Released under the GPL
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#endif
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/* FEC access macros */
+#if defined(CONFIG_8xx)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __fs_out32(addr, x)	__raw_writel(x, addr)
+#define __fs_out16(addr, x)	__raw_writew(x, addr)
+#define __fs_in32(addr)	__raw_readl(addr)
+#define __fs_in16(addr)	__raw_readw(addr)
+#else
+/* for others play it safe */
+#define __fs_out32(addr, x)	out_be32(addr, x)
+#define __fs_out16(addr, x)	out_be16(addr, x)
+#define __fs_in32(addr)	in_be32(addr)
+#define __fs_in16(addr)	in_be16(addr)
+#endif
+
+/* write */
+#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fs_ ## _reg, (_v))
+
+/* read */
+#define FR(_fecp, _reg)	__fs_in32(&(_fecp)->fs_ ## _reg)
+
+/* set bits */
+#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
+
+/* clear bits */
+#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
+
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS	64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR	0x80000000U	/* Heartbeat error          */
+#define FEC_ENET_BABR	0x40000000U	/* Babbling receiver        */
+#define FEC_ENET_BABT	0x20000000U	/* Babbling transmitter     */
+#define FEC_ENET_GRA	0x10000000U	/* Graceful stop complete   */
+#define FEC_ENET_TXF	0x08000000U	/* Full frame transmitted   */
+#define FEC_ENET_TXB	0x04000000U	/* A buffer was transmitted */
+#define FEC_ENET_RXF	0x02000000U	/* Full frame received      */
+#define FEC_ENET_RXB	0x01000000U	/* A buffer was received    */
+#define FEC_ENET_MII	0x00800000U	/* MII interrupt            */
+#define FEC_ENET_EBERR	0x00400000U	/* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX	0x00000004
+#define FEC_ECNTRL_ETHER_EN	0x00000002
+#define FEC_ECNTRL_RESET	0x00000001
+
+#define FEC_RCNTRL_BC_REJ	0x00000010
+#define FEC_RCNTRL_PROM		0x00000008
+#define FEC_RCNTRL_MII_MODE	0x00000004
+#define FEC_RCNTRL_DRT		0x00000002
+#define FEC_RCNTRL_LOOP		0x00000001
+
+#define FEC_TCNTRL_FDEN		0x00000004
+#define FEC_TCNTRL_HBC		0x00000002
+#define FEC_TCNTRL_GTS		0x00000001
+
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end		0
+
+#define FEC_MII_LOOPS	10000
+
+/*
+ * Delay to wait for FEC reset command to complete (in us) 
+ */
+#define FEC_RESET_DELAY		50
+
+static int whack_reset(fec_t * fecp)
+{
+	int i;
+
+	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
+	for (i = 0; i < FEC_RESET_DELAY; i++) {
+		if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
+			return 0;	/* OK */
+		udelay(1);
+	}
+
+	return -1;
+}
+
+#define FEC_NAPI_RX_EVENT_MSK	(FEC_ENET_RXF | FEC_ENET_RXB)
+#define FEC_RX_EVENT		(FEC_ENET_RXF)
+#define FEC_TX_EVENT		(FEC_ENET_TXF)
+#define FEC_ERR_EVENT_MSK	(FEC_ENET_HBERR | FEC_ENET_BABR | \
+				 FEC_ENET_BABT | FEC_ENET_EBERR)
+
+static int setup_data(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->fec.idx = fs_get_fec_index(fpi->fs_no);
+	switch (fep->fec.idx) {
+		case 0:
+			fep->fec.fecp = &((immap_t *)IMAP_ADDR)->im_cpm.cp_fec;
+			break;
+#ifdef CONFIG_DUET
+		case 1:
+			fep->fec.fecp = &((immap_t *)IMAP_ADDR)->im_cpm.cp_fec2;
+			break;
+#endif
+		default:
+			return -EINVAL;
+	}
+
+	fep->fec.hthi = 0;
+	fep->fec.htlo = 0;
+
+	fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
+	fep->ev_rx = FEC_RX_EVENT;
+	fep->ev_tx = FEC_TX_EVENT;
+	fep->ev_err = FEC_ERR_EVENT_MSK;
+
+	return 0;
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->fec.hthi = 0;
+	fep->fec.htlo = 0;
+}
+
+static void set_multicast_one(struct net_device *dev, const __u8 *mac)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	int temp, hash_index, i, j;
+	__u32 crc, csrVal;
+	__u8 byte, msb;
+
+	crc = 0xffffffff;
+	for (i = 0; i < 6; i++) {
+		byte = mac[i];
+		for (j = 0; j < 8; j++) {
+			msb = crc >> 31;
+			crc <<= 1;
+			if (msb ^ (byte & 0x1))
+				crc ^= FEC_CRC_POLY;
+			byte >>= 1;
+		}
+	}
+
+	temp = (crc & 0x3f) >> 1;
+	hash_index = ((temp & 0x01) << 4) |
+		     ((temp & 0x02) << 2) |
+		     ((temp & 0x04)) |
+		     ((temp & 0x08) >> 2) |
+		     ((temp & 0x10) >> 4);
+	csrVal = 1 << hash_index;
+	if (crc & 1)
+		fep->fec.hthi |= csrVal;
+	else
+		fep->fec.htlo |= csrVal;
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	/* if all multi or too many multicasts; just enable all */
+	if ((dev->flags & IFF_ALLMULTI) != 0 ||
+	    dev->mc_count > FEC_MAX_MULTICAST_ADDRS) {
+		fep->fec.hthi = 0xffffffffU;
+		fep->fec.htlo = 0xffffffffU;
+	}
+
+	FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
+	FW(fecp, hash_table_high, fep->fec.hthi);
+	FW(fecp, hash_table_low, fep->fec.htlo);
+}
+
+static void set_mac_address(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+	__u32 addrhi, addrlo;
+
+	/*
+	 * Set station address. 
+	 */
+	addrhi = ((__u32) dev->dev_addr[0] << 24) |
+		 ((__u32) dev->dev_addr[1] << 16) |
+	   	 ((__u32) dev->dev_addr[2] <<  8) |
+	    	  (__u32) dev->dev_addr[3];
+	addrlo = ((__u32) dev->dev_addr[4] << 24) |
+	    	 ((__u32) dev->dev_addr[5] << 16);
+	FW(fecp, addr_low, addrhi);
+	FW(fecp, addr_high, addrlo);
+}
+
+/*
+ * This function is called to start or restart the FEC during a link
+ * change.  This only happens when switching between half and full
+ * duplex.
+ */
+static void restart(struct net_device *dev, int duplex, int speed)
+{
+#ifdef CONFIG_DUET
+	immap_t *immap = (immap_t *) IMAP_ADDR;
+	__u32 cptr;
+#endif
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+	const struct fs_platform_info *fpi = fep->fpi;
+	int r;
+	__u32 addrhi, addrlo;
+
+	r = whack_reset(fep->fec.fecp);
+	if (r != 0)
+		printk(KERN_ERR DRV_MODULE_NAME
+				": %s FEC Reset FAILED!\n", dev->name);
+
+	/*
+	 * Set station address. 
+	 */
+	addrhi = ((__u32) dev->dev_addr[0] << 24) |
+		 ((__u32) dev->dev_addr[1] << 16) |
+		 ((__u32) dev->dev_addr[2] <<  8) |
+		 (__u32) dev->dev_addr[3];
+	addrlo = ((__u32) dev->dev_addr[4] << 24) |
+		 ((__u32) dev->dev_addr[5] << 16);
+	FW(fecp, addr_low, addrhi);
+	FW(fecp, addr_high, addrlo);
+
+	/*
+	 * Reset all multicast. 
+	 */
+	FW(fecp, hash_table_high, fep->fec.hthi);
+	FW(fecp, hash_table_low, fep->fec.htlo);
+
+	/*
+	 * Set maximum receive buffer size. 
+	 */
+	FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
+	FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+
+	/*
+	 * Set receive and transmit descriptor base. 
+	 */
+	FW(fecp, r_des_start, iopa((__u32)fep->rx_bd_base));
+	FW(fecp, x_des_start, iopa((__u32)fep->tx_bd_base));
+
+	fs_init_bds(dev);
+
+	/*
+	 * Enable big endian and don't care about SDMA FC. 
+	 */
+	FW(fecp, fun_code, 0x78000000);
+
+	/*
+	 * Set MII speed. 
+	 */
+	FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+
+	/*
+	 * Clear any outstanding interrupt. 
+	 */
+	FW(fecp, ievent, 0xffc0);
+	FW(fecp, ivec, (fpi->fs_irq / 2) << 29);
+
+	/*
+	 * adjust to speed (only for DUET & RMII) 
+	 */
+#ifdef CONFIG_DUET
+	cptr = in_be32(&immap->im_cpm.cp_cptr);
+	switch (fs_get_fec_index(fpi->fs_no)) {
+	case 0:
+		/*
+		 * check if in RMII mode 
+		 */
+		if ((cptr & 0x100) == 0)
+			break;
+
+		if (speed == 10)
+			cptr |= 0x0000010;
+		else if (speed == 100)
+			cptr &= ~0x0000010;
+		break;
+	case 1:
+		/*
+		 * check if in RMII mode 
+		 */
+		if ((cptr & 0x80) == 0)
+			break;
+
+		if (speed == 10)
+			cptr |= 0x0000008;
+		else if (speed == 100)
+			cptr &= ~0x0000008;
+		break;
+	default:
+		BUG();	/* should never happen */
+		break;
+	}
+	out_be32(&immap->im_cpm.cp_cptr, cptr);
+#endif
+
+	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	/*
+	 * adjust to duplex mode 
+	 */
+	if (duplex) {
+		FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
+		FS(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD enable */
+	} else {
+		FS(fecp, r_cntrl, FEC_RCNTRL_DRT);
+		FC(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD disable */
+	}
+
+	/*
+	 * Enable interrupts we wish to service. 
+	 */
+	FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB |
+	   FEC_ENET_RXF | FEC_ENET_RXB);
+
+	/*
+	 * And last, enable the transmit and receive processing. 
+	 */
+	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+	FW(fecp, r_des_active, 0x01000000);
+}
+
+static void stop(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+	int i;
+
+	if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
+		return;		/* already down */
+
+	FW(fecp, x_cntrl, 0x01);	/* Graceful transmit stop */
+	for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) &&
+	     i < FEC_RESET_DELAY; i++)
+		udelay(1);
+
+	if (i == FEC_RESET_DELAY)
+		printk(KERN_WARNING DRV_MODULE_NAME
+		       ": %s FEC timeout on graceful transmit stop\n",
+		       dev->name);
+	/*
+	 * Disable FEC. Let only MII interrupts. 
+	 */
+	FW(fecp, imask, 0);
+	FW(fecp, ecntrl, ~FEC_ECNTRL_ETHER_EN);
+
+	fs_cleanup_bds(dev);
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+	immap_t *immap = (immap_t *) IMAP_ADDR;
+	__u32 siel;
+
+	/* SIU interrupt */
+	if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) {
+
+		siel = in_be32(&immap->im_siu_conf.sc_siel);
+		if ((irq & 1) == 0)
+			siel |= (0x80000000 >> irq);
+		else
+			siel &= ~(0x80000000 >> (irq & ~1));
+		out_be32(&immap->im_siu_conf.sc_siel, siel);
+	}
+}
+
+static void post_free_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void napi_clear_rx_event(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, r_des_active, 0x01000000);
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, x_des_active, 0x01000000);
+}
+
+static __u32 get_int_events(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	return FR(fecp, ievent) & FR(fecp, imask);
+}
+
+static void clear_int_events(struct net_device *dev, __u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, ievent, int_events);
+}
+
+static void ev_error(struct net_device *dev, __u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	(void)fep;
+	printk(KERN_WARNING DRV_MODULE_NAME
+	       ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (*sizep < sizeof(fec_t))
+		return -EINVAL;
+
+	memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t));
+
+	return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+	return sizeof(fec_t);
+}
+
+void tx_restart(struct net_device *dev)
+{
+	/* nothing */
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fec_ops = {
+	.setup_data		= setup_data,
+	.cleanup_data		= cleanup_data,
+	.set_promiscuous_mode	= set_promiscuous_mode,
+	.set_multicast_start	= set_multicast_start,
+	.set_multicast_one	= set_multicast_one,
+	.set_multicast_finish	= set_multicast_finish,
+	.set_mac_address	= set_mac_address,
+	.restart		= restart,
+	.stop			= stop,
+	.pre_request_irq	= pre_request_irq,
+	.post_free_irq		= post_free_irq,
+	.napi_clear_rx_event	= napi_clear_rx_event,
+	.napi_enable_rx		= napi_enable_rx,
+	.napi_disable_rx	= napi_disable_rx,
+	.rx_bd_done		= rx_bd_done,
+	.tx_kickstart		= tx_kickstart,
+	.get_int_events		= get_int_events,
+	.clear_int_events	= clear_int_events,
+	.ev_error		= ev_error,
+	.get_regs		= get_regs,
+	.get_regs_len		= get_regs_len,
+	.tx_restart		= tx_restart,
+};
+
+/***********************************************************************/
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	fec_t *fecp = bus->fec.fecp;
+	int i, ret = -1;
+
+	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS) {
+		FW(fecp, ievent, FEC_ENET_MII);
+		ret = FR(fecp, mii_data) & 0xffff;
+	}
+
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
+{
+	fec_t *fecp = bus->fec.fecp;
+	int i;
+
+	/* this must never happen */
+	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS)
+		FW(fecp, ievent, FEC_ENET_MII);
+}
+
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
+{
+	bd_t *bd = (bd_t *)__res;
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+	fec_t *fecp;
+
+	switch (bi->id) {
+		case 0:
+			bus->fec.fecp = &((immap_t *)IMAP_ADDR)->im_cpm.cp_fec;
+			break;
+#ifdef CONFIG_DUET
+		case 1:
+			bus->fec.fecp = &((immap_t *)IMAP_ADDR)->im_cpm.cp_fec2;
+			break;
+#endif
+		default:
+			return -EINVAL;
+	}
+
+	bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
+				& 0x3F) << 1;
+
+	fecp = bus->fec.fecp;
+
+	FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+	FW(fecp, ievent, FEC_ENET_MII);
+	FW(fecp, mii_speed, bus->fec.mii_speed);
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}

^ permalink raw reply

* [PATCH  04/04] Freescale Ethernet combined driver
From: Pantelis Antoniou @ 2005-05-09 11:45 UTC (permalink / raw)
  To: Dan Malek, Kumar Gala, Eugene Surovegin, Vitaly Bordug, Tom Rini,
	Marcelo Tosatti, Jason McMullan, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 269 bytes --]

Hi

The following patch is a combined FCC/FEC ethernet driver
for the Freescale line of PowerQUICCs.

FECs on 8xx and FCCs on 82xx are supported.

This part of the patch contains the mii drivers.

Regards

Pantelis

Signed-off-by: Pantelis Antoniou <panto@intracom.gr>

[-- Attachment #2: fs_enet-04.patch --]
[-- Type: text/x-patch, Size: 10082 bytes --]

--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/mii-bitbang.c
@@ -0,0 +1,394 @@
+/*
+ * XXX blah blah
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+#ifdef CONFIG_8xx
+static int bitbang_prep_bit(__u8 **dirp, __u8 **datp, __u8 *mskp, int port, int bit)
+{
+	immap_t *im = (immap_t *)IMAP_ADDR;
+	void *dir, *dat, *ppar;
+	int adv;
+	__u8 msk;
+
+	switch (port) {
+		case fsiop_porta:
+			dir = &im->im_ioport.iop_padir;
+			dat = &im->im_ioport.iop_padat;
+			ppar = &im->im_ioport.iop_papar;
+			break;
+
+		case fsiop_portb:
+			dir = &im->im_cpm.cp_pbdir;
+			dat = &im->im_cpm.cp_pbdat;
+			ppar = &im->im_cpm.cp_pbpar;
+			break;
+
+		case fsiop_portc:
+			dir = &im->im_ioport.iop_pcdir;
+			dat = &im->im_ioport.iop_pcdat;
+			ppar = &im->im_ioport.iop_pcpar;
+			break;
+
+		case fsiop_portd:
+			dir = &im->im_ioport.iop_pddir;
+			dat = &im->im_ioport.iop_pddat;
+			ppar = &im->im_ioport.iop_pdpar;
+			break;
+
+		case fsiop_porte:
+			dir = &im->im_cpm.cp_pedir;
+			dat = &im->im_cpm.cp_pedat;
+			ppar = &im->im_cpm.cp_pepar;
+			break;
+
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       "Illegal port value %d!\n", port);
+			return -EINVAL;
+	}
+
+	adv = bit >> 3;
+	dir = (char *)dir + adv;
+	dat = (char *)dat + adv;
+	ppar = (char *)ppar + adv;
+
+	msk = 1 << (7 - (bit & 7));
+	if ((in_8(ppar) & msk) != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       "pin %d on port %d is not general purpose!\n", bit, port);
+		return -EINVAL;
+	}
+
+	*dirp = dir;
+	*datp = dat;
+	*mskp = msk;
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_8260
+static int bitbang_prep_bit(__u8 **dirp, __u8 **datp, __u8 *mskp, int port, int bit)
+{
+	iop_cpm2_t *io = &((cpm2_map_t *)CPM_MAP_ADDR)->im_ioport;
+	void *dir, *dat, *ppar;
+	int adv;
+	__u8 msk;
+
+	switch (port) {
+		case fsiop_porta:
+			dir = &io->iop_pdira;
+			dat = &io->iop_pdata;
+			ppar = &io->iop_ppara;
+			break;
+
+		case fsiop_portb:
+			dir = &io->iop_pdirb;
+			dat = &io->iop_pdatb;
+			ppar = &io->iop_pparb;
+			break;
+
+		case fsiop_portc:
+			dir = &io->iop_pdirc;
+			dat = &io->iop_pdatc;
+			ppar = &io->iop_pparc;
+			break;
+
+		case fsiop_portd:
+			dir = &io->iop_pdird;
+			dat = &io->iop_pdatd;
+			ppar = &io->iop_ppard;
+			break;
+
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       "Illegal port value %d!\n", port);
+			return -EINVAL;
+	}
+
+	adv = bit >> 3;
+	dir = (char *)dir + adv;
+	dat = (char *)dat + adv;
+	ppar = (char *)ppar + adv;
+
+	msk = 1 << (7 - (bit & 7));
+	if ((in_8(ppar) & msk) != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       "pin %d on port %d is not general purpose!\n", bit, port);
+		return -EINVAL;
+	}
+
+	*dirp = dir;
+	*datp = dat;
+	*mskp = msk;
+
+	return 0;
+}
+#endif
+
+static inline void bb_set(__u8 *p, __u8 m)
+{
+	out_8(p, in_8(p) | m);
+}
+
+static inline void bb_clr(__u8 *p, __u8 m)
+{
+	out_8(p, in_8(p) & ~m);
+}
+
+static inline int bb_read(__u8 *p, __u8 m)
+{
+	return (in_8(p) & m) != 0;
+}
+
+static inline void mdio_active(struct fs_enet_mii_bus *bus)
+{
+	bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+{
+	bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline int mdio_read(struct fs_enet_mii_bus *bus)
+{
+	return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+{
+	if (what)
+		bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+	else
+		bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+{
+	if (what)
+		bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+	else
+		bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+}
+
+static inline void mii_delay(struct fs_enet_mii_bus *bus)
+{
+	udelay(bus->bus_info->i.bitbang.delay);
+}
+
+/* Utility to send the preamble, address, and register (common to read and write). */
+static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, __u8 addr, __u8 reg)
+{
+	int j;
+
+	/*
+	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+	 * The IEEE spec says this is a PHY optional requirement.  The AMD
+	 * 79C874 requires one after power up and one after a MII communications
+	 * error.  This means that we are doing more preambles than we need,
+	 * but it is safer and will be much more robust.
+	 */
+
+	mdio_active(bus);
+	mdio(bus, 1);
+	for (j = 0; j < 32; j++) {
+		mdc(bus, 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+	}
+
+	/* send the start bit (01) and the read opcode (10) or write (10) */
+	mdc(bus, 0);
+	mdio(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, read);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, !read);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* send the PHY address */
+	for (j = 0; j < 5; j++) {
+		mdc(bus, 0);
+		mdio(bus, (addr & 0x10) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		addr <<= 1;
+	}
+
+	/* send the register address */
+	for (j = 0; j < 5; j++) {
+		mdc(bus, 0);
+		mdio(bus, (reg & 0x10) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		reg <<= 1;
+	}
+}
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	__u16 rdreg;
+	int ret, j;
+	__u8 addr = phy_id & 0xff;
+	__u8 reg = location & 0xff;
+
+	bitbang_pre(bus, 1, addr, reg);
+
+	/* tri-state our MDIO I/O pin so we can read */
+	mdc(bus, 0);
+	mdio_tristate(bus);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* check the turnaround bit: the PHY should be driving it to zero */
+	if (mdio_read(bus) != 0) {
+		/* puts ("PHY didn't drive TA low\n"); */
+		for (j = 0; j < 32; j++) {
+			mdc(bus, 0);
+			mii_delay(bus);
+			mdc(bus, 1);
+			mii_delay(bus);
+		}
+		ret = -1;
+		goto out;
+	}
+
+	mdc(bus, 0);
+	mii_delay(bus);
+
+	/* read 16 bits of register data, MSB first */
+	rdreg = 0;
+	for (j = 0; j < 16; j++) {
+		mdc(bus, 1);
+		mii_delay(bus);
+		rdreg <<= 1;
+		rdreg |= mdio_read(bus);
+		mdc(bus, 0);
+		mii_delay(bus);
+	}
+
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	ret = rdreg;
+out:
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+	int j;
+	__u8 addr = phy_id & 0xff;
+	__u8 reg = location & 0xff;
+	__u16 value = val & 0xffff;
+
+	bitbang_pre(bus, 0, addr, reg);
+
+	/* send the turnaround (10) */
+	mdc(bus, 0);
+	mdio(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* write 16 bits of register data, MSB first */
+	for (j = 0; j < 16; j++) {
+		mdc(bus, 0);
+		mdio(bus, (value & 0x8000) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		value <<= 1;
+	}
+
+	/*
+	 * Tri-state the MDIO line.
+	 */
+	mdio_tristate(bus);
+	mdc(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+}
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+{
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+	int r;
+
+	r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
+			 &bus->bitbang.mdio_dat,
+			 &bus->bitbang.mdio_msk,
+			 bi->i.bitbang.mdio_port,
+			 bi->i.bitbang.mdio_bit);
+	if (r != 0)
+		return r;
+
+	r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
+			 &bus->bitbang.mdc_dat,
+			 &bus->bitbang.mdc_msk,
+			 bi->i.bitbang.mdc_port,
+			 bi->i.bitbang.mdc_bit);
+	if (r != 0)
+		return r;
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}
--- /dev/null
+++ linux-2.6.11.7-fs_enet/drivers/net/fs_enet/mii-fixed.c
@@ -0,0 +1,81 @@
+/*
+ * XXX blah blah
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+static const __u16 mii_regs[7] = {
+	0x3100,
+	0x786d,
+	0x0fff,
+	0x0fff,
+	0x01e1,
+	0x45e1,
+	0x0003,
+};
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	int ret = 0;
+
+	if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
+		return -1;
+
+	if (location != 5)
+		ret = mii_regs[location];
+	else
+		ret = bus->fixed.lpa;
+
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+	/* do nothing */
+}
+
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
+{
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+
+	bus->fixed.lpa = 0x45e1;	/* default 100Mb, full duplex */
+
+	/* if speed is fixed at 10Mb, remove 100Mb modes */
+	if (bi->i.fixed.speed == 10)
+		bus->fixed.lpa &= ~LPA_100;
+
+	/* if duplex is half, remove full duplex modes */
+	if (bi->i.fixed.duplex == 0)
+		bus->fixed.lpa &= ~LPA_DUPLEX;
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}

^ permalink raw reply

* Re: 2.4.18: CPM1 stops when initializing ATM/UTOPIA.
From: Alex Zeffertt @ 2005-05-09 12:10 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <427BBA71.8040307@chello.nl>

It may be that you're getting a conflict in SCC usage.  Make sure you
have CONFIG_SERIAL_ATM undefined.  But if you really need it make sure
CONFIG_SERIAL_ATM_SCC is not used by anything else.  You may also want
to disable CONFIG_PTP_SWITCHING if you don't need it.  Finally you
probably want CONFIG_PHY_OTHER instead of CONFIG_PHY_SUNI_155 or
CONFIG_PHY_ATM_25.  These latter options make assumptions about the
memory mapping of your phy.

Note: a long while ago we had problems with PTP switching causing hangs
but this was fixed by a ucode patch from motorola.  If you really need
PTP switching you should get this.

Alex


On Fri, 06 May 2005 20:41:53 +0200
Theo Gjaltema <gjalt007@chello.nl> wrote:

> Hi,
> 
> Last week I was trying to integrate the atm/utopia driver
> (sourceforce) into a 2.4.18 kernel build for a 862, but mij attemtps
> failed. It appeared that wen on the first location of the SCC4 (now
> used for utopia) a buffer address is written, most CPM activities are
> halted, including the SCM1 which I used as console port. The console
> driver did write in the allocated buffer descriptors, but the
> tranmission of the data was never acknowledged, thus hanging the
> kernel.
> 
> Anyone an idea what happened?
> 
> Theo.
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: Linuxppc-embedded Digest, montavista
From: Wolfgang Denk @ 2005-05-09 12:49 UTC (permalink / raw)
  To: Gopala Krishnam Raju; +Cc: linuxppc-embedded
In-Reply-To: <83986B58C72FC447AAC98F916BAB6A5735D908@postman.facetime.com>

In message <83986B58C72FC447AAC98F916BAB6A5735D908@postman.facetime.com> you wrote:
> 
> I have created a boot image for montavista doing the following way.

Maybe you should contact MV support then...

> 7. got the bzImage in /linux..../arch/i386/boot/.  then i have copied =
                                        ^^^^

i386??

> 8. Made necessary changes in the grub.conf.

GRUB???

Are you really on a x86 target? Why do you post to a PowerPC  mailing
list then?

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
If the odds are a million to one against something occuring,  chances
are 50-50 it will.

^ permalink raw reply

* Re: PPC uImage build not reporting correctly
From: Kumar Gala @ 2005-05-09 15:19 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Tom Rini,
	<cpclark@xmission.com> <cpclark@xmission.com>,
	Linux Kernel list, linuxppc-embedded list
In-Reply-To: <Pine.LNX.4.63.0505061718380.6288@xmission.xmission.com>


On May 6, 2005, at 6:22 PM, <cpclark@xmission.com> wrote:

> On Fri, 6 May 2005, Kumar Gala wrote:
>  > I tried the following w/o success:
>  >
> > $(obj)/uImage: $(obj)/vmlinux.gz
> >=A0=A0=A0=A0=A0=A0=A0=A0 $(Q)rm -f $@
>  >=A0=A0=A0=A0=A0=A0=A0=A0 $(call if_changed,uimage)
> >=A0=A0=A0=A0=A0=A0=A0=A0 @echo '=A0 Image: $@' $(shell if [ -f $@ ]; =
then echo 'is=20
> ready'; else
>  > echo 'not made'; fi)
>
> Couldn't you eliminate the ($shell ..) construct altogether, like=20
> this?:
>
> $(obj)/uImage: $(obj)/vmlinux.gz
> =A0=A0=A0=A0=A0=A0=A0 $(Q)rm -f $@
>  =A0=A0=A0=A0=A0=A0=A0 $(call if_changed,uimage)
> =A0=A0=A0=A0=A0=A0=A0 @echo -n '=A0 Image: $@'
>  =A0=A0=A0=A0=A0=A0=A0 @if [ -f $@ ]; then echo 'is ready' ; else echo =
'not made'; fi

Yes, and this seems to actually work.

Sam, does this look reasonable to you.  If so I will work up a patch.

thanks

- kumar

^ permalink raw reply

* mpc 83xx immap_t question
From: Kostantinos Baliotis @ 2005-05-09 16:16 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 571 bytes --]

Hi folks,

 

I'm trying to port a custom driver to mpc8343E processor (a relatively
new one). I would be grateful if someone could point me out some links
with specific patches, sources (or if it is possible the appropriate
cross compile tool chain) for this target CPU.

At this stage my main concern is if this new freescale embedded
processor supports the immap_t structure (known from the good old
mpc860).

I should mention that I'm using a 2.4 Linux kernel at the moment.

Thank you for your time and consideration.

 

Kostas

 

 

 


[-- Attachment #2: Type: text/html, Size: 2709 bytes --]

^ permalink raw reply

* Re: mpc 83xx immap_t question
From: Kumar Gala @ 2005-05-09 16:58 UTC (permalink / raw)
  To: Kostantinos Baliotis; +Cc: linuxppc-embedded
In-Reply-To: <9EDE1664710B26419A57B21CBCBB8D0B01950175@XY01EX01.xy01.xyratex.com>


On May 9, 2005, at 11:16 AM, Kostantinos Baliotis wrote:

> Hi folks,
>
> =A0
>
> I=92m trying to port a custom driver to mpc8343E processor (a =
relatively=20
> new one). I would be grateful if someone could point me out some links=20=

> with specific patches, sources (or if it is possible the appropriate=20=

> cross compile tool chain) for this target CPU.

It uses a 603 based core so any standard PPC cross compiler should be=20
fine.

> At this stage my main concern is if this new freescale=20
> embedded=A0processor supports the immap_t structure (known from the =
good=20
> old mpc860).

Not exactly sure what you are mean here.  However, there are not any=20
plans to create master immap_t structures anymore.

> I should mention that I=92m using a 2.4 Linux kernel at the moment.

2.6 has basic support for 834x in 2.6.12-rc4.

- kumar=

^ permalink raw reply

* Re: [PATCH  01/04] Freescale Ethernet combined driver
From: Kumar Gala @ 2005-05-09 17:26 UTC (permalink / raw)
  To: Pantelis Antoniou; +Cc: Tom Rini, linuxppc-embedded
In-Reply-To: <427F4D38.70102@intracom.gr>

Any reason we dont allow this driver on 85xx?  (should be same as 82xx)

- kumar

On May 9, 2005, at 6:44 AM, Pantelis Antoniou wrote:

> Hi
>
> The following patch is a combined FCC/FEC ethernet driver
> for the Freescale line of PowerQUICCs.
>
> FECs on 8xx and FCCs on 82xx are supported.
>
> This part of the patch contains makefiles and friends.
>
> Regards
>
> Pantelis
>
> Signed-off-by: Pantelis Antoniou <panto@intracom.gr>
> <fs_enet-01.patch>

^ permalink raw reply

* Re: [PATCH] 8xx: fix usage of pinned 8Mbyte TLB entries
From: Marcelo Tosatti @ 2005-05-07 15:47 UTC (permalink / raw)
  To: Dan Malek; +Cc: linux-ppc-embedded
In-Reply-To: <42e4582f0d1644c2ece0a2cb86f49003@embeddededge.com>

On Sat, May 07, 2005 at 04:02:34PM -0400, Dan Malek wrote:
> 
> On May 7, 2005, at 9:16 AM, Marcelo Tosatti wrote:
> 
> >Not creating 4kb mappings for the first 8Mbytes of kernel
> >virtual addresses fixed the problem for me.
> 
> Fixed what problem?

page faults for initial 8Mbytes of kernel virtual map.

> In the TLB dump, you replaced the initial 8M entry with
> a bunch of 4K page entries, just as I would have expected
> to happen.  Since it was able to run and load these, the
> complete PTE tables must have been created.

Right, that was a dump of a "problematic" (ie 4kb pagefaults on
8Mbyte pinned region) kernel.

> How did you "not create" the 4K mappings?

I told mapin_ram() to start at KERNELBASE + 8Mb. 

But, as you said, thats not necessary. 

^ permalink raw reply

* [ANNOUNCE] mini_fo-0.6.0 overlay file system
From: Markus Klotzbuecher @ 2005-05-09 18:27 UTC (permalink / raw)
  To: linuxppc-embedded

mini_fo is a virtual kernel filesystem that can make read-only file
systems writable. This is done by redirecting modifying operations to
a writeable location called "storage directory", and leaving the
original data in the "base directory" untouched. When reading, the
file system merges the modifed and original data so that only the
newest versions will appear. This occurs transparently to the user,
who can access the data like on any other read-write file system.

mini_fo was originally developed for use in embedded systems, and
therefore is lightweight in terms of module size (~50K), memory usage
and storage usage. Nevertheless it has proved usefull for other
projects such as live cds or for sandboxing and testing.

For more information and download of the sources visit the project
page:

http://www.denx.de/twiki/bin/view/Know/MiniFOHome

ChangeLog for mini_fo-0-6-0:
   - support for 2.4 and 2.6 kernels.
   - mini_fo now implements all file system operations.
   - many bugfixes and code cleanup.


Markus Klotzbuecher

^ permalink raw reply

* Re: How to fix 8xx dcbst bug?
From: Marcelo Tosatti @ 2005-05-07 21:47 UTC (permalink / raw)
  To: Dan Malek; +Cc: Joakim Tjernlund, linux-ppc-embedded
In-Reply-To: <52dc3ae70f883699b1e48b7d742afcaf@embeddededge.com>

On Sat, May 07, 2005 at 09:10:17PM -0400, Dan Malek wrote:
> 
> On May 6, 2005, at 11:45 AM, Marcelo Tosatti wrote:
> 
> >
> >Hi Dan,
> >
> >So, restarting this conversation...
> 
> One of the things I don't want to lose sight of during
> all of this is the real performance problem in 2.6.
> Your test results show there is something that needs
> attention, regardless of using pinned entries.  We
> need to continue some of this investigation, it
> affects all processors.

True.

Follows some useful data: 

"itlb-content-before" and "itlb-content-after" are dumps of TLB cache
content before and after "sys_read()", for both v2.4 and v2.6.

The "diff" output shows which TLB's have been faulted in:

[marcelo@logos itlb]$ diff -u 24-itlb-content-before.txt 24-itlb-content-after.txt  
| grep SPR | grep 816 | grep "+"
+SPR  816 : 0x0ffe800f    268337167
+SPR  816 : 0x0ffeb00f    268349455
+SPR  816 : 0xc009e01f  -1073094625
+SPR  816 : 0xc009d01f  -1073098721
+SPR  816 : 0xc000301f  -1073729505
+SPR  816 : 0xc009c01f  -1073102817

[marcelo@logos itlb]$ diff -u 24-itlb-content-before.txt 24-itlb-content-after.txt  
| grep SPR | grep 818 | grep "+"  | wc -l
6

Now v2.6:

[marcelo@logos itlb]$ diff -u 26-itlb-before.txt 26-itlb-after.txt  
| grep 816 | grep SPR | grep "+"
+SPR  816 : 0x0feda16f    267231599
+SPR  816 : 0xc004b17f  -1073434241
+SPR  816 : 0xc004a17f  -1073438337
+SPR  816 : 0x0ff7e16f    267903343
+SPR  816 : 0x1001016f    268501359
+SPR  816 : 0xc000217f  -1073733249
+SPR  816 : 0xc001617f  -1073651329
+SPR  816 : 0xc002e17f  -1073553025
+SPR  816 : 0xc010e17f  -1072635521
+SPR  816 : 0xc002d17f  -1073557121
+SPR  816 : 0xc010d17f  -1072639617
+SPR  816 : 0xc000c17f  -1073692289
+SPR  816 : 0xc000317f  -1073729153

[marcelo@logos itlb]$ diff -u 26-itlb-before.txt 26-itlb-after.txt  
| grep 816 | grep SPR | grep "+" | wc -l
13

So, for sys_read() v2.6 i-cache translation footprint is about 100% 
more than v2.4.  

I suspect that actual cache footprint is higher, too.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox