change log for rtems (2011-08-01)

rtems-vc at rtems.org rtems-vc at rtems.org
Mon Aug 1 14:10:30 UTC 2011


 *jennifer*:
2011-08-01	Jennifer Averett <Jennifer.Averett at OARcorp.com>

	PR 1802
	* Makefile.am, configure.ac, preinstall.am, clock/ckinit.c,
	start/start16.S, startup/bspstart.c, startup/ldsegs.S: Add SMP
	support for i386.

M  1.278  c/src/lib/libbsp/i386/pc386/ChangeLog
M   1.61  c/src/lib/libbsp/i386/pc386/Makefile.am
M   1.25  c/src/lib/libbsp/i386/pc386/clock/ckinit.c
M   1.42  c/src/lib/libbsp/i386/pc386/configure.ac
M   1.11  c/src/lib/libbsp/i386/pc386/preinstall.am
M   1.15  c/src/lib/libbsp/i386/pc386/start/start16.S
M   1.51  c/src/lib/libbsp/i386/pc386/startup/bspstart.c
M   1.21  c/src/lib/libbsp/i386/pc386/startup/ldsegs.S

diff -u rtems/c/src/lib/libbsp/i386/pc386/ChangeLog:1.277 rtems/c/src/lib/libbsp/i386/pc386/ChangeLog:1.278
--- rtems/c/src/lib/libbsp/i386/pc386/ChangeLog:1.277	Wed Jul 20 11:50:19 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/ChangeLog	Mon Aug  1 08:41:36 2011
@@ -1,3 +1,10 @@
+2011-08-01	Jennifer Averett <Jennifer.Averett at OARcorp.com>
+
+	PR 1802
+	* Makefile.am, configure.ac, preinstall.am, clock/ckinit.c,
+	start/start16.S, startup/bspstart.c, startup/ldsegs.S: Add SMP
+	support for i386.
+
 2011-07-20	Jennifer Averett <Jennifer.Averett at OARcorp.com>
 
 	* start/start16.S: Removed tabs and added OAR standard copyright header

diff -u rtems/c/src/lib/libbsp/i386/pc386/Makefile.am:1.60 rtems/c/src/lib/libbsp/i386/pc386/Makefile.am:1.61
--- rtems/c/src/lib/libbsp/i386/pc386/Makefile.am:1.60	Sun Jun 19 16:16:36 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/Makefile.am	Mon Aug  1 08:41:37 2011
@@ -31,6 +31,11 @@
     ../../shared/include/irq-generic.h \
     ../../shared/include/irq-info.h
 
+if HAS_SMP
+include_bsp_HEADERS += ../../i386/shared/irq/apic.h
+include_bsp_HEADERS += ../../i386/shared/smp/smp-imps.h
+endif
+
 include_HEADERS += include/crt.h
 nodist_include_HEADERS += ../../shared/include/coverhd.h
 
@@ -109,8 +114,19 @@
 libbsp_a_SOURCES += ide/idecfg.c ide/ide.c
 
 if HAS_SMP
-libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \
-    ../../shared/smp/bspsmp_wait_for.c
+libbsp_a_SOURCES += ../../i386/shared/smp/getcpuid.c 
+libbsp_a_SOURCES += ../../i386/shared/smp/smp-imps.c 
+
+project_lib_DATA += appstart.$(OBJEXT)
+appcpustart.$(OBJEXT): start/start16.S
+	$(CPPASCOMPILE) $(AM_CPPFLAGS) -DSMP_SECONDARY_CORE -o $@ -c $<
+
+appstart.$(OBJEXT): appcpustart.$(OBJEXT)
+	$(LD) -N -T $(top_srcdir)/startup/linkcmds \
+	    -Ttext 0x70000 -e app_processor_start -nostdlib \
+	    -o appstart_tmp.exe $<
+	$(OBJCOPY) -O binary appstart_tmp.exe appstart.bin
+	$(OBJCOPY) -I binary -O elf32-i386 -B i386 appstart.bin $@
 endif
 
 if HAS_NETWORKING
@@ -144,6 +160,11 @@
 libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/cache.rel \
     ../../../libcpu/@RTEMS_CPU@/page.rel \
     ../../../libcpu/@RTEMS_CPU@/score.rel
+
+if HAS_SMP
+libbsp_a_LIBADD += appstart.$(OBJEXT)
+endif
+
 # We only build the Network library if HAS_NETWORKING was defined
 # dec21140 is supported via libchip
 if HAS_NETWORKING

diff -u rtems/c/src/lib/libbsp/i386/pc386/clock/ckinit.c:1.24 rtems/c/src/lib/libbsp/i386/pc386/clock/ckinit.c:1.25
--- rtems/c/src/lib/libbsp/i386/pc386/clock/ckinit.c:1.24	Wed Mar 10 11:16:01 2010
+++ rtems/c/src/lib/libbsp/i386/pc386/clock/ckinit.c	Mon Aug  1 08:41:37 2011
@@ -234,6 +234,8 @@
   }
   pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
 
+  BSP_irq_enable_at_i8259s( BSP_PERIODIC_TIMER - BSP_IRQ_VECTOR_BASE );
+
   #if 0
     printk( "configured usecs per tick=%d \n",
       rtems_configuration_get_microseconds_per_tick() );
@@ -271,15 +273,33 @@
 rtems_isr Clock_isr(
   rtems_vector_number vector
 );
+
+bool Clock_isr_enabled = false;
+void Clock_isr_handler(
+  rtems_irq_hdl_param param 
+)
+{
+  if ( Clock_isr_enabled )
+    Clock_isr( 0 );
+}
+
 static rtems_irq_connect_data clockIrqData = {
   BSP_PERIODIC_TIMER,
-  (void *)Clock_isr,
+  Clock_isr_handler,
   0,
   clockOn,
   clockOff,
   clockIsOn
 };
 
+void Clock_driver_install_handler(void)
+{
+  if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
+    printk("Unable to install system clock ISR handler\n");
+    rtems_fatal_error_occurred(1);
+  }
+}
+
 void Clock_driver_support_initialize_hardware(void)
 {
   bool use_tsc = false;
@@ -318,11 +338,7 @@
     Clock_driver_nanoseconds_since_last_tick
   );
 
-  if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
-    printk("Unable to initialize system clock\n");
-    rtems_fatal_error_occurred(1);
-  }
-
+  Clock_isr_enabled = true;
 }
 
 #define Clock_driver_support_shutdown_hardware() \

diff -u rtems/c/src/lib/libbsp/i386/pc386/configure.ac:1.41 rtems/c/src/lib/libbsp/i386/pc386/configure.ac:1.42
--- rtems/c/src/lib/libbsp/i386/pc386/configure.ac:1.41	Wed Mar 16 15:05:13 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/configure.ac	Mon Aug  1 08:41:37 2011
@@ -85,6 +85,12 @@
 [Always defined when on a pc386 to enable the pc386 support for
  determining the CPU core number in an SMP configuration.])
 
+## The PC386 BSP supports SMP configurations if this is enabled.
+RTEMS_BSPOPTS_SET([BSP_HAS_SMP],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_HAS_SMP],
+[Always defined when on a pc386 to enable the pc386 support for
+ determining the CPU core number in an SMP configuration.])
+
 ## if this is an i386, does gas have good code16 support?
 RTEMS_I386_GAS_CODE16
 AM_CONDITIONAL(RTEMS_GAS_CODE16,[test "$RTEMS_GAS_CODE16" = "yes"])

diff -u rtems/c/src/lib/libbsp/i386/pc386/preinstall.am:1.10 rtems/c/src/lib/libbsp/i386/pc386/preinstall.am:1.11
--- rtems/c/src/lib/libbsp/i386/pc386/preinstall.am:1.10	Mon Mar 14 09:57:00 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/preinstall.am	Mon Aug  1 08:41:37 2011
@@ -73,6 +73,15 @@
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
 
+if HAS_SMP
+$(PROJECT_INCLUDE)/bsp/apic.h: ../../i386/shared/irq/apic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/apic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/apic.h
+
+$(PROJECT_INCLUDE)/bsp/smp-imps.h: ../../i386/shared/smp/smp-imps.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/smp-imps.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/smp-imps.h
+endif
 $(PROJECT_INCLUDE)/crt.h: include/crt.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/crt.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/crt.h
@@ -122,6 +131,11 @@
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/uart.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/uart.h
 
+if HAS_SMP
+$(PROJECT_LIB)/appstart.$(OBJEXT): appstart.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_LIB)/appstart.$(OBJEXT)
+TMPINSTALL_FILES += $(PROJECT_LIB)/appstart.$(OBJEXT)
+endif
 if HAS_NETWORKING
 $(PROJECT_INCLUDE)/wd80x3.h: include/wd80x3.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/wd80x3.h

diff -u rtems/c/src/lib/libbsp/i386/pc386/start/start16.S:1.14 rtems/c/src/lib/libbsp/i386/pc386/start/start16.S:1.15
--- rtems/c/src/lib/libbsp/i386/pc386/start/start16.S:1.14	Wed Jul 20 11:50:19 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/start/start16.S	Mon Aug  1 08:41:37 2011
@@ -37,35 +37,57 @@
 | Constants
 +----------------------------------------------------------------------------*/
 
+#if defined(SMP_SECONDARY_CORE)
+.set PROT_CODE_SEG, 0x08        # offset of code segment descriptor into GDT
+#else
 .set PROT_CODE_SEG, 0x0         # offset of code segment descriptor into GDT
+#endif
+
 .set PROT_DATA_SEG, 0x10        # offset of code segment descriptor into GDT
 .set CR0_PE,        1           # protected mode flag on CR0 register
 .set HDRSTART,      HEADERADDR  # address of start of bin2boot header
 .set HDROFF,        0x24        # offset into bin2boot header of start32 addr
 .set STACKOFF,      0x200-0x10  # offset to load into %esp, from start of image
 
- /* #define NEW_GAS */
+/* #define NEW_GAS */
+#ifdef NEW_GAS
+  #define LJMPL ljmpl
+#else
+  #define LJMPL ljmp
+#endif
+
 /*----------------------------------------------------------------------------+
 | CODE section
 +----------------------------------------------------------------------------*/
 
 .text
-
+#if defined(SMP_SECONDARY_CORE)
+        .globl app_processor_start                # entry point
+app_processor_start:
+#else
         .globl _start16         # entry point
         .globl start16
 start16:
 _start16:
+#endif
 
 .code16
         cli                     # DISABLE INTERRUPTS!!!
+#if defined(SMP_SECONDARY_CORE)
+        jmp     1f
+	.align 4
+app_cpu_start:
+	.long   0
+app_cpu_stack:
+	.long   0
+1:
+#endif
+        movw    %cs, %ax                   # Initialize the rest of 
+        movw    %ax, %ds                   #   segment registers
+        movw    %ax, %es
+        movw    %ax, %ss
 
-        movw    %cs, %ax        #
-        movw    %ax, %ds        # set the rest of real mode registers
-        movw    %ax, %es        #
-        movw    %ax, %ss        #
-
-#if (RTEMS_VIDEO_80x50 == 1)
-
+#if !defined(SMP_SECONDARY_CODE) && (RTEMS_VIDEO_80x50 == 1)
         movl    $0x0040,%eax    # use 32 bit constant to ensure 16 MSB=0
         mov     %ax,%es
         movw    %es:0x4a, %ax   # get 16 bit number of columns
@@ -87,26 +109,30 @@
         movb    $0x01, %ah      # define cursor (scan lines 0 to 7)
         movw    $0x0007, %cx
         int     $0x10
-
 1:
-#endif /* RTEMS_VIDEO_80x50 */
+#endif /* !SMP_SECONDARY_CODE and RTEMS_VIDEO_80x50 */
 
         /*---------------------------------------------------------------------+
         | Bare PC machines boot in real mode! We have to turn protected mode on.
         +---------------------------------------------------------------------*/
 
+#if defined(SMP_SECONDARY_CORE)
+        lgdt    gdtptr - app_processor_start  # load Global Descriptor Table
+#else
         lgdt    gdtptr - start16        # load Global Descriptor Table
+#endif /* SMP_SECONDARY_CORE */
+
         movl    %cr0, %eax
         orl     $CR0_PE, %eax
         movl    %eax, %cr0              # turn on protected mode
-
-#ifdef NEW_GAS
-        ljmpl   $PROT_CODE_SEG, $1f     # flush prefetch queue, and reload %cs
+#if defined(SMP_SECONDARY_CORE)
+        LJMPL   $PROT_CODE_SEG, $2f     # flush prefetch queue, and reload %cs
 #else
-        ljmp    $PROT_CODE_SEG, $1f     # flush prefetch queue, and reload %cs
+        LJMPL   $PROT_CODE_SEG, $2f     # flush prefetch queue, and reload %cs
 #endif
 .code32
-1:
+2:
+
         /*---------------------------------------------------------------------+
         | load the other segment registers
         +---------------------------------------------------------------------*/
@@ -114,8 +140,13 @@
         movw    %ax, %ds
         movw    %ax, %es
         movw    %ax, %ss
+#if defined(SMP_SECONDARY_CORE)
+        movl    app_cpu_stack, %esp            # stack pointer
+        movl    app_cpu_stack, %ebp            # base pointer
+ #else
         movl    $start16 + STACKOFF, %esp       # set up stack pointer
         addl    $start16 + STACKOFF, %ebp       # set up stack pointer
+#endif  /* SMP_SECONDARY_CORE */
 
         /*---------------------------------------------------------------------+
         | we have to enable A20 in order to access memory above 1MByte
@@ -132,9 +163,14 @@
         call    pc386_delay
         call    pc386_delay
 
-        movl    %cs:HDRSTART + HDROFF, %eax     #
-        pushl   %eax                            # jump to start of 32 bit code
-        ret                                     #
+#if defined(SMP_SECONDARY_CORE)
+        movl    app_cpu_start, %eax             # jump to app CPU start
+#else
+        movl    %cs:HDRSTART + HDROFF, %eax     # jump to start of 32 bit code
+#endif  /* SMP_SECONDARY_CORE */
+        pushl   %eax                            
+        ret                                    
+ 
 
 /*----------------------------------------------------------------------------+
 | pc386_delay

diff -u rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c:1.50 rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c:1.51
--- rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c:1.50	Fri Jan 28 14:35:34 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c	Mon Aug  1 08:41:37 2011
@@ -31,6 +31,7 @@
 +--------------------------------------------------------------------------*/
 
 #include <bsp.h>
+#include <bsp/irq.h>
 #include <rtems/pci.h>
 #include <libcpu/cpuModel.h>
 
@@ -40,6 +41,7 @@
 extern void Calibrate_loop_1ms(void);
 extern void rtems_irq_mngt_init(void);
 extern void bsp_size_memory(void);
+void Clock_driver_install_handler(void);
 
 /*-------------------------------------------------------------------------+
 |         Function: bsp_start
@@ -80,6 +82,8 @@
       printk("PCI bus: could not initialize PCI BIOS interface\n");
   }
 
+  Clock_driver_install_handler();
+
   bsp_ide_cmdline_init();
 
 } /* bsp_start */

diff -u rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S:1.20 rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S:1.21
--- rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S:1.20	Fri Jan 28 14:35:34 2011
+++ rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S	Mon Aug  1 08:41:37 2011
@@ -96,7 +96,7 @@
 SYM (_load_segments):
 
 	lgdt SYM(gdtdesc)
-	lidt SYM(idtdesc)
+	lidt SYM(IDT_Descriptor)
 
 	/* Load CS, flush prefetched queue */
 	ljmp $0x8, $next_step
@@ -211,7 +211,8 @@
 +--------------------------------------------------------------------------*/
 
 	.p2align 4
-SYM(idtdesc):
+	PUBLIC(IDT_Descriptor)
+SYM(IDT_Descriptor):
 	.word  (256*8 - 1)
 	.long  SYM (Interrupt_descriptor_table)
 


 *jennifer*:
2011-08-01	Jennifer Averett <Jennifer.Averett at OARcorp.com>

	PR 1802
	* shared/irq/irq_asm.S, shared/irq/irq_init.c, shared/smp/smp-imps.c,
	shared/smp/smp-imps.h: Add SMP support for i386.
	* shared/smp/getcpuid.c: New file.

M   1.85  c/src/lib/libbsp/i386/ChangeLog
M   1.26  c/src/lib/libbsp/i386/shared/irq/irq_asm.S
M   1.21  c/src/lib/libbsp/i386/shared/irq/irq_init.c
A    1.1  c/src/lib/libbsp/i386/shared/smp/getcpuid.c
M    1.4  c/src/lib/libbsp/i386/shared/smp/smp-imps.h
M    1.4  c/src/lib/libbsp/i386/shared/smp/smp-imps.c

diff -u rtems/c/src/lib/libbsp/i386/ChangeLog:1.84 rtems/c/src/lib/libbsp/i386/ChangeLog:1.85
--- rtems/c/src/lib/libbsp/i386/ChangeLog:1.84	Mon Jul 18 11:33:30 2011
+++ rtems/c/src/lib/libbsp/i386/ChangeLog	Mon Aug  1 08:41:50 2011
@@ -1,3 +1,10 @@
+2011-08-01	Jennifer Averett <Jennifer.Averett at OARcorp.com>
+
+	PR 1802
+	* shared/irq/irq_asm.S, shared/irq/irq_init.c, shared/smp/smp-imps.c,
+	shared/smp/smp-imps.h: Add SMP support for i386.
+	* shared/smp/getcpuid.c: New file.
+
 2011-07-18	Joel Sherrill <joel.sherrill at oarcorp.com>
 
 	* shared/irq/apic.h, shared/smp/smp-imps.c, shared/smp/smp-imps.h:

diff -u rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.S:1.25 rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.S:1.26
--- rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.S:1.25	Mon Apr 11 12:16:50 2011
+++ rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.S	Mon Aug  1 08:41:50 2011
@@ -32,7 +32,7 @@
 #define EBP_OFF 12       /* code restoring ebp/esp relies on */
 #define ESP_OFF 16       /* esp being on top of ebp!         */
 #ifdef __SSE__
-/* need to be on 16 byte boundary for SSE */
+/* need to be on 16 byte boundary for SSE, add 12 to do that */
 #define FRM_SIZ (20+12+512)
 #define SSE_OFF 32
 #else
@@ -46,17 +46,9 @@
 	 *  Before this was point is reached the vectors unique
 	 *  entry point did the following:
 	 *
-	 *     1. saved scratch registers registers eax edx ecx"
+	 *     1. saved scratch registers registers eax edx ecx
 	 *     2. put the vector number in ecx.
 	 *
-	 * BEGINNING OF ESTABLISH SEGMENTS
-	 *
-	 *  WARNING: If an interrupt can occur when the segments are
-	 *           not correct, then this is where we should establish
-	 *           the segments.  In addition to establishing the
-	 *           segments, it may be necessary to establish a stack
-	 *           in the current data area on the outermost interrupt.
-	 *
 	 *  NOTE:  If the previous values of the segment registers are
 	 *         pushed, do not forget to adjust SAVED_REGS.
 	 *
@@ -104,9 +96,48 @@
 	ldmxcsr ARG_OFF(esp)            /* clean-slate MXCSR              */
 #endif
 
+.check_stack_switch:
+	movl      esp, ebp                  /* ebp = previous stack pointer */
+#if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
+	movl     $SYM(_Per_CPU_Information_p), ebx
+	call     SYM(bsp_smp_processor_id)
+	mov      (ebx,eax,4), ebx
+        pushl    ecx
+        call     SYM(_ISR_SMP_Enter)
+        popl     ecx
+        cmpl     $0, eax
+        jne      .i8259
+        movl     PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
+       
+#else
+	movl     $SYM(_Per_CPU_Information), ebx
+
+	/*
+         *  Is this the outermost interrupt?
+	 *  Switch stacks if necessary
+	 */
+	cmpl      $0, PER_CPU_ISR_NEST_LEVEL(ebx)
+	jne       nested                    /* No, then continue */
+	movl      PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
+
+	/*
+	 *  We want to insure that the old stack pointer is in ebp
+	 *  By saving it on every interrupt, all we have to do is
+	 *  movl ebp->esp near the end of every interrupt.
+	 */
+
+nested:
+	incl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one nest level deeper */
+	incl      SYM (_Thread_Dispatch_disable_level) /* disable multitasking */
+#endif
+        /*
+         *  i8259 Management
+         */
+
+.i8259:
         /* Do not disable any 8259 interrupts if this isn't from one */
 	cmp       ecx, 16               /* is this a PIC IRQ? */
-	jge       .check_stack_switch
+	jge       .end_of_i8259
 
 	/*
 	 * acknowledge the interrupt
@@ -136,44 +167,7 @@
 	outb      $PIC_SLAVE_COMMAND_IO_PORT
 .master:
 	outb      $PIC_MASTER_COMMAND_IO_PORT
-
-	/*
-	 *  Now switch stacks if necessary
-	 */
-
-PUBLIC (ISR_STOP)
-ISR_STOP:
-.check_stack_switch:
-	movl      esp, ebp                  /* ebp = previous stack pointer */
-#if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
-	movl     $SYM(_Per_CPU_Information_p), ebx
-	call     SYM(bsp_smp_processor_id)
-	mov      (ebx,eax,4), ebx
-#else
-	movl     $SYM(_Per_CPU_Information), ebx
-#endif
-
-	/* is this the outermost interrupt? */
-	cmpl      $0, PER_CPU_ISR_NEST_LEVEL(ebx)
-	jne       nested                    /* No, then continue */
-	movl      PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
-
-	/*
-	 *  We want to insure that the old stack pointer is in ebp
-	 *  By saving it on every interrupt, all we have to do is
-	 *  movl ebp->esp near the end of every interrupt.
-	 */
-
-nested:
-	incl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one nest level deeper */
-	incl      SYM (_Thread_Dispatch_disable_level) /* disable multitasking */
-
-        /*
-         * GCC versions starting with 4.3 no longer place the cld
-         * instruction before string operations.  We  need to ensure
-         * it is set correctly for ISR handlers.
-         */
-        cld
+.end_of_i8259:
 
 	/*
 	 * re-enable interrupts at processor level as the current
@@ -216,8 +210,14 @@
 	outb	  $PIC_MASTER_IMR_IO_PORT
 	movb	  ah, al
 	outb	  $PIC_SLAVE_IMR_IO_PORT
-
 .dont_restore_i8259:
+
+
+#if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
+        call    SYM(_ISR_SMP_Exit)
+	testl	eax, eax
+	je	.exit
+#else
 	decl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one less ISR nest level */
 	                                    /* If interrupts are nested, */
 	                                    /*   then dispatching is disabled */
@@ -231,6 +231,7 @@
 	                                    /* Is task switch necessary? */
 	jne       .schedule                 /* Yes, then call the scheduler */
 	jmp       .exit                     /* No, exit */
+#endif
 
 .schedule:
 	/*

diff -u rtems/c/src/lib/libbsp/i386/shared/irq/irq_init.c:1.20 rtems/c/src/lib/libbsp/i386/shared/irq/irq_init.c:1.21
--- rtems/c/src/lib/libbsp/i386/shared/irq/irq_init.c:1.20	Thu Jul 14 12:30:28 2011
+++ rtems/c/src/lib/libbsp/i386/shared/irq/irq_init.c	Mon Aug  1 08:41:50 2011
@@ -6,6 +6,9 @@
  *  Copyright (c) 2009 embedded brains GmbH
  *  CopyRight (C) 1998 valette at crf.canon.fr
  *
+ *  COPYRIGHT (c) 2011.
+ *  On-Line Applications Research Corporation (OAR).
+ *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.com/license/LICENSE.

diff -u /dev/null rtems/c/src/lib/libbsp/i386/shared/smp/getcpuid.c:1.1
--- /dev/null	Mon Aug  1 09:10:24 2011
+++ rtems/c/src/lib/libbsp/i386/shared/smp/getcpuid.c	Mon Aug  1 08:41:50 2011
@@ -0,0 +1,22 @@
+/*
+ *  COPYRIGHT (c) 2011.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ */
+
+#include <bsp/apic.h>
+#include <bsp/smp-imps.h>
+
+static int lapic_dummy = 0;
+unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
+
+int  bsp_smp_processor_id(void)
+{
+  return APIC_ID(IMPS_LAPIC_READ(LAPIC_ID));
+}
+

diff -u rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.h:1.3 rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.h:1.4
--- rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.h:1.3	Mon Jul 18 11:33:30 2011
+++ rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.h	Mon Aug  1 08:41:50 2011
@@ -37,6 +37,22 @@
  *  Intel literature center.
  */
 
+/*
+ *  This file is based upon code by Eric Boleyn as documented above.  
+ *  RTEMS support was added and minimal other changes were made.  
+ *  This should make it easier to compare this file with the original 
+ *  version.
+ *
+ *  COPYRIGHT (c) 2011.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ */
+
 #ifndef _SMP_IMPS_H
 #define _SMP_IMPS_H
 
@@ -194,47 +210,14 @@
  */
 
 /*
- *  "imps_enabled" is non-zero if the probe sequence found IMPS
- *  information and was successful.
- */
-extern int imps_enabled;
-
-/*
- *  This contains the local APIC hardware address.
- */
-extern unsigned imps_lapic_addr;
-
-/*
- *  This represents the number of CPUs found.
- */
-extern int imps_num_cpus;
-
-/*
  *  These map from virtual cpu numbers to APIC id's and back.
  */
 extern unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
 extern unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
 
-/*
- *  This is the primary function for probing for Intel MPS 1.1/1.4
- *  compatible hardware and BIOS information.  While probing the CPUs
- *  information returned from the BIOS, this also starts up each CPU
- *  and gets it ready for use.
- *
- *  Call this during the early stages of OS startup, before memory can
- *  be messed up.
- *
- *  Returns N if IMPS information was found (for number of CPUs started)
- *  and is valid, else 0.
- */
-int imps_probe(void);
-
-/*
- *  This one is used as a "force" function.  Give it the number of CPUs
- *  to start, and it will assume a certain number and try it.
- */
-int imps_force(int ncpus);
-
+/* base address of application processor reset code at 0x70000 */
+extern char _binary_appstart_bin_start[];
+extern char _binary_appstart_bin_size[];
 
 /*
  *  Defines that use variables

diff -u rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.c:1.3 rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.c:1.4
--- rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.c:1.3	Mon Jul 18 11:33:30 2011
+++ rtems/c/src/lib/libbsp/i386/shared/smp/smp-imps.c	Mon Aug  1 08:41:50 2011
@@ -47,6 +47,16 @@
 #define _SMP_IMPS_C
 
 /*
+ *  Includes here
+ */
+#if 0
+#define IMPS_DEBUG
+#endif
+
+#include <bsp/apic.h>
+#include <bsp/smp-imps.h>
+
+/*
  *  XXXXX  The following absolutely must be defined!!!
  *
  *  The "KERNEL_PRINT" could be made a null macro with no danger, of
@@ -63,17 +73,69 @@
 #define UDELAY(x)             /* delay roughly at least "x" microsecs */
 #define TEST_BOOTED(x)        /* test bootaddr x to see if CPU started */
 #define READ_MSR_LO(x)        /* Read MSR low function */
-#endif
+#else
+#include <string.h>
+#include <unistd.h>
+#include <rtems.h>
+#include <rtems/bspsmp.h>
+#include <rtems/bspIo.h>
+#include <libcpu/cpu.h>
+
+extern void _pc386_delay(void);
+
+/* #define KERNEL_PRINT(_format)       printk(_format) */
+
+static void CMOS_WRITE_BYTE(
+  unsigned int  offset,
+  unsigned char value
+)
+{
+  if ( offset < 128 ) {
+    outport_byte( 0x70, offset );
+    outport_byte( 0x71, value );
+  } else {
+    outport_byte( 0x72, offset );
+    outport_byte( 0x73, value );
+  }
+}
 
-/*
- *  Includes here
- */
+static unsigned char CMOS_READ_BYTE(
+  unsigned int  offset
+)
+{
+  unsigned char value;
+  if ( offset < 128 ) {
+    outport_byte( 0x70, offset );
+    inport_byte( 0x71, value );
+  } else {
+    outport_byte( 0x72, offset );
+    inport_byte( 0x73, value );
+  }
+  return value;
+}
 
-#define IMPS_DEBUG
+#define PHYS_TO_VIRTUAL(_x)    _x
+#define VIRTUAL_TO_PHYS(_x)    _x
+static void UDELAY(int x)
+{ int _i = x;
+  while ( _i-- )
+    _pc386_delay();
+}
+ 
+#define READ_MSR_LO(_x) \
+  (unsigned int)(read_msr(_x) & 0xffffffff)
 
-#include "apic.h"
-#include "smp-imps.h"
+#define TEST_BOOTED(_cpu) \
+  (_Per_CPU_Information[_cpu].state == RTEMS_BSP_SMP_CPU_INITIALIZED)
 
+static inline unsigned long long read_msr(unsigned int msr)
+{
+  unsigned long long value;
+ 
+  asm volatile("rdmsr" : "=A" (value) : "c" (msr));
+  return value;
+}
+#endif
 
 /*
  *  Defines that are here so as not to be in the global header file.
@@ -92,7 +154,6 @@
 
 #define DEF_ENTRIES  23
 
-static int lapic_dummy = 0;
 static struct {
   imps_processor proc[2];
   imps_bus bus[2];
@@ -132,10 +193,12 @@
 volatile int imps_release_cpus = 0;
 int imps_enabled = 0;
 int imps_num_cpus = 1;
-unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
 unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
 unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
 
+/* now defined in getcpuid.c */
+extern unsigned imps_lapic_addr;
+
 /*
  *  MPS checksum function
  *
@@ -180,10 +243,10 @@
  *  This must be modified to perform whatever OS-specific initialization
  *  that is required.
  */
-static int
+int
 boot_cpu(imps_processor *proc)
 {
-  int apicid = proc->apic_id, success = 1, to;
+  int apicid = proc->apic_id, success = 1;
   unsigned bootaddr, accept_status;
   unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
 
@@ -195,10 +258,19 @@
    * under the 1MB boundary.
    */
 
-  extern char patch_code_start[];
-  extern char patch_code_end[];
+  uint32_t *reset;
+
   bootaddr = (512-64)*1024;
-  memcpy((char *)bootaddr, patch_code_start, patch_code_end - patch_code_start);
+  reset= (uint32_t *)bootaddr;
+
+  memcpy(
+    (char *) bootaddr,
+    _binary_appstart_bin_start,
+    (size_t)_binary_appstart_bin_size
+  );
+
+  reset[1] = (uint32_t)rtems_smp_secondary_cpu_initialize;
+  reset[2] = (uint32_t)_Per_CPU_Information[apicid].interrupt_stack_high;
 
   /*
    *  Generic CPU startup sequence starts here.
@@ -214,8 +286,9 @@
 
   /* assert INIT IPI */
   send_ipi(
-    apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT);
-
+    apicid,
+    LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
+  );
   UDELAY(10000);
 
   /* de-assert INIT IPI */
@@ -238,14 +311,17 @@
   /*
    *  Check to see if other processor has started.
    */
-  to = 0;
-  while (!TEST_BOOTED(bootaddr) && to++ < 100)
-    UDELAY(10000);
-  if (to >= 100) {
-    KERNEL_PRINT(("CPU Not Responding, DISABLED"));
+  bsp_smp_wait_for(
+    (volatile unsigned int *)&_Per_CPU_Information[imps_num_cpus].state,
+    RTEMS_BSP_SMP_CPU_INITIALIZED,
+    1600
+  );
+  if ( _Per_CPU_Information[imps_num_cpus].state ==
+        RTEMS_BSP_SMP_CPU_INITIALIZED )
+    printk("#%d  Application Processor (AP)", imps_num_cpus);
+  else {
+    printk("CPU Not Responding, DISABLED");
     success = 0;
-  } else {
-    KERNEL_PRINT(("#%d  Application Processor (AP)", imps_num_cpus));
   }
 
   /*
@@ -260,7 +336,7 @@
   CMOS_WRITE_BYTE(CMOS_RESET_CODE, 0);
   *((volatile unsigned *) bios_reset_vector) = 0;
 
-  KERNEL_PRINT(("\n"));
+  printk("\n");
 
   return success;
 }
@@ -273,14 +349,13 @@
 {
   int apicid = proc->apic_id;
 
-  KERNEL_PRINT(("  Processor [APIC id %d ver %d]:  ",
-          apicid, proc->apic_ver));
+  printk("  Processor [APIC id %d ver %d]: ", apicid, proc->apic_ver);
   if (!(proc->flags & IMPS_FLAG_ENABLED)) {
-    KERNEL_PRINT(("DISABLED\n"));
+    printk("DISABLED\n");
     return;
   }
   if (proc->flags & (IMPS_CPUFLAG_BOOT)) {
-    KERNEL_PRINT(("#0  BootStrap Processor (BSP)\n"));
+    printk("#0  BootStrap Processor (BSP)\n");
     return;
   }
   if (boot_cpu(proc)) {
@@ -301,7 +376,7 @@
 
   memcpy(str, bus->bus_type, 6);
   str[6] = 0;
-  KERNEL_PRINT(("  Bus id %d is %s\n", bus->id, str));
+  printk("  Bus id %d is %s\n", bus->id, str);
 
   /*  XXXXX  add OS-specific code here */
 }
@@ -309,13 +384,13 @@
 static void
 add_ioapic(imps_ioapic *ioapic)
 {
-  KERNEL_PRINT(("  I/O APIC id %d ver %d, address: 0x%x  ",
-          ioapic->id, ioapic->ver, ioapic->addr));
+  printk("  I/O APIC id %d ver %d, address: 0x%x  ",
+          ioapic->id, ioapic->ver, ioapic->addr);
   if (!(ioapic->flags & IMPS_FLAG_ENABLED)) {
-    KERNEL_PRINT(("DISABLED\n"));
+    printk("DISABLED\n");
     return;
   }
-  KERNEL_PRINT(("\n"));
+  printk("\n");
 
   /*  XXXXX  add OS-specific code here */
 }
@@ -326,7 +401,10 @@
   while (count-- > 0) {
     switch (*((unsigned char *)start)) {
     case IMPS_BCT_PROCESSOR:
-      add_processor((imps_processor *)start);
+      if ( imps_num_cpus < rtems_configuration_smp_maximum_processors ) {
+	add_processor((imps_processor *)start);
+      } else 
+        imps_num_cpus++;
       start += 12;  /* 20 total */
       break;
     case IMPS_BCT_BUS:
@@ -350,6 +428,15 @@
     }
     start += 8;
   }
+  if ( imps_num_cpus > rtems_configuration_smp_maximum_processors ) {
+    printk(
+      "WARNING!! Found more CPUs (%d) than configured for (%d)!!\n",
+      imps_num_cpus - 1,
+      rtems_configuration_smp_maximum_processors
+    );
+    imps_num_cpus = rtems_configuration_smp_maximum_processors;
+    return;
+  }
 }
 
 static int
@@ -360,8 +447,8 @@
     = (imps_cth *) PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
 
   if (fps_ptr->feature_info[0] > IMPS_FPS_DEFAULT_MAX) {
-    KERNEL_PRINT(("    Invalid MP System Configuration type %d\n",
-            fps_ptr->feature_info[0]));
+    printk("    Invalid MP System Configuration type %d\n",
+            fps_ptr->feature_info[0]);
     return 1;
   }
 
@@ -369,17 +456,17 @@
     sum = get_checksum((unsigned)local_cth_ptr,
                                    local_cth_ptr->base_length);
     if (local_cth_ptr->sig != IMPS_CTH_SIGNATURE || sum) {
-      KERNEL_PRINT(
-        ("    Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",
+      printk(
+        "    Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",
         (unsigned)(fps_ptr->cth_ptr),
-        sum)
+        sum
       );
       return 1;
     }
     if (local_cth_ptr->spec_rev != fps_ptr->spec_rev) {
-      KERNEL_PRINT(
-        ("    Bad MP Config Table sub-revision # %d\n",
-        local_cth_ptr->spec_rev)
+      printk(
+        "    Bad MP Config Table sub-revision # %d\n",
+        local_cth_ptr->spec_rev
       );
       return 1;
     }
@@ -389,12 +476,12 @@
               local_cth_ptr->extended_length)
              + local_cth_ptr->extended_checksum) & 0xFF;
       if (sum) {
-        KERNEL_PRINT(("    Bad Extended MP Config Table checksum 0x%x\n", sum));
+        printk("    Bad Extended MP Config Table checksum 0x%x\n", sum);
         return 1;
       }
     }
   } else if (!fps_ptr->feature_info[0]) {
-    KERNEL_PRINT(("    Missing configuration information\n"));
+    printk("    Missing configuration information\n");
     return 1;
   }
 
@@ -410,15 +497,15 @@
     = (imps_cth *)PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
   char *str_ptr;
 
-  KERNEL_PRINT(("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
-          fps_ptr->spec_rev));
+  printk("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
+          fps_ptr->spec_rev);
 
   /*
    *  Do all checking of errors which would definitely
    *  lead to failure of the SMP boot here.
    */
   if (imps_bad_bios(fps_ptr)) {
-    KERNEL_PRINT(("    Disabling MPS support\n"));
+    printk("    Disabling MPS support\n");
     return;
   }
 
@@ -432,10 +519,10 @@
   } else {
     imps_lapic_addr = LAPIC_ADDR_DEFAULT;
   }
-  KERNEL_PRINT(("    APIC config: \"%s mode\"    Local APIC address: 0x%x\n",
-          str_ptr, imps_lapic_addr));
+  printk("    APIC config: \"%s mode\"    Local APIC address: 0x%x\n",
+          str_ptr, imps_lapic_addr);
   if (imps_lapic_addr != (READ_MSR_LO(0x1b) & 0xFFFFF000)) {
-    KERNEL_PRINT(("Inconsistent Local APIC address, Disabling SMP support\n"));
+    printk("Inconsistent Local APIC address, Disabling SMP support\n");
     return;
   }
   imps_lapic_addr = PHYS_TO_VIRTUAL(imps_lapic_addr);
@@ -455,7 +542,7 @@
     str1[8] = 0;
     memcpy(str2, local_cth_ptr->prod_id, 12);
     str2[12] = 0;
-    KERNEL_PRINT(("  OEM id: %s  Product id: %s\n", str1, str2));
+    printk("  OEM id: %s  Product id: %s\n", str1, str2);
     cth_start = ((unsigned) local_cth_ptr) + sizeof(imps_cth);
     cth_count = local_cth_ptr->entry_count;
   } else {
@@ -518,8 +605,7 @@
 static int
 imps_scan(unsigned start, unsigned length)
 {
-  IMPS_DEBUG_PRINT(("Scanning from 0x%x for %d bytes\n",
-        start, length));
+  printk("Scanning from 0x%x for %d bytes\n", start, length);
 
   while (length > 0) {
     imps_fps *fps_ptr = (imps_fps *) PHYS_TO_VIRTUAL(start);
@@ -528,7 +614,7 @@
      && fps_ptr->length == 1
      && (fps_ptr->spec_rev == 1 || fps_ptr->spec_rev == 4)
      && !get_checksum(start, 16)) {
-      IMPS_DEBUG_PRINT(("Found MP Floating Structure Pointer at %x\n", start));
+      printk("Found MP Floating Structure Pointer at %x\n", start);
       imps_read_bios(fps_ptr);
       return 1;
     }
@@ -540,6 +626,7 @@
   return 0;
 }
 
+#if !defined(__rtems__)
 /*
  *  This is the primary function to "force" SMP support, with
  *  the assumption that you have consecutively numbered APIC ids.
@@ -550,7 +637,7 @@
   int apicid, i;
   imps_processor p;
 
-  KERNEL_PRINT(("Intel MultiProcessor \"Force\" Support\n"));
+  printk("Intel MultiProcessor \"Force\" Support\n");
 
   imps_lapic_addr = (READ_MSR_LO(0x1b) & 0xFFFFF000);
   imps_lapic_addr = PHYS_TO_VIRTUAL(imps_lapic_addr);
@@ -580,6 +667,7 @@
 
   return imps_num_cpus;
 }
+#endif
 
 /*
  *  This is the primary function for probing for MPS compatible hardware
@@ -661,3 +749,116 @@
   return 0;
 }
 
+/*
+ *  RTEMS SMP BSP Support
+ */
+void smp_apic_ack(void)
+{
+  (void) IMPS_LAPIC_READ(LAPIC_SPIV);  /* dummy read */
+  IMPS_LAPIC_WRITE(LAPIC_EOI, 0 );     /* ACK the interrupt */
+}
+
+rtems_isr ap_ipi_isr(
+  rtems_vector_number vector
+)
+{
+  smp_apic_ack();
+
+  rtems_smp_process_interrupt();
+}
+
+#include <rtems/irq.h>
+
+static rtems_irq_connect_data apIPIIrqData = {
+  16,
+  (void *)ap_ipi_isr,
+  0,
+  NULL,            /* On */
+  NULL,            /* Off */
+  NULL,            /* IsOn */
+};
+
+extern void bsp_reset(void);
+void ipi_install_irq(void)
+{
+  if (!BSP_install_rtems_irq_handler (&apIPIIrqData)) {
+    printk("Unable to initialize IPI\n");
+    bsp_reset();
+  }
+}
+
+#ifdef __SSE__
+extern void enable_sse(void);
+#endif
+
+/* pc386 specific initialization */
+void bsp_smp_secondary_cpu_initialize(int cpu)
+{
+  int apicid;
+
+  asm volatile( "lidt IDT_Descriptor" );
+
+  apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
+  IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
+
+#ifdef __SSE__
+  enable_sse();
+#endif
+}
+
+#include <rtems/bspsmp.h>
+int bsp_smp_initialize(
+  int maximum
+)
+{
+  int cores;
+  /* XXX need to deal with finding too many cores */
+
+  cores = imps_probe();
+
+  if ( cores > 1 )
+    ipi_install_irq();
+  return cores;
+}
+
+void bsp_smp_interrupt_cpu(
+  int cpu
+)
+{
+  send_ipi( cpu, 0x30 );
+}
+
+void bsp_smp_broadcast_interrupt(void)
+{
+  /* Single broadcast interrupt */
+  send_ipi( 0, LAPIC_ICR_DS_ALLEX | 0x30 );
+}
+
+void bsp_smp_wait_for(
+  volatile unsigned int *address,
+  unsigned int           desired,
+  int                    maximum_usecs
+)
+{
+  int iterations;
+  volatile int i;
+  volatile unsigned int *p = (volatile unsigned int *)address;
+
+  for (iterations=0 ;  iterations < maximum_usecs ; iterations++ ) {
+    if ( *p == desired )
+      break;
+    #ifdef __SSE3__
+      __builtin_ia32_monitor( (const void *)address, 0, 0 );
+      if ( *p == desired )
+        break;
+      __builtin_ia32_mwait( 0, 0 );
+    #endif
+
+    /*
+     *  Until i386 ms delay does not depend upon the clock we
+     *  will use this less sophisticated delay. 
+     */
+    for(i=5000; i>0; i--)
+      ;
+  }
+}


 *joel*:
2011-08-01	Joel Sherrill <joel.sherrill at oarcorp.com>

	* psx16/Makefile.am: New file.

M  1.351  testsuites/psxtests/ChangeLog
M    1.2  testsuites/psxtests/psx16/Makefile.am

diff -u rtems/testsuites/psxtests/ChangeLog:1.350 rtems/testsuites/psxtests/ChangeLog:1.351
--- rtems/testsuites/psxtests/ChangeLog:1.350	Mon Aug  1 07:45:14 2011
+++ rtems/testsuites/psxtests/ChangeLog	Mon Aug  1 08:27:15 2011
@@ -1,3 +1,7 @@
+2011-08-01	Joel Sherrill <joel.sherrill at oarcorp.com>
+
+	* psx16/Makefile.am: New file.
+
 2011-08-01	Joel Sherrill <joel.sherrilL at OARcorp.com>
 
 	* psx16/.cvsignore, psx16/init.c, psx16/psx16.doc, psx16/psx16.scn: New

diff -u /dev/null rtems/testsuites/psxtests/psx16/Makefile.am:1.2
--- /dev/null	Mon Aug  1 09:10:25 2011
+++ rtems/testsuites/psxtests/psx16/Makefile.am	Mon Aug  1 08:27:15 2011
@@ -0,0 +1,28 @@
+##
+## $Id$
+##
+
+MANAGERS = all
+
+rtems_tests_PROGRAMS = psx16
+psx16_SOURCES = init.c ../include/pmacros.h
+
+dist_rtems_tests_DATA = psx16.scn
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+psx16_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel)
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psx16_OBJECTS) $(psx16_LDADD)
+LINK_LIBS = $(psx16_LDLIBS)
+
+psx16$(EXEEXT): $(psx16_OBJECTS) $(psx16_DEPENDENCIES)
+	@rm -f psx16$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am


 *joel*:
2011-08-01	Sebastien Bourdeauducq <sebastien.bourdeauducq at gmail.com>

	PR 1869/bsps
	* startup/bspclean.c: New file.
	* include/tm27.h: Removed.
	* ChangeLog, Makefile.am, README, preinstall.am, include/bsp.h,
	include/system_conf.h, make/custom/milkymist.cfg, startup/linkcmds:
	Complete BSP for Milkymist One supporting Milkymist SOC 1.0.x.
	Includes new or updated drivers for:
	  - Multi-standard video input (PAL/SECAM/NTSC)
	  - Two DMX512 (RS485) ports
	  - MIDI IN and MIDI OUT ports
	  - VGA output
	  - AC'97 audio
	  - NOR flash
	  - 10/100 Ethernet
	  - Memory card (experimental and incomplete)
	  - USB host connectors (input devices only)
	  - RC5 infrared receiver
	  - RS232 debug port

M    1.4  c/src/lib/libbsp/lm32/milkymist/ChangeLog
M    1.2  c/src/lib/libbsp/lm32/milkymist/Makefile.am
M    1.2  c/src/lib/libbsp/lm32/milkymist/README
M    1.2  c/src/lib/libbsp/lm32/milkymist/include/bsp.h
M    1.2  c/src/lib/libbsp/lm32/milkymist/include/system_conf.h
R    1.1  c/src/lib/libbsp/lm32/milkymist/include/tm27.h
M    1.2  c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg
M    1.2  c/src/lib/libbsp/lm32/milkymist/preinstall.am
A    1.1  c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c
M    1.2  c/src/lib/libbsp/lm32/milkymist/startup/linkcmds
A    1.1  c/src/lib/libbsp/lm32/shared/ChangeLog
M    1.4  c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c
A    1.1  c/src/lib/libbsp/lm32/shared/include/irq.h
A    1.1  c/src/lib/libbsp/lm32/shared/irq/irq.c
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_clock/clock.h
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_console/console.c
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h
M    1.2  c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h
M    1.3  c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c
M    1.3  c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h
A    1.1  c/src/lib/libbsp/lm32/shared/milkymist_video/video.c
M   1.10  c/src/lib/libbsp/lm32/shared/start/start.S
M    1.2  c/src/lib/libbsp/lm32/shared/startup/bspstart.c

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/ChangeLog:1.3 rtems/c/src/lib/libbsp/lm32/milkymist/ChangeLog:1.4
--- rtems/c/src/lib/libbsp/lm32/milkymist/ChangeLog:1.3	Wed Feb  2 08:58:27 2011
+++ rtems/c/src/lib/libbsp/lm32/milkymist/ChangeLog	Mon Aug  1 08:48:10 2011
@@ -1,3 +1,24 @@
+2011-08-01	Sebastien Bourdeauducq <sebastien.bourdeauducq at gmail.com>
+
+	PR 1869/bsps
+	* startup/bspclean.c: New file.
+	* include/tm27.h: Removed.
+	* ChangeLog, Makefile.am, README, preinstall.am, include/bsp.h,
+	include/system_conf.h, make/custom/milkymist.cfg, startup/linkcmds:
+	Complete BSP for Milkymist One supporting Milkymist SOC 1.0.x.
+	Includes new or updated drivers for:
+	  - Multi-standard video input (PAL/SECAM/NTSC)
+	  - Two DMX512 (RS485) ports
+	  - MIDI IN and MIDI OUT ports
+	  - VGA output
+	  - AC'97 audio
+	  - NOR flash
+	  - 10/100 Ethernet
+	  - Memory card (experimental and incomplete)
+	  - USB host connectors (input devices only)
+	  - RC5 infrared receiver
+	  - RS232 debug port
+
 2011-02-02	Ralf Corsépius <ralf.corsepius at rtems.org>
 
 	* configure.ac: Require autoconf-2.68, automake-1.11.1.
@@ -13,5 +34,3 @@
 	preinstall.am, Documentation/uart.txt, include/.cvsignore,
 	include/bsp.h, include/system_conf.h, include/tm27.h,
 	make/custom/milkymist.cfg, startup/linkcmds: New files.
-
-08 / 12 / 2010 : <Yann Sionneau> Added Milkymist BSP

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/Makefile.am:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/Makefile.am:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/Makefile.am:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/Makefile.am	Mon Aug  1 08:48:11 2011
@@ -10,8 +10,25 @@
 
 dist_project_lib_DATA = bsp_specs
 
-include_HEADERS = include/bsp.h
-include_HEADERS += include/tm27.h
+include_HEADERS  = include/bsp.h
+include_HEADERS += ../../shared/include/coverhd.h
+include_HEADERS += ../../shared/include/tm27.h
+
+include_bsp_HEADERS  = ../../lm32/shared/include/irq.h
+include_bsp_HEADERS += ../../shared/include/irq-generic.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_gpio/milkymist_gpio.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_buttons/milkymist_buttons.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_ac97/milkymist_ac97.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_usbinput/milkymist_usbinput.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_pfpu/milkymist_pfpu.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_tmu/milkymist_tmu.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_memcard/milkymist_memcard.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_flash/milkymist_flash.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_dmx/milkymist_dmx.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_midi/milkymist_midi.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_ir/milkymist_ir.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_video/milkymist_video.h
+include_bsp_HEADERS += ../../lm32/shared/milkymist_versions/milkymist_versions.h
 
 nodist_include_HEADERS = include/bspopts.h
 nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h
@@ -19,7 +36,6 @@
 
 noinst_PROGRAMS =
 
-include_HEADERS += ../../shared/include/coverhd.h
 include_HEADERS += include/system_conf.h
 
 noinst_LIBRARIES = libbspstart.a
@@ -33,33 +49,74 @@
 libbsp_a_LIBADD =
 
 # startup
-libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
-    ../../shared/bsppost.c ../shared/startup/bspstart.c \
-    ../../shared/bspreset.c ../../shared/bsppretaskinghook.c \
-    ../../shared/bspgetworkarea.c ../../shared/bootcard.c \
-    ../../shared/sbrk.c ../../lm32/shared/startup/setvec.c \
-    ../../shared/gnatinstallhandler.c
+libbsp_a_SOURCES += startup/bspclean.c
+libbsp_a_SOURCES += ../../shared/bsplibc.c
+libbsp_a_SOURCES += ../../shared/bsppost.c
+libbsp_a_SOURCES += ../shared/startup/bspstart.c
+libbsp_a_SOURCES += ../../shared/bsppretaskinghook.c
+libbsp_a_SOURCES += ../../shared/bspgetworkarea.c
+libbsp_a_SOURCES += ../../shared/bootcard.c
+libbsp_a_SOURCES += ../../shared/sbrk.c
+libbsp_a_SOURCES += ../../shared/gnatinstallhandler.c
 
-# clock
+# irq
+libbsp_a_SOURCES += ../../lm32/shared/irq/irq.c
 
+# clock
 libbsp_a_SOURCES += ../../lm32/shared/milkymist_clock/ckinit.c
 
 # console
-libbsp_a_SOURCES += ../../lm32/shared/milkymist_console/console.c \
-    ../../lm32/shared/milkymist_console/uart.c
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_console/console.c
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_console/uart.c
+
 # timer
 libbsp_a_SOURCES += ../../lm32/shared/milkymist_timer/timer.c
 
 # framebuffer
 libbsp_a_SOURCES += ../../lm32/shared/milkymist_framebuffer/framebuffer.c
 
-# gpio
+# GPIO
 libbsp_a_SOURCES += ../../lm32/shared/milkymist_gpio/gpio.c
 
+# buttons
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_buttons/buttons.c
+
+# ac97
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_ac97/ac97.c
+
+# usbinput
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_usbinput/usbinput.c
+
+# PFPU
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_pfpu/pfpu.c
+
+# TMU
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_tmu/tmu.c
+
+# memory card
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_memcard/memcard.c
+
+# flash
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_flash/flash.c
+
+# DMX
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_dmx/dmx.c
+
+# MIDI
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_midi/midi.c
+
+# IR
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_ir/ir.c
+
+# video input
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_video/video.c
+
+# versions
+libbsp_a_SOURCES += ../../lm32/shared/milkymist_versions/versions.c
+
 if HAS_NETWORKING
 noinst_PROGRAMS += network.rel
-network_rel_SOURCES = ../../lm32/shared/milkymist_networking/network.c \
-    ../../lm32/shared/milkymist_networking/mm_crc32.c
+network_rel_SOURCES = ../../lm32/shared/milkymist_networking/network.c
 network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
 network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
 libbsp_a_LIBADD += network.rel

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/README:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/README:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/README:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/README	Mon Aug  1 08:48:11 2011
@@ -2,20 +2,19 @@
 # $Id$
 #
 
-This is a BSP written by Yann Sionneau <yann.sionneau at telecom-sudparis.eu>
-as part of Google Summer of Code 2010.
+Full RTEMS port to the Milkymist One. Supports Milkymist SoC 1.0.x.
 
-This is a BSP to make RTEMS run on Milkymist One board using Milkymist SoC
+Includes drivers for:
+- Multi-standard video input (PAL/SECAM/NTSC)
+- Two DMX512 (RS485) ports
+- MIDI IN and MIDI OUT ports
+- VGA output
+- AC'97 audio
+- NOR flash
+- 10/100 Ethernet
+- Memory card (experimental and incomplete)
+- USB host connectors (input devices only, using the softusb-input firmware)
+- RC5 infrared receiver
+- RS232 debug port
 
-It provides driver for timer, uart, ethernet, framebuffer so far.
-
-Milkymist SoC is running @ 83 MHz with 128 MB of 32-bit DDR400 SDRAM
-The SoC is based on a XC6SLX45 Spartan-6 FPGA running 
-the LatticeMico32 softcore.
-
-More informations available at : http://www.milkymist.org/
-
-Information about the porting can be found in Yann Sionneau's blog
-at http://sionneau.net/
-
-Milkymist is a project leaded by Sebastien Bourdeauducq (aka lekernel)
+For more information: http://www.milkymist.org/

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/include/bsp.h:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/include/bsp.h:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/include/bsp.h:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/include/bsp.h	Mon Aug  1 08:48:11 2011
@@ -8,8 +8,7 @@
  *
  *  $Id$
  *
- *  Yann Sionneau <yann.sionneau at telecom-sudparis.eu>, (GSoC 2010)
- *  Telecom SudParis
+ *  COPYRIGHT (c) 2011 Sebastien Bourdeauducq
  */
 
 #ifndef _BSP_H
@@ -22,22 +21,16 @@
 #include <rtems/console.h>
 #include <rtems/clockdrv.h>
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define BSP_DIRTY_MEMORY 1
-
 #define BSP_HAS_FRAME_BUFFER 1
 
-#define GPIO_DRIVER_TABLE_ENTRY { gpio_initialize, \
-gpio_open, gpio_close, gpio_read, gpio_write, gpio_control}
-
-  /*
-   * lm32 requires certain aligment of mbuf because unaligned uint32_t
-   * accesses are not handled properly.
-   */
+/*
+ * lm32 requires certain aligment of mbuf because unaligned uint32_t
+ * accesses are not handled properly.
+ */
 
 #define CPU_U32_FIX
 
@@ -50,25 +43,8 @@
 #define RTEMS_BSP_NETWORK_DRIVER_NAME "minimac0"
 #endif
 
-  /*
-   *  Simple spin delay in microsecond units for device drivers.
-   *  This is very dependent on the clock speed of the target.
-   */
-
-#define rtems_bsp_delay( microseconds ) \
-  { \
-  }
-
-/* functions */
-lm32_isr_entry set_vector(                     /* returns old vector */
-  rtems_isr_entry     handler,                  /* isr routine        */
-  rtems_vector_number vector,                   /* vector number      */
-  int                 type                      /* RTEMS or RAW intr  */
-);
-
 #ifdef __cplusplus
 }
 #endif
 
 #endif
-/* end of include file */

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h	Mon Aug  1 08:48:11 2011
@@ -1,56 +1,304 @@
 /*  system_conf.h
  *  Global System conf
- * 
+ *
  *  Milkymist port of RTEMS
  *
- *  The license and distribution terms for this file may be 
+ *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
  *  http://www.rtems.com/license/LICENSE.
  *
  *  $Id$
  *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
  */
 
 #ifndef __SYSTEM_CONFIG_H_
 #define __SYSTEM_CONFIG_H_
 
-#define CPU_FREQUENCY (83333333)
-#define UART_BAUD_RATE  (115200)
+#define CPU_FREQUENCY           (80000000)
+#define UART_BAUD_RATE          (115200)
+
+/* FML bridge */
+#define FMLBRG_FLUSH_BASE       (0xc8000000)
+#define FMLBRG_LINE_LENGTH      (32)
+#define FMLBRG_LINE_COUNT       (512)
+
+/* UART */
+#define MM_UART_RXTX            (0xe0000000)
+#define MM_UART_DIV             (0xe0000004)
+
+/* Timers */
+#define MM_TIMER1_COMPARE       (0xe0001024)
+#define MM_TIMER1_COUNTER       (0xe0001028)
+#define MM_TIMER1_CONTROL       (0xe0001020)
+
+#define MM_TIMER0_COMPARE       (0xe0001014)
+#define MM_TIMER0_COUNTER       (0xe0001018)
+#define MM_TIMER0_CONTROL       (0xe0001010)
+
+#define TIMER_ENABLE            (0x01)
+#define TIMER_AUTORESTART       (0x02)
+
+/* GPIO */
+#define MM_GPIO_IN              (0xe0001000)
+#define MM_GPIO_OUT             (0xe0001004)
+#define MM_GPIO_INTEN           (0xe0001008)
+
+#define GPIO_BTN1               (0x00000001)
+#define GPIO_BTN2               (0x00000002)
+#define GPIO_BTN3               (0x00000004)
+#define GPIO_PCBREV0            (0x00000008)
+#define GPIO_PCBREV1            (0x00000010)
+#define GPIO_PCBREV2            (0x00000020)
+#define GPIO_PCBREV3            (0x00000040)
+#define GPIO_LED1               (0x00000001)
+#define GPIO_LED2               (0x00000002)
+
+/* System ID and reset */
+#define MM_SYSTEM_ID            (0xe000103c)
+
+/* ICAP */
+#define MM_ICAP                 (0xe0001034)
+
+#define ICAP_READY              (0x01)
+#define ICAP_CE                 (0x10000)
+#define ICAP_WRITE              (0x20000)
+
+/* VGA */
+#define MM_VGA_RESET            (0xe0003000)
+
+#define MM_VGA_HRES             (0xe0003004)
+#define MM_VGA_HSYNC_START      (0xe0003008)
+#define MM_VGA_HSYNC_END        (0xe000300C)
+#define MM_VGA_HSCAN            (0xe0003010)
+
+#define MM_VGA_VRES             (0xe0003014)
+#define MM_VGA_VSYNC_START      (0xe0003018)
+#define MM_VGA_VSYNC_END        (0xe000301C)
+#define MM_VGA_VSCAN            (0xe0003020)
 
-#define MM_TIMER1_COMPARE (0xe0001024)
-#define MM_TIMER1_COUNTER (0xe0001028)
-#define MM_TIMER1_CONTROL (0xe0001020)
-
-#define MM_TIMER0_COMPARE (0xe0001014)
-#define MM_TIMER0_COUNTER (0xe0001018)
-#define MM_TIMER0_CONTROL (0xe0001010)
-
-#define TIMER_ENABLE  (0x01)
-#define TIMER_AUTORESTART (0x02)
-
-#define MM_VGA_RESET_MODE (0x01)
-#define MM_VGA_RESET  (0xe0003000)
-#define MM_VGA_BASEADDRESS (0xe0003024)
+#define MM_VGA_BASEADDRESS      (0xe0003024)
 #define MM_VGA_BASEADDRESS_ACT  (0xe0003028)
 
-#define MM_MINIMAC_SETUP  (0xe0009000)
-#define MM_MINIMAC_STATE0  (0xe0009008)
-#define MM_MINIMAC_ADDR0 (0xe000900C)
-#define MM_MINIMAC_COUNT0  (0xe0009010)
-
-#define MM_MINIMAC_STATE1  (0xe0009014)
-#define MM_MINIMAC_ADDR1 (0xe0009018)
-#define MM_MINIMAC_COUNT1  (0xe000901C)
-
-#define MM_MINIMAC_STATE2  (0xe0009020)
-#define MM_MINIMAC_ADDR2 (0xe0009024)
-#define MM_MINIMAC_COUNT2  (0xe0009028)
-
-#define MM_MINIMAC_STATE3  (0xe000902C)
-#define MM_MINIMAC_ADDR3 (0xe0009030)
-#define MM_MINIMAC_COUNT3  (0xe0009034)
+#define MM_VGA_BURST_COUNT      (0xe000302C)
+
+#define MM_VGA_DDC              (0xe0003030)
+
+#define MM_VGA_CLKSEL           (0xe0003034)
 
-#define MM_MINIMAC_TXREMAINING  (0xe000903C)
-#define MM_MINIMAC_TXADR (0xe0009038)
+#define VGA_RESET               (0x01)
+#define VGA_DDC_SDAIN           (0x1)
+#define VGA_DDC_SDAOUT          (0x2)
+#define VGA_DDC_SDAOE           (0x4)
+#define VGA_DDC_SDC             (0x8)
+
+/* Ethernet */
+#define MM_MINIMAC_SETUP        (0xe0008000)
+#define MM_MINIMAC_MDIO         (0xe0008004)
+
+#define MM_MINIMAC_STATE0       (0xe0008008)
+#define MM_MINIMAC_COUNT0       (0xe000800C)
+#define MM_MINIMAC_STATE1       (0xe0008010)
+#define MM_MINIMAC_COUNT1       (0xe0008014)
+
+#define MM_MINIMAC_TXCOUNT      (0xe0008018)
+
+#define MINIMAC_RX0_BASE        (0xb0000000)
+#define MINIMAC_RX1_BASE        (0xb0000800)
+#define MINIMAC_TX_BASE         (0xb0001000)
+
+#define MINIMAC_SETUP_PHYRST    (0x1)
+
+#define MINIMAC_STATE_EMPTY     (0x0)
+#define MINIMAC_STATE_LOADED    (0x1)
+#define MINIMAC_STATE_PENDING   (0x2)
+
+/* AC97 */
+#define MM_AC97_CRCTL           (0xe0005000)
+
+#define AC97_CRCTL_RQEN         (0x01)
+#define AC97_CRCTL_WRITE        (0x02)
+
+#define MM_AC97_CRADDR          (0xe0005004)
+#define MM_AC97_CRDATAOUT       (0xe0005008)
+#define MM_AC97_CRDATAIN        (0xe000500C)
+
+#define MM_AC97_DCTL            (0xe0005010)
+#define MM_AC97_DADDRESS        (0xe0005014)
+#define MM_AC97_DREMAINING      (0xe0005018)
+
+#define MM_AC97_UCTL            (0xe0005020)
+#define MM_AC97_UADDRESS        (0xe0005024)
+#define MM_AC97_UREMAINING      (0xe0005028)
+
+#define AC97_SCTL_EN            (0x01)
+
+#define AC97_MAX_DMASIZE        (0x3fffc)
+
+/* SoftUSB */
+#define MM_SOFTUSB_CONTROL      (0xe000f000)
+
+#define SOFTUSB_CONTROL_RESET   (0x1)
+
+#define MM_SOFTUSB_PMEM_BASE    (0xa0000000)
+#define MM_SOFTUSB_DMEM_BASE    (0xa0020000)
+
+#define SOFTUSB_PMEM_SIZE       (1 << 12)
+#define SOFTUSB_DMEM_SIZE       (1 << 13)
+
+/* PFPU */
+#define MM_PFPU_CTL             (0xe0006000)
+#define PFPU_CTL_START          (0x01)
+#define PFPU_CTL_BUSY           (0x01)
+
+#define MM_PFPU_MESHBASE        (0xe0006004)
+#define MM_PFPU_HMESHLAST       (0xe0006008)
+#define MM_PFPU_VMESHLAST       (0xe000600C)
+
+#define MM_PFPU_CODEPAGE        (0xe0006010)
+
+#define MM_PFPU_DREGBASE        (0xe0006400)
+#define MM_PFPU_CODEBASE        (0xe0006800)
+
+#define PFPU_PAGESIZE           (512)
+#define PFPU_SPREG_COUNT        (2)
+#define PFPU_REG_X              (0)
+#define PFPU_REG_Y              (1)
+
+/* TMU */
+#define MM_TMU_CTL              (0xe0007000)
+#define TMU_CTL_START           (0x01)
+#define TMU_CTL_BUSY            (0x01)
+#define TMU_CTL_CHROMAKEY       (0x02)
+
+#define MM_TMU_HMESHLAST        (0xe0007004)
+#define MM_TMU_VMESHLAST        (0xe0007008)
+#define MM_TMU_BRIGHTNESS       (0xe000700C)
+#define MM_TMU_CHROMAKEY        (0xe0007010)
+
+#define MM_TMU_VERTICESADR      (0xe0007014)
+#define MM_TMU_TEXFBUF          (0xe0007018)
+#define MM_TMU_TEXHRES          (0xe000701C)
+#define MM_TMU_TEXVRES          (0xe0007020)
+#define MM_TMU_TEXHMASK         (0xe0007024)
+#define MM_TMU_TEXVMASK         (0xe0007028)
+
+#define MM_TMU_DSTFBUF          (0xe000702C)
+#define MM_TMU_DSTHRES          (0xe0007030)
+#define MM_TMU_DSTVRES          (0xe0007034)
+#define MM_TMU_DSTHOFFSET       (0xe0007038)
+#define MM_TMU_DSTVOFFSET       (0xe000703C)
+#define MM_TMU_DSTSQUAREW       (0xe0007040)
+#define MM_TMU_DSTSQUAREH       (0xe0007044)
+
+#define MM_TMU_ALPHA            (0xe0007048)
+
+/* Memory card */
+#define MM_MEMCARD_CLK2XDIV     (0xe0004000)
+
+#define MM_MEMCARD_ENABLE       (0xe0004004)
+
+#define MEMCARD_ENABLE_CMD_TX   (0x1)
+#define MEMCARD_ENABLE_CMD_RX   (0x2)
+#define MEMCARD_ENABLE_DAT_TX   (0x4)
+#define MEMCARD_ENABLE_DAT_RX   (0x8)
+
+#define MM_MEMCARD_PENDING      (0xe0004008)
+
+#define MEMCARD_PENDING_CMD_TX  (0x1)
+#define MEMCARD_PENDING_CMD_RX  (0x2)
+#define MEMCARD_PENDING_DAT_TX  (0x4)
+#define MEMCARD_PENDING_DAT_RX  (0x8)
+
+#define MM_MEMCARD_START        (0xe000400c)
+
+#define MEMCARD_START_CMD_RX    (0x1)
+#define MEMCARD_START_DAT_RX    (0x2)
+
+#define MM_MEMCARD_CMD          (0xe0004010)
+#define MM_MEMCARD_DAT          (0xe0004014)
+
+/* DMX */
+#define MM_DMX_TX(x)            (0xe000c000+4*(x))
+#define MM_DMX_THRU             (0xe000c800)
+#define MM_DMX_RX(x)            (0xe000d000+4*(x))
+
+/* MIDI */
+#define MM_MIDI_RXTX            (0xe000b000)
+#define MM_MIDI_DIVISOR         (0xe000b004)
+#define MM_MIDI_THRU            (0xe000b008)
+
+/* IR */
+#define MM_IR_RX                (0xe000e000)
+
+/* Video input */
+#define MM_BT656_I2C            (0xe000a000)
+#define MM_BT656_FILTERSTATUS   (0xe000a004)
+#define MM_BT656_BASE           (0xe000a008)
+#define MM_BT656_MAXBURSTS      (0xe000a00c)
+#define MM_BT656_DONEBURSTS     (0xe000a010)
+
+#define BT656_I2C_SDAIN         (0x1)
+#define BT656_I2C_SDAOUT        (0x2)
+#define BT656_I2C_SDAOE         (0x4)
+#define BT656_I2C_SDC           (0x8)
+
+#define BT656_FILTER_FIELD1     (0x1)
+#define BT656_FILTER_FIELD2     (0x2)
+#define BT656_FILTER_INFRAME    (0x4)
+
+/* Interrupts */
+#define MM_IRQ_UARTRX           (0)
+#define MM_IRQ_UARTTX           (1)
+#define MM_IRQ_GPIO             (2)
+#define MM_IRQ_TIMER0           (3)
+#define MM_IRQ_TIMER1           (4)
+#define MM_IRQ_AC97CRREQUEST    (5)
+#define MM_IRQ_AC97CRREPLY      (6)
+#define MM_IRQ_AC97DMAR         (7)
+#define MM_IRQ_AC97DMAW         (8)
+#define MM_IRQ_PFPU             (9)
+#define MM_IRQ_TMU              (10)
+#define MM_IRQ_ETHRX            (11)
+#define MM_IRQ_ETHTX            (12)
+#define MM_IRQ_VIDEOIN          (13)
+#define MM_IRQ_MIDIRX           (14)
+#define MM_IRQ_MIDITX           (15)
+#define MM_IRQ_IR               (16)
+#define MM_IRQ_USB              (17)
+
+/* Flash layout */
+#define FLASH_BASE                      (0x80000000)
+
+#define FLASH_OFFSET_STANDBY_BITSTREAM  (0x80000000)
+
+#define FLASH_OFFSET_RESCUE_BITSTREAM   (0x800A0000)
+#define FLASH_OFFSET_RESCUE_BIOS        (0x80220000)
+#define FLASH_OFFSET_MAC_ADDRESS        (0x802200E0)
+#define FLASH_OFFSET_RESCUE_SPLASH      (0x80240000)
+#define FLASH_OFFSET_RESCUE_APP         (0x802E0000)
+
+#define FLASH_OFFSET_REGULAR_BITSTREAM  (0x806E0000)
+#define FLASH_OFFSET_REGULAR_BIOS       (0x80860000)
+#define FLASH_OFFSET_REGULAR_SPLASH     (0x80880000)
+#define FLASH_OFFSET_REGULAR_APP        (0x80920000)
+
+/* MMIO */
+#define MM_READ(reg) (*((volatile unsigned int *)(reg)))
+#define MM_WRITE(reg, val) *((volatile unsigned int *)(reg)) = val
+
+/* Flash partitions */
+
+#define FLASH_SECTOR_SIZE     (128*1024)
+
+#define FLASH_PARTITION_COUNT (5)
+
+#define FLASH_PARTITIONS { \
+  { .start_address = 0x806E0000, .length = 0x0180000 }, \
+  { .start_address = 0x80860000, .length = 0x0020000 }, \
+  { .start_address = 0x80880000, .length = 0x00A0000 }, \
+  { .start_address = 0x80920000, .length = 0x0400000 }, \
+  { .start_address = 0x80D20000, .length = 0x12E0000 }, \
+}
 
 #endif /* __SYSTEM_CONFIG_H_ */

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg	Mon Aug  1 08:48:11 2011
@@ -18,7 +18,6 @@
             -mdivide-enabled -msign-extend-enabled
 
 # optimize flag: typically -O2
-# ATM, doesn't work with optimization levels > 0
 CFLAGS_OPTIMIZE_V = -O2 -g
 
 define bsp-post-link

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/preinstall.am:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/preinstall.am:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/preinstall.am:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/preinstall.am	Mon Aug  1 08:48:11 2011
@@ -41,10 +41,74 @@
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h
 
-$(PROJECT_INCLUDE)/tm27.h: include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
+$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
+
+$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h
 
+$(PROJECT_INCLUDE)/bsp/irq.h: ../../lm32/shared/include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+
+$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_gpio.h: ../../lm32/shared/milkymist_gpio/milkymist_gpio.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_gpio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_gpio.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_buttons.h: ../../lm32/shared/milkymist_buttons/milkymist_buttons.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_buttons.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_buttons.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_ac97.h: ../../lm32/shared/milkymist_ac97/milkymist_ac97.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_ac97.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_ac97.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_usbinput.h: ../../lm32/shared/milkymist_usbinput/milkymist_usbinput.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_usbinput.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_usbinput.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_pfpu.h: ../../lm32/shared/milkymist_pfpu/milkymist_pfpu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_pfpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_pfpu.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_tmu.h: ../../lm32/shared/milkymist_tmu/milkymist_tmu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_tmu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_tmu.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_memcard.h: ../../lm32/shared/milkymist_memcard/milkymist_memcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_memcard.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_memcard.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_flash.h: ../../lm32/shared/milkymist_flash/milkymist_flash.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_flash.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_flash.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_dmx.h: ../../lm32/shared/milkymist_dmx/milkymist_dmx.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_dmx.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_dmx.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_midi.h: ../../lm32/shared/milkymist_midi/milkymist_midi.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_midi.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_midi.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_ir.h: ../../lm32/shared/milkymist_ir/milkymist_ir.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_ir.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_ir.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_video.h: ../../lm32/shared/milkymist_video/milkymist_video.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_video.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_video.h
+
+$(PROJECT_INCLUDE)/bsp/milkymist_versions.h: ../../lm32/shared/milkymist_versions/milkymist_versions.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/milkymist_versions.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/milkymist_versions.h
+
 $(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h
@@ -53,10 +117,6 @@
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h
 
-$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp)
-	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h
-PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h
-
 $(PROJECT_INCLUDE)/system_conf.h: include/system_conf.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/system_conf.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/system_conf.h

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c:1.1
--- /dev/null	Mon Aug  1 09:10:25 2011
+++ rtems/c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c	Mon Aug  1 08:48:11 2011
@@ -0,0 +1,56 @@
+/*  bspclean.c
+ *
+ *  Milkymist shutdown routine
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ */
+
+#include <rtems.h>
+#include "../include/system_conf.h"
+
+static void reboot(void)
+{
+  /* Writing to CSR_SYSTEM_ID causes a system reset */
+  MM_WRITE(MM_SYSTEM_ID, 1);
+}
+
+static void icap_write(int val, unsigned int w)
+{
+  while (!(MM_READ(MM_ICAP) & ICAP_READY));
+  if (!val)
+    w |= ICAP_CE|ICAP_WRITE;
+  MM_WRITE(MM_ICAP, w);
+}
+static void reconf(void)
+{
+  icap_write(0, 0xffff); /* dummy word */
+  icap_write(0, 0xffff); /* dummy word */
+  icap_write(0, 0xffff); /* dummy word */
+  icap_write(0, 0xffff); /* dummy word */
+  icap_write(1, 0xaa99); /* sync word part 1 */
+  icap_write(1, 0x5566); /* sync word part 2 */
+  icap_write(1, 0x30a1); /* write to command register */
+  icap_write(1, 0x0000); /* null command */
+  icap_write(1, 0x30a1); /* write to command register */
+  icap_write(1, 0x000e); /* reboot command */
+  icap_write(1, 0x2000); /* NOP */
+  icap_write(1, 0x2000); /* NOP */
+  icap_write(1, 0x2000); /* NOP */
+  icap_write(1, 0x2000); /* NOP */
+  icap_write(0, 0x1111); /* NULL */
+  icap_write(0, 0xffff); /* dummy word */
+}
+
+void bsp_cleanup(uint32_t status)
+{
+  if (status)
+    reconf();
+  else
+    reboot();
+}

diff -u rtems/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds:1.1 rtems/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds:1.2
--- rtems/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds:1.1	Fri Aug 20 16:22:27 2010
+++ rtems/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds	Mon Aug  1 08:48:11 2011
@@ -9,13 +9,13 @@
  * Declare some sizes. Heap is sized at whatever ram space is left.
  */
 RamBase = DEFINED(RamBase) ? RamBase : 0x40000000;
-RamSize = DEFINED(RamSize) ? RamSize : 64M;
-HeapSize = DEFINED(HeapSize) ? HeapSize : 2M;
+RamSize = DEFINED(RamSize) ? RamSize : 128M;
+HeapSize = DEFINED(HeapSize) ? HeapSize : 92M;
 _StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000;
 
 PROVIDE (__stack = 0);
 MEMORY {
-	sdram   : ORIGIN = 0x40000000 , LENGTH = 64M
+	sdram   : ORIGIN = 0x40000000 , LENGTH = 128M
 }
 SECTIONS
 {

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/ChangeLog:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/ChangeLog	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,21 @@
+2011-08-01	Sebastien Bourdeauducq <sebastien.bourdeauducq at gmail.com>
+
+	PR 1869/bsps
+	* startup/bspclean.c: New file.
+	* include/tm27.h: Removed.
+	* ChangeLog, Makefile.am, README, preinstall.am, include/bsp.h,
+	include/system_conf.h, make/custom/milkymist.cfg, startup/linkcmds:
+	Complete BSP for Milkymist One supporting Milkymist SOC 1.0.x.
+	Includes new or updated drivers for:
+	  - Multi-standard video input (PAL/SECAM/NTSC)
+	  - Two DMX512 (RS485) ports
+	  - MIDI IN and MIDI OUT ports
+	  - VGA output
+	  - AC'97 audio
+	  - NOR flash
+	  - 10/100 Ethernet
+	  - Memory card (experimental and incomplete)
+	  - USB host connectors (input devices only)
+	  - RC5 infrared receiver
+	  - RS232 debug port
+

diff -u rtems/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c:1.3 rtems/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c:1.4
--- rtems/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c:1.3	Sun Nov 29 08:48:22 2009
+++ rtems/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c	Mon Aug  1 08:48:39 2011
@@ -25,6 +25,8 @@
  * SUCH DAMAGE.
  */
 
+/* $Id$ */
+
 #include <bsp.h>
 #include <string.h>
 #include <signal.h>

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/include/irq.h:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/include/irq.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,49 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief BSP interrupt support for LM32.
+ */
+
+/*
+ * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
+ *
+ * Copyright (c) 2008, 2009, 2010
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef LIBBSP_LM32_IRQ_CONFIG_H
+#define LIBBSP_LM32_IRQ_CONFIG_H
+
+#include <stdint.h>
+
+/**
+ * @addtogroup bsp_interrupt
+ *
+ * @{
+ */
+
+/**
+ * @brief Minimum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MIN 0
+
+/**
+ * @brief Maximum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MAX 31
+
+/** @} */
+
+#endif /* LIBBSP_LM32_IRQ_CONFIG_H */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/irq/irq.c:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/irq/irq.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,37 @@
+/* irq.c
+ *
+ *  Copyright (c) 2010 Sebastien Bourdeauducq
+ *
+ *  The license and distribution terms for this file may be
+ *  found in found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ */
+
+#include <bsp.h>
+#include <rtems/score/cpu.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+  lm32_interrupt_unmask(1 << vector);
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+  lm32_interrupt_mask(1 << vector);
+  return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+  printk("spurious interrupt: %u\n", vector);
+}

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c	Mon Aug  1 08:48:39 2011
@@ -1,7 +1,6 @@
 /*  ac97.c
  *
- *  This file is the sound driver for the Milkymist One board
- *  It does an OSS style character device in /dev/snd
+ *  Sound driver for Milkymist SoC
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -9,111 +8,419 @@
  *
  *  $Id$
  *
- *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu> (GSoC 2010)
- *  Telecom SudParis
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <pthread.h>
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
 #include <rtems.h>
 #include <bsp.h>
-#include "../include/system_conf.h"
+#include <bsp/irq-generic.h>
 #include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_ac97.h"
 
-#define GPIO_DRIVER_TABLE_ENTRY { ac97_initialize, \
-ac97_open, ac97_close, ac97_read, ac97_write, ac97_control}
+#define SND_DEVICE_NAME "/dev/snd"
+#define MIXER_DEVICE_NAME "/dev/mixer"
 
-#define SND_DEVICE_NAME  "/dev/snd"
+static rtems_id cr_write_sem;
+static rtems_id cr_read_sem;
 
-static struct milkymist_ac97 {
-  rtems_device_minor_number minor;
-  pthread_mutex_t mutex;
-} ac97_driver;
+static rtems_isr crrequest_handler(rtems_vector_number n)
+{
+  rtems_semaphore_release(cr_write_sem);
+  lm32_interrupt_ack(1 << MM_IRQ_AC97CRREQUEST);
+}
 
-rtems_device_driver gpio_initialize(
-rtems_device_major_number  major,
-rtems_device_minor_number  minor,
-void *arg)
+static rtems_isr crreply_handler(rtems_vector_number n)
 {
-  rtems_status_code status;
+  rtems_semaphore_release(cr_read_sem);
+  lm32_interrupt_ack(1 << MM_IRQ_AC97CRREPLY);
+}
 
-  printk( "ac97 driver initializing..\n" );
+/* queued playback buffers */
+#define PLAY_Q_SIZE 8
+#define PLAY_Q_MASK (PLAY_Q_SIZE-1)
+
+static struct snd_buffer *play_q[PLAY_Q_SIZE];
+static int play_produce;
+static int play_consume;
+static int play_level;
 
-  status = rtems_io_register_name(SND_DEVICE_NAME, major, 0);
-  if (status != RTEMS_SUCCESSFUL)
-  {
-    printk("Error registering /dev/snd ac97 device \n");
-    rtems_fatal_error_occurred( status );
-  }
-  gpio[0].minor = 0;
-  gpio[0].mutex = PTHREAD_MUTEX_INITIALIZER;
+/* buffers played, for application to collect */
+static rtems_id play_q_done;
 
-  return RTEMS_SUCCESSFUL;
+static void play_start(struct snd_buffer *buf)
+{
+  if (buf->nsamples > (AC97_MAX_DMASIZE/4))
+    buf->nsamples = AC97_MAX_DMASIZE/4;
+
+  MM_WRITE(MM_AC97_DADDRESS, (unsigned int)buf->samples);
+  MM_WRITE(MM_AC97_DREMAINING, buf->nsamples*4);
+  MM_WRITE(MM_AC97_DCTL, AC97_SCTL_EN);
 }
 
-rtems_device_driver gpio_close(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
+static rtems_isr pcmplay_handler(rtems_vector_number n)
+{
+  lm32_interrupt_ack(1 << MM_IRQ_AC97DMAR);
+
+  rtems_message_queue_send(play_q_done, &play_q[play_consume],
+    sizeof(void *));
+
+  play_consume = (play_consume + 1) & PLAY_Q_MASK;
+  play_level--;
+
+  if(play_level > 0)
+    play_start(play_q[play_consume]);
+  else
+    MM_WRITE(MM_AC97_DCTL, 0);
+}
+
+/* queued record buffers */
+#define RECORD_Q_SIZE 8
+#define RECORD_Q_MASK (RECORD_Q_SIZE-1)
+
+static struct snd_buffer *record_q[RECORD_Q_SIZE];
+static int record_produce;
+static int record_consume;
+static int record_level;
+
+/* buffers recorded, for application to collect */
+static rtems_id record_q_done;
+
+static void record_start(struct snd_buffer *buf)
+{
+  if (buf->nsamples > (AC97_MAX_DMASIZE/4))
+    buf->nsamples = AC97_MAX_DMASIZE/4;
+
+  MM_WRITE(MM_AC97_UADDRESS, (unsigned int)buf->samples);
+  MM_WRITE(MM_AC97_UREMAINING, buf->nsamples*4);
+  MM_WRITE(MM_AC97_UCTL, AC97_SCTL_EN);
+}
+
+static rtems_isr pcmrecord_handler(rtems_vector_number n)
+{
+  lm32_interrupt_ack(1 << MM_IRQ_AC97DMAW);
+
+  __asm__ volatile( /* Invalidate Level-1 data cache */
+      "wcsr DCC, r0\n"
+      "nop\n"
+    );
+
+  rtems_message_queue_send(record_q_done, &record_q[record_consume],
+    sizeof(void *));
+
+  record_consume = (record_consume + 1) & RECORD_Q_MASK;
+  record_level--;
+
+  if(record_level > 0)
+    record_start(record_q[record_consume]);
+  else
+    MM_WRITE(MM_AC97_UCTL, 0);
+}
+
+rtems_device_driver ac97_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
   void *arg
 )
 {
-  if (pthread_mutex_unlock(&ac97_driver.mutex) == 0){
-    return RTEMS_SUCCESSFUL;
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(SND_DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create snd device");
+
+  sc = rtems_io_register_name(MIXER_DEVICE_NAME, major, 1);
+  RTEMS_CHECK_SC(sc, "create mixer device");
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('C', 'R', 'W', 'S'),
+    0,
+    RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &cr_write_sem
+  );
+  RTEMS_CHECK_SC(sc, "create AC97 register write semaphore");
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('C', 'R', 'R', 'S'),
+    0,
+    RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &cr_read_sem
+  );
+  RTEMS_CHECK_SC(sc, "create AC97 register read semaphore");
+
+  sc = rtems_message_queue_create(
+    rtems_build_name('P', 'L', 'Y', 'Q'),
+    PLAY_Q_SIZE*2,
+    sizeof(void *),
+    0,
+    &play_q_done
+  );
+  RTEMS_CHECK_SC(sc, "create playback done queue");
+
+  sc = rtems_message_queue_create(
+    rtems_build_name('R', 'E', 'C', 'Q'),
+    RECORD_Q_SIZE*2,
+    sizeof(void *),
+    0,
+    &record_q_done
+  );
+  RTEMS_CHECK_SC(sc, "create record done queue");
+
+  rtems_interrupt_catch(crrequest_handler, MM_IRQ_AC97CRREQUEST, &dummy);
+  rtems_interrupt_catch(crreply_handler, MM_IRQ_AC97CRREPLY, &dummy);
+  rtems_interrupt_catch(pcmplay_handler, MM_IRQ_AC97DMAR, &dummy);
+  rtems_interrupt_catch(pcmrecord_handler, MM_IRQ_AC97DMAW, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_AC97CRREQUEST);
+  bsp_interrupt_vector_enable(MM_IRQ_AC97CRREPLY);
+  bsp_interrupt_vector_enable(MM_IRQ_AC97DMAR);
+  bsp_interrupt_vector_enable(MM_IRQ_AC97DMAW);
+
+  play_produce = 0;
+  play_consume = 0;
+  play_level = 0;
+
+  record_produce = 0;
+  record_consume = 0;
+  record_level = 0;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code submit_play(struct snd_buffer *buf)
+{
+  bsp_interrupt_vector_disable(MM_IRQ_AC97DMAR);
+  if (play_level == PLAY_Q_SIZE) {
+    bsp_interrupt_vector_enable(MM_IRQ_AC97DMAR);
+    return RTEMS_UNSATISFIED;
   }
-  return RTEMS_UNSATISFIED;
+  play_q[play_produce] = buf;
+  play_produce = (play_produce + 1) & PLAY_Q_MASK;
+  play_level++;
+
+  if (play_level == 1)
+    play_start(buf);
+
+  bsp_interrupt_vector_enable(MM_IRQ_AC97DMAR);
+  return RTEMS_SUCCESSFUL;
 }
 
-rtems_device_driver gpio_open(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void *arg
-)
+static rtems_status_code collect_play(struct snd_buffer **buf)
 {
-  if (pthread_mutex_trylock(&ac97_driver.mutex) == 0){
-    return RTEMS_SUCCESSFUL;
+  size_t s;
+
+  return rtems_message_queue_receive(
+    play_q_done,
+    buf,
+    &s,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+}
+
+static rtems_status_code submit_record(struct snd_buffer *buf)
+{
+  bsp_interrupt_vector_disable(MM_IRQ_AC97DMAW);
+  if (record_level == RECORD_Q_SIZE) {
+    bsp_interrupt_vector_enable(MM_IRQ_AC97DMAW);
+    return RTEMS_UNSATISFIED;
   }
-  return RTEMS_UNSATISFIED;
+  record_q[record_produce] = buf;
+  record_produce = (record_produce + 1) & RECORD_Q_MASK;
+  record_level++;
+
+  if (record_level == 1)
+    record_start(buf);
+
+  bsp_interrupt_vector_enable(MM_IRQ_AC97DMAW);
+  return RTEMS_SUCCESSFUL;
 }
 
+static rtems_status_code collect_record(struct snd_buffer **buf)
+{
+  size_t s;
+
+  return rtems_message_queue_receive(
+    record_q_done,
+    buf,
+    &s,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+}
+
+#define CR_TIMEOUT 10
+
+static int read_cr(unsigned int adr)
+{
+  rtems_status_code sc;
+
+  MM_WRITE(MM_AC97_CRADDR, adr);
+  MM_WRITE(MM_AC97_CRCTL, AC97_CRCTL_RQEN);
+  sc = rtems_semaphore_obtain(cr_write_sem, RTEMS_WAIT, CR_TIMEOUT);
+  if (sc != RTEMS_SUCCESSFUL)
+    return -1;
+  sc = rtems_semaphore_obtain(cr_read_sem, RTEMS_WAIT, CR_TIMEOUT);
+  if (sc != RTEMS_SUCCESSFUL)
+    return -1;
+  return MM_READ(MM_AC97_CRDATAIN);
+}
+
+static int write_cr(unsigned int adr, unsigned int val)
+{
+  rtems_status_code sc;
+
+  MM_WRITE(MM_AC97_CRADDR, adr);
+  MM_WRITE(MM_AC97_CRDATAOUT, val);
+  MM_WRITE(MM_AC97_CRCTL, AC97_CRCTL_RQEN|AC97_CRCTL_WRITE);
+  sc = rtems_semaphore_obtain(cr_write_sem, RTEMS_WAIT, CR_TIMEOUT);
+  if (sc != RTEMS_SUCCESSFUL)
+    return 0;
+  return 1;
+}
 
-rtems_device_driver gpio_read(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
+rtems_device_driver ac97_open(
+   rtems_device_major_number major,
+   rtems_device_minor_number minor,
+   void *arg
 )
 {
-  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  int codec_id;
   
+  if (minor == 0) {
+    /* snd */
+    return RTEMS_SUCCESSFUL;
+  } else {
+    /* mixer */
+    codec_id = read_cr(0x00);
+    if ((codec_id != 0x0d50) && (codec_id != 0x6150)) {
+      printk("AC97 codec detection failed\n");
+      return RTEMS_UNSATISFIED;
+    }
+    write_cr(0x02, 0x0000); /* master volume */
+    write_cr(0x04, 0x0f0f); /* headphones volume */
+    write_cr(0x18, 0x0000); /* PCM out volume */
+    write_cr(0x1c, 0x0f0f); /* record gain */
+
+    write_cr(0x1a, 0x0505); /* record select: stereo mix */
+
+    return RTEMS_SUCCESSFUL;
+  }
+}
+
+static rtems_status_code ioctl_read_channel(void *buf,
+  unsigned int chan, int mono)
+{
+  unsigned int *val = (unsigned int *)buf;
+  int codec;
+  int left, right;
+
+  codec = read_cr(chan);
+  if (codec < 0)
+    return RTEMS_UNSATISFIED;
+  if (codec & 0x8000) {
+    /* muted */
+    *val = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+  if (mono) {
+    right = left = 100-(((codec & 0x1f) + 1)*100)/32;
+  } else {
+    right = 100-(((codec & 0x1f) + 1)*100)/32;
+    left = 100-((((codec & 0x1f00) >> 8) + 1)*100)/32;
+  }
+  *val = left | (right << 8);
   return RTEMS_SUCCESSFUL;
 }
 
-rtems_device_driver gpio_write(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
-)
+static rtems_status_code ioctl_write_channel(void *buf,
+  unsigned int chan, int mono)
 {
-  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  unsigned int *val = (unsigned int *)buf;
+  int left, right;
+  int codec;
+  rtems_status_code sc;
+
+  left = *val & 0xff;
+  left = (left*32)/100 - 1;
+  if(left < 0)
+    left = 0;
+
+  if (mono)
+    right = 31;
+  else {
+    right = (*val >> 8) & 0xff;
+    right = (right*32)/100 - 1;
+    if(right < 0)
+      right = 0;
+  }
 
-  return RTEMS_SUCCESSFUL;
+  if ((left == 0) && (right == 0))
+    /* mute */
+    codec = 0x8000;
+  else
+    codec = (31-left) | ((31-right) << 8);
+
+  if (!write_cr(chan, codec))
+    sc = RTEMS_UNSATISFIED;
+  else
+    sc = RTEMS_SUCCESSFUL;
+  return sc;
 }
 
-rtems_device_driver gpio_control(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
+rtems_device_driver ac97_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
 )
 {
   rtems_libio_ioctl_args_t *args = arg;
+  rtems_status_code sc;
 
-  switch( args->command ) {
-    default:
-     args->ioctl_return = 0;
-     break;
+  args->ioctl_return = -1;
+  if(minor == 0) {
+    /* dsp */
+    switch (args->command) {
+      case SOUND_SND_SUBMIT_PLAY:
+        return submit_play((struct snd_buffer *)args->buffer);
+      case SOUND_SND_COLLECT_PLAY:
+        return collect_play((struct snd_buffer **)args->buffer);
+      case SOUND_SND_SUBMIT_RECORD:
+        return submit_record((struct snd_buffer *)args->buffer);
+      case SOUND_SND_COLLECT_RECORD:
+        return collect_record((struct snd_buffer **)args->buffer);
+      default:
+        return RTEMS_UNSATISFIED;
+    }
+  } else {
+    /* mixer */
+    switch (args->command) {
+      case SOUND_MIXER_READ(SOUND_MIXER_MIC):
+        sc = ioctl_read_channel(args->buffer, 0x0e, 1);
+        if(sc == RTEMS_SUCCESSFUL)
+          args->ioctl_return = 0;
+        return sc;
+      case SOUND_MIXER_READ(SOUND_MIXER_LINE):
+        sc = ioctl_read_channel(args->buffer, 0x10, 0);
+        if(sc == RTEMS_SUCCESSFUL)
+          args->ioctl_return = 0;
+        return sc;
+      case SOUND_MIXER_WRITE(SOUND_MIXER_MIC):
+        sc = ioctl_write_channel(args->buffer, 0x0e, 1);
+        if(sc == RTEMS_SUCCESSFUL)
+          args->ioctl_return = 0;
+        return sc;
+      case SOUND_MIXER_WRITE(SOUND_MIXER_LINE):
+        sc = ioctl_write_channel(args->buffer, 0x10, 0);
+        if(sc == RTEMS_SUCCESSFUL)
+          args->ioctl_return = 0;
+        return sc;
+      default:
+        return RTEMS_UNSATISFIED;
+    }
   }
-  return RTEMS_SUCCESSFUL;
 }
-

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,63 @@
+/*  milkymist_ac97.h
+ *
+ *  Milkymist AC97 driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_AC97_H_
+#define __MILKYMIST_AC97_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ioctls. 0x41 is 'A' */
+#define SOUND_MIXER_MIC             0x0
+#define SOUND_MIXER_LINE            0x1
+#define SOUND_MIXER_READ(x)         (0x4100+x)
+#define SOUND_MIXER_WRITE(x)        (0x4110+x)
+
+#define SOUND_SND_SUBMIT_PLAY       0x4120
+#define SOUND_SND_COLLECT_PLAY      0x4121
+#define SOUND_SND_SUBMIT_RECORD     0x4122
+#define SOUND_SND_COLLECT_RECORD    0x4123
+
+struct snd_buffer {
+  unsigned int nsamples;
+  void *user;
+  unsigned int samples[];
+};
+
+rtems_device_driver ac97_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver ac97_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver ac97_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define AC97_DRIVER_TABLE_ENTRY {ac97_initialize, \
+ac97_open, NULL, NULL, NULL, ac97_control}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_AC97_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,132 @@
+/*  buttons.c
+ *
+ *  Buttons driver for the Milkymist One board
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <rtems/status-checks.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_buttons.h"
+
+#define DEVICE_NAME "/dev/buttons"
+
+static rtems_id event_q;
+
+static void send_byte(char b)
+{
+  rtems_message_queue_send(event_q, &b, 1);
+}
+
+static rtems_isr interrupt_handler(rtems_vector_number n)
+{
+  static unsigned int previous_keys;
+  unsigned int keys, pushed_keys, released_keys;
+  
+  keys = MM_READ(MM_GPIO_IN) & (GPIO_BTN1|GPIO_BTN2|GPIO_BTN3);
+  pushed_keys = keys & ~previous_keys;
+  released_keys = previous_keys & ~keys;
+  previous_keys = keys;
+  
+  if(pushed_keys & GPIO_BTN1)
+    send_byte('A');
+  if(pushed_keys & GPIO_BTN2)
+    send_byte('B');
+  if(pushed_keys & GPIO_BTN3)
+    send_byte('C');
+
+  if(released_keys & GPIO_BTN1)
+    send_byte('a');
+  if(released_keys & GPIO_BTN2)
+    send_byte('b');
+  if(released_keys & GPIO_BTN3)
+    send_byte('c');
+  
+  lm32_interrupt_ack(1 << MM_IRQ_GPIO);
+}
+
+rtems_device_driver buttons_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create buttons device");
+  
+  sc = rtems_message_queue_create(
+    rtems_build_name('B', 'T', 'N', 'Q'),
+    24,
+    1,
+    0,
+    &event_q
+  );
+  RTEMS_CHECK_SC(sc, "create buttons event queue");
+  
+  rtems_interrupt_catch(interrupt_handler, MM_IRQ_GPIO, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_GPIO);
+  MM_WRITE(MM_GPIO_INTEN, GPIO_BTN1|GPIO_BTN2|GPIO_BTN3);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver buttons_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  uint32_t count;
+
+  rtems_message_queue_flush(event_q, &count);
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver buttons_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rtems_status_code sc;
+
+  if(rw_args->count < 1) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+
+  sc = rtems_message_queue_receive(
+    event_q,
+    rw_args->buffer,
+    (size_t *)&rw_args->bytes_moved,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+
+  if(sc == RTEMS_SUCCESSFUL)
+    return RTEMS_SUCCESSFUL;
+  else {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h:1.1
--- /dev/null	Mon Aug  1 09:10:26 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,46 @@
+/*  milkymist_buttons.h
+ *
+ *  Milkymist buttons driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2011 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_BUTTONS_H_
+#define __MILKYMIST_BUTTONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver buttons_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver buttons_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver buttons_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define BUTTONS_DRIVER_TABLE_ENTRY { buttons_initialize, \
+buttons_open, NULL, buttons_read, NULL, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_BUTTONS_H_ */

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c	Mon Aug  1 08:48:39 2011
@@ -13,6 +13,7 @@
  */
 
 #include <bsp.h>
+#include <bsp/irq-generic.h>
 #include "../include/system_conf.h"
 #include "clock.h"
 #include "bspopts.h"
@@ -21,50 +22,29 @@
 #define CLOCK_DRIVER_USE_FAST_IDLE
 #endif
 
-static inline int clockread(unsigned int reg)
-{
-  return *((int*)(reg));
-}
-
-static inline void clockwrite(unsigned int reg, int value)
-{
-  *((int*)reg) = value;
-}
-
-/*
- *  The interrupt vector number associated with the clock tick device
- *  driver.
- */
-
-#define TIMER0_IRQ              (1)
-
-#define CLOCK_VECTOR    ( TIMER0_IRQ )
-#define CLOCK_IRQMASK   ( 1 << CLOCK_VECTOR )
-
 #define Clock_driver_support_at_tick() \
   do { \
-    lm32_interrupt_ack(CLOCK_IRQMASK); \
+    lm32_interrupt_ack(1 << MM_IRQ_TIMER0); \
   } while (0)
 
 #define Clock_driver_support_install_isr(_new, _old ) \
   do { \
-	  _old = (rtems_isr_entry) set_vector( _new, CLOCK_VECTOR, 1 ); \
+    rtems_interrupt_catch(_new, MM_IRQ_TIMER0, &_old); \
   } while (0)
 
 void Clock_driver_support_initialize_hardware(void)
 {
-  clockwrite(MM_TIMER0_COMPARE, (CPU_FREQUENCY / (1000000 / rtems_configuration_get_microseconds_per_tick())));
-	
-  clockwrite(MM_TIMER0_COUNTER, 0);
-  clockwrite(MM_TIMER0_CONTROL, TIMER_ENABLE | TIMER_AUTORESTART);
-  lm32_interrupt_unmask(CLOCK_IRQMASK);
+  MM_WRITE(MM_TIMER0_COMPARE, 
+   (CPU_FREQUENCY/(1000000/rtems_configuration_get_microseconds_per_tick())));
+  MM_WRITE(MM_TIMER0_COUNTER, 0);
+  MM_WRITE(MM_TIMER0_CONTROL, TIMER_ENABLE | TIMER_AUTORESTART);
+  bsp_interrupt_vector_enable(MM_IRQ_TIMER0);
 }
 
 void Clock_driver_support_shutdown_hardware(void)
 {
-  lm32_interrupt_mask(CLOCK_IRQMASK);
-  clockwrite(MM_TIMER0_CONTROL, 0);
+  bsp_interrupt_vector_disable(MM_IRQ_TIMER0);
+  MM_WRITE(MM_TIMER0_CONTROL, 0);
 }
 
 #include "../../../shared/clockdrv_shell.h"
-

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c	Mon Aug  1 08:48:39 2011
@@ -1,5 +1,5 @@
 /*
- *  Console driver for Lattice Mico32 (lm32).
+ *  Console driver for Milkymist
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -7,220 +7,214 @@
  *
  *  $Id$
  *
- *  Jukka Pietarinen <jukka.pietarinen at mrf.fi>, 2008,
- *  Micro-Research Finland Oy
- *
- *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu>, GSoc 2010
- *  Telecom SudParis
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
  */
 
-#define NO_BSP_INIT
+#include <unistd.h>
+#include <termios.h>
 
 #include <rtems.h>
-#include <bsp.h>
 #include <rtems/libio.h>
+#include <rtems/console.h>
+#include <rtems/termiostypes.h>
+#include <bsp/irq-generic.h>
 
-void BSP_uart_polled_write(char ch);
-int BSP_uart_polled_read( void );
-char BSP_uart_is_character_ready(char *ch);
+#include "../include/system_conf.h"
+#include "uart.h"
 
-/*  console_initialize
- *
- *  This routine initializes the console IO driver.
- *
- *  Input parameters: NONE
- *
- *  Output parameters:  NONE
- *
- *  Return values:
- */
+BSP_output_char_function_type BSP_output_char = BSP_uart_polled_write;
+BSP_polling_getchar_function_type BSP_poll_char = BSP_uart_polled_read;
 
-rtems_device_driver console_initialize(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
-)
-{
-  rtems_status_code status;
+static struct rtems_termios_tty *tty;
 
-  printk("console_initialize\n");
+static int mmconsole_first_open(int major, int minor, void *arg)
+{
+  tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
+  return rtems_termios_set_initial_baud(tty, UART_BAUD_RATE);
+}
 
-  status = rtems_io_register_name(
-    "/dev/console",
-    major,
-    (rtems_device_minor_number) 0
-  );
+static int mmconsole_last_close(int major, int minor, void *arg)
+{
+  return 0;
+}
 
-  if (status != RTEMS_SUCCESSFUL)
-    rtems_fatal_error_occurred(status);
+static int mmconsole_set_attributes(int minor, const struct termios *t)
+{
+  int baud;
 
-  return RTEMS_SUCCESSFUL;
-}
+  switch (t->c_cflag & CBAUD) {
+    case B0:
+      baud = 0;
+      break;
+    case B50:
+      baud = 50;
+      break;
+    case B75:
+      baud = 75;
+      break;
+    case B110:
+      baud = 110;
+      break;
+    case B134:
+      baud = 134;
+      break;
+    case B150:
+      baud = 150;
+      break;
+    case B200:
+      baud = 200;
+      break;
+    case B300:
+      baud = 300;
+      break;
+    case B600:
+      baud = 600;
+      break;
+    case B1200:
+      baud = 1200;
+      break;
+    case B1800:
+      baud = 1800;
+      break;
+    case B2400:
+      baud = 2400;
+      break;
+    case B4800:
+      baud = 4800;
+      break;
+    case B9600:
+      baud = 9600;
+      break;
+    case B19200:
+      baud = 19200;
+      break;
+    case B38400:
+      baud = 38400;
+      break;
+    case B57600:
+      baud = 57600;
+      break;
+    case B115200:
+      baud = 115200;
+      break;
+    case B230400:
+      baud = 230400;
+      break;
+    case B460800:
+      baud = 460800;
+      break;
+    default:
+      baud = -1;
+      break;
+  }
 
-/*  is_character_ready
- *
- *  This routine returns TRUE if a character is available.
- *
- *  Input parameters: NONE
- *
- *  Output parameters:  NONE
- *
- *  Return values:
- */
+  if (baud > 0)
+    MM_WRITE(MM_UART_DIV, CPU_FREQUENCY/baud/16);
 
-bool is_character_ready(
-  char *ch
-)
-{
-  return BSP_uart_is_character_ready(ch);
+  return 0;
 }
 
-/*  inbyte
- *
- *  This routine reads a character from the SOURCE.
- *
- *  Input parameters: NONE
- *
- *  Output parameters:  NONE
- *
- *  Return values:
- *    character read from SOURCE
- */
-
-int inbyte( void )
+static ssize_t mmconsole_write(int minor, const char *buf, size_t n)
 {
-  /*
-   *  If polling, wait until a character is available.
-   */
+  rtems_interrupt_level level;
 
-  return BSP_uart_polled_read();
+  rtems_interrupt_disable(level);
+  BSP_uart_txbusy = true;
+  MM_WRITE(MM_UART_RXTX, *buf);
+  rtems_interrupt_enable(level);
+  return 0;
 }
 
-/*  outbyte
- *
- *  This routine transmits a character out the SOURCE.  It may support
- *  XON/XOFF flow control.
- *
- *  Input parameters:
- *    ch  - character to be transmitted
- *
- *  Output parameters:  NONE
- */
+static rtems_isr mmconsole_txdone(rtems_vector_number n)
+{
+  BSP_uart_txbusy = false;
+  lm32_interrupt_ack(1 << MM_IRQ_UARTTX);
+  rtems_termios_dequeue_characters(tty, 1);
+}
+
+static rtems_isr mmconsole_rxdone(rtems_vector_number n)
+{
+  char c;
+  c = MM_READ(MM_UART_RXTX);
+  lm32_interrupt_ack(1 << MM_IRQ_UARTRX);
+  rtems_termios_enqueue_raw_characters(tty, &c, 1);
+}
+
+static const rtems_termios_callbacks mmconsole_callbacks = {
+  .firstOpen = mmconsole_first_open,
+  .lastClose = mmconsole_last_close,
+  .pollRead = NULL,
+  .write = mmconsole_write,
+  .setAttributes = mmconsole_set_attributes,
+  .stopRemoteTx = NULL,
+  .startRemoteTx = NULL,
+  .outputUsesInterrupts = TERMIOS_IRQ_DRIVEN
+};
 
-void outbyte(
-  char ch
+rtems_device_driver console_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
 )
 {
-  /*
-   *  If polling, wait for the transmitter to be ready.
-   *  Check for flow control requests and process.
-   *  Then output the character.
-   */
+  rtems_status_code status;
+  rtems_isr_entry dummy;
 
-  BSP_uart_polled_write(ch);
-}
+  rtems_termios_initialize();
 
-/*
- *  Open entry point
- */
+  status = rtems_io_register_name("/dev/console", major, 0);
+  if (status != RTEMS_SUCCESSFUL)
+    rtems_fatal_error_occurred(status);
+
+  rtems_interrupt_catch(mmconsole_txdone, MM_IRQ_UARTTX, &dummy);
+  rtems_interrupt_catch(mmconsole_rxdone, MM_IRQ_UARTRX, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_UARTTX);
+  bsp_interrupt_vector_enable(MM_IRQ_UARTRX);
+
+  return RTEMS_SUCCESSFUL;
+}
 
 rtems_device_driver console_open(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
-  void                    * arg
+  void  *arg
 )
 {
-  return RTEMS_SUCCESSFUL;
+  return rtems_termios_open(major, minor, arg, &mmconsole_callbacks);
 }
 
-/*
- *  Close entry point
- */
-
 rtems_device_driver console_close(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
-  void                    * arg
+  void *arg
 )
 {
-  return RTEMS_SUCCESSFUL;
+  return rtems_termios_close(arg);
 }
 
-/*
- * read bytes from the serial port. We only have stdin.
- */
-
 rtems_device_driver console_read(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
-  void                    * arg
+  void *arg
 )
 {
-  rtems_libio_rw_args_t *rw_args;
-  char *buffer;
-  int maximum;
-  int count = 0;
-
-  rw_args = (rtems_libio_rw_args_t *) arg;
-
-  buffer = rw_args->buffer;
-  maximum = rw_args->count;
-
-  for (count = 0; count < maximum; count++) {
-    buffer[ count ] = inbyte();
-    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
-      buffer[ count++ ]  = '\n';
-      break;
-    }
-  }
-
-  rw_args->bytes_moved = count;
-  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
+  return rtems_termios_read(arg);
 }
 
-/*
- * write bytes to the serial port. Stdout and stderr are the same.
- */
-
 rtems_device_driver console_write(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
-  void                    * arg
+  void *arg
 )
 {
-  int count;
-  int maximum;
-  rtems_libio_rw_args_t *rw_args;
-  char *buffer;
-
-  rw_args = (rtems_libio_rw_args_t *) arg;
-
-  buffer = rw_args->buffer;
-  maximum = rw_args->count;
-
-  for (count = 0; count < maximum; count++) {
-    if ( buffer[ count ] == '\n') {
-      outbyte('\r');
-    }
-    outbyte( buffer[ count ] );
-  }
-
-  rw_args->bytes_moved = maximum;
-  return 0;
+  return rtems_termios_write(arg);
 }
 
-/*
- *  IO Control entry point
- */
-
 rtems_device_driver console_control(
   rtems_device_major_number major,
   rtems_device_minor_number minor,
-  void                    * arg
+  void *arg
 )
 {
-  return RTEMS_SUCCESSFUL;
+  return rtems_termios_ioctl(arg);
 }
-
-BSP_output_char_function_type BSP_output_char = BSP_uart_polled_write;
-BSP_polling_getchar_function_type BSP_poll_char = BSP_uart_polled_read;

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h	Mon Aug  1 08:48:39 2011
@@ -14,13 +14,10 @@
 #ifndef _BSPUART_H
 #define _BSPUART_H
 
-void BSP_uart_init(int baud);
-
-#define MM_UART_RXTX	(0xe0000000)
+extern bool BSP_uart_txbusy;
 
-#define MM_UART_DIV     (0xe0000004)
-
-#define MM_IRQ_UARTTX	(0x00000010) /* 4 */
-#define MM_IRQ_UARTRX	(0x00000008) /* 3 */
+void BSP_uart_init(int baud);
+void BSP_uart_polled_write(char ch);
+int BSP_uart_polled_read(void);
 
 #endif /* _BSPUART_H */

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c	Mon Aug  1 08:48:39 2011
@@ -1,5 +1,5 @@
 /*
- *  Uart driver for Lattice Mico32 (lm32) UART
+ *  Driver for Milkymist UART
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -7,63 +7,60 @@
  *
  *  $Id$
  *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
  *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu> (GSoC 2010)
  *  Telecom SudParis
  */
 
+#include <rtems.h>
+#include <rtems/libio.h>
 #include "../include/system_conf.h"
 #include "uart.h"
-#include <rtems/libio.h>
 
-static inline int uartread(unsigned int reg)
-{
-  return *((int*)(reg));
-}
-
-static inline void uartwrite(unsigned int reg, int value)
-{
-  *((int*)(reg)) = value;
-}
+bool BSP_uart_txbusy;
 
 void BSP_uart_init(int baud)
 {
-
-  /* Set baud rate */
-  uartwrite(MM_UART_DIV, CPU_FREQUENCY/baud/16);
+  MM_WRITE(MM_UART_DIV, CPU_FREQUENCY/baud/16);
 }
 
 void BSP_uart_polled_write(char ch)
 {
   int ip;
-  /* Wait until THR is empty. */
-  uartwrite(MM_UART_RXTX, ch);
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  if (BSP_uart_txbusy) {
+    /* wait for the end of the transmission by the IRQ-based driver */
+    do {
+      lm32_read_interrupts(ip);
+    } while (!(ip & (1 << MM_IRQ_UARTTX)));
+    lm32_interrupt_ack(1 << MM_IRQ_UARTTX);
+  }
+  MM_WRITE(MM_UART_RXTX, ch);
   do {
     lm32_read_interrupts(ip);
-  } while (! (ip & MM_IRQ_UARTTX) );
-  lm32_interrupt_ack(MM_IRQ_UARTTX);
+  } while (!(ip & (1 << MM_IRQ_UARTTX)));
+  /* if TX was busy, do not ack the IRQ
+   * so that the IRQ-based driver ISR is run */
+  if (!BSP_uart_txbusy)
+    lm32_interrupt_ack(1 << MM_IRQ_UARTTX);
+  rtems_interrupt_enable(level);
 }
 
-char BSP_uart_polled_read( void )
+int BSP_uart_polled_read(void)
 {
   int ip;
-  /* Wait until there is a byte in RBR */
+  char r;
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
   do {
     lm32_read_interrupts(ip);
-  } while(! (ip & MM_IRQ_UARTRX) );
-  lm32_interrupt_ack(MM_IRQ_UARTRX);
-  return (char) uartread(MM_UART_RXTX);
-}
+  } while (!(ip & (1 << MM_IRQ_UARTRX)));
+  lm32_interrupt_ack(1 << MM_IRQ_UARTRX);
+  r = MM_READ(MM_UART_RXTX);
+  rtems_interrupt_enable(level);
 
-char BSP_uart_is_character_ready(char *ch)
-{
-  int ip;
-  lm32_read_interrupts(ip);
-  if (ip & MM_IRQ_UARTRX)
-    {
-      *ch = (char) uartread(MM_UART_RXTX);
-      lm32_interrupt_ack(MM_IRQ_UARTRX);
-      return true;
-    }
-  *ch = '0';
-  return false;
+  return r;
 }

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,130 @@
+/*  dmx.c
+ *
+ *  Milkymist DMX512 driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <rtems/status-checks.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_dmx.h"
+
+#define IN_DEVICE_NAME "/dev/dmx_in"
+#define OUT_DEVICE_NAME "/dev/dmx_out"
+
+rtems_device_driver dmx_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+
+  sc = rtems_io_register_name(IN_DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create DMX input device");
+
+  sc = rtems_io_register_name(OUT_DEVICE_NAME, major, 1);
+  RTEMS_CHECK_SC(sc, "create DMX output device");
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver dmx_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  int len;
+  unsigned int i;
+  unsigned char *values = (unsigned char *)rw_args->buffer;
+
+  len = 512 - rw_args->offset;
+  if (len < 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+  if (len > rw_args->count)
+    len = rw_args->count;
+
+  if (minor == 0) {
+    for (i=0;i<len;i++)
+      values[i] = MM_READ(MM_DMX_RX((unsigned int)rw_args->offset+i));
+  } else {
+    for (i=0;i<len;i++)
+      values[i] = MM_READ(MM_DMX_TX((unsigned int)rw_args->offset+i));
+  }
+
+  rw_args->bytes_moved = len;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver dmx_write(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  int len;
+  unsigned int i;
+  unsigned char *values = (unsigned char *)rw_args->buffer;
+
+  if (minor == 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+
+  len = 512 - rw_args->offset;
+  if (len < 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+  if (len > rw_args->count)
+    len = rw_args->count;
+
+  for (i=0;i<len;i++)
+    MM_WRITE(MM_DMX_TX((unsigned int)rw_args->offset+i), values[i]);
+
+  rw_args->bytes_moved = len;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver dmx_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  switch (args->command) {
+    case DMX_SET_THRU:
+      args->ioctl_return = 0;
+      MM_WRITE(MM_DMX_THRU, (unsigned int)args->buffer);
+      return RTEMS_SUCCESSFUL;
+    case DMX_GET_THRU:
+      args->ioctl_return = 0;
+      *((unsigned int *)args->buffer) = MM_READ(MM_DMX_THRU);
+      return RTEMS_SUCCESSFUL;
+    default:
+      args->ioctl_return = -1;
+      return RTEMS_UNSATISFIED;
+  }
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,55 @@
+/*  milkymist_dmx.h
+ *
+ *  Milkymist DMX512 driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_DMX_H_
+#define __MILKYMIST_DMX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DMX_SET_THRU       0x4400
+#define DMX_GET_THRU       0x4401
+
+rtems_device_driver dmx_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver dmx_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver dmx_write(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver dmx_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define DMX_DRIVER_TABLE_ENTRY {dmx_initialize, \
+NULL, NULL, dmx_read, dmx_write, dmx_control}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_DMX_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,195 @@
+/*  flash.c
+ *
+ *  Milkymist flash driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <rtems.h>
+#include <stdio.h>
+#include <bsp.h>
+#include <string.h>
+#include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_flash.h"
+
+static struct flash_partition partitions[FLASH_PARTITION_COUNT]
+  = FLASH_PARTITIONS;
+
+static rtems_id flash_lock;
+
+rtems_device_driver flash_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  int i;
+  char devname[16];
+
+  for (i=0;i<FLASH_PARTITION_COUNT;i++) {
+    sprintf(devname, "/dev/flash%d", i+1);
+    sc = rtems_io_register_name(devname, major, i);
+    RTEMS_CHECK_SC(sc, "Create flash device");
+  }
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('F', 'L', 'S', 'H'),
+    1,
+    RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &flash_lock
+  );
+  RTEMS_CHECK_SC(sc, "create semaphore");
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver flash_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  void *startaddr;
+  int len;
+
+  if (minor >= FLASH_PARTITION_COUNT)
+    return RTEMS_UNSATISFIED;
+
+  startaddr = (void *)(partitions[minor].start_address
+    + (unsigned int)rw_args->offset);
+  len = partitions[minor].length - rw_args->offset;
+  if (len > rw_args->count)
+    len = rw_args->count;
+  if (len <= 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+  
+  rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  memcpy(rw_args->buffer, startaddr, len);
+  rtems_semaphore_release(flash_lock);
+
+  rw_args->bytes_moved = len;
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver flash_write(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  volatile unsigned short *startaddr;
+  unsigned short *srcdata;
+  int len;
+  int this_time;
+  int remaining;
+  int i;
+
+  if (minor >= FLASH_PARTITION_COUNT)
+    return RTEMS_UNSATISFIED;
+
+  startaddr = (unsigned short *)(partitions[minor].start_address
+    + (unsigned int)rw_args->offset);
+  len = partitions[minor].length - rw_args->offset;
+  if (len > rw_args->count)
+    len = rw_args->count;
+  if (len <= 2) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+  len /= 2;
+  srcdata = (unsigned short *)rw_args->buffer;
+  remaining = len;
+
+  rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  while (remaining > 0) {
+    this_time = remaining;
+    if (this_time > 256)
+      this_time = 256;
+    /* Issue "Buffered Programming Setup" command
+     * and wait for buffer available.
+     */
+    do {
+      *startaddr = 0x00e8;
+    } while (!(*startaddr & 0x0080));
+    /* Load word count */
+    *startaddr = this_time-1;
+    /* Fill buffer */
+    for(i=0;i<this_time;i++)
+      startaddr[i] = srcdata[i];
+    /* Issue "Buffer Programming Confirm" command */
+    *startaddr = 0x00d0;
+    while (!(*startaddr & 0x0080)); /* read status register, wait for ready */
+    *startaddr = 0x0050; /* clear status register */
+    /* update state */
+    startaddr += this_time;
+    srcdata += this_time;
+    remaining -= this_time;
+  }
+  *startaddr = 0x00ff; /* back to read array mode */
+  rtems_semaphore_release(flash_lock);
+
+  rw_args->bytes_moved = 2*len;
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver flash_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+  unsigned int eraseaddr_i;
+  volatile unsigned short *eraseaddr;
+
+  if (minor >= FLASH_PARTITION_COUNT) {
+    args->ioctl_return = -1;
+    return RTEMS_UNSATISFIED;
+  }
+
+  switch (args->command) {
+    case FLASH_GET_SIZE:
+      *((unsigned int *)args->buffer) = partitions[minor].length;
+      break;
+    case FLASH_GET_BLOCKSIZE:
+      *((unsigned int *)args->buffer) = 128*1024;
+      break;
+    case FLASH_ERASE_BLOCK:
+      eraseaddr_i = (unsigned int)args->buffer;
+      if (eraseaddr_i >= partitions[minor].length) {
+        args->ioctl_return = -1;
+        return RTEMS_UNSATISFIED;
+      }
+      eraseaddr_i = eraseaddr_i + partitions[minor].start_address;
+      eraseaddr = (unsigned short *)eraseaddr_i;
+      rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+      *eraseaddr = 0x0020; /* erase */
+      *eraseaddr = 0x00d0;
+      while(!(*eraseaddr & 0x0080)); /* read status register, wait for ready */
+      *eraseaddr = 0x0050; /* clear status register */
+      *eraseaddr = 0x00ff; /* back to read array mode */
+      rtems_semaphore_release(flash_lock);
+      break;
+    default:
+      args->ioctl_return = -1;
+      return RTEMS_UNSATISFIED;
+  }
+  args->ioctl_return = 0;
+  return RTEMS_SUCCESSFUL;
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,53 @@
+/*  milkymist_flash.h
+ *  
+ *  Copyright (C) 2010 Sebastien Bourdeauducq
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ */
+
+#ifndef __MILKYMIST_FLASH_H_
+#define __MILKYMIST_FLASH_H_
+
+/* Ioctls */
+#define FLASH_GET_SIZE            0x4600
+#define FLASH_GET_BLOCKSIZE       0x4601
+#define FLASH_ERASE_BLOCK         0x4602
+
+struct flash_partition {
+	unsigned int start_address;
+	unsigned int length;
+};
+
+rtems_device_driver flash_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver flash_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver flash_write(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver flash_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define FLASH_DRIVER_TABLE_ENTRY {flash_initialize, \
+NULL, NULL, flash_read, flash_write, flash_control}
+
+#endif /* __MILKYMIST_FLASH_H_ */

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c	Mon Aug  1 08:48:39 2011
@@ -11,13 +11,13 @@
  *
  *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu> (GSoC 2010)
  *  Telecom SudParis
+ *  Copyright (c) 2011 Sebastien Bourdeauducq
  */
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <pthread.h>
 #include <rtems.h>
 #include <bsp.h>
 #include "../include/system_conf.h"
@@ -26,45 +26,30 @@
 
 #define FRAMEBUFFER_DEVICE_NAME "/dev/fb"
 
-pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static unsigned short int framebufferA[1024*768]
+  __attribute__((aligned(32)));
+static unsigned short int framebufferB[1024*768]
+  __attribute__((aligned(32)));
+static unsigned short int framebufferC[1024*768]
+  __attribute__((aligned(32)));
+
+static unsigned short int *frontbuffer;
+static unsigned short int *backbuffer;
+static unsigned short int *lastbuffer;
 
-static unsigned short int framebufferA[640*480] __attribute__((aligned(32)));
-static unsigned short int framebufferB[640*480] __attribute__((aligned(32)));
-static unsigned short int framebufferC[640*480] __attribute__((aligned(32)));
-
-static unsigned short int *frontbuffer = framebufferA;
-static unsigned short int *backbuffer = framebufferB;
-static unsigned short int *lastbuffer = framebufferC;
-
-static inline void fb_write(unsigned int reg, int value)
-{
-  *((int*)reg) = value;
-}
-
-static inline int fb_read(unsigned int reg)
-{
-  return *((int*)(reg));
-}
-
-/* screen information for the VGA driver */
-static struct fb_var_screeninfo fb_var =
-{
+static struct fb_var_screeninfo fb_var = {
   .xres                = 640,
   .yres                = 480,
   .bits_per_pixel      = 16
 };
 
-static struct fb_fix_screeninfo fb_fix =
-{
-// this is initialized at start-up
-  .smem_len            = 640 * 480 * 2,                      /* buffer size       */
-// 2 bytes per pixels
-  .type                = FB_TYPE_VGA_PLANES,           /* type of display    */
-  .visual              = FB_VISUAL_TRUECOLOR,        /* color scheme used */
-  .line_length         = 80                            /* chars per line    */
+static struct fb_fix_screeninfo fb_fix = {
+  .smem_len            = 1024 * 768 * 2,
+  .type                = FB_TYPE_VGA_PLANES,
+  .visual              = FB_VISUAL_TRUECOLOR,
+  .line_length         = 80
 };
 
-
 static int get_fix_screen_info( struct fb_fix_screeninfo *info )
 {
   *info = fb_fix;
@@ -77,168 +62,191 @@
   return 0;
 }
 
+static void init_buffers(void)
+{
+  frontbuffer = framebufferA;
+  backbuffer = framebufferB;
+  lastbuffer = framebufferC;
+}
+
+static void swap_buffers(void)
+{
+  unsigned short int *p;
+
+  /* Make sure last buffer swap has been executed */
+  while (MM_READ(MM_VGA_BASEADDRESS_ACT) != MM_READ(MM_VGA_BASEADDRESS));
+
+  p = frontbuffer;
+  frontbuffer = backbuffer;
+  backbuffer = lastbuffer;
+  lastbuffer = p;
+
+  fb_fix.smem_start = (volatile char *)backbuffer;
+  MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer);
+}
+
+static void set_video_mode(int mode)
+{
+  int hres, vres;
+  
+  MM_WRITE(MM_VGA_RESET, VGA_RESET);
+  hres = vres = 0;
+  switch(mode) {
+    case 0: // 640x480, pixel clock: 25MHz
+      hres = 640;
+      vres = 480;
+      MM_WRITE(MM_VGA_HSYNC_START, 656);
+      MM_WRITE(MM_VGA_HSYNC_END, 752);
+      MM_WRITE(MM_VGA_HSCAN, 799);
+      MM_WRITE(MM_VGA_VSYNC_START, 491);
+      MM_WRITE(MM_VGA_VSYNC_END, 493);
+      MM_WRITE(MM_VGA_VSCAN, 523);
+      MM_WRITE(MM_VGA_CLKSEL, 0);
+      break;
+    case 1: // 800x600, pixel clock: 50MHz
+      hres = 800;
+      vres = 600;
+      MM_WRITE(MM_VGA_HSYNC_START, 848);
+      MM_WRITE(MM_VGA_HSYNC_END, 976);
+      MM_WRITE(MM_VGA_HSCAN, 1040);
+      MM_WRITE(MM_VGA_VSYNC_START, 637);
+      MM_WRITE(MM_VGA_VSYNC_END, 643);
+      MM_WRITE(MM_VGA_VSCAN, 666);
+      MM_WRITE(MM_VGA_CLKSEL, 1);
+      break;
+    case 2: // 1024x768, pixel clock: 65MHz
+      hres = 1024;
+      vres = 768;
+      MM_WRITE(MM_VGA_HSYNC_START, 1048);
+      MM_WRITE(MM_VGA_HSYNC_END, 1184);
+      MM_WRITE(MM_VGA_HSCAN, 1344);
+      MM_WRITE(MM_VGA_VSYNC_START, 771);
+      MM_WRITE(MM_VGA_VSYNC_END, 777);
+      MM_WRITE(MM_VGA_VSCAN, 806);
+      MM_WRITE(MM_VGA_CLKSEL, 2);
+      break;
+  }
+  if((hres != 0) && (vres != 0)) {
+    MM_WRITE(MM_VGA_HRES, hres);
+    MM_WRITE(MM_VGA_VRES, vres);
+    fb_var.xres = hres;
+    fb_var.yres = vres;
+    memset(framebufferA, 0, hres*vres*2);
+    memset(framebufferB, 0, hres*vres*2);
+    memset(framebufferC, 0, hres*vres*2);
+    MM_WRITE(MM_VGA_BURST_COUNT, hres*vres/16);
+    MM_WRITE(MM_VGA_RESET, 0);
+  } /* otherwise, leave the VGA controller in reset */
+}
 
 rtems_device_driver frame_buffer_initialize(
-rtems_device_major_number  major,
-rtems_device_minor_number  minor,
-void *arg)
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
 {
   rtems_status_code status;
 
-  printk( "frame buffer driver initializing..\n" );
-
+  init_buffers();
   fb_fix.smem_start = (volatile char *)frontbuffer;
+  MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer);
 
-  fb_write(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer);
-  fb_write(MM_VGA_RESET, (unsigned int)0);
-
-  /*
-  * Register the device
-  */
   status = rtems_io_register_name(FRAMEBUFFER_DEVICE_NAME, major, 0);
-  if (status != RTEMS_SUCCESSFUL)
-  {
+  if (status != RTEMS_SUCCESSFUL) {
     printk("Error registering frame buffer device!\n");
     rtems_fatal_error_occurred( status );
   }
 
-  printk("VGA: initialized at resolution %dx%d\n", fb_var.xres, fb_var.yres);
-  printk("VGA: framebuffers at 0x%08x 0x%08x 0x%08x\n",
-  (unsigned int)frontbuffer, (unsigned int)backbuffer,
-  (unsigned int)lastbuffer);
-
-  /*
-  * graphics hardware initialization goes here for non-console
-  * devices
-  */
   return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver frame_buffer_close(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
   void *arg
 )
 {
-  if (pthread_mutex_unlock(&mutex) == 0){
-  /* restore previous state.  for VGA this means return to text mode.
-   * leave out if graphics hardware has been initialized in
-   * frame_buffer_initialize() */
-    fb_write(MM_VGA_RESET, MM_VGA_RESET_MODE);
-    return RTEMS_SUCCESSFUL;
-  }
-  return RTEMS_UNSATISFIED;
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver frame_buffer_open(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
   void *arg
 )
 {
-  if (pthread_mutex_trylock(&mutex) == 0){
-    fb_write(MM_VGA_RESET, (unsigned int)0);
-    return RTEMS_SUCCESSFUL;
-  }
-  return RTEMS_UNSATISFIED;
-}
-
-static void vga_swap_buffers(void)
-{
-  unsigned short int *p;
-
-  /*
-  * Make sure last buffer swap has been executed.
-  * Beware, DMA address registers of vgafb are incomplete
-  * (only LSBs are present) so don't compare them directly
-  * with CPU pointers.
-  */
-  while( fb_read(MM_VGA_BASEADDRESS_ACT) != fb_read(MM_VGA_BASEADDRESS) );
-
-  p = frontbuffer;
-  frontbuffer = backbuffer;
-  backbuffer = lastbuffer;
-  lastbuffer = p;
-
-  fb_fix.smem_start = (volatile char *)backbuffer;
-
-  fb_write(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer);
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver frame_buffer_read(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
 )
 {
   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
-  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
-  memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len)
+    ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy(rw_args->buffer, (const void *)(fb_fix.smem_start + rw_args->offset),
+    rw_args->bytes_moved);
   return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver frame_buffer_write(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
 )
 {
   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
-  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
-  memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
+  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len)
+     ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+  memcpy((void *)(fb_fix.smem_start + rw_args->offset), rw_args->buffer,
+    rw_args->bytes_moved);
   return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver frame_buffer_control(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
 )
 {
   rtems_libio_ioctl_args_t *args = arg;
 
-  switch( args->command ) {
+  switch (args->command) {
     case FBIOGET_FSCREENINFO:
-      args->ioctl_return =  get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
-      break;
+      args->ioctl_return =
+        get_fix_screen_info((struct fb_fix_screeninfo *)args->buffer);
+      return RTEMS_SUCCESSFUL;
     case FBIOGET_VSCREENINFO:
-      args->ioctl_return =  get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
-      break;
-    case FBIOPUT_VSCREENINFO:
-      /* not implemented yet */
-      args->ioctl_return = -1;
-      return RTEMS_UNSATISFIED;
-    case FBIOGETCMAP:
-      /* not implemented yet */
-      args->ioctl_return = -1;
-      return RTEMS_UNSATISFIED;
-      break;
-    case FBIOPUTCMAP:
-      /* not implemented yet */
-      args->ioctl_return = -1;
-      return RTEMS_UNSATISFIED;
-      break;
+      args->ioctl_return =
+        get_var_screen_info((struct fb_var_screeninfo *)args->buffer);
+      return RTEMS_SUCCESSFUL;
     case FBIOSWAPBUFFERS:
-      vga_swap_buffers();
+      swap_buffers();
       args->ioctl_return = 0;
-      break;
+      return RTEMS_SUCCESSFUL;
     case FBIOSETBUFFERMODE:
       args->ioctl_return = 0;
-      switch ( (unsigned int)args->buffer ) {
+      switch ((unsigned int)args->buffer) {
         case FB_SINGLE_BUFFERED:
+          init_buffers();
           fb_fix.smem_start = (volatile char *)frontbuffer;
-          break;
-        case  FB_TRIPLE_BUFFERED:
+          MM_WRITE(MM_VGA_BASEADDRESS, (unsigned int)frontbuffer);
+          return RTEMS_SUCCESSFUL;
+        case FB_TRIPLE_BUFFERED:
           fb_fix.smem_start = (volatile char *)backbuffer;
-          break;
+          return RTEMS_SUCCESSFUL;
         default:
-          printk("[framebuffer] : error no such buffer mode\n");
+          return RTEMS_UNSATISFIED;
       }
-      break;
+    case FBIOSETVIDEOMODE:
+      set_video_mode((int)args->buffer);
+      return RTEMS_SUCCESSFUL;
     default:
-     args->ioctl_return = 0;
-     break;
+      args->ioctl_return = -1;
+      return RTEMS_UNSATISFIED;
   }
-  return RTEMS_SUCCESSFUL;
 }
 

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c	Mon Aug  1 08:48:39 2011
@@ -1,6 +1,6 @@
 /*  gpio.c
  *
- *  This file is the gpio driver for the Milkymist One board
+ *  GPIO driver for the Milkymist One board
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -8,184 +8,114 @@
  *
  *  $Id$
  *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
  *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu> (GSoC 2010)
  *  Telecom SudParis
  */
 
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <pthread.h>
 #include <rtems.h>
+#include <rtems/status-checks.h>
 #include <bsp.h>
-#include "../include/system_conf.h"
 #include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_gpio.h"
 
-#define GPIO_DRIVER_TABLE_ENTRY { gpio_initialize, \
-gpio_open, gpio_close, gpio_read, gpio_write, gpio_control}
-
-#define LED1_DEVICE_NAME  "/dev/led1"
-#define LED2_DEVICE_NAME  "/dev/led2"
-#define BTN1_DEVICE_NAME  "/dev/btn1"
-#define BTN2_DEVICE_NAME  "/dev/btn2"
-#define BTN3_DEVICE_NAME  "/dev/btn3"
-
-static struct milkymist_gpio {
-  rtems_device_minor_number minor;
-  unsigned int *address;
-  unsigned int offset;
-  uint8_t readonly;
-  pthread_mutex_t mutex;
-} gpio[5];
-
-rtems_device_driver gpio_initialize(
-rtems_device_major_number  major,
-rtems_device_minor_number  minor,
-void *arg)
-{
-  rtems_status_code status;
-
-  printk( "gpio driver initializing..\n" );
+struct milkymist_gpio {
+  char *name;
+  unsigned int mask;
+  bool readonly;
+};
 
-  status = rtems_io_register_name(LED1_DEVICE_NAME, major, 0);
-  if (status != RTEMS_SUCCESSFUL)
+static const struct milkymist_gpio gpio[] = {
   {
-    printk("Error registering gpio device led1\n");
-    rtems_fatal_error_occurred( status );
-  }
-  gpio[0].minor = 0;
-  gpio[0].readonly = 0;
-  gpio[0].offset = 0x00000001;
-  gpio[0].address = (unsigned int *)0xe0001004;
-  gpio[0].mutex = PTHREAD_MUTEX_INITIALIZER;
-
-  status = rtems_io_register_name(LED2_DEVICE_NAME, major, 1);
-  if (status != RTEMS_SUCCESSFUL)
+    .name = "/dev/led1",
+    .mask = GPIO_LED1,
+    .readonly = false
+  },
   {
-    printk("Error registering gpio device led2\n");
-    rtems_fatal_error_occurred( status );
-  }
-  gpio[1].minor = 1;
-  gpio[1].readonly = 0;
-  gpio[1].offset = 0x00000002;
-  gpio[1].address = (unsigned int *)0xe0001004;
-  gpio[1].mutex = PTHREAD_MUTEX_INITIALIZER;
+    .name = "/dev/led2",
+    .mask = GPIO_LED2,
+    .readonly = false
+  },
+};
 
-  status = rtems_io_register_name(BTN1_DEVICE_NAME, major, 2);
-  if (status != RTEMS_SUCCESSFUL)
-  {
-    printk("Error registering gpio device btn1\n");
-    rtems_fatal_error_occurred( status );
-  }
-  gpio[2].minor = 2;
-  gpio[2].readonly = 1;
-  gpio[2].offset = 0x00000001;
-  gpio[2].address = (unsigned int *)0xe0001000;
-  gpio[2].mutex = PTHREAD_MUTEX_INITIALIZER;
-  status = rtems_io_register_name(BTN2_DEVICE_NAME, major, 3);
-  if (status != RTEMS_SUCCESSFUL)
-  {
-    printk("Error registering gpio device btn2\n");
-    rtems_fatal_error_occurred( status );
-  }
-  gpio[3].minor = 3;
-  gpio[3].readonly = 1;
-  gpio[3].address = (unsigned int *)0xe0001000;
-  gpio[3].offset = 0x00000002;
-  gpio[3].mutex = PTHREAD_MUTEX_INITIALIZER;
+rtems_device_driver gpio_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  int i;
 
-  status = rtems_io_register_name(BTN3_DEVICE_NAME, major, 4);
-  if (status != RTEMS_SUCCESSFUL)
-  {
-    printk("Error registering gpio device btn3\n");
-    rtems_fatal_error_occurred( status );
+  for (i=0;i<sizeof(gpio)/sizeof(struct milkymist_gpio);i++) {
+    sc = rtems_io_register_name(gpio[i].name, major, i);
+    RTEMS_CHECK_SC(sc, "create GPIO device");
   }
 
-  gpio[4].minor = 4;
-  gpio[4].readonly = 1;
-  gpio[4].offset = 0x00000004;
-  gpio[4].address = (unsigned int *)0xe0001000;
-  gpio[4].mutex = PTHREAD_MUTEX_INITIALIZER;
-
   return RTEMS_SUCCESSFUL;
 }
 
-rtems_device_driver gpio_close(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
+rtems_device_driver gpio_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
   void *arg
 )
 {
-  if (pthread_mutex_unlock(&gpio[minor].mutex) == 0){
-    return RTEMS_SUCCESSFUL;
-  }
-  return RTEMS_UNSATISFIED;
-}
+  unsigned int data;
 
-rtems_device_driver gpio_open(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void *arg
-)
-{
-  if (pthread_mutex_trylock(&gpio[minor].mutex) == 0){
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+
+  if (rw_args->offset > 0) {
+    rw_args->bytes_moved = 0;
     return RTEMS_SUCCESSFUL;
   }
-  return RTEMS_UNSATISFIED;
-}
-
 
-rtems_device_driver gpio_read(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
-)
-{
-  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
   rw_args->bytes_moved = 1;
-  
-  if ( *gpio[minor].address & gpio[minor].offset )
-    *(uint8_t *)rw_args->buffer = 1;
+
+  if (gpio[minor].readonly)
+    data = MM_READ(MM_GPIO_IN);
   else
-    *(uint8_t *)rw_args->buffer = 0;
-  
+    data = MM_READ(MM_GPIO_OUT);
+
+  if (data & gpio[minor].mask)
+    *(uint8_t *)rw_args->buffer = '1';
+  else
+    *(uint8_t *)rw_args->buffer = '0';
+
   return RTEMS_SUCCESSFUL;
 }
 
 rtems_device_driver gpio_write(
   rtems_device_major_number  major,
   rtems_device_minor_number  minor,
-  void                      *arg
+  void *arg
 )
 {
   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
-  rw_args->bytes_moved = 1;
 
-  if (gpio[minor].readonly)
+  if (gpio[minor].readonly) {
+    rw_args->bytes_moved = 0;
     return RTEMS_UNSATISFIED;
+  }
 
-  if ( *(uint8_t *)rw_args->buffer )
-    *gpio[minor].address |= gpio[minor].offset;
-  else
-    *gpio[minor].address &= ~gpio[minor].offset;
+  if (rw_args->offset > 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
 
-  return RTEMS_SUCCESSFUL;
-}
+  rw_args->bytes_moved = 1;
 
-rtems_device_driver gpio_control(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
-)
-{
-  rtems_libio_ioctl_args_t *args = arg;
+  if (*(uint8_t *)rw_args->buffer == '1')
+    MM_WRITE(MM_GPIO_OUT, MM_READ(MM_GPIO_OUT)|gpio[minor].mask);
+  else
+    MM_WRITE(MM_GPIO_OUT, MM_READ(MM_GPIO_OUT) & ~gpio[minor].mask);
 
-  switch( args->command ) {
-    default:
-     args->ioctl_return = 0;
-     break;
-  }
   return RTEMS_SUCCESSFUL;
 }
-

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,46 @@
+/*  milkymist_gpio.h
+ *
+ *  Milkymist GPIO driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_GPIO_H_
+#define __MILKYMIST_GPIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver gpio_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver gpio_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver gpio_write(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+);
+
+#define GPIO_DRIVER_TABLE_ENTRY { gpio_initialize, \
+NULL, NULL, gpio_read, gpio_write, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_GPIO_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c:1.1
--- /dev/null	Mon Aug  1 09:10:27 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,106 @@
+/*  ir.c
+ *
+ *  Milkymist RC5 IR driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <rtems/status-checks.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_ir.h"
+
+#define DEVICE_NAME "/dev/ir"
+
+static rtems_id ir_q;
+
+static rtems_isr interrupt_handler(rtems_vector_number n)
+{
+  unsigned short int msg;
+
+  lm32_interrupt_ack(1 << MM_IRQ_IR);
+  msg = MM_READ(MM_IR_RX);
+  rtems_message_queue_send(ir_q, &msg, 2);
+}
+
+rtems_device_driver ir_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create IR input device");
+
+ sc = rtems_message_queue_create(
+    rtems_build_name('R', 'C', '5', 'Q'),
+    64,
+    2,
+    0,
+    &ir_q
+  );
+  RTEMS_CHECK_SC(sc, "create IR queue");
+
+  rtems_interrupt_catch(interrupt_handler, MM_IRQ_IR, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_IR);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver ir_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  uint32_t count;
+
+  rtems_message_queue_flush(ir_q, &count);
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver ir_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rtems_status_code sc;
+
+  if (rw_args->count < 2) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+
+  sc = rtems_message_queue_receive(
+    ir_q,
+    rw_args->buffer,
+    (size_t *)&rw_args->bytes_moved,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+
+  if(sc == RTEMS_SUCCESSFUL)
+    return RTEMS_SUCCESSFUL;
+  else {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,46 @@
+/*  milkymist_ir.h
+ *
+ *  Milkymist RC5 IR driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_IR_H_
+#define __MILKYMIST_IR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver ir_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver ir_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver ir_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define IR_DRIVER_TABLE_ENTRY {ir_initialize, \
+ir_open, NULL, ir_read, NULL, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_IR_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c	Mon Aug  1 08:48:39 2011
@@ -0,0 +1,370 @@
+/*  memcard.c
+ *
+ *  Milkymist memory card driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/diskdevs.h>
+#include <rtems/blkdev.h>
+#include <rtems/status-checks.h>
+#include <errno.h>
+#include <bsp.h>
+#include "../include/system_conf.h"
+#include "milkymist_memcard.h"
+
+//#define MEMCARD_DEBUG
+
+#define BLOCK_SIZE 512
+
+static void memcard_start_cmd_tx(void)
+{
+  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_TX);
+}
+
+static void memcard_start_cmd_rx(void)
+{
+  MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
+  MM_WRITE(MM_MEMCARD_START, MEMCARD_START_CMD_RX);
+  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_RX);
+}
+
+static void memcard_start_cmd_dat_rx(void)
+{
+  MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX);
+  MM_WRITE(MM_MEMCARD_START, MEMCARD_START_CMD_RX|MEMCARD_START_DAT_RX);
+  MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_CMD_RX|MEMCARD_ENABLE_DAT_RX);
+}
+
+static void memcard_send_command(unsigned char cmd, unsigned int arg)
+{
+  unsigned char packet[6];
+  int a;
+  int i;
+  unsigned char data;
+  unsigned char crc;
+
+  packet[0] = cmd | 0x40;
+  packet[1] = ((arg >> 24) & 0xff);
+  packet[2] = ((arg >> 16) & 0xff);
+  packet[3] = ((arg >> 8) & 0xff);
+  packet[4] = (arg & 0xff);
+
+  crc = 0;
+  for(a=0;a<5;a++) {
+    data = packet[a];
+    for(i=0;i<8;i++) {
+      crc <<= 1;
+      if((data & 0x80) ^ (crc & 0x80))
+        crc ^= 0x09;
+      data <<= 1;
+    }
+  }
+  crc = (crc<<1) | 1;
+
+  packet[5] = crc;
+
+#ifdef MEMCARD_DEBUG
+  printk(">> %02x %02x %02x %02x %02x %02x\n",
+    packet[0], packet[1], packet[2], packet[3], packet[4], packet[5]);
+#endif
+
+  for(i=0;i<6;i++) {
+    MM_WRITE(MM_MEMCARD_CMD, packet[i]);
+    while(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_TX);
+  }
+}
+
+static void memcard_send_dummy(void)
+{
+  MM_WRITE(MM_MEMCARD_CMD, 0xff);
+  while(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_TX);
+}
+
+static bool memcard_receive_command(unsigned char *buffer, int len)
+{
+  int i;
+  int timeout;
+
+  for(i=0;i<len;i++) {
+    timeout = 2000000;
+    while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX)) {
+      timeout--;
+      if(timeout == 0) {
+        #ifdef MEMCARD_DEBUG
+        printk("Command receive timeout\n");
+        #endif
+        return false;
+      }
+    }
+    buffer[i] = MM_READ(MM_MEMCARD_CMD);
+    MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
+  }
+
+  while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX));
+
+  #ifdef MEMCARD_DEBUG
+  printk("<< ");
+  for(i=0;i<len;i++)
+    printk("%02x ", buffer[i]);
+  printk("\n");
+  #endif
+
+  return true;
+}
+
+static bool memcard_receive_command_data(unsigned char *command,
+  unsigned int *data)
+{
+  int i, j;
+  int timeout;
+
+  i = 0;
+  j = 0;
+  while(j < 128) {
+    timeout = 2000000;
+    while(!(MM_READ(MM_MEMCARD_PENDING) &
+      (MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX))) {
+      timeout--;
+      if(timeout == 0) {
+        #ifdef MEMCARD_DEBUG
+        printk("Command receive timeout\n");
+        #endif
+        return false;
+      }
+    }
+    if(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_CMD_RX) {
+      command[i++] = MM_READ(MM_MEMCARD_CMD);
+      MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_CMD_RX);
+      if(i == 6)
+        /* disable command RX */
+        MM_WRITE(MM_MEMCARD_ENABLE, MEMCARD_ENABLE_DAT_RX);
+    }
+    if(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX) {
+      data[j++] = MM_READ(MM_MEMCARD_DAT);
+      MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_DAT_RX);
+    }
+  }
+
+  /* Get CRC (ignored) */
+  for(i=0;i<2;i++) {
+    while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX));
+    #ifdef MEMCARD_DEBUG
+    printk("CRC: %08x\n", MM_READ(MM_MEMCARD_DAT));
+    #endif
+    MM_WRITE(MM_MEMCARD_PENDING, MEMCARD_PENDING_DAT_RX);
+  }
+
+  while(!(MM_READ(MM_MEMCARD_PENDING) & MEMCARD_PENDING_DAT_RX));
+
+  #ifdef MEMCARD_DEBUG
+  printk("<< %02x %02x %02x %02x %02x %02x\n",
+    command[0], command[1], command[2], command[3], command[4], command[5]);
+  #endif
+
+  //for(i=0;i<128;i++)
+  //  printk("%08x ", data[i]);
+  //printk("\n");
+
+  return true;
+}
+
+static unsigned int block_count;
+
+static int memcard_disk_block_read(rtems_blkdev_request *r)
+{
+  unsigned char b[6];
+  unsigned int i, nblocks;
+  unsigned int block;
+
+  block = RTEMS_BLKDEV_START_BLOCK(r);
+  nblocks = r->bufnum;
+
+  for(i=0;i<nblocks;i++) {
+    /* CMD17 - read block */
+    memcard_start_cmd_tx();
+    memcard_send_command(17, (block+i)*BLOCK_SIZE);
+    memcard_start_cmd_dat_rx();
+    if(!memcard_receive_command_data(b, (unsigned int *)r->bufs[i].buffer))
+      return -RTEMS_IO_ERROR;
+  }
+
+  r->req_done(r->done_arg, RTEMS_SUCCESSFUL);
+
+  return 0;
+}
+
+static int memcard_disk_block_write(rtems_blkdev_request *r)
+{
+  return -RTEMS_IO_ERROR;
+}
+
+static rtems_status_code memcard_init(void)
+{
+  unsigned char b[17];
+  unsigned int rca;
+  unsigned int block_shift;
+  unsigned int c_size;
+  unsigned int c_size_mult;
+
+  MM_WRITE(MM_MEMCARD_CLK2XDIV, 250);
+
+  /* CMD0 */
+  memcard_start_cmd_tx();
+  memcard_send_command(0, 0);
+
+  memcard_send_dummy();
+
+  /* CMD8 */
+  memcard_send_command(8, 0x1aa);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+
+  /* ACMD41 - initialize */
+  while(1) {
+    memcard_start_cmd_tx();
+    memcard_send_command(55, 0);
+    memcard_start_cmd_rx();
+    if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+    memcard_start_cmd_tx();
+    memcard_send_command(41, 0x00300000);
+    memcard_start_cmd_rx();
+    if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+    if(b[1] & 0x80) break;
+    #ifdef MEMCARD_DEBUG
+    printk("Card is busy, retrying\n");
+    #endif
+  }
+
+  /* CMD2 - get CID */
+  memcard_start_cmd_tx();
+  memcard_send_command(2, 0);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 17)) return RTEMS_IO_ERROR;
+
+  /* CMD3 - get RCA */
+  memcard_start_cmd_tx();
+  memcard_send_command(3, 0);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+  rca = (((unsigned int)b[1]) << 8)|((unsigned int)b[2]);
+  #ifdef MEMCARD_DEBUG
+  printk("RCA: %04x\n", rca);
+  #endif
+
+  /* CMD9 - get CSD */
+  memcard_start_cmd_tx();
+  memcard_send_command(9, rca << 16);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 17)) return RTEMS_IO_ERROR;
+
+  if(((b)[0] >> 6) != 0)
+    return RTEMS_IO_ERROR;
+
+  block_shift = ((unsigned int)(b)[5] & 0xf);
+  c_size = ((((unsigned int)(b)[6] & 0x3) << 10)
+    + (((unsigned int)(b)[7]) << 2)
+    + ((((unsigned int)(b)[8]) >> 6) & 0x3));
+  c_size_mult = ((((b)[9] & 0x3) << 1) + (((b)[10] >> 7) & 0x1));
+  block_count = (c_size + 1) * (1U << (c_size_mult + 2));
+
+  /* convert to 512-byte blocks for the sake of simplicity */
+  if(block_shift < 9)
+    return RTEMS_IO_ERROR;
+  block_count <<= block_shift - 9;
+
+  /* CMD7 - select card */
+  memcard_start_cmd_tx();
+  memcard_send_command(7, rca << 16);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+
+  /* ACMD6 - set bus width */
+  memcard_start_cmd_tx();
+  memcard_send_command(55, rca << 16);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+  memcard_start_cmd_tx();
+  memcard_send_command(6, 2);
+  memcard_start_cmd_rx();
+  if(!memcard_receive_command(b, 6)) return RTEMS_IO_ERROR;
+
+  MM_WRITE(MM_MEMCARD_CLK2XDIV, 3);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static int memcard_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
+{
+  if (req == RTEMS_BLKIO_REQUEST) {
+    rtems_blkdev_request *r = (rtems_blkdev_request *)arg;
+    switch (r->req) {
+      case RTEMS_BLKDEV_REQ_READ:
+        return memcard_disk_block_read(r);
+      case RTEMS_BLKDEV_REQ_WRITE:
+        return memcard_disk_block_write(r);
+      default:
+        errno = EINVAL;
+        return -1;
+    }
+  } else if (req == RTEMS_BLKIO_CAPABILITIES) {
+    *(uint32_t *)arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
+    return 0;
+  } else {
+    errno = EINVAL;
+    return -1;
+  }
+}
+
+static rtems_status_code memcard_disk_init(
+  rtems_device_major_number major, rtems_device_minor_number minor,
+  void *arg)
+{
+  rtems_status_code sc;
+  dev_t dev;
+
+  sc = rtems_disk_io_initialize();
+  RTEMS_CHECK_SC(sc, "Initialize RTEMS disk IO");
+
+  dev = rtems_filesystem_make_dev_t(major, 0);
+
+  sc = memcard_init();
+  RTEMS_CHECK_SC(sc, "Initialize memory card");
+
+  sc = rtems_disk_create_phys(dev, BLOCK_SIZE, block_count, memcard_disk_ioctl,
+    NULL, "/dev/memcard");
+  RTEMS_CHECK_SC(sc, "Create disk device");
+
+  return RTEMS_SUCCESSFUL;
+}
+
+
+static const rtems_driver_address_table memcard_disk_ops = {
+  .initialization_entry = memcard_disk_init,
+  .open_entry = rtems_blkdev_generic_open,
+  .close_entry = rtems_blkdev_generic_close,
+  .read_entry = rtems_blkdev_generic_read,
+  .write_entry = rtems_blkdev_generic_write,
+  .control_entry = rtems_blkdev_generic_ioctl
+};
+
+rtems_status_code memcard_register(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_device_major_number major = 0;
+
+  sc = rtems_io_register_driver(0, &memcard_disk_ops, &major);
+  RTEMS_CHECK_SC(sc, "Register disk memory card driver");
+
+  return RTEMS_SUCCESSFUL;
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,19 @@
+/*  milkymist_memcard.h
+ *
+ *  Milkymist memory card driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_MEMCARD_H_
+#define __MILKYMIST_MEMCARD_H_
+
+rtems_status_code memcard_register(void);
+
+#endif /* __MILKYMIST_MEMCARD_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,104 @@
+/*  midi.c
+ *
+ *  Milkymist MIDI driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <rtems/status-checks.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_midi.h"
+
+#define DEVICE_NAME "/dev/midi"
+
+static rtems_id midi_q;
+
+static rtems_isr interrupt_handler(rtems_vector_number n)
+{
+  unsigned char msg;
+
+  lm32_interrupt_ack(1 << MM_IRQ_MIDIRX);
+  msg = MM_READ(MM_MIDI_RXTX);
+  rtems_message_queue_send(midi_q, &msg, 1);
+}
+
+rtems_device_driver midi_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create MIDI input device");
+
+ sc = rtems_message_queue_create(
+    rtems_build_name('M', 'I', 'D', 'I'),
+    64,
+    1,
+    0,
+    &midi_q
+  );
+  RTEMS_CHECK_SC(sc, "create MIDI queue");
+
+  rtems_interrupt_catch(interrupt_handler, MM_IRQ_MIDIRX, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_MIDIRX);
+
+  /* Only MIDI THRU mode is supported atm */
+  MM_WRITE(MM_MIDI_THRU, 1);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver midi_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  uint32_t count;
+
+  rtems_message_queue_flush(midi_q, &count);
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver midi_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rtems_status_code sc;
+
+  sc = rtems_message_queue_receive(
+    midi_q,
+    rw_args->buffer,
+    (size_t *)&rw_args->bytes_moved,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+
+  if(sc == RTEMS_SUCCESSFUL)
+    return RTEMS_SUCCESSFUL;
+  else {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,46 @@
+/*  milkymist_midi.h
+ *
+ *  Milkymist MIDI driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_MIDI_H_
+#define __MILKYMIST_MIDI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver midi_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver midi_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver midi_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define MIDI_DRIVER_TABLE_ENTRY {midi_initialize, \
+midi_open, NULL, midi_read, NULL, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_MIDI_H_ */

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h:1.1 rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h:1.1	Fri Aug 20 16:23:27 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h	Mon Aug  1 08:48:40 2011
@@ -13,68 +13,9 @@
  */
 
 
-#ifndef _MM_NETWORKING_H_
-#define _MM_NETWORKING_H_
-
-#include "../include/system_conf.h"
-
-#define IRQ_ETHRX 11
-#define IRQ_ETHTX 12
-
-#define INTERRUPT_EVENT RTEMS_EVENT_1
-#define START_TRANSMIT_EVENT  RTEMS_EVENT_2
-
-#define MINIMAC_STATE_EMPTY (0x0)
-#define MINIMAC_STATE_LOADED  (0x1)
-#define MINIMAC_STATE_PENDING (0x2)
-
-#define MINIMAC_SETUP_RXRST (0x1)
-#define MINIMAC_SETUP_TXRST (0x2)
-
-#define NB_RX_SLOTS 4
-
-#define MM_ETHTX_IRQMASK  (1 << IRQ_ETHTX)
-#define MM_ETHRX_IRQMASK  (1 << IRQ_ETHRX)
-#define ETHERNET_FRAME_LENGTH 1532
-
-struct mm_packet {
-  unsigned char preamble[8];
-  char raw_data[MLEN];
-} __attribute__((aligned(4), packed));
-
-struct minimac_softc {
-
-  struct arpcom arpcom;
-  uint8_t registered;
-
-  /*
-   *  Statistics
-   */
-
-  rtems_id  rxDaemonTid;
-  rtems_id  txDaemonTid;
-
-  unsigned long int rxInterrupts;
-  unsigned long int txInterrupts;
-  unsigned long int rxedPackets;
-  unsigned long int txFifoFull;
-  unsigned long int txErrors;
-};
+#ifndef __MILKYMIST_NETWORKING_H_
+#define __MILKYMIST_NETWORKING_H_
 
 int rtems_minimac_driver_attach (struct rtems_bsdnet_ifconfig *, int);
 
-static void minimac_start(struct ifnet *);
-static void minimac_init(void *);
-static int minimac_ioctl(struct ifnet *, ioctl_command_t, caddr_t);
-static void minimac_stop(struct minimac_softc *);
-
-static void minimac_txDaemon(void *);
-static void minimac_rxDaemon(void *);
-static void minimac_sendpacket(struct ifnet *, struct mbuf *);
-
-static rtems_isr minimac_rx_interrupt_handler (rtems_vector_number);
-static rtems_isr minimac_tx_interrupt_handler (rtems_vector_number);
-
-static void minimac_stats(struct minimac_softc *);
-
 #endif

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c:1.2 rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c:1.3
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c:1.2	Fri Feb 11 06:13:12 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c	Mon Aug  1 08:48:40 2011
@@ -1,5 +1,5 @@
 /*
- *  RTEMS driver for Minimac ethernet IP-core of Milkymist SoC
+ *  RTEMS driver for Minimac2 ethernet IP-core of Milkymist SoC
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -9,121 +9,94 @@
  *
  *  COPYRIGHT (c) Yann Sionneau <yann.sionneau at telecom-sudparis.eu> (GSoC 2010)
  *  Telecom SudParis, France
+ *  Copyright (C) 2011 Sebastien Bourdeauducq
  */
 
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
 
 #include <bsp.h>
-#include "../include/system_conf.h"
-#include "bspopts.h"
+#include <bsp/irq-generic.h>
 #include <stdio.h>
+#include <string.h>
 #include <rtems/rtems_bsdnet.h>
+#include <rtems/status-checks.h>
 #include <sys/param.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <net/if.h>
+#include <net/ethernet.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <rtems.h>
+#include "bspopts.h"
+#include "../include/system_conf.h"
 #include "network.h"
 
-unsigned int mm_ether_crc32(const unsigned char *buffer, unsigned int len);
-static char rxbuff0[ETHERNET_FRAME_LENGTH] __attribute__((aligned (4)));
-static char rxbuff1[ETHERNET_FRAME_LENGTH] __attribute__((aligned (4)));
-static char rxbuff2[ETHERNET_FRAME_LENGTH] __attribute__((aligned (4)));
-static char rxbuff3[ETHERNET_FRAME_LENGTH] __attribute__((aligned (4)));
-
-static char *rxbuffs[4] = {rxbuff0, rxbuff1, rxbuff2, rxbuff3};
-
-static struct minimac_softc minimac_softc;
-
-static uint32_t rx_slot_state[4] = {MM_MINIMAC_STATE0, MM_MINIMAC_STATE1,
-                            MM_MINIMAC_STATE2, MM_MINIMAC_STATE3};
-
-static uint32_t rx_slot_addr[4] = {MM_MINIMAC_ADDR0, MM_MINIMAC_ADDR1,
-                            MM_MINIMAC_ADDR2, MM_MINIMAC_ADDR3};
-
-static uint32_t rx_slot_count[4] = {MM_MINIMAC_COUNT0, MM_MINIMAC_COUNT1,
-                            MM_MINIMAC_COUNT2, MM_MINIMAC_COUNT3};
-#ifdef CPU_U32_FIX
-
-/*
- * Routine to align the received packet so that the ip header
- * is on a 32-bit boundary. Necessary for cpu's that do not
- * allow unaligned loads and stores and when the 32-bit DMA
- * mode is used.
- *
- * Transfers are done on word basis to avoid possibly slow byte
- * and half-word writes.
- *
- * Copied over from sonic.c driver
- */
-
-void ipalign(struct mbuf *m)
-{
-  unsigned int *first, *last, data;
-  unsigned int tmp = 0;
-
-  if ((((int) m->m_data) & 2) && (m->m_len)) {
-    last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
-    first = (unsigned int *) (((int) m->m_data) & ~3);
-    tmp = *first << 16;
-    first++;
-    do {
-      data = *first;
-      *first = tmp | (data >> 16);
-      tmp = data << 16;
-      first++;
-    } while (first <= last);
+#define CTS_EVENT             RTEMS_EVENT_1
+#define RX_EVENT              RTEMS_EVENT_1
+#define START_TRANSMIT_EVENT  RTEMS_EVENT_2
+
+static struct arpcom arpcom;
+static rtems_id rx_daemon_id;
+static rtems_id tx_daemon_id;
+
+static void minimac_init(void *arg);
+static int minimac_ioctl(struct ifnet *ifp, ioctl_command_t command,
+  caddr_t data);
+static void minimac_start(struct ifnet *ifp);
+
+static void rx_daemon(void *arg);
+static void tx_daemon(void *arg);
+static rtems_isr rx_interrupt_handler(rtems_vector_number vector);
+static rtems_isr tx_interrupt_handler(rtems_vector_number vector);
 
-    m->m_data = (caddr_t)(((int) m->m_data) + 2);
-  }
-}
-#endif
-
-static inline int minimac_read(unsigned int reg)
+static bool validate_mac(const char *m)
 {
-  return *((int*)(reg));
+  int i;
+  
+  for(i=0;i<6;i++)
+    if((m[i] != 0x00) && (m[i] != 0xff))
+      return true;
+  return false;
 }
 
-static inline void minimac_write(unsigned int reg, int value)
+static const char *get_mac_address(void)
 {
-  *((int*)reg) = value;
+  const char *flash_mac = (const char *)FLASH_OFFSET_MAC_ADDRESS;
+  static const char fallback_mac[6] = { 0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00 };
+  
+  if(validate_mac(flash_mac))
+    return flash_mac;
+  else {
+    printk("Warning: using fallback MAC address\n");
+    return fallback_mac;
+  }
 }
 
-int rtems_minimac_driver_attach (struct rtems_bsdnet_ifconfig *config, 
+int rtems_minimac_driver_attach(struct rtems_bsdnet_ifconfig *config,
   int attaching)
 {
-  struct minimac_softc *sc;
   struct ifnet *ifp;
-  
+  rtems_isr_entry dummy;
+  int i;
+  static int registered;
+  uint8_t *tx_buffer = (uint8_t *)MINIMAC_TX_BASE;
 
-  if (!attaching) {
-    printk ("MINIMAC driver cannot be detached.\n");
+  if(!attaching) {
+    printk("Minimac driver cannot be detached.\n");
     return 0;
   }
 
-  sc = &minimac_softc;
-  ifp = &(sc->arpcom.ac_if);
+  ifp = &(arpcom.ac_if);
 
-  if (sc->registered) {
-    printk ("Driver already in use.\n");
+  if(registered) {
+    printk("Minimac driver already in use.\n");
     return 0;
   }
+  registered = 1;
 
-  sc->registered = 1;
-
-  /*
-   *  Mac address of Milkymist One board is 1 by default
-   */
-
-  sc->arpcom.ac_enaddr[0] = 0x00;
-  sc->arpcom.ac_enaddr[1] = 0x23;
-  sc->arpcom.ac_enaddr[2] = 0x8b;
-  sc->arpcom.ac_enaddr[3] = 0x47;
-  sc->arpcom.ac_enaddr[4] = 0x86;
-  sc->arpcom.ac_enaddr[5] = 0x20;
-  ifp->if_softc = sc;
+  memcpy(arpcom.ac_enaddr, get_mac_address(), 6);
   ifp->if_mtu = ETHERMTU;
   ifp->if_unit = 0;
   ifp->if_name = "minimac";
@@ -134,268 +107,213 @@
   ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
   ifp->if_snd.ifq_maxlen = ifqmaxlen;
 
-  if_attach (ifp);
+  if_attach(ifp);
   ether_ifattach(ifp);
-  printk("[minimac] Ethernet driver attached\n");
+
+  rx_daemon_id = rtems_bsdnet_newproc("mrxd", 4096, rx_daemon, NULL);
+  tx_daemon_id = rtems_bsdnet_newproc("mtxd", 4096, tx_daemon, NULL);
+  rtems_interrupt_catch(rx_interrupt_handler, MM_IRQ_ETHRX, &dummy);
+  rtems_interrupt_catch(tx_interrupt_handler, MM_IRQ_ETHTX, &dummy);
+  
+  MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_LOADED);
+  MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_LOADED);
+
+  for(i=0;i<7; i++)
+    tx_buffer[i] = 0x55;
+  tx_buffer[7] = 0xd5;
+  MM_WRITE(MM_MINIMAC_SETUP, 0);
+  rtems_event_send(tx_daemon_id, CTS_EVENT);
+  
+  bsp_interrupt_vector_enable(MM_IRQ_ETHRX);
+  bsp_interrupt_vector_enable(MM_IRQ_ETHTX);
+
   return 1;
 }
 
 static void minimac_start(struct ifnet *ifp)
 {
-  struct minimac_softc *sc = ifp->if_softc;
-  rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
+  rtems_event_send(tx_daemon_id, START_TRANSMIT_EVENT);
   ifp->if_flags |= IFF_OACTIVE;
-//  printk("[minimac] start();\n");
 }
 
-/*
- *  Initialize and start the device
- */
-static void minimac_init (void *arg)
+static void minimac_init(void *arg)
 {
-  struct minimac_softc *sc = arg;
-  struct ifnet *ifp = &sc->arpcom.ac_if;
-  unsigned char j;
-  if (sc->txDaemonTid == 0) {
-    sc->txDaemonTid = rtems_bsdnet_newproc ("MINIMACtx", 4096, minimac_txDaemon, sc);
-    sc->rxDaemonTid = rtems_bsdnet_newproc ("MINIMACrx", 4096, minimac_rxDaemon, sc);
-    set_vector(minimac_rx_interrupt_handler, IRQ_ETHRX, 1);
-    set_vector(minimac_tx_interrupt_handler, IRQ_ETHTX, 1);
-    lm32_interrupt_unmask(MM_ETHRX_IRQMASK);
-    lm32_interrupt_unmask(MM_ETHTX_IRQMASK);
-  }
- 
-  /*   
-   *  Tell the world that we're running.
-   */
+  struct ifnet *ifp = &arpcom.ac_if;
   ifp->if_flags |= IFF_RUNNING;
+}
 
-  /*
-   *  Start the receiver and transmitter
-   */
-
-  lm32_interrupt_ack( MM_ETHTX_IRQMASK | MM_ETHRX_IRQMASK );
-  minimac_write(MM_MINIMAC_TXREMAINING, 0);
+static void minimac_stop(void)
+{
+  struct ifnet *ifp = &arpcom.ac_if;
+  ifp->if_flags &= ~IFF_RUNNING;
+}
 
-  for (j = 0 ; j < NB_RX_SLOTS ; j++) {
-    minimac_write(rx_slot_addr[j], (unsigned int)rxbuffs[j]);
-    minimac_write(rx_slot_state[j], MINIMAC_STATE_LOADED);
-  }
+static int minimac_ioctl(struct ifnet *ifp, ioctl_command_t command,
+  caddr_t data)
+{
+  int error;
   
+  error = 0;
+  switch (command) {
+    case SIOCGIFADDR:
+    case SIOCSIFADDR:
+      ether_ioctl(ifp, command, data);
+      break;
+
+    case SIOCSIFFLAGS:
+      switch(ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+        case IFF_RUNNING:
+          minimac_stop();
+          break;
+        case IFF_UP:
+          minimac_init(NULL);
+          break;
+        case IFF_UP | IFF_RUNNING:
+          minimac_stop();
+          minimac_init(NULL);
+          break;
+        default:
+          break;
+      }
+      break;
 
-  minimac_write(MM_MINIMAC_SETUP, 0);
-  rtems_event_send(sc->rxDaemonTid, INTERRUPT_EVENT);
+    default:
+      error = EINVAL;
+      break;
+  }
+  return error;
 }
 
-static void minimac_stop (struct minimac_softc *sc)
-{
-  struct ifnet *ifp = &sc->arpcom.ac_if;
-  unsigned char j;
-  ifp->if_flags &= ~IFF_RUNNING;
 
-  /*
-   *  Shuts down receiver and transmitter
+static rtems_isr rx_interrupt_handler(rtems_vector_number vector)
+{
+  /* Deassert IRQ line.
+   * The RX daemon will then read all the slots we marked as empty.
    */
-  for (j = 0 ; j < NB_RX_SLOTS ; j++)
-    minimac_write(rx_slot_state[j], MINIMAC_STATE_EMPTY);
-  minimac_write(MM_MINIMAC_TXREMAINING, 0);
-  minimac_write(MM_MINIMAC_SETUP, MINIMAC_SETUP_RXRST | MINIMAC_SETUP_TXRST);
-}
-
-static int minimac_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
-{
-
-        struct minimac_softc *sc = ifp->if_softc;
-        int error = 0; 
-        switch (command) {
-        case SIOCGIFADDR:
-        case SIOCSIFADDR:
-                ether_ioctl (ifp, command, data);
-                break;
-
-        case SIOCSIFFLAGS:
-                switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
-                case IFF_RUNNING:
-                        minimac_stop (sc);
-                        break;
-
-                case IFF_UP:
-                        minimac_init (sc);
-                        break;
-
-                case IFF_UP | IFF_RUNNING:
-                        minimac_stop (sc);
-                        minimac_init (sc);
-                        break;
-
-                default:
-                        break;
-                }    
-                break;
-
-        case SIO_RTEMS_SHOW_STATS:
-                minimac_stats (sc);
-                break;
-  
-        /*
-         * FIXME: All sorts of multicast commands need to be added here!
-         */
-        default:
-                error = EINVAL;
-                break;
-        }
-        return error;
+  if(MM_READ(MM_MINIMAC_STATE0) == MINIMAC_STATE_PENDING)
+    MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_EMPTY);
+  if(MM_READ(MM_MINIMAC_STATE1) == MINIMAC_STATE_PENDING)
+    MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_EMPTY);
 
+  rtems_event_send(rx_daemon_id, RX_EVENT);
 
+  lm32_interrupt_ack(1 << MM_IRQ_ETHRX);
 }
 
-rtems_isr minimac_rx_interrupt_handler(rtems_vector_number vector)
+static void receive_packet(uint8_t *buffer, int length)
 {
-  unsigned int ip;
-  struct minimac_softc *sc = &minimac_softc;
-  lm32_read_interrupts(ip);
-  if (ip & MM_ETHRX_IRQMASK) {
-    lm32_interrupt_mask(MM_ETHRX_IRQMASK);
-    rtems_event_send(sc->rxDaemonTid, INTERRUPT_EVENT);
-    sc->rxInterrupts++; // update stats
+  struct ifnet *ifp = &arpcom.ac_if;
+  struct mbuf *m;
+  struct ether_header *eh;
+  uint32_t computed_crc, net_crc;
+  
+  if(length < 64) {
+    printk("Warning: Ethernet packet too short\n");
+    return;
   }
+
+  length -= 4; /* strip CRC */
+  net_crc = ((uint32_t)buffer[length])
+    | ((uint32_t)buffer[length+1] << 8)
+    | ((uint32_t)buffer[length+2] << 16)
+    | ((uint32_t)buffer[length+3] << 24);
+  length -= 8; /* strip preamble */
+  computed_crc = ether_crc32_le(&buffer[8], length) ^ 0xffffffff;
+  if(computed_crc == net_crc) {
+    MGETHDR(m, M_WAIT, MT_DATA);
+    MCLGET(m, M_WAIT);
+    length -= sizeof(struct ether_header); /* strip Ethernet header */
+    memcpy(m->m_data, &buffer[8+sizeof(struct ether_header)], length);
+    m->m_len = m->m_pkthdr.len = length;
+    m->m_pkthdr.rcvif = ifp;
+    eh = (struct ether_header *)&buffer[8];
+    ether_input(ifp, eh, m);
+  } else
+    printk("Ethernet CRC error: got %08x expected %08x (len=%d)\n",
+      net_crc, computed_crc, length);
 }
 
-rtems_isr minimac_tx_interrupt_handler(rtems_vector_number vector)
+static void rx_daemon(void *arg)
 {
-  int ip;
-  struct minimac_softc *sc = &minimac_softc;
-  lm32_read_interrupts(ip);
-  if (ip & MM_ETHTX_IRQMASK) {
-    lm32_interrupt_ack(MM_ETHTX_IRQMASK);
-    rtems_event_send(sc->txDaemonTid, INTERRUPT_EVENT);
-    sc->txInterrupts++; // update stats
+  rtems_event_set events;
+  
+  while(1) {
+    rtems_bsdnet_event_receive(RX_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT,
+      RTEMS_NO_TIMEOUT, &events);
+
+    if(MM_READ(MM_MINIMAC_STATE0) == MINIMAC_STATE_EMPTY) {
+      receive_packet((uint8_t *)MINIMAC_RX0_BASE, MM_READ(MM_MINIMAC_COUNT0));
+      MM_WRITE(MM_MINIMAC_STATE0, MINIMAC_STATE_LOADED);
+    }
+    if(MM_READ(MM_MINIMAC_STATE1) == MINIMAC_STATE_EMPTY) {
+      receive_packet((uint8_t *)MINIMAC_RX1_BASE, MM_READ(MM_MINIMAC_COUNT1));
+      MM_WRITE(MM_MINIMAC_STATE1, MINIMAC_STATE_LOADED);
+    }
   }
 }
 
-
-static void minimac_rxDaemon(void *arg)
+/* RTEMS apparently doesn't support m_length() ... */
+static int copy_mbuf_chain(struct mbuf *m, uint8_t *target)
 {
-  struct ifnet *ifp = &minimac_softc.arpcom.ac_if;
-  rtems_event_set events;
-  struct minimac_softc *sc = &minimac_softc;
-  for (;;) {
-    uint32_t *buf;
-    int rxlen;
-    uint8_t j;
-    struct mbuf *m;
-    struct ether_header *eh;
-    rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
-    RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events);
-    if(minimac_read(MM_MINIMAC_SETUP) & MINIMAC_SETUP_RXRST ) {
-      printk("Minimac RX FIFO overflow!\n");
-      minimac_write(MM_MINIMAC_SETUP, 0);
-      lm32_interrupt_ack(MM_ETHRX_IRQMASK);
-      lm32_interrupt_unmask(MM_ETHRX_IRQMASK);
-      sc->txFifoFull++; // update stats
-    }
+  int len;
 
-    for (j = 0 ; j < NB_RX_SLOTS ; j++) {
-      if (minimac_read(rx_slot_state[j]) == MINIMAC_STATE_PENDING) {
-        __asm__ volatile( /* Invalidate Level-1 data cache */
-          "wcsr DCC, r0\n"
-          "nop\n"
-        );
-        rxlen = minimac_read(rx_slot_count[j]);
-        rxlen -= 8; // we drop the preamble
-        MGETHDR(m, M_WAIT, MT_DATA);
-        MCLGET(m, M_WAIT);
-        m->m_pkthdr.rcvif = ifp;
-        buf = (uint32_t *) mtod(m, uint32_t*);
-        memcpy(buf, (uint8_t *)minimac_read(rx_slot_addr[j]) + 8, rxlen);
-        m->m_len = m->m_pkthdr.len = rxlen - sizeof(uint32_t) - sizeof(struct ether_header);
-
-        minimac_write(rx_slot_state[j], MINIMAC_STATE_EMPTY);
-        minimac_write(rx_slot_state[j], MINIMAC_STATE_LOADED);
-        eh = mtod(m, struct ether_header*);
-        m->m_data += sizeof(struct ether_header);
-#ifdef  CPU_U32_FIX
-        ipalign(m);
-#endif
-        ether_input(ifp, eh, m);
-      }
+  len = 0;
+  while(m != NULL) {
+    if(m->m_len > 0) {
+      m_copydata(m, 0, m->m_len, (caddr_t)(target + len));
+      len += m->m_len;
     }
-    lm32_interrupt_ack(MM_ETHRX_IRQMASK); // we ack once for all the rx interruptions
-    lm32_interrupt_unmask(MM_ETHRX_IRQMASK);
+    m = m->m_next;
   }
+  return len;
 }
-static void minimac_txDaemon(void *arg)
+
+static void send_packet(struct ifnet *ifp, struct mbuf *m)
 {
-  struct ifnet *ifp = &minimac_softc.arpcom.ac_if;
-  rtems_event_set events;
-  struct mbuf *m;
-  int txq;
+  unsigned int len;
+  unsigned int crc;
+  uint8_t *tx_buffer = (uint8_t *)(MINIMAC_TX_BASE+8);
+  
+  len = copy_mbuf_chain(m, tx_buffer);
+  for(;len<60;len++)
+    tx_buffer[len] = 0x00; // Padding
 
-  for (;;) {
-    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
-    for (;;) {
-      txq = 2048;
+  crc = ether_crc32_le(tx_buffer, len) ^ 0xffffffff;
 
-      if (txq < ifp->if_mtu)
-        break;
+  tx_buffer[len] = crc & 0xff;
+  tx_buffer[len+1] = (crc & 0xff00) >> 8;
+  tx_buffer[len+2] = (crc & 0xff0000) >> 16;
+  tx_buffer[len+3] = crc >> 24;
 
-      IF_DEQUEUE(&ifp->if_snd, m);
+  len += 4; // We add 4 bytes of CRC32
 
-      if (!m)
-        break;
-      minimac_sendpacket(ifp, m);
-      m_freem(m);
-    }
-  ifp->if_flags &= ~IFF_OACTIVE;
-  }
+  MM_WRITE(MM_MINIMAC_TXCOUNT, len + 8);
 }
 
-static void minimac_stats(struct minimac_softc *sc)
+static rtems_isr tx_interrupt_handler(rtems_vector_number vector)
 {
-
+  lm32_interrupt_ack(1 << MM_IRQ_ETHTX);
+  rtems_event_send(tx_daemon_id, CTS_EVENT);
 }
 
-
-static void minimac_sendpacket(struct ifnet *ifp, struct mbuf *m)
+static void tx_daemon(void *arg)
 {
-  struct mbuf *nm = m;
-  struct minimac_softc *sc = &minimac_softc;
-  unsigned int len = 0;
-  struct mm_packet p;
-  unsigned int crc;
-  uint8_t i;
-  for (i = 0 ; i < 7 ; i++) // Preamble
-    p.preamble[i] = 0x55;
-  p.preamble[7] = 0xd5;
+  struct ifnet *ifp = &arpcom.ac_if;
+  rtems_event_set events;
+  struct mbuf *m;
   
-  do
-    {
-      unsigned int mlen;
-      mlen = nm->m_len;
-      if (nm->m_len > 0) {
-        m_copydata(nm, 0, mlen, p.raw_data + len);
-        len += nm->m_len;
-      }
-
-    } while ( (nm = nm->m_next) != 0 );
-    for ( ; len < 60 ; len++)
-      p.raw_data[len] = 0x00; // Padding
-
-    crc = mm_ether_crc32((uint8_t *)p.raw_data, len); // CRC32
-
-    p.raw_data[len] = crc & 0xff;
-    p.raw_data[len+1] = (crc & 0xff00) >> 8;
-    p.raw_data[len+2] = (crc & 0xff0000) >> 16;
-    p.raw_data[len+3] = crc >> 24;
-    
-    len += 4; // We add 4 bytes of CRC32
-
-    if (len + 8 < 64) {
-      printk("[minimac] Packet is too small !\n");
-      sc->txErrors++; // update stats
-      return;
+  while(1) {
+    rtems_bsdnet_event_receive(START_TRANSMIT_EVENT,
+      RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
+    while(1) {
+      IF_DEQUEUE(&ifp->if_snd, m);
+      if(m == NULL)
+        break;
+      rtems_bsdnet_event_receive(CTS_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT,
+        RTEMS_NO_TIMEOUT, &events);
+      send_packet(ifp, m);
+      m_freem(m);
     }
-    
-    minimac_write(MM_MINIMAC_TXADR, (unsigned int)&p);
-    minimac_write(MM_MINIMAC_TXREMAINING, (unsigned int)(len + 8));
+    ifp->if_flags &= ~IFF_OACTIVE;
+  }
 }

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,57 @@
+/*  milkymist_pfpu.h
+ *
+ *  Milkymist PFPU driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_PFPU_H_
+#define __MILKYMIST_PFPU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ioctls */
+#define PFPU_EXECUTE       0x4600
+
+#define PFPU_PROGSIZE		   (2048)
+#define PFPU_REG_COUNT		 (128)
+
+struct pfpu_td {
+	unsigned int *output;
+	unsigned int hmeshlast;
+	unsigned int vmeshlast;
+	unsigned int *program;
+	unsigned int progsize;
+	float *registers;
+	bool update; /* < shall we update the "registers" array after completion */
+	bool invalidate; /* < shall we invalidate L1 data cache after completion */
+};
+
+rtems_device_driver pfpu_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver pfpu_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define PFPU_DRIVER_TABLE_ENTRY {pfpu_initialize, \
+NULL, NULL, NULL, NULL, pfpu_control}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_PFPU_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,144 @@
+/*  pfpu.c
+ *
+ *  Milkymist PFPU driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_pfpu.h"
+
+#define DEVICE_NAME "/dev/pfpu"
+
+static rtems_id done_sem;
+
+static rtems_isr done_handler(rtems_vector_number n)
+{
+  rtems_semaphore_release(done_sem);
+  lm32_interrupt_ack(1 << MM_IRQ_PFPU);
+}
+
+rtems_device_driver pfpu_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create PFPU device");
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('P', 'F', 'P', 'U'),
+    0,
+    RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &done_sem
+  );
+  RTEMS_CHECK_SC(sc, "create PFPU done semaphore");
+
+  rtems_interrupt_catch(done_handler, MM_IRQ_PFPU, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_PFPU);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static void load_program(unsigned int *program, int size)
+{
+  int page;
+  int word;
+  volatile unsigned int *pfpu_prog = (unsigned int *)MM_PFPU_CODEBASE;
+
+  for (page=0;page<(PFPU_PROGSIZE/PFPU_PAGESIZE);page++) {
+    MM_WRITE(MM_PFPU_CODEPAGE, page);
+    for (word=0;word<PFPU_PAGESIZE;word++) {
+      if (size == 0) return;
+      pfpu_prog[word] = *program;
+      program++;
+      size--;
+    }
+  }
+}
+
+static void load_registers(float *registers)
+{
+  volatile float *pfpu_regs = (float *)MM_PFPU_DREGBASE;
+  int i;
+
+  for (i=PFPU_SPREG_COUNT;i<PFPU_REG_COUNT;i++)
+    pfpu_regs[i] = registers[i];
+}
+
+static void update_registers(float *registers)
+{
+  volatile float *pfpu_regs = (float *)MM_PFPU_DREGBASE;
+  int i;
+
+  for (i=PFPU_SPREG_COUNT;i<PFPU_REG_COUNT;i++)
+    registers[i] = pfpu_regs[i];
+}
+
+static rtems_status_code pfpu_execute(struct pfpu_td *td)
+{
+  rtems_status_code sc;
+
+  load_program(td->program, td->progsize);
+  load_registers(td->registers);
+  MM_WRITE(MM_PFPU_MESHBASE, (unsigned int)td->output);
+  MM_WRITE(MM_PFPU_HMESHLAST, td->hmeshlast);
+  MM_WRITE(MM_PFPU_VMESHLAST, td->vmeshlast);
+  MM_WRITE(MM_PFPU_CTL, PFPU_CTL_START);
+
+  sc = rtems_semaphore_obtain(done_sem, RTEMS_WAIT, 10);
+  if (sc != RTEMS_SUCCESSFUL)
+    return sc;
+
+  if (td->update)
+    update_registers(td->registers);
+    if (td->invalidate) {
+      __asm__ volatile( /* Invalidate Level-1 data cache */
+      "wcsr DCC, r0\n"
+      "nop\n"
+    );
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver pfpu_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+
+  args->ioctl_return = -1;
+  if (args->command != PFPU_EXECUTE)
+    return RTEMS_UNSATISFIED;
+
+  if (pfpu_execute((struct pfpu_td *)args->buffer) != RTEMS_SUCCESSFUL)
+    return RTEMS_UNSATISFIED;
+
+  args->ioctl_return = 0;
+  return RTEMS_SUCCESSFUL;
+}

diff -u rtems/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c:1.2 rtems/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c:1.3
--- rtems/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c:1.2	Wed Feb  9 02:19:30 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c	Mon Aug  1 08:48:40 2011
@@ -25,23 +25,13 @@
 #include "../include/system_conf.h"
 #include "../../shared/clock/clock.h"
 
-static inline int timerread(unsigned int reg)
-{
-  return *((int*)(reg));
-}
-
-static inline void timerwrite(unsigned int reg, int value)
-{
-  *((int*)reg) = value;
-}
-
 bool benchmark_timer_find_average_overhead;
 
-void benchmark_timer_initialize( void )
+void benchmark_timer_initialize(void)
 {
-  timerwrite(MM_TIMER1_COMPARE, 0xffffffff);
-  timerwrite(MM_TIMER1_COUNTER, 0);
-  timerwrite(MM_TIMER1_CONTROL, TIMER_ENABLE);
+  MM_WRITE(MM_TIMER1_COMPARE, 0xffffffff);
+  MM_WRITE(MM_TIMER1_COUNTER, 0);
+  MM_WRITE(MM_TIMER1_CONTROL, TIMER_ENABLE);
 }
 
 /*
@@ -59,25 +49,25 @@
                              /* This value is in microseconds. */
 #define LEAST_VALID       4  /* Don't trust a clicks value lower than this */
 
-uint32_t benchmark_timer_read( void )
+uint32_t benchmark_timer_read(void)
 {
   uint32_t ticks;
   uint32_t total;
-  ticks = timerread(MM_TIMER1_COUNTER);
+
+  ticks = MM_READ(MM_TIMER1_COUNTER);
   if (ticks == 0xffffffff)
     printk("Timer overflow!\n");
 
   total = ticks / (CPU_FREQUENCY / 1000000);
 
-  if ( benchmark_timer_find_average_overhead == true )
+  if (benchmark_timer_find_average_overhead)
     return total;
   else
   {
-    if ( total < LEAST_VALID )
+    if (total < LEAST_VALID)
       return 0;
 
     return (total - AVG_OVERHEAD);
-
   }
 }
 

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h:1.1
--- /dev/null	Mon Aug  1 09:10:28 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,85 @@
+/*  milkymist_tmu.h
+ *
+ *  Milkymist TMU driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_TMU_H_
+#define __MILKYMIST_TMU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ioctls */
+#define TMU_EXECUTE             0x5400
+#define TMU_EXECUTE_NONBLOCK    0x5401
+#define TMU_EXECUTE_WAIT        0x5402
+
+struct tmu_vertex {
+  int x;
+  int y;
+} __attribute__((packed));
+
+struct tmu_td {
+  unsigned int flags;
+  unsigned int hmeshlast;
+  unsigned int vmeshlast;
+  unsigned int brightness;
+  unsigned short chromakey;
+  struct tmu_vertex *vertices;
+  unsigned short *texfbuf;
+  unsigned int texhres;
+  unsigned int texvres;
+  unsigned int texhmask;
+  unsigned int texvmask;
+  unsigned short *dstfbuf;
+  unsigned int dsthres;
+  unsigned int dstvres;
+  int dsthoffset;
+  int dstvoffset;
+  unsigned int dstsquarew;
+  unsigned int dstsquareh;
+  unsigned int alpha;
+
+  bool invalidate_before;
+  bool invalidate_after;
+};
+
+#define TMU_BRIGHTNESS_MAX     (63)
+#define TMU_MASK_NOFILTER      (0x3ffc0)
+#define TMU_MASK_FULL          (0x3ffff)
+#define TMU_FIXEDPOINT_SHIFT   (6)
+#define TMU_ALPHA_MAX          (63)
+#define TMU_MESH_MAXSIZE       (128)
+
+#define TMU_FLAG_CHROMAKEY     (2)
+#define TMU_FLAG_ADDITIVE      (4)
+
+rtems_device_driver tmu_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver tmu_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define TMU_DRIVER_TABLE_ENTRY {tmu_initialize, \
+NULL, NULL, NULL, NULL, tmu_control}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_TMU_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,163 @@
+/*  tmu.c
+ *
+ *  Milkymist TMU driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_tmu.h"
+
+#define DEVICE_NAME "/dev/tmu"
+
+static rtems_id done_sem;
+
+static rtems_isr done_handler(rtems_vector_number n)
+{
+  rtems_semaphore_release(done_sem);
+  lm32_interrupt_ack(1 << MM_IRQ_TMU);
+}
+
+rtems_device_driver tmu_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create TMU device");
+
+  sc = rtems_semaphore_create(
+    rtems_build_name('T', 'M', 'U', ' '),
+    0,
+    RTEMS_SIMPLE_BINARY_SEMAPHORE,
+    0,
+    &done_sem
+  );
+  RTEMS_CHECK_SC(sc, "create TMU done semaphore");
+
+  rtems_interrupt_catch(done_handler, MM_IRQ_TMU, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_TMU);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static void invalidate_l2(void)
+{
+  volatile char *flushbase = (char *)FMLBRG_FLUSH_BASE;
+  int i, offset;
+
+  offset = 0;
+  for (i=0;i<FMLBRG_LINE_COUNT;i++) {
+    flushbase[offset] = 0;
+    offset += FMLBRG_LINE_LENGTH;
+  }
+}
+
+static bool invalidate_after;
+
+static void tmu_start(struct tmu_td *td)
+{
+  if (td->invalidate_before)
+    invalidate_l2();
+
+  MM_WRITE(MM_TMU_HMESHLAST, td->hmeshlast);
+  MM_WRITE(MM_TMU_VMESHLAST, td->vmeshlast);
+  MM_WRITE(MM_TMU_BRIGHTNESS, td->brightness);
+  MM_WRITE(MM_TMU_CHROMAKEY, td->chromakey);
+
+  MM_WRITE(MM_TMU_VERTICESADR, (unsigned int)td->vertices);
+  MM_WRITE(MM_TMU_TEXFBUF, (unsigned int)td->texfbuf);
+  MM_WRITE(MM_TMU_TEXHRES, td->texhres);
+  MM_WRITE(MM_TMU_TEXVRES, td->texvres);
+  MM_WRITE(MM_TMU_TEXHMASK, td->texhmask);
+  MM_WRITE(MM_TMU_TEXVMASK, td->texvmask);
+
+  MM_WRITE(MM_TMU_DSTFBUF, (unsigned int)td->dstfbuf);
+  MM_WRITE(MM_TMU_DSTHRES, td->dsthres);
+  MM_WRITE(MM_TMU_DSTVRES, td->dstvres);
+  MM_WRITE(MM_TMU_DSTHOFFSET, td->dsthoffset);
+  MM_WRITE(MM_TMU_DSTVOFFSET, td->dstvoffset);
+  MM_WRITE(MM_TMU_DSTSQUAREW, td->dstsquarew);
+  MM_WRITE(MM_TMU_DSTSQUAREH, td->dstsquareh);
+
+  MM_WRITE(MM_TMU_ALPHA, td->alpha);
+
+  MM_WRITE(MM_TMU_CTL, td->flags|TMU_CTL_START);
+
+  invalidate_after = td->invalidate_after;
+}
+
+static rtems_status_code tmu_finalize(void)
+{
+  rtems_status_code sc;
+
+  sc = rtems_semaphore_obtain(done_sem, RTEMS_WAIT, 100);
+  if (sc != RTEMS_SUCCESSFUL)
+    return sc;
+
+  if (invalidate_after) {
+    invalidate_l2();
+    __asm__ volatile( /* Invalidate Level-1 data cache */
+      "wcsr DCC, r0\n"
+      "nop\n"
+    );
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver tmu_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+  struct tmu_td *td = (struct tmu_td *)args->buffer;
+  rtems_status_code sc;
+
+  switch (args->command) {
+    case TMU_EXECUTE:
+      tmu_start(td);
+      sc = tmu_finalize();
+      break;
+    case TMU_EXECUTE_NONBLOCK:
+      tmu_start(td);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case TMU_EXECUTE_WAIT:
+      sc = tmu_finalize();
+      break;
+    default:
+      sc = RTEMS_UNSATISFIED;
+      break;
+  }
+
+  if (sc == RTEMS_SUCCESSFUL)
+    args->ioctl_return = 0;
+  else
+    args->ioctl_return = -1;
+
+  return sc;
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,26 @@
+/*  comloc.h
+ *
+ *  Milkymist USB input devices driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __COMLOC_H_
+#define __COMLOC_H_
+
+#define COMLOCV(x)  (*(volatile unsigned char *)(x))
+
+#define COMLOC_DEBUG_PRODUCE  COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1000)
+#define COMLOC_DEBUG(offset)  COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1001+offset)
+#define COMLOC_MEVT_PRODUCE COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1101)
+#define COMLOC_MEVT(offset) COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1102+offset)
+#define COMLOC_KEVT_PRODUCE	COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1142)
+#define COMLOC_KEVT(offset)	COMLOCV(MM_SOFTUSB_DMEM_BASE+0x1143+offset)
+
+#endif /* __COMLOC_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,46 @@
+/*  milkymist_usbinput.h
+ *
+ *  Milkymist USB input devices driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_USBINPUT_H_
+#define __MILKYMIST_USBINPUT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver usbinput_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver usbinput_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver usbinput_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define USBINPUT_DRIVER_TABLE_ENTRY {usbinput_initialize, \
+usbinput_open, NULL, usbinput_read, NULL, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_USBINPUT_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,329 @@
+/*  softusb-input.h
+ *
+ *  Milkymist USB input devices driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+  0x0f, 0xef, 0x0e, 0xbf, 0x0f, 0xe1, 0x0d, 0xbf, 0xfb, 0xd5, 0x27, 0xc4,
+  0x5d, 0xc4, 0x76, 0xc4, 0x87, 0xc4, 0xa3, 0xc4, 0xda, 0xc4, 0x32, 0xc5,
+  0x52, 0xc5, 0x73, 0x6f, 0x66, 0x74, 0x75, 0x73, 0x62, 0x2d, 0x69, 0x6e,
+  0x70, 0x75, 0x74, 0x20, 0x76, 0x31, 0x2e, 0x30, 0x52, 0x43, 0x31, 0x0a,
+  0x00, 0x46, 0x75, 0x6c, 0x6c, 0x20, 0x73, 0x70, 0x65, 0x65, 0x64, 0x20,
+  0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x6f,
+  0x72, 0x74, 0x20, 0x00, 0x4c, 0x6f, 0x77, 0x20, 0x73, 0x70, 0x65, 0x65,
+  0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x6e, 0x20,
+  0x70, 0x6f, 0x72, 0x74, 0x20, 0x00, 0x56, 0x49, 0x44, 0x3a, 0x20, 0x00,
+  0x2c, 0x20, 0x50, 0x49, 0x44, 0x3a, 0x20, 0x00, 0x46, 0x6f, 0x75, 0x6e,
+  0x64, 0x20, 0x00, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
+  0x65, 0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0a, 0x00, 0x6b,
+  0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x0a, 0x00, 0x6d, 0x6f, 0x75,
+  0x73, 0x65, 0x0a, 0x00, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x64,
+  0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x6f, 0x6e,
+  0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x00, 0x43, 0x6f, 0x6e, 0x74, 0x72,
+  0x6f, 0x6c, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x20,
+  0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x0a, 0x00, 0x53, 0x45, 0x54,
+  0x55, 0x50, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x3a, 0x0a, 0x00, 0x49,
+  0x4e, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x3a, 0x0a, 0x00, 0x4f, 0x55,
+  0x54, 0x2f, 0x44, 0x41, 0x54, 0x41, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79,
+  0x3a, 0x0a, 0x00, 0x28, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74,
+  0x69, 0x6f, 0x6e, 0x29, 0x0a, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66,
+  0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x00, 0x52,
+  0x58, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x65, 0x72,
+  0x72, 0x6f, 0x72, 0x0a, 0x00, 0x52, 0x58, 0x20, 0x62, 0x69, 0x74, 0x73,
+  0x74, 0x75, 0x66, 0x66, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x00,
+  0x52, 0x65, 0x74, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20,
+  0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2c, 0x20, 0x64, 0x69,
+  0x73, 0x61, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x76, 0x69,
+  0x63, 0x65, 0x2e, 0x0a, 0x00, 0x44, 0x41, 0x54, 0x41, 0x78, 0x20, 0x6d,
+  0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x28, 0x6e, 0x6f,
+  0x20, 0x64, 0x61, 0x74, 0x61, 0x29, 0x0a, 0x00, 0x30, 0x31, 0x32, 0x33,
+  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+  0x00, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81,
+  0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41, 0x01, 0xc0, 0x80,
+  0x41, 0x00, 0xc1, 0x81, 0x40, 0x00, 0xc0, 0xc1, 0x01, 0xc3, 0x03, 0x02,
+  0xc2, 0xc6, 0x06, 0x07, 0xc7, 0x05, 0xc5, 0xc4, 0x04, 0xcc, 0x0c, 0x0d,
+  0xcd, 0x0f, 0xcf, 0xce, 0x0e, 0x0a, 0xca, 0xcb, 0x0b, 0xc9, 0x09, 0x08,
+  0xc8, 0xd8, 0x18, 0x19, 0xd9, 0x1b, 0xdb, 0xda, 0x1a, 0x1e, 0xde, 0xdf,
+  0x1f, 0xdd, 0x1d, 0x1c, 0xdc, 0x14, 0xd4, 0xd5, 0x15, 0xd7, 0x17, 0x16,
+  0xd6, 0xd2, 0x12, 0x13, 0xd3, 0x11, 0xd1, 0xd0, 0x10, 0xf0, 0x30, 0x31,
+  0xf1, 0x33, 0xf3, 0xf2, 0x32, 0x36, 0xf6, 0xf7, 0x37, 0xf5, 0x35, 0x34,
+  0xf4, 0x3c, 0xfc, 0xfd, 0x3d, 0xff, 0x3f, 0x3e, 0xfe, 0xfa, 0x3a, 0x3b,
+  0xfb, 0x39, 0xf9, 0xf8, 0x38, 0x28, 0xe8, 0xe9, 0x29, 0xeb, 0x2b, 0x2a,
+  0xea, 0xee, 0x2e, 0x2f, 0xef, 0x2d, 0xed, 0xec, 0x2c, 0xe4, 0x24, 0x25,
+  0xe5, 0x27, 0xe7, 0xe6, 0x26, 0x22, 0xe2, 0xe3, 0x23, 0xe1, 0x21, 0x20,
+  0xe0, 0xa0, 0x60, 0x61, 0xa1, 0x63, 0xa3, 0xa2, 0x62, 0x66, 0xa6, 0xa7,
+  0x67, 0xa5, 0x65, 0x64, 0xa4, 0x6c, 0xac, 0xad, 0x6d, 0xaf, 0x6f, 0x6e,
+  0xae, 0xaa, 0x6a, 0x6b, 0xab, 0x69, 0xa9, 0xa8, 0x68, 0x78, 0xb8, 0xb9,
+  0x79, 0xbb, 0x7b, 0x7a, 0xba, 0xbe, 0x7e, 0x7f, 0xbf, 0x7d, 0xbd, 0xbc,
+  0x7c, 0xb4, 0x74, 0x75, 0xb5, 0x77, 0xb7, 0xb6, 0x76, 0x72, 0xb2, 0xb3,
+  0x73, 0xb1, 0x71, 0x70, 0xb0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52,
+  0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9c, 0x5c, 0x5d,
+  0x9d, 0x5f, 0x9f, 0x9e, 0x5e, 0x5a, 0x9a, 0x9b, 0x5b, 0x99, 0x59, 0x58,
+  0x98, 0x88, 0x48, 0x49, 0x89, 0x4b, 0x8b, 0x8a, 0x4a, 0x4e, 0x8e, 0x8f,
+  0x4f, 0x8d, 0x4d, 0x4c, 0x8c, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46,
+  0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40, 0x00, 0x28, 0x2f,
+  0x39, 0x2f, 0x80, 0xe8, 0x84, 0xb9, 0x85, 0xb1, 0x88, 0x23, 0xe9, 0xf7,
+  0xe2, 0x2f, 0xf3, 0x2f, 0x90, 0xe0, 0x07, 0xc0, 0x80, 0x81, 0x84, 0xb9,
+  0x85, 0xb1, 0x88, 0x23, 0xe9, 0xf7, 0x9f, 0x5f, 0x31, 0x96, 0x96, 0x17,
+  0xb8, 0xf3, 0x80, 0xe0, 0x86, 0xb9, 0x87, 0xb1, 0x88, 0x23, 0xe9, 0xf7,
+  0x08, 0x95, 0x48, 0x2f, 0x59, 0x2f, 0x2f, 0xef, 0x3f, 0xe0, 0x10, 0xc0,
+  0x21, 0x15, 0x31, 0x05, 0x21, 0xf4, 0x8e, 0xe0, 0x91, 0xe0, 0x60, 0xd4,
+  0x20, 0xc0, 0x8c, 0xb1, 0x88, 0x23, 0x21, 0xf0, 0x8e, 0xe0, 0x91, 0xe0,
+  0x59, 0xd4, 0x10, 0xc0, 0x21, 0x50, 0x30, 0x40, 0x8a, 0xb1, 0x88, 0x23,
+  0x69, 0xf3, 0x24, 0x2f, 0x35, 0x2f, 0xe2, 0x2f, 0xf3, 0x2f, 0x90, 0xe0,
+  0x2f, 0xef, 0x3f, 0xe0, 0x12, 0xc0, 0x8c, 0xb1, 0x88, 0x23, 0x19, 0xf0,
+  0x81, 0xe3, 0x91, 0xe0, 0x08, 0xc0, 0x8b, 0xb1, 0x88, 0x23, 0x99, 0xf0,
+  0x21, 0x15, 0x31, 0x05, 0x21, 0xf4, 0x8f, 0xe1, 0x91, 0xe0, 0x3c, 0xd4,
+  0x0b, 0xc0, 0x21, 0x50, 0x30, 0x40, 0x8a, 0xb1, 0x88, 0x23, 0x59, 0xf3,
+  0x96, 0x17, 0x21, 0xf0, 0x89, 0xb1, 0x81, 0x93, 0x9f, 0x5f, 0xe2, 0xcf,
+  0x90, 0xe0, 0x89, 0x2f, 0x08, 0x95, 0xcf, 0x93, 0xdf, 0x93, 0xc8, 0x2f,
+  0xd9, 0x2f, 0x8b, 0x81, 0x8f, 0x5f, 0x8b, 0x83, 0x81, 0x50, 0x85, 0x31,
+  0x2c, 0xf0, 0x84, 0xe4, 0x91, 0xe0, 0x20, 0xd4, 0x88, 0xe0, 0x88, 0x83,
+  0xdf, 0x91, 0xcf, 0x91, 0x08, 0x95, 0xff, 0x92, 0x0f, 0x93, 0x1f, 0x93,
+  0x04, 0x2f, 0x15, 0x2f, 0xe4, 0x2f, 0xf5, 0x2f, 0x80, 0x83, 0x61, 0x83,
+  0x60, 0x70, 0x77, 0x70, 0xf7, 0x2e, 0x72, 0x83, 0x81, 0x81, 0x67, 0x2f,
+  0xbb, 0xd4, 0x88, 0x0f, 0x88, 0x0f, 0x88, 0x0f, 0xf8, 0x2a, 0xe0, 0x2f,
+  0xf1, 0x2f, 0xf2, 0x82, 0x1f, 0x91, 0x0f, 0x91, 0xff, 0x90, 0x08, 0x95,
+  0x2f, 0x92, 0x3f, 0x92, 0x4f, 0x92, 0x5f, 0x92, 0x6f, 0x92, 0x7f, 0x92,
+  0x8f, 0x92, 0x9f, 0x92, 0xaf, 0x92, 0xbf, 0x92, 0xcf, 0x92, 0xdf, 0x92,
+  0xef, 0x92, 0xff, 0x92, 0x0f, 0x93, 0x1f, 0x93, 0xdf, 0x93, 0xcf, 0x93,
+  0xcd, 0xb7, 0xde, 0xb7, 0x2b, 0x97, 0xde, 0xbf, 0xcd, 0xbf, 0x38, 0x2e,
+  0xf6, 0x2e, 0xe7, 0x2e, 0x24, 0x2e, 0xa2, 0x2e, 0xb3, 0x2e, 0x40, 0x2e,
+  0x51, 0x2e, 0x8d, 0xe2, 0x63, 0x2d, 0x70, 0xe0, 0x0c, 0x2f, 0x1d, 0x2f,
+  0x0f, 0x5f, 0x1f, 0x4f, 0x40, 0x2f, 0x51, 0x2f, 0xbc, 0xdf, 0x80, 0x2f,
+  0x91, 0x2f, 0x63, 0xe0, 0x4e, 0xdf, 0x83, 0xec, 0x89, 0x83, 0xac, 0x2f,
+  0xbd, 0x2f, 0x12, 0x96, 0x8f, 0x2d, 0x9e, 0x2d, 0xe8, 0x2f, 0xf9, 0x2f,
+  0x88, 0xe0, 0x01, 0x90, 0x0d, 0x92, 0x81, 0x50, 0xe1, 0xf7, 0x32, 0xe0,
+  0x83, 0x2e, 0x91, 0x2c, 0x8c, 0x0e, 0x9d, 0x1e, 0x88, 0x2d, 0x99, 0x2d,
+  0x68, 0xe0, 0x4c, 0x2f, 0x5d, 0x2f, 0x46, 0x5f, 0x5f, 0x4f, 0x88, 0xd4,
+  0x0c, 0x2f, 0x1d, 0x2f, 0x0f, 0x5f, 0x1f, 0x4f, 0x80, 0x2f, 0x91, 0x2f,
+  0x6b, 0xe0, 0x2b, 0xdf, 0x80, 0x2f, 0x91, 0x2f, 0x6b, 0xe0, 0x41, 0xdf,
+  0xf8, 0x2e, 0x41, 0xe0, 0x84, 0x17, 0x19, 0xf4, 0x89, 0x81, 0x82, 0x3d,
+  0x31, 0xf0, 0x8b, 0xeb, 0x90, 0xe0, 0xa2, 0xd3, 0x85, 0xed, 0x90, 0xe0,
+  0x5b, 0xc0, 0x22, 0x20, 0x09, 0xf4, 0x66, 0xc0, 0xdd, 0x24, 0xcc, 0x24,
+  0xc3, 0x94, 0x60, 0x2e, 0x71, 0x2e, 0x88, 0x2d, 0x99, 0x2d, 0x99, 0x2e,
+  0x64, 0x2d, 0x6d, 0x19, 0x09, 0xf4, 0xb5, 0xc0, 0xe6, 0x2e, 0x58, 0xe0,
+  0x56, 0x17, 0x14, 0xf4, 0x28, 0xe0, 0xe2, 0x2e, 0x81, 0xee, 0x63, 0x2d,
+  0x70, 0xe0, 0x46, 0x2d, 0x57, 0x2d, 0x69, 0xdf, 0x86, 0x2d, 0x97, 0x2d,
+  0x63, 0xe0, 0xfb, 0xde, 0x80, 0xe0, 0xcc, 0x20, 0x09, 0xf4, 0x81, 0xe0,
+  0xc8, 0x2e, 0x88, 0x23, 0x11, 0xf4, 0x8b, 0xe4, 0x01, 0xc0, 0x83, 0xec,
+  0x89, 0x83, 0x0e, 0x2d, 0x11, 0x27, 0x07, 0xfd, 0x10, 0x95, 0x88, 0x2d,
+  0x99, 0x2d, 0x6a, 0x2d, 0x7b, 0x2d, 0x40, 0x2f, 0x51, 0x2f, 0x62, 0xd4,
+  0x40, 0x2f, 0x51, 0x2f, 0x4f, 0x5f, 0x5f, 0x4f, 0x46, 0x0d, 0x57, 0x1d,
+  0x88, 0x2d, 0x99, 0x2d, 0x6e, 0x2d, 0x30, 0xd4, 0x6e, 0x2d, 0x6d, 0x5f,
+  0x86, 0x2d, 0x97, 0x2d, 0xd6, 0xde, 0x86, 0x2d, 0x97, 0x2d, 0x6b, 0xe0,
+  0xec, 0xde, 0xf8, 0x2e, 0x81, 0xe0, 0xf8, 0x16, 0x21, 0xf4, 0x89, 0x81,
+  0x82, 0x3d, 0x19, 0xf4, 0x11, 0xc0, 0x1f, 0x14, 0x24, 0xf4, 0x89, 0x81,
+  0x8a, 0x35, 0x09, 0xf4, 0xb5, 0xcf, 0x8b, 0xeb, 0x90, 0xe0, 0x46, 0xd3,
+  0x83, 0xee, 0x90, 0xe0, 0x43, 0xd3, 0x8c, 0x2f, 0x9d, 0x2f, 0x01, 0x96,
+  0x6f, 0x2d, 0xca, 0xc0, 0xde, 0x0c, 0x48, 0xe0, 0xe4, 0x16, 0x09, 0xf0,
+  0x5e, 0xc0, 0xa0, 0x0e, 0xb1, 0x1e, 0xa2, 0xcf, 0x41, 0x14, 0x51, 0x04,
+  0x11, 0xf4, 0xdd, 0x24, 0x54, 0xc0, 0xdd, 0x24, 0x80, 0x2f, 0x91, 0x2f,
+  0xc0, 0x2e, 0xe9, 0x2e, 0x88, 0x2d, 0x99, 0x2d, 0x99, 0x2e, 0x92, 0xed,
+  0x79, 0x2e, 0x89, 0xe6, 0x63, 0x2d, 0x70, 0xe0, 0x4c, 0x2d, 0x5e, 0x2d,
+  0x06, 0xdf, 0x8c, 0x2d, 0x9e, 0x2d, 0x63, 0xe0, 0x98, 0xde, 0x8c, 0x2d,
+  0x9e, 0x2d, 0x6b, 0xe0, 0xae, 0xde, 0x18, 0x2f, 0x83, 0x30, 0x34, 0xf0,
+  0x89, 0x81, 0x83, 0x3c, 0x59, 0xf0, 0x8b, 0x34, 0x19, 0xf4, 0x08, 0xc0,
+  0x18, 0x16, 0x1c, 0xf4, 0x89, 0x81, 0x8a, 0x35, 0x21, 0xf3, 0x8b, 0xeb,
+  0x90, 0xe0, 0x59, 0xc0, 0x8d, 0xef, 0xf8, 0x2e, 0xf1, 0x0e, 0x8f, 0x2d,
+  0x99, 0x27, 0x87, 0xfd, 0x90, 0x95, 0x2d, 0x2d, 0x33, 0x27, 0x27, 0xfd,
+  0x30, 0x95, 0x44, 0x2d, 0x55, 0x2d, 0x42, 0x1b, 0x53, 0x0b, 0x48, 0x17,
+  0x59, 0x07, 0x14, 0xf4, 0xf4, 0x2c, 0xfd, 0x18, 0x0f, 0x2d, 0x11, 0x27,
+  0x07, 0xfd, 0x10, 0x95, 0x8a, 0x2d, 0x9b, 0x2d, 0x68, 0x2d, 0x79, 0x2d,
+  0x40, 0x2f, 0x51, 0x2f, 0xe1, 0xd3, 0x79, 0x82, 0x8c, 0x2d, 0x9e, 0x2d,
+  0x61, 0xe0, 0x5f, 0xde, 0xdf, 0x0c, 0x57, 0xe0, 0x5f, 0x15, 0x1c, 0xf4,
+  0xa0, 0x0e, 0xb1, 0x1e, 0xb6, 0xcf, 0xcc, 0x24, 0xc3, 0x94, 0xec, 0x2e,
+  0xfd, 0x2e, 0x08, 0x94, 0xe1, 0x1c, 0xf1, 0x1c, 0x22, 0x20, 0x11, 0xf4,
+  0x81, 0xee, 0x01, 0xc0, 0x89, 0xe6, 0x63, 0x2d, 0x70, 0xe0, 0x4e, 0x2d,
+  0x5f, 0x2d, 0xb1, 0xde, 0x8e, 0x2d, 0x9f, 0x2d, 0x63, 0xe0, 0x43, 0xde,
+  0x22, 0x20, 0x19, 0xf1, 0x8e, 0x2d, 0x9f, 0x2d, 0x6b, 0xe0, 0x57, 0xde,
+  0x18, 0x2f, 0x83, 0x30, 0x31, 0xf4, 0x89, 0x81, 0x83, 0x3c, 0x89, 0xf0,
+  0x8b, 0x34, 0x19, 0xf4, 0x0e, 0xc0, 0x18, 0x16, 0x1c, 0xf4, 0x89, 0x81,
+  0x8a, 0x35, 0xf1, 0xf2, 0x8b, 0xeb, 0x90, 0xe0, 0xb1, 0xd2, 0x8f, 0xef,
+  0x90, 0xe0, 0xae, 0xd2, 0x8e, 0xee, 0x90, 0xe0, 0x32, 0xc0, 0x82, 0xed,
+  0x89, 0x83, 0x8c, 0x2f, 0x9d, 0x2f, 0x01, 0x96, 0x61, 0xe0, 0x1f, 0xde,
+  0x32, 0xc0, 0x80, 0xe0, 0xcc, 0x20, 0x09, 0xf4, 0x81, 0xe0, 0xc8, 0x2e,
+  0x88, 0x23, 0x11, 0xf4, 0x8b, 0xe4, 0x01, 0xc0, 0x83, 0xec, 0x89, 0x83,
+  0x1b, 0x82, 0x1a, 0x82, 0x8e, 0x2d, 0x9f, 0x2d, 0x63, 0xe0, 0x0d, 0xde,
+  0x8e, 0x2d, 0x9f, 0x2d, 0x6b, 0xe0, 0x23, 0xde, 0x18, 0x2f, 0x81, 0x30,
+  0x21, 0xf4, 0x89, 0x81, 0x82, 0x3d, 0x19, 0xf4, 0x16, 0xc0, 0x18, 0x16,
+  0x24, 0xf4, 0x89, 0x81, 0x8a, 0x35, 0x09, 0xf4, 0xad, 0xcf, 0x8b, 0xeb,
+  0x90, 0xe0, 0x7e, 0xd2, 0x8f, 0xef, 0x90, 0xe0, 0x7b, 0xd2, 0x83, 0xee,
+  0x90, 0xe0, 0x78, 0xd2, 0x8c, 0x2f, 0x9d, 0x2f, 0x01, 0x96, 0x61, 0x2f,
+  0xb5, 0xd2, 0xdd, 0x24, 0xda, 0x94, 0x8d, 0x2d, 0x2b, 0x96, 0xde, 0xbf,
+  0xcd, 0xbf, 0xcf, 0x91, 0xdf, 0x91, 0x1f, 0x91, 0x0f, 0x91, 0xff, 0x90,
+  0xef, 0x90, 0xdf, 0x90, 0xcf, 0x90, 0xbf, 0x90, 0xaf, 0x90, 0x9f, 0x90,
+  0x8f, 0x90, 0x7f, 0x90, 0x6f, 0x90, 0x5f, 0x90, 0x4f, 0x90, 0x3f, 0x90,
+  0x2f, 0x90, 0x08, 0x95, 0xcf, 0x92, 0xdf, 0x92, 0xef, 0x92, 0xff, 0x92,
+  0x0f, 0x93, 0x1f, 0x93, 0xdf, 0x93, 0xcf, 0x93, 0xcd, 0xb7, 0xde, 0xb7,
+  0xc4, 0x5a, 0xd0, 0x40, 0xde, 0xbf, 0xcd, 0xbf, 0xe8, 0x2e, 0xf9, 0x2e,
+  0x06, 0x2f, 0xe8, 0x2f, 0xf9, 0x2f, 0x80, 0x81, 0x82, 0x30, 0x8c, 0xf0,
+  0x61, 0x34, 0x11, 0xf4, 0x80, 0xb1, 0x01, 0xc0, 0x81, 0xb1, 0x88, 0x23,
+  0x51, 0xf4, 0x80, 0xea, 0x90, 0xe0, 0x3a, 0xd2, 0x80, 0x2f, 0x2b, 0xd2,
+  0x8a, 0xe0, 0x29, 0xd2, 0xee, 0x2d, 0xff, 0x2d, 0x10, 0x82, 0xee, 0x2d,
+  0xff, 0x2d, 0x80, 0x81, 0xe8, 0x2f, 0xff, 0x27, 0xe7, 0xfd, 0xf0, 0x95,
+  0xe8, 0x30, 0xf1, 0x05, 0x08, 0xf0, 0xc9, 0xc1, 0xeb, 0x5f, 0xff, 0x4f,
+  0x09, 0x94, 0x01, 0x34, 0x11, 0xf4, 0x10, 0xb1, 0x01, 0xc0, 0x11, 0xb1,
+  0x11, 0x30, 0x61, 0xf4, 0x81, 0xe3, 0x90, 0xe0, 0x1b, 0xd2, 0x80, 0x2f,
+  0x0c, 0xd2, 0x8a, 0xe0, 0x0a, 0xd2, 0xee, 0x2d, 0xff, 0x2d, 0x11, 0x83,
+  0x88, 0xe0, 0x3c, 0xc0, 0x12, 0x30, 0x09, 0xf0, 0xb0, 0xc1, 0x8c, 0xe4,
+  0x90, 0xe0, 0x0c, 0xd2, 0x80, 0x2f, 0xfd, 0xd1, 0x8a, 0xe0, 0xfb, 0xd1,
+  0xee, 0x2d, 0xff, 0x2d, 0x11, 0x82, 0x01, 0x34, 0x21, 0xf4, 0x88, 0xb1,
+  0x81, 0x60, 0x88, 0xb9, 0x03, 0xc0, 0x88, 0xb1, 0x82, 0x60, 0x88, 0xb9,
+  0x81, 0xe0, 0xee, 0x2d, 0xff, 0x2d, 0x80, 0x83, 0x80, 0x91, 0x0e, 0x00,
+  0x90, 0x91, 0x0f, 0x00, 0x82, 0x5a, 0x9e, 0x4f, 0x97, 0x70, 0x95, 0x83,
+  0x84, 0x83, 0x8f, 0xc1, 0x20, 0x91, 0x0e, 0x00, 0x30, 0x91, 0x0f, 0x00,
+  0xee, 0x2d, 0xff, 0x2d, 0x84, 0x81, 0x95, 0x81, 0x28, 0x17, 0x39, 0x07,
+  0x09, 0xf0, 0x83, 0xc1, 0x01, 0x34, 0x21, 0xf4, 0x88, 0xb1, 0x82, 0x70,
+  0x88, 0xb9, 0x03, 0xc0, 0x88, 0xb1, 0x81, 0x70, 0x88, 0xb9, 0x82, 0xe0,
+  0xee, 0x2d, 0xff, 0x2d, 0x80, 0x83, 0x75, 0xc1, 0xee, 0x2d, 0xff, 0x2d,
+  0x84, 0x81, 0x95, 0x81, 0x86, 0x50, 0x9f, 0x4f, 0x97, 0x70, 0x20, 0x91,
+  0x0e, 0x00, 0x30, 0x91, 0x0f, 0x00, 0x28, 0x17, 0x39, 0x07, 0x09, 0xf0,
+  0x66, 0xc1, 0x13, 0x82, 0x83, 0xe0, 0xec, 0xcf, 0x19, 0x82, 0x85, 0xe0,
+  0x8a, 0x83, 0x81, 0xe0, 0x8b, 0x83, 0x1c, 0x82, 0x1d, 0x82, 0x1e, 0x82,
+  0x1f, 0x82, 0x18, 0x86, 0x80, 0xe0, 0x6c, 0x2f, 0x7d, 0x2f, 0x6f, 0x5f,
+  0x7f, 0x4f, 0x41, 0xe0, 0x20, 0xe0, 0x30, 0xe0, 0x00, 0xe0, 0x10, 0xe0,
+  0xad, 0xdd, 0x88, 0x23, 0x09, 0xf0, 0xb3, 0xc0, 0xee, 0x2d, 0xff, 0x2d,
+  0x13, 0x82, 0x84, 0xe0, 0xad, 0xc0, 0x80, 0xe8, 0x89, 0x83, 0x86, 0xe0,
+  0x8a, 0x83, 0x1b, 0x82, 0x81, 0xe0, 0x8c, 0x83, 0x1d, 0x82, 0x1e, 0x82,
+  0x82, 0xe1, 0x8f, 0x83, 0x18, 0x86, 0x81, 0xe0, 0x6c, 0x2f, 0x7d, 0x2f,
+  0x6f, 0x5f, 0x7f, 0x4f, 0x40, 0xe0, 0x2c, 0x2f, 0x3d, 0x2f, 0x2c, 0x5e,
+  0x3f, 0x4f, 0x02, 0xe1, 0x10, 0xe0, 0x8c, 0xdd, 0x87, 0xfd, 0x93, 0xc0,
+  0xee, 0x2d, 0xff, 0x2d, 0x13, 0x82, 0x86, 0xe6, 0x90, 0xe0, 0x84, 0xd1,
+  0x8d, 0x8d, 0x9a, 0xd1, 0x8c, 0x8d, 0x98, 0xd1, 0x8c, 0xe6, 0x90, 0xe0,
+  0x7d, 0xd1, 0x8f, 0x8d, 0x93, 0xd1, 0x8e, 0x8d, 0x91, 0xd1, 0x8a, 0xe0,
+  0x6a, 0xd1, 0x88, 0x8d, 0x88, 0x23, 0x09, 0xf0, 0x4d, 0xc0, 0x89, 0x8d,
+  0x88, 0x23, 0x09, 0xf0, 0x49, 0xc0, 0x85, 0xe0, 0x56, 0xc0, 0x80, 0xe8,
+  0x89, 0x83, 0x86, 0xe0, 0x8a, 0x83, 0x1b, 0x82, 0x82, 0xe0, 0x8c, 0x83,
+  0x1d, 0x82, 0x1e, 0x82, 0x8f, 0xe7, 0x8f, 0x83, 0x18, 0x86, 0x46, 0xe2,
+  0xc4, 0x2e, 0xd1, 0x2c, 0xcc, 0x0e, 0xdd, 0x1e, 0x81, 0xe0, 0x6c, 0x2f,
+  0x7d, 0x2f, 0x6f, 0x5f, 0x7f, 0x4f, 0x40, 0xe0, 0x2c, 0x2d, 0x3d, 0x2d,
+  0x0f, 0xe7, 0x10, 0xe0, 0x51, 0xdd, 0x48, 0x2f, 0x87, 0xfd, 0x57, 0xc0,
+  0xee, 0x2d, 0xff, 0x2d, 0x13, 0x82, 0x90, 0xe0, 0x2c, 0x2d, 0x3d, 0x2d,
+  0x1f, 0xc0, 0xe9, 0x2f, 0xff, 0x27, 0xe7, 0xfd, 0xf0, 0x95, 0xe2, 0x0f,
+  0xf3, 0x1f, 0x81, 0x81, 0x84, 0x30, 0xa1, 0xf4, 0x85, 0x81, 0x83, 0x30,
+  0xa9, 0xf4, 0x86, 0x81, 0x81, 0x30, 0x91, 0xf4, 0x87, 0x81, 0x81, 0x30,
+  0x19, 0xf0, 0x82, 0x30, 0x69, 0xf4, 0x04, 0xc0, 0xee, 0x2d, 0xff, 0x2d,
+  0x82, 0x83, 0xc5, 0xc0, 0xee, 0x2d, 0xff, 0x2d, 0x12, 0x82, 0xc1, 0xc0,
+  0x80, 0x81, 0x98, 0x0f, 0x94, 0x17, 0xfc, 0xf2, 0x84, 0xe7, 0x90, 0xe0,
+  0x23, 0xd1, 0x8b, 0xe7, 0x90, 0xe0, 0x20, 0xd1, 0x88, 0xe0, 0x07, 0xc0,
+  0x8f, 0xe8, 0x90, 0xe0, 0x02, 0xc0, 0x89, 0xe9, 0x90, 0xe0, 0x18, 0xd1,
+  0x86, 0xe0, 0xee, 0x2d, 0xff, 0x2d, 0x1c, 0xc0, 0x19, 0x82, 0x89, 0xe0,
+  0x8a, 0x83, 0x81, 0xe0, 0x8b, 0x83, 0x1c, 0x82, 0x1d, 0x82, 0x1e, 0x82,
+  0x1f, 0x82, 0x18, 0x86, 0x6c, 0x2f, 0x7d, 0x2f, 0x6f, 0x5f, 0x7f, 0x4f,
+  0x41, 0xe0, 0x20, 0xe0, 0x30, 0xe0, 0x00, 0xe0, 0x10, 0xe0, 0x00, 0xdd,
+  0x88, 0x23, 0x39, 0xf4, 0xee, 0x2d, 0xff, 0x2d, 0x13, 0x82, 0x83, 0xec,
+  0x86, 0x83, 0x87, 0xe0, 0x80, 0x83, 0x8e, 0x2d, 0x9f, 0x2d, 0xc7, 0xdc,
+  0x94, 0xc0, 0x0c, 0x2f, 0x1d, 0x2f, 0x07, 0x5f, 0x1f, 0x4f, 0x89, 0xe6,
+  0x61, 0xe8, 0x70, 0xe0, 0x40, 0x2f, 0x51, 0x2f, 0xce, 0xdc, 0x80, 0x2f,
+  0x91, 0x2f, 0x63, 0xe0, 0x60, 0xdc, 0x80, 0x2f, 0x91, 0x2f, 0x6b, 0xe0,
+  0x76, 0xdc, 0xd8, 0x2e, 0xf6, 0xe0, 0xf8, 0x17, 0x08, 0xf0, 0x7d, 0xc0,
+  0x99, 0x85, 0xee, 0x2d, 0xff, 0x2d, 0x86, 0x81, 0x98, 0x17, 0x81, 0xf0,
+  0x93, 0x3c, 0x19, 0xf0, 0x9b, 0x34, 0x09, 0xf0, 0x72, 0xc0, 0x82, 0xed,
+  0x89, 0x87, 0x8c, 0x2f, 0x9d, 0x2f, 0x09, 0x96, 0x61, 0xe0, 0x45, 0xdc,
+  0x8d, 0xe6, 0x91, 0xe0, 0xc7, 0xd0, 0x67, 0xc0, 0x82, 0xed, 0x89, 0x87,
+  0x80, 0x2f, 0x91, 0x2f, 0x61, 0xe0, 0x3b, 0xdc, 0xee, 0x2d, 0xff, 0x2d,
+  0x86, 0x81, 0x83, 0x3c, 0x11, 0xf4, 0x8b, 0xe4, 0x03, 0xc0, 0x83, 0xec,
+  0xee, 0x2d, 0xff, 0x2d, 0x86, 0x83, 0xee, 0x2d, 0xff, 0x2d, 0x82, 0x81,
+  0x88, 0x23, 0x29, 0xf1, 0xf8, 0xe0, 0xfd, 0x15, 0x08, 0xf0, 0x40, 0xc0,
+  0x90, 0x91, 0x42, 0x11, 0x89, 0x2f, 0x88, 0x0f, 0x88, 0x0f, 0x88, 0x0f,
+  0xac, 0x2f, 0xbd, 0x2f, 0x1a, 0x96, 0x29, 0xe3, 0x31, 0xe1, 0x2c, 0x1b,
+  0x3d, 0x0b, 0x28, 0x0f, 0x31, 0x1d, 0x4c, 0x2f, 0x5d, 0x2f, 0x4e, 0x5e,
+  0x5f, 0x4f, 0xe2, 0x2f, 0xf3, 0x2f, 0xea, 0x0f, 0xfb, 0x1f, 0x8d, 0x91,
+  0x80, 0x83, 0xa4, 0x17, 0xb5, 0x07, 0xb9, 0xf7, 0x9f, 0x5f, 0x97, 0x70,
+  0x90, 0x93, 0x42, 0x11, 0x1f, 0xc0, 0x90, 0x91, 0x01, 0x11, 0x89, 0x2f,
+  0x88, 0x0f, 0x88, 0x0f, 0xac, 0x2f, 0xbd, 0x2f, 0x1a, 0x96, 0x28, 0xef,
+  0x30, 0xe1, 0x2c, 0x1b, 0x3d, 0x0b, 0x28, 0x0f, 0x31, 0x1d, 0x4c, 0x2f,
+  0x5d, 0x2f, 0x42, 0x5f, 0x5f, 0x4f, 0xe2, 0x2f, 0xf3, 0x2f, 0xea, 0x0f,
+  0xfb, 0x1f, 0x8d, 0x91, 0x80, 0x83, 0xa4, 0x17, 0xb5, 0x07, 0xb9, 0xf7,
+  0x9f, 0x5f, 0x9f, 0x70, 0x90, 0x93, 0x01, 0x11, 0x81, 0xe0, 0x85, 0xbb,
+  0x0a, 0xc0, 0x84, 0xe7, 0x90, 0xe0, 0x66, 0xd0, 0xee, 0x2d, 0xff, 0x2d,
+  0x82, 0x81, 0x88, 0x23, 0x09, 0xf0, 0x42, 0xcf, 0x44, 0xcf, 0xcc, 0x55,
+  0xdf, 0x4f, 0xde, 0xbf, 0xcd, 0xbf, 0xcf, 0x91, 0xdf, 0x91, 0x1f, 0x91,
+  0x0f, 0x91, 0xff, 0x90, 0xef, 0x90, 0xdf, 0x90, 0xcf, 0x90, 0x08, 0x95,
+  0xff, 0x92, 0x0f, 0x93, 0x1f, 0x93, 0x8a, 0xe1, 0x90, 0xe0, 0x4c, 0xd0,
+  0x81, 0xe0, 0x8d, 0xb9, 0x83, 0xe0, 0x8e, 0xb9, 0x80, 0xe0, 0x81, 0xbb,
+  0x00, 0xe0, 0x11, 0xe0, 0x52, 0xe0, 0xf5, 0x2e, 0x82, 0xb3, 0x8b, 0x3b,
+  0xe8, 0xf3, 0x81, 0xb3, 0x80, 0x37, 0xd0, 0xf3, 0x01, 0xbb, 0x90, 0xe0,
+  0x80, 0x91, 0x00, 0x00, 0x82, 0x30, 0x09, 0xf4, 0x91, 0xe0, 0x80, 0x91,
+  0x07, 0x00, 0x82, 0x30, 0x09, 0xf4, 0x92, 0x60, 0x93, 0xb9, 0x1f, 0xb9,
+  0x87, 0xb1, 0x88, 0x23, 0xe9, 0xf7, 0x00, 0x00, 0x8f, 0x5f, 0x80, 0x38,
+  0xe1, 0xf7, 0x02, 0xb9, 0x13, 0xb9, 0x80, 0xe0, 0x90, 0xe0, 0x61, 0xe4,
+  0xc7, 0xdd, 0x87, 0xb1, 0x88, 0x23, 0xe9, 0xf7, 0x12, 0xb9, 0xf3, 0xb8,
+  0x87, 0xe0, 0x90, 0xe0, 0x62, 0xe4, 0xbe, 0xdd, 0x80, 0x91, 0x0e, 0x00,
+  0x90, 0x91, 0x0f, 0x00, 0x01, 0x96, 0x97, 0x70, 0x90, 0x93, 0x0f, 0x00,
+  0x80, 0x93, 0x0e, 0x00, 0xcb, 0xcf, 0xa0, 0xe0, 0xb0, 0xe1, 0x9c, 0x91,
+  0xe9, 0x2f, 0xf0, 0xe0, 0xef, 0x5f, 0xff, 0x4e, 0x80, 0x83, 0x9f, 0x5f,
+  0x9c, 0x93, 0x81, 0xe0, 0x85, 0xbb, 0x08, 0x95, 0x28, 0x2f, 0x39, 0x2f,
+  0x41, 0xe0, 0x0d, 0xc0, 0x80, 0x91, 0x00, 0x10, 0xe8, 0x2f, 0xf0, 0xe0,
+  0xef, 0x5f, 0xff, 0x4e, 0x90, 0x83, 0x8f, 0x5f, 0x80, 0x93, 0x00, 0x10,
+  0x45, 0xbb, 0x2f, 0x5f, 0x3f, 0x4f, 0xe2, 0x2f, 0xf3, 0x2f, 0xc8, 0x95,
+  0x90, 0x2d, 0x99, 0x23, 0x69, 0xf7, 0x08, 0x95, 0x28, 0x2f, 0x82, 0x95,
+  0x8f, 0x70, 0xe8, 0xe8, 0xf1, 0xe0, 0xe8, 0x0f, 0xf1, 0x1d, 0xc8, 0x95,
+  0x90, 0x2d, 0xa0, 0xe0, 0xb0, 0xe1, 0x8c, 0x91, 0xe8, 0x2f, 0xf0, 0xe0,
+  0xef, 0x5f, 0xff, 0x4e, 0x90, 0x83, 0x8f, 0x5f, 0x8c, 0x93, 0x81, 0xe0,
+  0x85, 0xbb, 0xe2, 0x2f, 0xf0, 0xe0, 0xef, 0x70, 0xf0, 0x70, 0xe8, 0x57,
+  0xfe, 0x4f, 0xc8, 0x95, 0x90, 0x2d, 0xa0, 0xe0, 0xb0, 0xe1, 0x8c, 0x91,
+  0xe8, 0x2f, 0xf0, 0xe0, 0xef, 0x5f, 0xff, 0x4e, 0x90, 0x83, 0x8f, 0x5f,
+  0x8c, 0x93, 0x81, 0xe0, 0x85, 0xbb, 0x08, 0x95, 0xdf, 0x92, 0xef, 0x92,
+  0xff, 0x92, 0x0f, 0x93, 0x1f, 0x93, 0xcf, 0x93, 0xdf, 0x93, 0x28, 0x2f,
+  0x39, 0x2f, 0x06, 0x2f, 0x66, 0x23, 0x51, 0xf0, 0xc2, 0x2f, 0xd3, 0x2f,
+  0x10, 0xe0, 0x90, 0xe2, 0xd9, 0x2e, 0xff, 0x24, 0xf3, 0x94, 0x8a, 0xe0,
+  0xe8, 0x2e, 0x20, 0xc0, 0x8d, 0xe7, 0x91, 0xe0, 0xa5, 0xdf, 0x2d, 0xc0,
+  0x88, 0x81, 0xba, 0xdf, 0x81, 0x2f, 0x8f, 0x70, 0x51, 0xf4, 0x11, 0x23,
+  0x41, 0xf0, 0x80, 0x91, 0x00, 0x10, 0xe8, 0x2f, 0xf0, 0xe0, 0xef, 0x5f,
+  0xff, 0x4e, 0xe0, 0x82, 0x07, 0xc0, 0x80, 0x91, 0x00, 0x10, 0xe8, 0x2f,
+  0xf0, 0xe0, 0xef, 0x5f, 0xff, 0x4e, 0xd0, 0x82, 0x8f, 0x5f, 0x80, 0x93,
+  0x00, 0x10, 0xf5, 0xba, 0x1f, 0x5f, 0x21, 0x96, 0x10, 0x17, 0x10, 0xf3,
+  0x0f, 0x70, 0x69, 0xf0, 0x90, 0x91, 0x00, 0x10, 0xe9, 0x2f, 0xf0, 0xe0,
+  0xef, 0x5f, 0xff, 0x4e, 0x8a, 0xe0, 0x80, 0x83, 0x9f, 0x5f, 0x90, 0x93,
+  0x00, 0x10, 0x81, 0xe0, 0x85, 0xbb, 0xdf, 0x91, 0xcf, 0x91, 0x1f, 0x91,
+  0x0f, 0x91, 0xff, 0x90, 0xef, 0x90, 0xdf, 0x90, 0x08, 0x95, 0x98, 0xe0,
+  0x96, 0x1b, 0x38, 0x2f, 0x01, 0xc0, 0x33, 0x0f, 0x9a, 0x95, 0xea, 0xf7,
+  0x20, 0xe0, 0x41, 0xe0, 0x12, 0xc0, 0x93, 0x2f, 0x99, 0x1f, 0x99, 0x27,
+  0x99, 0x1f, 0x90, 0x5d, 0x80, 0x91, 0x00, 0x10, 0xe8, 0x2f, 0xf0, 0xe0,
+  0xef, 0x5f, 0xff, 0x4e, 0x90, 0x83, 0x8f, 0x5f, 0x80, 0x93, 0x00, 0x10,
+  0x45, 0xbb, 0x33, 0x0f, 0x2f, 0x5f, 0x26, 0x17, 0x60, 0xf3, 0x08, 0x95,
+  0x48, 0x2f, 0x2f, 0xe1, 0x30, 0xe0, 0x54, 0xe1, 0x94, 0x2f, 0x91, 0x70,
+  0x46, 0x95, 0x82, 0x2f, 0x81, 0x70, 0x26, 0x95, 0x98, 0x13, 0x25, 0x27,
+  0x3f, 0x5f, 0x38, 0x30, 0xa9, 0xf7, 0x30, 0xe0, 0x44, 0xe1, 0x96, 0x2f,
+  0x91, 0x70, 0x66, 0x95, 0x82, 0x2f, 0x81, 0x70, 0x26, 0x95, 0x98, 0x13,
+  0x24, 0x27, 0x3f, 0x5f, 0x33, 0x30, 0xa9, 0xf7, 0x20, 0x95, 0x82, 0x2f,
+  0x8f, 0x71, 0x08, 0x95, 0xcf, 0x93, 0xdf, 0x93, 0xc4, 0x2f, 0xd5, 0x2f,
+  0xa8, 0x2f, 0xb9, 0x2f, 0x9f, 0xef, 0x2f, 0xef, 0x30, 0xe0, 0x15, 0xc0,
+  0x8d, 0x91, 0x98, 0x27, 0x49, 0x2f, 0x50, 0xe0, 0x84, 0x2f, 0x95, 0x2f,
+  0x87, 0x56, 0x9e, 0x4f, 0xe8, 0x2f, 0xf9, 0x2f, 0xc8, 0x95, 0x90, 0x2d,
+  0x92, 0x27, 0x47, 0x56, 0x5d, 0x4f, 0xe4, 0x2f, 0xf5, 0x2f, 0xc8, 0x95,
+  0x80, 0x2d, 0x3f, 0x5f, 0x28, 0x2f, 0x36, 0x17, 0x48, 0xf3, 0x90, 0x95,
+  0x98, 0x83, 0x20, 0x95, 0x29, 0x83, 0xdf, 0x91, 0xcf, 0x91, 0x08, 0x95,
+  0xcf, 0x93, 0xdf, 0x93, 0xc8, 0x2f, 0xd9, 0x2f, 0x20, 0xe0, 0x30, 0xe0,
+  0x0c, 0xc0, 0xec, 0x2f, 0xfd, 0x2f, 0xe2, 0x0f, 0xf3, 0x1f, 0xa6, 0x2f,
+  0xb7, 0x2f, 0xa2, 0x0f, 0xb3, 0x1f, 0x8c, 0x91, 0x80, 0x83, 0x2f, 0x5f,
+  0x3f, 0x4f, 0x24, 0x17, 0x35, 0x07, 0x8c, 0xf3, 0x8c, 0x2f, 0x9d, 0x2f,
+  0xdf, 0x91, 0xcf, 0x91, 0x08, 0x95

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,149 @@
+/*  usbinput.c
+ *
+ *  Milkymist USB input devices driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_usbinput.h"
+
+static const unsigned char input_firmware[] = {
+#include "softusb-input.h"
+};
+
+#include "comloc.h"
+
+#define DEVICE_NAME "/dev/usbinput"
+
+static int mouse_consume;
+static int keyboard_consume;
+
+static rtems_id event_q;
+
+static rtems_isr interrupt_handler(rtems_vector_number n)
+{
+  unsigned char msg[8];
+  int i;
+
+  lm32_interrupt_ack(1 << MM_IRQ_USB);
+
+  while(mouse_consume != COMLOC_MEVT_PRODUCE) {
+    for(i=0;i<4;i++)
+      msg[i] = COMLOC_MEVT(4*mouse_consume+i);
+    rtems_message_queue_send(event_q, msg, 4);
+    mouse_consume = (mouse_consume + 1) & 0x0f;
+  }
+
+  while(keyboard_consume != COMLOC_KEVT_PRODUCE) {
+    for(i=0;i<8;i++)
+      msg[i] = COMLOC_KEVT(8*keyboard_consume+i);
+    rtems_message_queue_send(event_q, msg, 8);
+    keyboard_consume = (keyboard_consume + 1) & 0x07;
+  }
+}
+
+rtems_device_driver usbinput_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  volatile unsigned int *usb_dmem
+    = (volatile unsigned int *)MM_SOFTUSB_DMEM_BASE;
+  volatile unsigned int *usb_pmem
+    = (volatile unsigned int *)MM_SOFTUSB_PMEM_BASE;
+  int i, nwords;
+  rtems_isr_entry dummy;
+
+  MM_WRITE(MM_SOFTUSB_CONTROL, SOFTUSB_CONTROL_RESET);
+  for(i=0;i<SOFTUSB_DMEM_SIZE/4;i++)
+    usb_dmem[i] = 0;
+  for(i=0;i<SOFTUSB_PMEM_SIZE/2;i++)
+    usb_pmem[i] = 0;
+  nwords = (sizeof(input_firmware)+1)/2;
+  for(i=0;i<nwords;i++)
+    usb_pmem[i] = ((unsigned int)(input_firmware[2*i]))
+      |((unsigned int)(input_firmware[2*i+1]) << 8);
+  MM_WRITE(MM_SOFTUSB_CONTROL, 0);
+
+  mouse_consume = 0;
+  keyboard_consume = 0;
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create USB input device");
+
+  sc = rtems_message_queue_create(
+    rtems_build_name('U', 'S', 'B', 'I'),
+    64,
+    8,
+    0,
+    &event_q
+  );
+  RTEMS_CHECK_SC(sc, "create USB event queue");
+
+  rtems_interrupt_catch(interrupt_handler, MM_IRQ_USB, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_USB);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver usbinput_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  uint32_t count;
+
+  rtems_message_queue_flush(event_q, &count);
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver usbinput_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+  rtems_status_code sc;
+
+  if(rw_args->count < 8) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+
+  sc = rtems_message_queue_receive(
+    event_q,
+    rw_args->buffer,
+    (size_t *)&rw_args->bytes_moved,
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+
+  if(sc == RTEMS_SUCCESSFUL)
+    return RTEMS_SUCCESSFUL;
+  else {
+    rw_args->bytes_moved = 0;
+    return RTEMS_UNSATISFIED;
+  }
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,40 @@
+/*  milkymist_versions.h
+ *
+ *  Milkymist versioning driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_VERSIONS_H_
+#define __MILKYMIST_VERSIONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+rtems_device_driver versions_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver versions_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define VERSIONS_DRIVER_TABLE_ENTRY {versions_initialize, \
+NULL, NULL, versions_read, NULL, NULL}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_VERSIONS_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,133 @@
+/*  versions.c
+ *
+ *  Milkymist versioning driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <rtems/status-checks.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+#include "../include/system_conf.h"
+#include "milkymist_versions.h"
+
+#define SOC_DEVICE_NAME "/dev/soc"
+#define PCB_DEVICE_NAME "/dev/pcb"
+#define PCBREV_DEVICE_NAME "/dev/pcb_rev"
+
+rtems_device_driver versions_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+
+  sc = rtems_io_register_name(SOC_DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create SoC version device");
+  sc = rtems_io_register_name(PCB_DEVICE_NAME, major, 1);
+  RTEMS_CHECK_SC(sc, "create PCB type device");
+  sc = rtems_io_register_name(PCBREV_DEVICE_NAME, major, 2);
+  RTEMS_CHECK_SC(sc, "create PCB revision device");
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static int get_soc_version(char *buffer)
+{
+  char fmt[13];
+  char *version;
+  int len;
+  unsigned int id;
+  unsigned int major, minor, subminor, rc;
+
+  id = MM_READ(MM_SYSTEM_ID);
+	major = (id & 0xf0000000) >> 28;
+	minor = (id & 0x0f000000) >> 24;
+	subminor = (id & 0x00f00000) >> 20;
+	rc = (id & 0x000f0000) >> 16;
+
+  version = fmt;
+  version += sprintf(version, "%u.%u", major, minor);
+	if (subminor != 0)
+		version += sprintf(version, ".%u", subminor);
+	if (rc != 0)
+		version += sprintf(version, "RC%u", rc);
+
+  len = version - fmt;
+  memcpy(buffer, fmt, len);
+  return len;
+}
+
+static int get_pcb_type(char *buffer)
+{
+  unsigned int id;
+
+  id = MM_READ(MM_SYSTEM_ID);
+  buffer[0] = (id & 0x0000ff00) >> 8;
+  buffer[1] = id & 0x000000ff;
+  return 2;
+}
+
+static int get_pcb_revision(char *buffer)
+{
+  unsigned int v;
+
+  v = MM_READ(MM_GPIO_IN);
+  v = (v & 0x78) >> 3;
+  buffer[0] = '0' + v;
+  return 1;
+}
+
+rtems_device_driver versions_read(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+
+  if(rw_args->offset != 0) {
+    rw_args->bytes_moved = 0;
+    return RTEMS_SUCCESSFUL;
+  }
+
+  switch (minor) {
+    case 0:
+      if (rw_args->count < 12) {
+        rw_args->bytes_moved = 0;
+        return RTEMS_UNSATISFIED;
+      }
+      rw_args->bytes_moved = get_soc_version((char *)rw_args->buffer);
+      return RTEMS_SUCCESSFUL;
+    case 1:
+      if (rw_args->count < 2) {
+        rw_args->bytes_moved = 0;
+        return RTEMS_UNSATISFIED;
+      }
+      rw_args->bytes_moved = get_pcb_type((char *)rw_args->buffer);
+      return RTEMS_SUCCESSFUL;
+    case 2:
+      if (rw_args->count < 1) {
+        rw_args->bytes_moved = 0;
+        return RTEMS_UNSATISFIED;
+      }
+      rw_args->bytes_moved = get_pcb_revision((char *)rw_args->buffer);
+      return RTEMS_SUCCESSFUL;
+  }
+
+  rw_args->bytes_moved = 0;
+  return RTEMS_UNSATISFIED;
+}

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,67 @@
+/*  milkymist_video.h
+ *
+ *  Milkymist video input driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010 Sebastien Bourdeauducq
+ */
+
+#ifndef __MILKYMIST_VIDEO_H_
+#define __MILKYMIST_VIDEO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ioctls */
+#define VIDEO_BUFFER_LOCK      0x5600
+#define VIDEO_BUFFER_UNLOCK    0x5601
+
+#define VIDEO_SET_BRIGHTNESS   0x5602
+#define VIDEO_GET_BRIGHTNESS   0x5603
+#define VIDEO_SET_CONTRAST     0x5604
+#define VIDEO_GET_CONTRAST     0x5605
+#define VIDEO_SET_HUE          0x5606
+#define VIDEO_GET_HUE          0x5607
+#define VIDEO_GET_SIGNAL       0x5608
+
+#define VIDEO_SET_REGISTER     0x5609
+#define VIDEO_GET_REGISTER     0x560a
+
+rtems_device_driver video_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver video_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver video_close(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+rtems_device_driver video_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+);
+
+#define VIDEO_DRIVER_TABLE_ENTRY {video_initialize, \
+video_open, video_close, NULL, NULL, video_control}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MILKYMIST_VIDEO_H_ */

diff -u /dev/null rtems/c/src/lib/libbsp/lm32/shared/milkymist_video/video.c:1.1
--- /dev/null	Mon Aug  1 09:10:29 2011
+++ rtems/c/src/lib/libbsp/lm32/shared/milkymist_video/video.c	Mon Aug  1 08:48:40 2011
@@ -0,0 +1,356 @@
+/*  video.c
+ *
+ *  Milkymist video input driver for RTEMS
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id$
+ *
+ *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
+ */
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <rtems/libio.h>
+#include <rtems/status-checks.h>
+#include "../include/system_conf.h"
+#include "milkymist_video.h"
+
+#define DEVICE_NAME "/dev/video"
+#define N_BUFFERS 3
+#define FRAME_W 720
+#define FRAME_H 288
+
+static bool buffers_locked[N_BUFFERS];
+static void *buffers[N_BUFFERS];
+static int last_buffer;
+static int current_buffer;
+
+static rtems_isr frame_handler(rtems_vector_number n)
+{
+  int remaining_attempts;
+
+  lm32_interrupt_ack(1 << MM_IRQ_VIDEOIN);
+  
+  last_buffer = current_buffer;
+  
+  /* get a new buffer */
+  remaining_attempts = N_BUFFERS;
+  do {
+    current_buffer++;
+    if(current_buffer == N_BUFFERS)
+      current_buffer = 0;
+    remaining_attempts--;
+  } while(buffers_locked[current_buffer] && (remaining_attempts > 0));
+
+  MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]);
+  
+  if(buffers_locked[current_buffer])
+    printk("Failed to find unlocked buffer\n");
+}
+
+static void i2c_delay(void)
+{
+  unsigned int i;
+
+  for(i=0;i<1000;i++) __asm__("nop");
+}
+
+/* I2C bit-banging functions from http://en.wikipedia.org/wiki/I2c */
+static unsigned int i2c_read_bit(void)
+{
+  unsigned int bit;
+
+  /* Let the slave drive data */
+  MM_WRITE(MM_BT656_I2C, 0);
+  i2c_delay();
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
+  i2c_delay();
+  bit = MM_READ(MM_BT656_I2C) & BT656_I2C_SDAIN;
+  i2c_delay();
+  MM_WRITE(MM_BT656_I2C, 0);
+  return bit;
+}
+
+static void i2c_write_bit(unsigned int bit)
+{
+  if(bit) {
+    MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT);
+  } else {
+    MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
+  }
+  i2c_delay();
+  MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC);
+  i2c_delay();
+  MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) & ~BT656_I2C_SDC);
+}
+
+static int i2c_started;
+
+static void i2c_start_cond(void)
+{
+  if(i2c_started) {
+    /* set SDA to 1 */
+    MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDAOUT);
+    i2c_delay();
+    MM_WRITE(MM_BT656_I2C, MM_READ(MM_BT656_I2C) | BT656_I2C_SDC);
+  }
+  /* SCL is high, set SDA from 1 to 0 */
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC);
+  i2c_delay();
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
+  i2c_started = 1;
+}
+
+static void i2c_stop_cond(void)
+{
+  /* set SDA to 0 */
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE);
+  i2c_delay();
+  /* Clock stretching */
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDAOE|BT656_I2C_SDC);
+  /* SCL is high, set SDA from 0 to 1 */
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
+  i2c_delay();
+  i2c_started = 0;
+}
+
+static unsigned int i2c_write(unsigned char byte)
+{
+  unsigned int bit;
+  unsigned int ack;
+
+  for(bit = 0; bit < 8; bit++) {
+    i2c_write_bit(byte & 0x80);
+    byte <<= 1;
+  }
+  ack = !i2c_read_bit();
+  return ack;
+}
+
+static unsigned char i2c_read(int ack)
+{
+  unsigned char byte = 0;
+  unsigned int bit;
+
+  for(bit = 0; bit < 8; bit++) {
+    byte <<= 1;
+    byte |= i2c_read_bit();
+  }
+  i2c_write_bit(!ack);
+  return byte;
+}
+
+static unsigned char read_reg(unsigned char addr)
+{
+  unsigned char r;
+
+  i2c_start_cond();
+  i2c_write(0x40);
+  i2c_write(addr);
+  i2c_start_cond();
+  i2c_write(0x41);
+  r = i2c_read(0);
+  i2c_stop_cond();
+
+  return r;
+}
+
+static void write_reg(unsigned char addr, unsigned char val)
+{
+  i2c_start_cond();
+  i2c_write(0x40);
+  i2c_write(addr);
+  i2c_write(val);
+  i2c_stop_cond();
+}
+
+static const char vreg_addr[] = {
+  0x1d, 0xc3, 0xc4
+};
+
+static const char vreg_dat[] = {
+  0x40, 0x05, 0x80
+};
+
+rtems_device_driver video_initialize(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_status_code sc;
+  rtems_isr_entry dummy;
+  int i;
+  
+  MM_WRITE(MM_BT656_I2C, BT656_I2C_SDC);
+
+  sc = rtems_io_register_name(DEVICE_NAME, major, 0);
+  RTEMS_CHECK_SC(sc, "create video input device");
+
+  rtems_interrupt_catch(frame_handler, MM_IRQ_VIDEOIN, &dummy);
+  bsp_interrupt_vector_enable(MM_IRQ_VIDEOIN);
+  
+  for(i=0;i<sizeof(vreg_addr);i++)
+    write_reg(vreg_addr[i], vreg_dat[i]);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver video_open(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  int i;
+  int status;
+
+  for(i=0;i<N_BUFFERS;i++) {
+    status = posix_memalign(&buffers[i], 32, 2*FRAME_W*FRAME_H);
+    if(status != 0) {
+      i--;
+      while(i > 0) {
+        free(buffers[i]);
+        i--;
+      }
+      return RTEMS_UNSATISFIED;
+    }
+  }
+  
+  last_buffer = -1;
+  current_buffer = 0;
+  
+  MM_WRITE(MM_BT656_BASE, (unsigned int)buffers[current_buffer]);
+  MM_WRITE(MM_BT656_FILTERSTATUS, BT656_FILTER_FIELD1);
+  
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver video_close(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  int i;
+  
+  MM_WRITE(MM_BT656_FILTERSTATUS, 0);
+  while(MM_READ(MM_BT656_FILTERSTATUS) & BT656_FILTER_INFRAME);
+  for(i=0;i<N_BUFFERS;i++)
+    free(buffers[i]);
+  return RTEMS_SUCCESSFUL;
+}
+
+static void invalidate_caches(void)
+{
+  volatile char *flushbase = (char *)FMLBRG_FLUSH_BASE;
+  int i, offset;
+
+  offset = 0;
+  for (i=0;i<FMLBRG_LINE_COUNT;i++) {
+    flushbase[offset] = 0;
+    offset += FMLBRG_LINE_LENGTH;
+  }
+  __asm__ volatile( /* Invalidate Level-1 data cache */
+    "wcsr DCC, r0\n"
+    "nop\n"
+  );
+}
+
+rtems_device_driver video_control(
+  rtems_device_major_number major,
+  rtems_device_minor_number minor,
+  void *arg
+)
+{
+  rtems_libio_ioctl_args_t *args = arg;
+  unsigned int *a = (unsigned int *)args->buffer;
+  rtems_status_code sc;
+
+  switch (args->command) {
+    case VIDEO_BUFFER_LOCK:
+      if (last_buffer == -1) {
+        *a = 0;
+      } else {
+        bsp_interrupt_vector_disable(MM_IRQ_VIDEOIN);
+        if(*a) invalidate_caches();
+        *a = (unsigned int)buffers[last_buffer];
+        buffers_locked[last_buffer] = true;
+        bsp_interrupt_vector_enable(MM_IRQ_VIDEOIN);
+      }
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_BUFFER_UNLOCK: {
+      int i;
+      for(i=0;i<N_BUFFERS;i++) {
+        if ((unsigned int)buffers[i] == (unsigned int)a) {
+          buffers_locked[i] = false;
+          break;
+        }
+      }
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    }
+    
+    case VIDEO_SET_BRIGHTNESS:
+      write_reg(0x0a, (unsigned int)a);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_GET_BRIGHTNESS:
+      *a = read_reg(0x0a);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_SET_CONTRAST:
+      write_reg(0x08, (unsigned int)a);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_GET_CONTRAST:
+      *a = read_reg(0x08);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_SET_HUE:
+      write_reg(0x0b, (unsigned int)a);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_GET_HUE:
+      *a = read_reg(0x0b);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    
+    case VIDEO_GET_SIGNAL:
+      *a = read_reg(0x10);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    
+    case VIDEO_SET_REGISTER:
+      write_reg(((unsigned int )a & 0xffff0000) >> 16,
+        (unsigned int)a & 0x0000ffff);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    case VIDEO_GET_REGISTER:
+      *a = read_reg(*a);
+      sc = RTEMS_SUCCESSFUL;
+      break;
+    
+    default:
+      sc = RTEMS_UNSATISFIED;
+      break;
+  }
+
+  if (sc == RTEMS_SUCCESSFUL)
+    args->ioctl_return = 0;
+  else
+    args->ioctl_return = -1;
+
+  return sc;
+}

diff -u rtems/c/src/lib/libbsp/lm32/shared/start/start.S:1.9 rtems/c/src/lib/libbsp/lm32/shared/start/start.S:1.10
--- rtems/c/src/lib/libbsp/lm32/shared/start/start.S:1.9	Fri May  7 14:25:08 2010
+++ rtems/c/src/lib/libbsp/lm32/shared/start/start.S	Mon Aug  1 08:48:40 2011
@@ -145,24 +145,18 @@
 	bi	.clear_bss
 .end_clear_bss:
 	mvi	r1, 0
+	be	r4, r0, .no_rescue
+	mvhi	r1, hi(.rescue_str)
+	ori	r1, r1, lo(.rescue_str)
+.no_rescue:
 	mvhi	r7, hi(boot_card)
 	ori	r7, r7, lo(boot_card)
 	call	r7
 	# boot_card returns when RTEMS is shutdown
-#if ON_SIMULATOR
-    #if defined(ON_GDB_SIM)
-	#define	SYS_exit	1
-        mvi     r8, SYS_exit
-        scall
-    #else
-	# on qemu-lm32
-	#define	SYS_CTRL_REG 0xffff0000
-	mvhi	r7, hi(SYS_CTRL_REG)
-	ori	r7, r7, lo(SYS_CTRL_REG)
-	sw	(r7+0), r0
-    #endif
-#endif
-
 .dead_end:
 	bi	.dead_end
 
+.section .rodata
+.rescue_str:
+	.ascii "rescue"
+

diff -u rtems/c/src/lib/libbsp/lm32/shared/startup/bspstart.c:1.1 rtems/c/src/lib/libbsp/lm32/shared/startup/bspstart.c:1.2
--- rtems/c/src/lib/libbsp/lm32/shared/startup/bspstart.c:1.1	Thu Dec  4 16:55:13 2008
+++ rtems/c/src/lib/libbsp/lm32/shared/startup/bspstart.c	Mon Aug  1 08:48:40 2011
@@ -35,10 +35,9 @@
  *  This routine does the bulk of the system initialization.
  */
 
-void bsp_start( void )
+void bsp_start(void)
 {
-  /* Setup console baud rate which we derive from
-     Mico System Builder (MSB) generated system_conf.h */
+  /* Setup console baud rate */
   BSP_uart_init(UART_BAUD_RATE);
 }
 



--

Generated by Deluxe Loginfo [http://www.codewiz.org/projects/index.html#loginfo] 2.122 by Bernardo Innocenti <bernie at develer.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/vc/attachments/20110801/0bac48f3/attachment.html>


More information about the vc mailing list