diff --git a/tos/jtagwait/Makefile b/tos/jtagwait/Makefile
new file mode 100755
index 0000000..2773cd5
--- /dev/null
+++ b/tos/jtagwait/Makefile
@@ -0,0 +1,97 @@
+CROSS=Y
+
+CROSSBINDIR_IS_Y=m68k-atari-mint-
+CROSSBINDIR_IS_N=
+
+CROSSBINDIR=$(CROSSBINDIR_IS_$(CROSS))
+
+UNAME := $(shell uname)
+ifeq ($(CROSS), Y)
+ifeq ($(UNAME),Linux)
+PREFIX=m68k-atari-mint
+HATARI=hatari
+else
+PREFIX=m68k-atari-mint
+HATARI=/usr/local/bin/hatari
+endif
+else
+PREFIX=/usr
+endif
+
+DEPEND=depend
+TOPDIR = ../..
+
+INCLUDE=-I$(TOPDIR)/../libcmini/include -nostdlib
+LIBS=-lcmini -nostdlib -lgcc
+CC=$(PREFIX)/bin/gcc
+
+CC=$(CROSSBINDIR)gcc
+STRIP=$(CROSSBINDIR)strip
+STACK=$(CROSSBINDIR)stack
+
+APP=jtagwait.prg
+TEST_APP=$(APP)
+
+CFLAGS=\
+ -Os\
+ -g\
+ -Wl,-Map,mapfile\
+ -Wall
+
+SRCDIR=sources
+INCDIR=include
+INCLUDE+=-I$(INCDIR)
+
+CSRCS=\
+ $(SRCDIR)/jtagwait.c
+ASRCS=
+
+COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS)))
+AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS)))
+OBJS=$(COBJS) $(AOBJS)
+
+TRGTDIRS=./m5475 ./m5475/mshort
+OBJDIRS=$(patsubst %,%/objs,$(TRGTDIRS))
+
+#
+# multilib flags. These must match m68k-atari-mint-gcc -print-multi-lib output
+#
+m5475/$(APP):CFLAGS += -mcpu=5475
+m5475/mshort/$(APP): CFLAGS += -mcpu=5475 -mshort
+
+all:$(patsubst %,%/$(APP),$(TRGTDIRS))
+#
+# generate pattern rules for multilib object files.
+#
+define CC_TEMPLATE
+$(1)/objs/%.o:$(SRCDIR)/%.c
+ $(CC) $$(CFLAGS) $(INCLUDE) -c $$< -o $$@
+
+$(1)/objs/%.o:$(SRCDIR)/%.S
+ $(CC) $$(CFLAGS) $(INCLUDE) -c $$< -o $$@
+
+$(1)_OBJS=$(patsubst %,$(1)/objs/%,$(OBJS))
+$(1)/$(APP): $$($(1)_OBJS)
+ $(CC) $$(CFLAGS) -o $$@ $(TOPDIR)/../libcmini/$(1)/startup.o $$($(1)_OBJS) -L$(TOPDIR)/../libcmini/$(1) $(LIBS)
+ $(STRIP) $$@
+endef
+$(foreach DIR,$(TRGTDIRS),$(eval $(call CC_TEMPLATE,$(DIR))))
+
+$(DEPEND): $(ASRCS) $(CSRCS)
+ -rm -f $(DEPEND)
+ for d in $(TRGTDIRS);\
+ do $(CC) $(CFLAGS) $(INCLUDE) -M $(ASRCS) $(CSRCS) | sed -e "s#^\(.*\).o:#$$d/objs/\1.o:#" >> $(DEPEND); \
+ done
+
+
+clean:
+ @rm -f $(patsubst %,%/objs/*.o,$(TRGTDIRS)) $(patsubst %,%/$(APP),$(TRGTDIRS))
+ @rm -f $(DEPEND) mapfile
+
+.PHONY: printvars
+printvars:
+ @$(foreach V,$(.VARIABLES), $(if $(filter-out environment% default automatic, $(origin $V)),$(warning $V=$($V))))
+
+ifneq (clean,$(MAKECMDGOALS))
+-include $(DEPEND)
+endif
diff --git a/tos/jtagwait/include/driver_vec.h b/tos/jtagwait/include/driver_vec.h
new file mode 100644
index 0000000..8b9352a
--- /dev/null
+++ b/tos/jtagwait/include/driver_vec.h
@@ -0,0 +1,125 @@
+/*
+ * driver_vec.h
+ *
+ * Interface for exposure of BaS drivers to the OS
+ *
+ * This file is part of BaS_gcc.
+ *
+ * BaS_gcc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * BaS_gcc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with BaS_gcc. If not, see .
+ *
+ * Created on: 24.10.2013
+ * Author: Markus Fröschle
+ */
+
+#ifndef _DRIVER_VEC_H_
+#define _DRIVER_VEC_H_
+
+
+enum driver_type
+{
+ END_OF_DRIVERS, /* marks end of driver list */
+ BLOCKDEV_DRIVER,
+ CHARDEV_DRIVER,
+ VIDEO_DRIVER,
+ XHDI_DRIVER,
+ MCD_DRIVER,
+};
+
+struct generic_driver_interface
+{
+ uint32_t (*init)(void);
+ uint32_t (*read)(void *buf, size_t count);
+ uint32_t (*write)(const void *buf, size_t count);
+ uint32_t (*ioctl)(uint32_t request, ...);
+};
+
+
+/* Chained buffer descriptor */
+typedef volatile struct MCD_bufDesc_struct MCD_bufDesc;
+struct MCD_bufDesc_struct {
+ uint32_t flags; /* flags describing the DMA */
+ uint32_t csumResult; /* checksum from checksumming performed since last checksum reset */
+ int8_t *srcAddr; /* the address to move data from */
+ int8_t *destAddr; /* the address to move data to */
+ int8_t *lastDestAddr; /* the last address written to */
+ uint32_t dmaSize; /* the number of bytes to transfer independent of the transfer size */
+ MCD_bufDesc *next; /* next buffer descriptor in chain */
+ uint32_t info; /* private information about this descriptor; DMA does not affect it */
+};
+
+/* Progress Query struct */
+typedef volatile struct MCD_XferProg_struct {
+ int8_t *lastSrcAddr; /* the most-recent or last, post-increment source address */
+ int8_t *lastDestAddr; /* the most-recent or last, post-increment destination address */
+ uint32_t dmaSize; /* the amount of data transferred for the current buffer */
+ MCD_bufDesc *currBufDesc;/* pointer to the current buffer descriptor being DMAed */
+} MCD_XferProg;
+
+struct dma_driver_interface
+{
+ int32_t version;
+ int32_t magic;
+ int32_t (*dma_set_initiator)(int initiator);
+ uint32_t (*dma_get_initiator)(int requestor);
+ void (*dma_free_initiator)(int requestor);
+ int32_t (*dma_set_channel)(int requestor, void (*handler)(void));
+ int (*dma_get_channel)(int requestor);
+ void (*dma_free_channel)(int requestor);
+ void (*dma_clear_channel)(int channel);
+ int (*MCD_startDma)(int channel, int8_t *srcAddr, int16_t srcIncr, int8_t *destAddr, int16_t destIncr,
+ uint32_t dmaSize, uint32_t xferSize, uint32_t initiator, int32_t priority, uint32_t flags,
+ uint32_t funcDesc);
+ int (*MCD_dmaStatus)(int channel);
+ int (*MCD_XferProgrQuery)(int channel, MCD_XferProg *progRep);
+ int (*MCD_killDma)(int channel);
+ int (*MCD_continDma)(int channel);
+ int (*MCD_pauseDma)(int channel);
+ int (*MCD_resumeDma)(int channel);
+ int (*MCD_csumQuery)(int channel, uint32_t *csum);
+ void *(*dma_malloc)(long amount);
+ int (*dma_free)(void *addr);
+};
+
+struct xhdi_driver_interface
+{
+ uint32_t (*xhdivec)();
+};
+
+union interface
+{
+ struct generic_driver_interface *gdi;
+ struct xhdi_driver_interface *xhdi;
+ struct dma_driver_interface *dma;
+};
+
+struct generic_interface
+{
+ enum driver_type type;
+ char name[16];
+ char description[64];
+ int version;
+ int revision;
+ union interface interface;
+};
+
+struct driver_table
+{
+ uint32_t bas_version;
+ uint32_t bas_revision;
+ uint32_t (*remove_handler)(); /* calling this will disable the BaS' hook into trap #0 */
+ struct generic_interface *interfaces;
+};
+
+
+#endif /* _DRIVER_VEC_H_ */
diff --git a/tos/jtagwait/jtagwait.config b/tos/jtagwait/jtagwait.config
new file mode 100644
index 0000000..8cec188
--- /dev/null
+++ b/tos/jtagwait/jtagwait.config
@@ -0,0 +1 @@
+// ADD PREDEFINED MACROS HERE!
diff --git a/tos/jtagwait/jtagwait.creator b/tos/jtagwait/jtagwait.creator
new file mode 100644
index 0000000..e94cbbd
--- /dev/null
+++ b/tos/jtagwait/jtagwait.creator
@@ -0,0 +1 @@
+[General]
diff --git a/tos/jtagwait/jtagwait.creator.user b/tos/jtagwait/jtagwait.creator.user
new file mode 100644
index 0000000..e0172af
--- /dev/null
+++ b/tos/jtagwait/jtagwait.creator.user
@@ -0,0 +1,186 @@
+
+
+
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ true
+ 1
+ true
+ 0
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ {8a828d48-5359-4872-acb6-81070c6b7c12}
+ 0
+ 0
+ 0
+
+ /home/mfro/Dokumente/Development/workspace/jtagwait
+
+
+
+ all
+
+ false
+
+
+ true
+ Make
+
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Build
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+
+ clean
+
+ true
+
+
+ true
+ Make
+
+ GenericProjectManager.GenericMakeStep
+
+ 1
+ Clean
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Default
+ Default
+ GenericProjectManager.GenericBuildConfiguration
+
+ 1
+
+
+ 0
+ Deploy
+
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+ Deploy locally
+
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+ 2
+
+
+
+ false
+ %{buildDir}
+ Custom Executable
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+ 3768
+ true
+ false
+ false
+ false
+ true
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.EnvironmentId
+ {d01d0a15-4efd-4fa2-8e2c-f26845794427}
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 15
+
+
diff --git a/tos/jtagwait/jtagwait.files b/tos/jtagwait/jtagwait.files
new file mode 100644
index 0000000..dcdeec8
--- /dev/null
+++ b/tos/jtagwait/jtagwait.files
@@ -0,0 +1,2 @@
+include/driver_vec.h
+sources/jtagwait.c
\ No newline at end of file
diff --git a/tos/jtagwait/jtagwait.includes b/tos/jtagwait/jtagwait.includes
new file mode 100644
index 0000000..2996fba
--- /dev/null
+++ b/tos/jtagwait/jtagwait.includes
@@ -0,0 +1 @@
+include
\ No newline at end of file
diff --git a/tos/jtagwait/sources/jtagwait.c b/tos/jtagwait/sources/jtagwait.c
new file mode 100644
index 0000000..3a4f7c8
--- /dev/null
+++ b/tos/jtagwait/sources/jtagwait.c
@@ -0,0 +1,72 @@
+#include
+#include
+#include
+#include
+
+#include "driver_vec.h"
+
+#define FPGA_JTAG_LOADED_FLAG ((volatile int32_t *) 0xFF101000)
+
+#define _MBAR ((volatile uint8_t *) 0xFF000000)
+#define MCF_GPIO_PDDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA17]))
+#define MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 (0x10)
+#define MCF_GPIO_PPDSDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA27]))
+#define FPGA_CONFIG (1 << 2)
+#define FPGA_CONF_DONE (1 << 5)
+
+static inline uint32_t set_ipl(uint32_t ipl)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__(
+ " move.w sr,%[ret]\r\n" /* retrieve status register */
+ " andi.l #0x07,%[ipl]\n\t" /* mask out ipl bits on new value */
+ " lsl.l #8,%[ipl]\n\t" /* shift them to position */
+ " move.l %[ret],d0\n\t" /* retrieve original value */
+ " andi.l #0x0000f8ff,d0\n\t" /* clear ipl part */
+ " or.l %[ipl],d0\n\t" /* or in new value */
+ " move.w d0,sr\n\t" /* put it in place */
+ " andi.l #0x0700,%[ret]\r\n" /* mask out ipl bits */
+ " lsr.l #8,%[ret]\r\n" /* shift them to position */
+ : [ret] "=&d" (ret) /* output */
+ : [ipl] "d" (ipl) /* input */
+ : "d0" /* clobber */
+ );
+
+ return ret;
+}
+
+void wait_for_jtag(void)
+{
+ set_ipl(7); /* disable interrupts */
+ /*
+ * configure FEC1L port directions to enable external JTAG configuration download to FPGA
+ */
+ *MCF_GPIO_PDDR_FEC1L = 0 |
+ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
+ /* all other bits = input */
+ /*
+ * now that this GPIO ports have been switched to input, we can poll for FPGA config
+ * started from the JTAG interface (CONFIGn goes high) and finish (CONF_DONE goes high)
+ */
+ while (*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG); /* wait for JTAG reset */
+ while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG)); /* wait for JTAG config load starting */
+ while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load finished */
+
+ *FPGA_JTAG_LOADED_FLAG = 1; /* indicate jtag loaded FPGA config to BaS */
+
+ __asm__ __volatile__(
+ "jmp 0xE0000000\n\t"
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ printf("\033E\r\nFPGA JTAG configuration support\r\n");
+ printf("You may now savely load a new FPGA configuration through the JTAG interface\r\n"
+ "and your Firebee will reboot once finished using that new configuration.\r\n");
+ Supexec(wait_for_jtag);
+
+ return 0; /* just to make the compiler happy, we will never return */
+}
+
diff --git a/tos/mcdcook/Makefile b/tos/mcdcook/Makefile
new file mode 100755
index 0000000..46afdfc
--- /dev/null
+++ b/tos/mcdcook/Makefile
@@ -0,0 +1,117 @@
+CROSS=Y
+
+CROSSBINDIR_IS_Y=m68k-atari-mint-
+CROSSBINDIR_IS_N=
+
+CROSSBINDIR=$(CROSSBINDIR_IS_$(CROSS))
+
+UNAME := $(shell uname)
+ifeq ($(CROSS), Y)
+ifeq ($(UNAME),Linux)
+PREFIX=m68k-atari-mint
+HATARI=hatari
+else
+PREFIX=m68k-atari-mint
+HATARI=/usr/local/bin/hatari
+endif
+else
+PREFIX=/usr
+endif
+
+DEPEND=depend
+TOPDIR= ../..
+
+INCLUDE=-I$(TOPDIR)/../libcmini/include -nostdlib
+LIBS=-lcmini -nostdlib -lgcc
+CC=$(PREFIX)/bin/gcc
+
+CC=$(CROSSBINDIR)gcc
+STRIP=$(CROSSBINDIR)strip
+STACK=$(CROSSBINDIR)stack
+
+APP=mcdcook.prg
+TEST_APP=$(APP)
+
+CFLAGS=\
+ -Os\
+ -g\
+ -Wl,-Map,mapfile\
+ -Wall
+
+SRCDIR=sources
+INCDIR=include
+INCLUDE+=-I$(INCDIR)
+
+CSRCS=\
+ $(SRCDIR)/mcdcook.c
+ASRCS=
+
+COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS)))
+AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS)))
+OBJS=$(COBJS) $(AOBJS)
+
+TRGTDIRS=. ./m68020-60 ./m5475 ./mshort ./m68020-60/mshort ./m5475/mshort
+OBJDIRS=$(patsubst %,%/objs,$(TRGTDIRS))
+
+#
+# multilib flags. These must match m68k-atari-mint-gcc -print-multi-lib output
+#
+m68020-60/$(APP):CFLAGS += -m68020-60
+m5475/$(APP):CFLAGS += -mcpu=5475
+mshort/$(APP):CFLAGS += -mshort
+m68020-60/mshort/$(APP): CFLAGS += -m68020-60 -mshort
+m5475/mshort/$(APP): CFLAGS += -mcpu=5475 -mshort
+
+ctest: $(TEST_APP)
+all:$(patsubst %,%/$(APP),$(TRGTDIRS))
+#
+# generate pattern rules for multilib object files.
+#
+define CC_TEMPLATE
+$(1)/objs/%.o:$(SRCDIR)/%.c
+ $(CC) $$(CFLAGS) $(INCLUDE) -c $$< -o $$@
+
+$(1)/objs/%.o:$(SRCDIR)/%.S
+ $(CC) $$(CFLAGS) $(INCLUDE) -c $$< -o $$@
+
+$(1)_OBJS=$(patsubst %,$(1)/objs/%,$(OBJS))
+$(1)/$(APP): $$($(1)_OBJS)
+ $(CC) $$(CFLAGS) -o $$@ $(TOPDIR)/../libcmini/$(1)/startup.o $$($(1)_OBJS) -L$(TOPDIR)/../libcmini/$(1) $(LIBS)
+ $(STRIP) $$@
+endef
+$(foreach DIR,$(TRGTDIRS),$(eval $(call CC_TEMPLATE,$(DIR))))
+
+$(DEPEND): $(ASRCS) $(CSRCS)
+ -rm -f $(DEPEND)
+ for d in $(TRGTDIRS);\
+ do $(CC) $(CFLAGS) $(INCLUDE) -M $(ASRCS) $(CSRCS) | sed -e "s#^\(.*\).o:#$$d/objs/\1.o:#" >> $(DEPEND); \
+ done
+
+
+clean:
+ @rm -f $(patsubst %,%/objs/*.o,$(TRGTDIRS)) $(patsubst %,%/$(APP),$(TRGTDIRS))
+ @rm -f $(DEPEND) mapfile
+
+.PHONY: printvars
+printvars:
+ @$(foreach V,$(.VARIABLES), $(if $(filter-out environment% default automatic, $(origin $V)),$(warning $V=$($V))))
+
+ifneq (clean,$(MAKECMDGOALS))
+-include $(DEPEND)
+endif
+
+test: $(TEST_APP)
+ $(HATARI) --grab -w --tos $(TOPDIR)/../emutos/etos512k.img \
+ --machine falcon -s 14 --cpuclock 32 --cpulevel 3 --vdi true --vdi-planes 4 \
+ --vdi-width 640 --vdi-height 480 -d . $(APP)
+
+ftest: $(TEST_APP)
+ $(HATARI) --grab -w --tos /usr/share/hatari/TOS404.IMG \
+ --machine falcon --cpuclock 32 --cpulevel 3 \
+ -d . $(APP)
+
+sttest: $(TEST_APP)
+ $(HATARI) --grab -w --tos "/usr/share/hatari/tos106de.img" \
+ --machine st --cpuclock 32 --cpulevel 3 --vdi true --vdi-planes 4 \
+ --vdi-width 640 --vdi-height 480 \
+ -d . $(APP)
diff --git a/tos/mcdcook/include/driver_vec.h b/tos/mcdcook/include/driver_vec.h
new file mode 100644
index 0000000..8b9352a
--- /dev/null
+++ b/tos/mcdcook/include/driver_vec.h
@@ -0,0 +1,125 @@
+/*
+ * driver_vec.h
+ *
+ * Interface for exposure of BaS drivers to the OS
+ *
+ * This file is part of BaS_gcc.
+ *
+ * BaS_gcc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * BaS_gcc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with BaS_gcc. If not, see .
+ *
+ * Created on: 24.10.2013
+ * Author: Markus Fröschle
+ */
+
+#ifndef _DRIVER_VEC_H_
+#define _DRIVER_VEC_H_
+
+
+enum driver_type
+{
+ END_OF_DRIVERS, /* marks end of driver list */
+ BLOCKDEV_DRIVER,
+ CHARDEV_DRIVER,
+ VIDEO_DRIVER,
+ XHDI_DRIVER,
+ MCD_DRIVER,
+};
+
+struct generic_driver_interface
+{
+ uint32_t (*init)(void);
+ uint32_t (*read)(void *buf, size_t count);
+ uint32_t (*write)(const void *buf, size_t count);
+ uint32_t (*ioctl)(uint32_t request, ...);
+};
+
+
+/* Chained buffer descriptor */
+typedef volatile struct MCD_bufDesc_struct MCD_bufDesc;
+struct MCD_bufDesc_struct {
+ uint32_t flags; /* flags describing the DMA */
+ uint32_t csumResult; /* checksum from checksumming performed since last checksum reset */
+ int8_t *srcAddr; /* the address to move data from */
+ int8_t *destAddr; /* the address to move data to */
+ int8_t *lastDestAddr; /* the last address written to */
+ uint32_t dmaSize; /* the number of bytes to transfer independent of the transfer size */
+ MCD_bufDesc *next; /* next buffer descriptor in chain */
+ uint32_t info; /* private information about this descriptor; DMA does not affect it */
+};
+
+/* Progress Query struct */
+typedef volatile struct MCD_XferProg_struct {
+ int8_t *lastSrcAddr; /* the most-recent or last, post-increment source address */
+ int8_t *lastDestAddr; /* the most-recent or last, post-increment destination address */
+ uint32_t dmaSize; /* the amount of data transferred for the current buffer */
+ MCD_bufDesc *currBufDesc;/* pointer to the current buffer descriptor being DMAed */
+} MCD_XferProg;
+
+struct dma_driver_interface
+{
+ int32_t version;
+ int32_t magic;
+ int32_t (*dma_set_initiator)(int initiator);
+ uint32_t (*dma_get_initiator)(int requestor);
+ void (*dma_free_initiator)(int requestor);
+ int32_t (*dma_set_channel)(int requestor, void (*handler)(void));
+ int (*dma_get_channel)(int requestor);
+ void (*dma_free_channel)(int requestor);
+ void (*dma_clear_channel)(int channel);
+ int (*MCD_startDma)(int channel, int8_t *srcAddr, int16_t srcIncr, int8_t *destAddr, int16_t destIncr,
+ uint32_t dmaSize, uint32_t xferSize, uint32_t initiator, int32_t priority, uint32_t flags,
+ uint32_t funcDesc);
+ int (*MCD_dmaStatus)(int channel);
+ int (*MCD_XferProgrQuery)(int channel, MCD_XferProg *progRep);
+ int (*MCD_killDma)(int channel);
+ int (*MCD_continDma)(int channel);
+ int (*MCD_pauseDma)(int channel);
+ int (*MCD_resumeDma)(int channel);
+ int (*MCD_csumQuery)(int channel, uint32_t *csum);
+ void *(*dma_malloc)(long amount);
+ int (*dma_free)(void *addr);
+};
+
+struct xhdi_driver_interface
+{
+ uint32_t (*xhdivec)();
+};
+
+union interface
+{
+ struct generic_driver_interface *gdi;
+ struct xhdi_driver_interface *xhdi;
+ struct dma_driver_interface *dma;
+};
+
+struct generic_interface
+{
+ enum driver_type type;
+ char name[16];
+ char description[64];
+ int version;
+ int revision;
+ union interface interface;
+};
+
+struct driver_table
+{
+ uint32_t bas_version;
+ uint32_t bas_revision;
+ uint32_t (*remove_handler)(); /* calling this will disable the BaS' hook into trap #0 */
+ struct generic_interface *interfaces;
+};
+
+
+#endif /* _DRIVER_VEC_H_ */
diff --git a/tos/mcdcook/sources/mcdcook.c b/tos/mcdcook/sources/mcdcook.c
new file mode 100644
index 0000000..5d55a0d
--- /dev/null
+++ b/tos/mcdcook/sources/mcdcook.c
@@ -0,0 +1,121 @@
+#include
+#include
+#include
+#include
+
+#include "driver_vec.h"
+
+struct driver_table *get_bas_drivers(void)
+{
+ struct driver_table *ret = NULL;
+
+ __asm__ __volatile(
+ " trap #0\n\t"
+ " move.l d0,%[ret]\n\t"
+ : [ret] "=m" (ret) /* output */
+ : /* no inputs */
+ : /* clobbered */
+ );
+
+ return ret;
+}
+
+static uint32_t cookieptr(void)
+{
+ return * (uint32_t *) 0x5a0L;
+}
+
+void setcookie(uint32_t cookie, uint32_t value)
+{
+ uint32_t *cookiejar = (uint32_t *) Supexec(cookieptr);
+ int num_slots;
+ int max_slots;
+
+ num_slots = max_slots = 0;
+ do
+ {
+ if (cookiejar[0] == cookie)
+ {
+ cookiejar[1] = value;
+ return;
+ }
+ cookiejar = &(cookiejar[2]);
+ num_slots++;
+ } while (cookiejar[-2]);
+
+ /*
+ * Here we are at the end of the list and did not find our cookie.
+ * Let's check if there is any space left and append our value to the
+ * list if so. If not, we are lost (extending the cookie jar does only
+ * work from TSRs)
+ */
+ if (cookiejar[-1])
+ max_slots = cookiejar[-1];
+
+ if (max_slots > num_slots)
+ {
+ /* relief, there is space left, extend the list */
+ cookiejar[0] = cookiejar[-2];
+ cookiejar[1] = cookiejar[-1];
+ /* add the new element */
+ cookiejar[-2] = cookie;
+ cookiejar[-1] = value;
+ }
+ else
+ printf("cannot set cookie, cookie jar is full!\r\n");
+}
+
+# define COOKIE_DMAC 0x444D4143L /* FireTOS DMA API */
+
+static char *dt_to_str(enum driver_type dt)
+{
+ switch (dt)
+ {
+ case BLOCKDEV_DRIVER: return "generic block device driver";
+ case CHARDEV_DRIVER: return "generic character device driver";
+ case VIDEO_DRIVER: return "video/framebuffer driver";
+ case XHDI_DRIVER: return "XHDI compatible hard disk driver";
+ case MCD_DRIVER: return "multichannel DMA driver";
+ default: return "unknown driver type";
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ struct driver_table *dt;
+ void *ssp;
+
+ (void) Cconws("retrieve BaS driver interface\r\n");
+
+ ssp = (void *) Super(0L);
+ dt = get_bas_drivers();
+ if (dt)
+ {
+ struct generic_interface *ifc = &dt->interfaces[0];
+
+ printf("BaS driver table found at %p, BaS version is %d.%d\r\n", dt,
+ dt->bas_version, dt->bas_revision);
+
+ while (ifc->type != END_OF_DRIVERS)
+ {
+ printf("driver \"%s (%s)\" found,\r\n"
+ "interface type is %d (%s),\r\n"
+ "version %d.%d\r\n\r\n",
+ ifc->name, ifc->description, ifc->type, dt_to_str(ifc->type),
+ ifc->version, ifc->revision);
+ if (ifc->type == MCD_DRIVER)
+ {
+ setcookie(COOKIE_DMAC, ifc->interface.dma);
+ printf("\r\nDMAC cookie set to %p\r\n", ifc->interface.dma);
+ }
+ ifc++;
+ }
+ }
+ Super(ssp);
+
+ while (Cconis()) Cconin(); /* eat keys */
+ printf("press any key to continue\n\r");
+ // while (! Cconis());
+ return 0;
+}
+