summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/lm32
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2011-08-01 13:48:40 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2011-08-01 13:48:40 +0000
commitdce1032b6cdc2cd3c4e6b0ca3695aca6558c56c3 (patch)
treee485d78b238db7255395470e037305af8b8a642c /c/src/lib/libbsp/lm32
parent2011-08-01 Jennifer Averett <Jennifer.Averett@OARcorp.com> (diff)
downloadrtems-dce1032b6cdc2cd3c4e6b0ca3695aca6558c56c3.tar.bz2
2011-08-01 Sebastien Bourdeauducq <sebastien.bourdeauducq@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
Diffstat (limited to 'c/src/lib/libbsp/lm32')
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/ChangeLog23
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/Makefile.am87
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/README29
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/include/bsp.h34
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/include/system_conf.h308
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/include/tm27.h32
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg1
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/preinstall.am70
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c56
-rw-r--r--c/src/lib/libbsp/lm32/milkymist/startup/linkcmds6
-rw-r--r--c/src/lib/libbsp/lm32/shared/ChangeLog21
-rw-r--r--c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c2
-rw-r--r--c/src/lib/libbsp/lm32/shared/include/irq.h49
-rw-r--r--c/src/lib/libbsp/lm32/shared/irq/irq.c37
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c443
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h63
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c132
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h46
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c40
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_console/console.c306
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c69
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h11
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c130
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h55
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c195
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h53
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c278
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c198
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h46
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c106
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h46
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c370
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h19
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c104
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h46
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c504
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h63
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h57
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c144
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c28
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h85
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c163
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h26
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h46
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h329
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c149
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h40
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c133
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h67
-rw-r--r--c/src/lib/libbsp/lm32/shared/milkymist_video/video.c356
-rw-r--r--c/src/lib/libbsp/lm32/shared/start/start.S22
-rw-r--r--c/src/lib/libbsp/lm32/shared/startup/bspstart.c5
52 files changed, 4640 insertions, 1088 deletions
diff --git a/c/src/lib/libbsp/lm32/milkymist/ChangeLog b/c/src/lib/libbsp/lm32/milkymist/ChangeLog
index d4008aa6cb..eb7582ed24 100644
--- a/c/src/lib/libbsp/lm32/milkymist/ChangeLog
+++ b/c/src/lib/libbsp/lm32/milkymist/ChangeLog
@@ -1,3 +1,24 @@
+2011-08-01 Sebastien Bourdeauducq <sebastien.bourdeauducq@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@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 --git a/c/src/lib/libbsp/lm32/milkymist/Makefile.am b/c/src/lib/libbsp/lm32/milkymist/Makefile.am
index 0e09d57949..5d4d5580c3 100644
--- a/c/src/lib/libbsp/lm32/milkymist/Makefile.am
+++ b/c/src/lib/libbsp/lm32/milkymist/Makefile.am
@@ -10,8 +10,25 @@ include_bspdir = $(includedir)/bsp
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 @@ DISTCLEANFILES = include/bspopts.h
noinst_PROGRAMS =
-include_HEADERS += ../../shared/include/coverhd.h
include_HEADERS += include/system_conf.h
noinst_LIBRARIES = libbspstart.a
@@ -33,33 +49,74 @@ libbsp_a_SOURCES =
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
+
+# 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 --git a/c/src/lib/libbsp/lm32/milkymist/README b/c/src/lib/libbsp/lm32/milkymist/README
index 20568ee496..b44d3735c2 100644
--- a/c/src/lib/libbsp/lm32/milkymist/README
+++ b/c/src/lib/libbsp/lm32/milkymist/README
@@ -2,20 +2,19 @@
# $Id$
#
-This is a BSP written by Yann Sionneau <yann.sionneau@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 --git a/c/src/lib/libbsp/lm32/milkymist/include/bsp.h b/c/src/lib/libbsp/lm32/milkymist/include/bsp.h
index 2d5a91c7c0..940e280fa2 100644
--- a/c/src/lib/libbsp/lm32/milkymist/include/bsp.h
+++ b/c/src/lib/libbsp/lm32/milkymist/include/bsp.h
@@ -8,8 +8,7 @@
*
* $Id$
*
- * Yann Sionneau <yann.sionneau@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 @@ extern int rtems_minimac_driver_attach (struct rtems_bsdnet_ifconfig *config,
#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 --git a/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h b/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h
index 5f49c91f76..6588e8f5eb 100644
--- a/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h
+++ b/c/src/lib/libbsp/lm32/milkymist/include/system_conf.h
@@ -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)
-#define MM_TIMER1_COMPARE (0xe0001024)
-#define MM_TIMER1_COUNTER (0xe0001028)
-#define MM_TIMER1_CONTROL (0xe0001020)
+/* System ID and reset */
+#define MM_SYSTEM_ID (0xe000103c)
-#define MM_TIMER0_COMPARE (0xe0001014)
-#define MM_TIMER0_COUNTER (0xe0001018)
-#define MM_TIMER0_CONTROL (0xe0001010)
+/* ICAP */
+#define MM_ICAP (0xe0001034)
-#define TIMER_ENABLE (0x01)
-#define TIMER_AUTORESTART (0x02)
+#define ICAP_READY (0x01)
+#define ICAP_CE (0x10000)
+#define ICAP_WRITE (0x20000)
-#define MM_VGA_RESET_MODE (0x01)
-#define MM_VGA_RESET (0xe0003000)
-#define MM_VGA_BASEADDRESS (0xe0003024)
+/* 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_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_VGA_BURST_COUNT (0xe000302C)
+
+#define MM_VGA_DDC (0xe0003030)
+
+#define MM_VGA_CLKSEL (0xe0003034)
+
+#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
-#define MM_MINIMAC_STATE1 (0xe0009014)
-#define MM_MINIMAC_ADDR1 (0xe0009018)
-#define MM_MINIMAC_COUNT1 (0xe000901C)
+/* Flash partitions */
-#define MM_MINIMAC_STATE2 (0xe0009020)
-#define MM_MINIMAC_ADDR2 (0xe0009024)
-#define MM_MINIMAC_COUNT2 (0xe0009028)
+#define FLASH_SECTOR_SIZE (128*1024)
-#define MM_MINIMAC_STATE3 (0xe000902C)
-#define MM_MINIMAC_ADDR3 (0xe0009030)
-#define MM_MINIMAC_COUNT3 (0xe0009034)
+#define FLASH_PARTITION_COUNT (5)
-#define MM_MINIMAC_TXREMAINING (0xe000903C)
-#define MM_MINIMAC_TXADR (0xe0009038)
+#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 --git a/c/src/lib/libbsp/lm32/milkymist/include/tm27.h b/c/src/lib/libbsp/lm32/milkymist/include/tm27.h
deleted file mode 100644
index a10e11cab1..0000000000
--- a/c/src/lib/libbsp/lm32/milkymist/include/tm27.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * tm27.h
- *
- * 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 _RTEMS_TMTEST27
-#error "This is an RTEMS internal file you must not include directly."
-#endif
-
-#ifndef __tm27_h
-#define __tm27_h
-
-/*
- * Stuff for Time Test 27
- */
-
-#define MUST_WAIT_FOR_INTERRUPT 0
-
-#define Install_tm27_vector( handler ) set_vector( (handler), 0, 1 )
-
-#define Cause_tm27_intr() /* empty */
-
-#define Clear_tm27_intr() /* empty */
-
-#define Lower_tm27_intr() /* empty */
-
-#endif
diff --git a/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg b/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg
index 5571f7b113..5a44658389 100644
--- a/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg
+++ b/c/src/lib/libbsp/lm32/milkymist/make/custom/milkymist.cfg
@@ -18,7 +18,6 @@ CPU_CFLAGS = -mbarrel-shift-enabled -mmultiply-enabled \
-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 --git a/c/src/lib/libbsp/lm32/milkymist/preinstall.am b/c/src/lib/libbsp/lm32/milkymist/preinstall.am
index b3375ceee9..c3217ef01a 100644
--- a/c/src/lib/libbsp/lm32/milkymist/preinstall.am
+++ b/c/src/lib/libbsp/lm32/milkymist/preinstall.am
@@ -41,10 +41,74 @@ $(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
$(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 @@ $(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INC
$(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 --git a/c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c b/c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c
new file mode 100644
index 0000000000..202ff47c0d
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/milkymist/startup/bspclean.c
@@ -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 --git a/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds b/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds
index 490ae6093a..aeebec78d1 100644
--- a/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds
+++ b/c/src/lib/libbsp/lm32/milkymist/startup/linkcmds
@@ -9,13 +9,13 @@ ENTRY(_start)
* 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 --git a/c/src/lib/libbsp/lm32/shared/ChangeLog b/c/src/lib/libbsp/lm32/shared/ChangeLog
new file mode 100644
index 0000000000..c7fa29ca85
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/ChangeLog
@@ -0,0 +1,21 @@
+2011-08-01 Sebastien Bourdeauducq <sebastien.bourdeauducq@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 --git a/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c b/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c
index b1d453e691..a4dc3f66f0 100644
--- a/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c
+++ b/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c
@@ -25,6 +25,8 @@
* SUCH DAMAGE.
*/
+/* $Id$ */
+
#include <bsp.h>
#include <string.h>
#include <signal.h>
diff --git a/c/src/lib/libbsp/lm32/shared/include/irq.h b/c/src/lib/libbsp/lm32/shared/include/irq.h
new file mode 100644
index 0000000000..784b0c0221
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/include/irq.h
@@ -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@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 --git a/c/src/lib/libbsp/lm32/shared/irq/irq.c b/c/src/lib/libbsp/lm32/shared/irq/irq.c
new file mode 100644
index 0000000000..f5d9f82050
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/irq/irq.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c b/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c
index 671d4f165b..b467538122 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_ac97/ac97.c
@@ -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@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)
- 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;
+static struct snd_buffer *play_q[PLAY_Q_SIZE];
+static int play_produce;
+static int play_consume;
+static int play_level;
- return RTEMS_SUCCESSFUL;
+/* buffers played, for application to collect */
+static rtems_id play_q_done;
+
+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);
+}
+
+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 gpio_close(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
+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;
- return RTEMS_SUCCESSFUL;
+ 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;
+ }
}
-rtems_device_driver gpio_write(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg
-)
+static rtems_status_code ioctl_read_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 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_control(
- 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)
+{
+ 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;
+ }
+
+ 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 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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h b/c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h
new file mode 100644
index 0000000000..a13a0481ee
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_ac97/milkymist_ac97.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c b/c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c
new file mode 100644
index 0000000000..5772a781a1
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_buttons/buttons.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h b/c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h
new file mode 100644
index 0000000000..59eedb1e4b
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_buttons/milkymist_buttons.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
index eb28ead0cc..72c770b608 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c b/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c
index 05ac7803df..6a000090f2 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_console/console.c
@@ -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@mrf.fi>, 2008,
- * Micro-Research Finland Oy
- *
- * COPYRIGHT (c) Yann Sionneau <yann.sionneau@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
-)
+static struct rtems_termios_tty *tty;
+
+static int mmconsole_first_open(int major, int minor, void *arg)
{
- rtems_status_code status;
+ tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
+ return rtems_termios_set_initial_baud(tty, UART_BAUD_RATE);
+}
- printk("console_initialize\n");
+static int mmconsole_last_close(int major, int minor, void *arg)
+{
+ return 0;
+}
- status = rtems_io_register_name(
- "/dev/console",
- major,
- (rtems_device_minor_number) 0
- );
+static int mmconsole_set_attributes(int minor, const struct termios *t)
+{
+ int baud;
- if (status != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(status);
+ 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;
+ }
- return RTEMS_SUCCESSFUL;
-}
+ if (baud > 0)
+ MM_WRITE(MM_UART_DIV, CPU_FREQUENCY/baud/16);
-/* is_character_ready
- *
- * This routine returns TRUE if a character is available.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- *
- * Return values:
- */
+ return 0;
+}
-bool is_character_ready(
- char *ch
-)
+static ssize_t mmconsole_write(int minor, const char *buf, size_t n)
{
- return BSP_uart_is_character_ready(ch);
-}
+ rtems_interrupt_level level;
-/* inbyte
- *
- * This routine reads a character from the SOURCE.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- *
- * Return values:
- * character read from SOURCE
- */
+ rtems_interrupt_disable(level);
+ BSP_uart_txbusy = true;
+ MM_WRITE(MM_UART_RXTX, *buf);
+ rtems_interrupt_enable(level);
+ return 0;
+}
-int inbyte( void )
+static rtems_isr mmconsole_txdone(rtems_vector_number n)
{
- /*
- * If polling, wait until a character is available.
- */
+ BSP_uart_txbusy = false;
+ lm32_interrupt_ack(1 << MM_IRQ_UARTTX);
+ rtems_termios_dequeue_characters(tty, 1);
+}
- return BSP_uart_polled_read();
+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);
}
-/* 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 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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c b/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c
index 229ee40985..f32a1615fd 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.c
@@ -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@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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h b/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h
index 1aded4231d..806f491bba 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_console/uart.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c b/c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c
new file mode 100644
index 0000000000..a51d17da1c
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_dmx/dmx.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h b/c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h
new file mode 100644
index 0000000000..dd4177d7a4
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_dmx/milkymist_dmx.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c b/c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c
new file mode 100644
index 0000000000..2efc08c458
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_flash/flash.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h b/c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h
new file mode 100644
index 0000000000..f8d5532f84
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_flash/milkymist_flash.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c b/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c
index 2fbb9c0eca..b1d0612e51 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_framebuffer/framebuffer.c
@@ -11,13 +11,13 @@
*
* COPYRIGHT (c) Yann Sionneau <yann.sionneau@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 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;
+static unsigned short int *backbuffer;
+static unsigned short int *lastbuffer;
-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 @@ static int get_var_screen_info( struct fb_var_screeninfo *info )
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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c b/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c
index 430d36514c..5112897e4a 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_gpio/gpio.c
@@ -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@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"
+struct milkymist_gpio {
+ char *name;
+ unsigned int mask;
+ bool readonly;
+};
-static struct milkymist_gpio {
- rtems_device_minor_number minor;
- unsigned int *address;
- unsigned int offset;
- uint8_t readonly;
- pthread_mutex_t mutex;
-} gpio[5];
+static const struct milkymist_gpio gpio[] = {
+ {
+ .name = "/dev/led1",
+ .mask = GPIO_LED1,
+ .readonly = false
+ },
+ {
+ .name = "/dev/led2",
+ .mask = GPIO_LED2,
+ .readonly = false
+ },
+};
rtems_device_driver gpio_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;
+ rtems_status_code sc;
+ int i;
- printk( "gpio driver initializing..\n" );
-
- status = rtems_io_register_name(LED1_DEVICE_NAME, major, 0);
- if (status != RTEMS_SUCCESSFUL)
- {
- 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)
- {
- 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;
-
- 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;
-
- 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
+ data = MM_READ(MM_GPIO_OUT);
+
+ if (data & gpio[minor].mask)
+ *(uint8_t *)rw_args->buffer = '1';
else
- *(uint8_t *)rw_args->buffer = 0;
-
+ *(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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h b/c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h
new file mode 100644
index 0000000000..f83f79e583
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_gpio/milkymist_gpio.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c b/c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c
new file mode 100644
index 0000000000..0a7f215cb8
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_ir/ir.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h b/c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h
new file mode 100644
index 0000000000..9464ac92b6
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_ir/milkymist_ir.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c b/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c
new file mode 100644
index 0000000000..6ad1268d58
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_memcard/memcard.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h b/c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h
new file mode 100644
index 0000000000..252a3ded45
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_memcard/milkymist_memcard.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c b/c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c
new file mode 100644
index 0000000000..e71350bf1f
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_midi/midi.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h b/c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h
new file mode 100644
index 0000000000..203a945e6d
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_midi/milkymist_midi.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c b/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c
index 81ac56a7a7..5624cd2c50 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.c
@@ -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@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;
+#define CTS_EVENT RTEMS_EVENT_1
+#define RX_EVENT RTEMS_EVENT_1
+#define START_TRANSMIT_EVENT RTEMS_EVENT_2
-static uint32_t rx_slot_state[4] = {MM_MINIMAC_STATE0, MM_MINIMAC_STATE1,
- MM_MINIMAC_STATE2, MM_MINIMAC_STATE3};
+static struct arpcom arpcom;
+static rtems_id rx_daemon_id;
+static rtems_id tx_daemon_id;
-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
- */
+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);
-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);
-
- m->m_data = (caddr_t)(((int) m->m_data) + 2);
- }
-}
-#endif
+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);
-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 @@ int rtems_minimac_driver_attach (struct rtems_bsdnet_ifconfig *config,
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);
-
- 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);
- }
-
-
- minimac_write(MM_MINIMAC_SETUP, 0);
- rtems_event_send(sc->rxDaemonTid, INTERRUPT_EVENT);
}
-static void minimac_stop (struct minimac_softc *sc)
+static void minimac_stop(void)
{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- unsigned char j;
+ struct ifnet *ifp = &arpcom.ac_if;
ifp->if_flags &= ~IFF_RUNNING;
-
- /*
- * Shuts down receiver and transmitter
- */
- 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)
+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;
+ int error;
- /*
- * FIXME: All sorts of multicast commands need to be added here!
- */
+ 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:
- error = EINVAL;
- break;
- }
- return error;
-
+ break;
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
}
-rtems_isr minimac_rx_interrupt_handler(rtems_vector_number vector)
+
+static rtems_isr rx_interrupt_handler(rtems_vector_number vector)
{
- 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
- }
+ /* Deassert IRQ line.
+ * The RX daemon will then read all the slots we marked as empty.
+ */
+ 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_tx_interrupt_handler(rtems_vector_number vector)
+static void receive_packet(uint8_t *buffer, int length)
{
- 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
+ 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);
+}
-static void minimac_rxDaemon(void *arg)
+static void rx_daemon(void *arg)
{
- 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
- }
+
+ while(1) {
+ rtems_bsdnet_event_receive(RX_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT, &events);
- 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);
- }
+ 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);
}
- lm32_interrupt_ack(MM_ETHRX_IRQMASK); // we ack once for all the rx interruptions
- lm32_interrupt_unmask(MM_ETHRX_IRQMASK);
- }
-}
-static void minimac_txDaemon(void *arg)
-{
- struct ifnet *ifp = &minimac_softc.arpcom.ac_if;
- rtems_event_set events;
- struct mbuf *m;
- int txq;
-
- for (;;) {
- rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
- for (;;) {
- txq = 2048;
-
- if (txq < ifp->if_mtu)
- break;
-
- IF_DEQUEUE(&ifp->if_snd, m);
-
- if (!m)
- break;
- minimac_sendpacket(ifp, m);
- m_freem(m);
+ 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);
}
- ifp->if_flags &= ~IFF_OACTIVE;
}
}
-static void minimac_stats(struct minimac_softc *sc)
+/* RTEMS apparently doesn't support m_length() ... */
+static int copy_mbuf_chain(struct mbuf *m, uint8_t *target)
{
+ int len;
+ 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;
+ }
+ m = m->m_next;
+ }
+ return len;
}
-
-static void minimac_sendpacket(struct ifnet *ifp, struct mbuf *m)
+static void send_packet(struct ifnet *ifp, struct mbuf *m)
{
- struct mbuf *nm = m;
- struct minimac_softc *sc = &minimac_softc;
- unsigned int len = 0;
- struct mm_packet p;
+ unsigned int len;
unsigned int crc;
- uint8_t i;
- for (i = 0 ; i < 7 ; i++) // Preamble
- p.preamble[i] = 0x55;
- p.preamble[7] = 0xd5;
+ uint8_t *tx_buffer = (uint8_t *)(MINIMAC_TX_BASE+8);
- 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;
- }
+ len = copy_mbuf_chain(m, tx_buffer);
+ for(;len<60;len++)
+ tx_buffer[len] = 0x00; // Padding
- } while ( (nm = nm->m_next) != 0 );
- for ( ; len < 60 ; len++)
- p.raw_data[len] = 0x00; // Padding
+ crc = ether_crc32_le(tx_buffer, len) ^ 0xffffffff;
- crc = mm_ether_crc32((uint8_t *)p.raw_data, len); // CRC32
+ 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;
- 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
+ len += 4; // We add 4 bytes of CRC32
- if (len + 8 < 64) {
- printk("[minimac] Packet is too small !\n");
- sc->txErrors++; // update stats
- return;
+ MM_WRITE(MM_MINIMAC_TXCOUNT, len + 8);
+}
+
+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 tx_daemon(void *arg)
+{
+ struct ifnet *ifp = &arpcom.ac_if;
+ rtems_event_set events;
+ struct mbuf *m;
+
+ 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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h b/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h
index 6d967c5b6c..3cdde6838c 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_networking/network.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h b/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h
new file mode 100644
index 0000000000..a9c8bd58b9
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/milkymist_pfpu.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c b/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c
new file mode 100644
index 0000000000..ae0df355ea
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_pfpu/pfpu.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c b/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c
index bf9134fa75..ece2cf3912 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_timer/timer.c
@@ -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 @@ void benchmark_timer_initialize( void )
/* 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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h b/c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h
new file mode 100644
index 0000000000..71f544e498
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_tmu/milkymist_tmu.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c b/c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c
new file mode 100644
index 0000000000..b057fc9582
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_tmu/tmu.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h
new file mode 100644
index 0000000000..538022b30d
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/comloc.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h
new file mode 100644
index 0000000000..dc912124de
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/milkymist_usbinput.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h
new file mode 100644
index 0000000000..26feda0459
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/softusb-input.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c
new file mode 100644
index 0000000000..022d7306f6
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_usbinput/usbinput.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h b/c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h
new file mode 100644
index 0000000000..9799ad44c6
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_versions/milkymist_versions.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c b/c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c
new file mode 100644
index 0000000000..421419e77b
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_versions/versions.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h b/c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h
new file mode 100644
index 0000000000..8f8090872c
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_video/milkymist_video.h
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/milkymist_video/video.c b/c/src/lib/libbsp/lm32/shared/milkymist_video/video.c
new file mode 100644
index 0000000000..d8d706baaf
--- /dev/null
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_video/video.c
@@ -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 --git a/c/src/lib/libbsp/lm32/shared/start/start.S b/c/src/lib/libbsp/lm32/shared/start/start.S
index e155852b37..cd5cbe02ba 100644
--- a/c/src/lib/libbsp/lm32/shared/start/start.S
+++ b/c/src/lib/libbsp/lm32/shared/start/start.S
@@ -145,24 +145,18 @@ crt0:
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 --git a/c/src/lib/libbsp/lm32/shared/startup/bspstart.c b/c/src/lib/libbsp/lm32/shared/startup/bspstart.c
index 770d8d81b4..e2b118a73d 100644
--- a/c/src/lib/libbsp/lm32/shared/startup/bspstart.c
+++ b/c/src/lib/libbsp/lm32/shared/startup/bspstart.c
@@ -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);
}