Compare commits

...

55 Commits

Author SHA1 Message Date
Markus Fröschle
705c9610f3 branched to enable main branch to return to the old MMU handling code since the new style couldn't be made to work (for now). 2014-06-20 16:06:08 +00:00
Markus Fröschle
69c982c795 moved FPGA config GPIO initialization into init_fpga.c to enable external JTAG FPGA configuration 2014-06-20 12:02:11 +00:00
David Gálvez
4d40bd775a make PCI memory non-cacheable 2014-05-25 19:13:45 +00:00
David Gálvez
d98727a182 add missing parameter initialization 2014-05-25 17:00:19 +00:00
Markus Fröschle
927833d601 eliminated wrong types warning when calling memcpy() 2014-05-12 07:40:55 +00:00
Markus Fröschle
65a7986e34 reformatted 2014-05-11 20:38:33 +00:00
Markus Fröschle
ccec42e55c modified dbg() in several files 2014-05-11 20:31:57 +00:00
Markus Fröschle
dc646c75ad reformatted assembler code 2014-05-11 14:08:27 +00:00
Markus Fröschle
b0fb7b8df3 fixed wrong MMU mapping of emulated Falcon video memory (phys and virt
where the wrong way round)
2014-05-11 06:57:09 +00:00
Markus Fröschle
fb9c4aaa1d modified project to support Qt Creator inferior debugging through BDM. 2014-05-11 06:40:48 +00:00
Markus Fröschle
2f311aedbf modified dbg() macro
corrected irq6 handler
reimplemented MFP interrupt LED blinker in C
2014-05-10 13:21:11 +00:00
Markus Fröschle
5a836c6ca7 reformatted assembly 2014-04-22 10:47:36 +00:00
Markus Fröschle
e94becff75 added to QtCreator 2014-04-22 10:44:56 +00:00
Markus Fröschle
dee448549c translated copy loop to C 2014-02-04 20:06:29 +00:00
Markus Fröschle
fcd3b885ce started "translating" MMU update code for video pages 2014-02-04 07:17:51 +00:00
Markus Fröschle
91ae86a487 completed page loop 2014-02-03 21:42:25 +00:00
Markus Fröschle
25f66ae7f9 more conversion to C 2014-02-02 22:27:10 +00:00
Markus Fröschle
fe5b7d466d translated more of the assembler code into C 2014-02-02 21:35:46 +00:00
Markus Fröschle
ff3514c2d0 added missing include file to SVN 2014-02-02 10:16:16 +00:00
Markus Fröschle
90371bb3c9 optimized for size - reduces codesize by half 2014-02-01 23:54:32 +00:00
Markus Fröschle
5a557524b0 moved PSC3 interrupt handler to C code 2014-02-01 23:37:30 +00:00
Markus Fröschle
1fb6c756ae modified to throw errors if an unknown machine type is detected 2014-01-28 15:49:05 +00:00
Markus Fröschle
8a1da417e7 modified ACR settings 2014-01-28 14:11:08 +00:00
Markus Fröschle
703352fc9d added m54455 (Freescale EVB) platform 2014-01-21 14:52:46 +00:00
Markus Fröschle
6a6e7cf84e fixed: compare virtual address instead of physical in lookup_mapping() 2014-01-21 12:43:32 +00:00
Markus Fröschle
430f03a8ed fixed bug in determining if access error hit in TLB (checked bit 0 instead of 1). 2014-01-20 14:23:55 +00:00
Markus Fröschle
d3fb521ad1 modified MMU mapping table to use symbolic constants from include file 2014-01-19 19:26:52 +00:00
Markus Fröschle
bf8cea26ab simplified MMU code. Still hangs somewhere in EmuTOS 2014-01-19 18:27:05 +00:00
Markus Fröschle
0f5942436a removed locked MMU pages 2014-01-18 20:59:42 +00:00
Markus Fröschle
8544307830 removed inlining in wait.c, added (simple) map-based MMU handling 2014-01-18 14:03:25 +00:00
Markus Fröschle
386a921f84 modified to map memory dynamically based on a static memory map 2014-01-18 08:04:44 +00:00
Markus Fröschle
58418f2436 moved ACR register handling macros to include file 2014-01-17 06:45:33 +00:00
Markus Fröschle
8025af85dd modified access_error to do all MMU mappings dynamically 2014-01-16 20:42:04 +00:00
Markus Fröschle
1c316ec11b extended mmu_map_page() by size and flags args 2014-01-16 16:29:29 +00:00
Markus Fröschle
3779d1cb2e modified ACRs to cover complete SDRAM 2014-01-16 16:18:43 +00:00
Markus Fröschle
c9c76a4757 test using ACR0 & ACR2 to provide supervisor stack access 2014-01-15 16:03:54 +00:00
Markus Fröschle
afa9490c1e fixed typo in strcmp() 2014-01-15 07:17:21 +00:00
Markus Fröschle
26cadc699a fixed formatting 2014-01-14 21:39:05 +00:00
Markus Fröschle
9da82d046b modified comments 2014-01-14 21:15:56 +00:00
Markus Fröschle
4112590363 moved page alignment responsibility to caller 2014-01-14 20:28:13 +00:00
Markus Fröschle
fdf945c702 fixed missing parameter in debug print 2014-01-14 18:18:20 +00:00
Markus Fröschle
9b89377caf removed type field from isr_register_handler() and friends 2014-01-14 07:48:38 +00:00
Markus Fröschle
3966bfd6ec fixed comments 2014-01-13 22:05:20 +00:00
Markus Fröschle
bdf5cd6c0d added vim modeline to asm sources. Needs "set modeline:set modeline=5" in .vimrc 2014-01-13 21:34:24 +00:00
Markus Fröschle
ba1a951952 cleaned up debug printouts 2014-01-13 21:30:39 +00:00
Markus Fröschle
fcb5204fc8 renamed mmutr_miss() to mmu_map_page() (that's what its doing) 2014-01-13 21:26:42 +00:00
Markus Fröschle
63b19853a9 corrected FASTRAM_END comparision 2014-01-13 21:20:24 +00:00
Markus Fröschle
be94d72097 refactored assembler routines from exceptions.S into mmu.c (access exception handler). Seems to be better, but still hang. 2014-01-13 19:39:42 +00:00
Markus Fröschle
9b099d935c implemented safe stack for access exception handler 2014-01-13 15:13:29 +00:00
Markus Fröschle
a97469a53d switch to a safe stack in access_exception.
Assembles, but not tested yet.
2014-01-13 07:19:09 +00:00
Markus Fröschle
3a1c07a2e8 added better matching descriptive text to debug messages 2014-01-08 13:57:35 +00:00
Markus Fröschle
4f29f6af80 FEC interrupts to level 1 2014-01-08 09:59:44 +00:00
Markus Fröschle
8d53a1feb9 fixed - carelessly choosen - interrupt level for FEC interrupts 2014-01-08 09:01:43 +00:00
Markus Fröschle
99e5352807 changed MAC address to original address dbug assigns 2014-01-07 10:50:22 +00:00
Markus Fröschle
785ca43b11 cleaned up 2014-01-07 05:57:17 +00:00
47 changed files with 2165 additions and 1461 deletions

View File

@@ -1,7 +1,8 @@
#set disassemble-next-line on #set disassemble-next-line on
define tr define tr
#target remote | m68k-bdm-gdbserver pipe /dev/bdmcf3 !killall m68k-bdm-gdbserver
target remote | m68k-bdm-gdbserver pipe /dev/tblcf3 target remote | m68k-bdm-gdbserver pipe /dev/bdmcf3
#target remote | m68k-bdm-gdbserver pipe /dev/tblcf3
#target dbug /dev/ttyS0 #target dbug /dev/ttyS0
#monitor bdm-reset #monitor bdm-reset
end end

1
BaS_gcc.config Normal file
View File

@@ -0,0 +1 @@
// ADD PREDEFINED MACROS HERE!

1
BaS_gcc.creator Normal file
View File

@@ -0,0 +1 @@
[General]

231
BaS_gcc.files Normal file
View File

@@ -0,0 +1,231 @@
dma/dma.c
dma/MCD_dmaApi.c
dma/MCD_tasks.c
dma/MCD_tasksInit.c
exe/basflash.c
exe/basflash_start.c
firebee/bas.elf
firebee/bas.lk
firebee/bas.map
firebee/bas.s19
firebee/basflash.elf
firebee/basflash.map
firebee/basflash.s19
firebee/bashflash.lk
firebee/depend
firebee/libbas.a
firebee/ram.elf
firebee/ram.lk
firebee/ram.map
firebee/ram.s19
flash/flash.c
flash/s19reader.c
fs/cc932.c
fs/cc936.c
fs/cc949.c
fs/cc950.c
fs/ccsbcs.c
fs/ff.c
fs/unicode.c
if/driver_vec.c
include/acia.h
include/am79c874.h
include/arp.h
include/ati_ids.h
include/bas_printf.h
include/bas_string.h
include/bas_types.h
include/bas_utils.h
include/bcm5222.h
include/bootp.h
include/cache.h
include/diskio.h
include/dma.h
include/driver_mem.h
include/driver_vec.h
include/edid.h
include/ehci.h
include/eth.h
include/exceptions.h
include/fb.h
include/fec.h
include/fecbd.h
include/ff.h
include/ffconf.h
include/firebee.h
include/i2c-algo-bit.h
include/i2c.h
include/icmp.h
include/ikbd.h
include/interrupts.h
include/ip.h
include/m54455.h
include/m5484l.h
include/MCD_dma.h
include/mcd_initiators.h
include/MCD_progCheck.h
include/MCD_tasksInit.h
include/MCF5475.h
include/MCF5475_CLOCK.h
include/MCF5475_CTM.h
include/MCF5475_DMA.h
include/MCF5475_DSPI.h
include/MCF5475_EPORT.h
include/MCF5475_FBCS.h
include/MCF5475_FEC.h
include/MCF5475_GPIO.h
include/MCF5475_GPT.h
include/MCF5475_I2C.h
include/MCF5475_INTC.h
include/MCF5475_MMU.h
include/MCF5475_PAD.h
include/MCF5475_PCI.h
include/MCF5475_PCIARB.h
include/MCF5475_PSC.h
include/MCF5475_SDRAMC.h
include/MCF5475_SEC.h
include/MCF5475_SIU.h
include/MCF5475_SLT.h
include/MCF5475_SRAM.h
include/MCF5475_USB.h
include/MCF5475_XLB.h
include/mmu.h
include/mod_devicetable.h
include/nbuf.h
include/net.h
include/net_timer.h
include/nif.h
include/ohci.h
include/part.h
include/pci.h
include/pci_ids.h
include/queue.h
include/radeon_reg.h
include/radeonfb.h
include/s19reader.h
include/screen.h
include/sd_card.h
include/startcf.h
include/sysinit.h
include/tftp.h
include/udp.h
include/usb.h
include/usb_defs.h
include/user_io.h
include/util.h
include/version.h
include/videl.h
include/video.h
include/wait.h
include/x86debug.h
include/x86decode.h
include/x86emu.h
include/x86emui.h
include/x86fpu.h
include/x86fpu_regs.h
include/x86ops.h
include/x86pcibios.h
include/x86prim_asm.h
include/x86prim_ops.h
include/x86regs.h
include/xhdi_sd.h
kbd/ikbd.c
m54455/bas.elf
m54455/bas.lk
m54455/bas.map
m54455/bas.s19
m54455/basflash.elf
m54455/basflash.map
m54455/basflash.s19
m54455/bashflash.lk
m54455/depend
m54455/libbas.a
m54455/ram.elf
m54455/ram.lk
m54455/ram.map
m54455/ram.s19
m5484lite/bas.elf
m5484lite/bas.lk
m5484lite/bas.map
m5484lite/bas.s19
m5484lite/basflash.elf
m5484lite/basflash.map
m5484lite/basflash.s19
m5484lite/bashflash.lk
m5484lite/depend
m5484lite/libbas.a
m5484lite/ram.elf
m5484lite/ram.lk
m5484lite/ram.map
m5484lite/ram.s19
net/am79c874.c
net/arp.c
net/bcm5222.c
net/bootp.c
net/fec.c
net/fecbd.c
net/ip.c
net/nbuf.c
net/net_timer.c
net/nif.c
net/queue.c
net/tftp.c
net/udp.c
nutil/s19header
nutil/s19header.c
pci/ehci-hcd.c
pci/ohci-hcd.c
pci/pci.c
radeon/radeon_accel.c
radeon/radeon_base.c
radeon/radeon_cursor.c
radeon/radeon_monitor.c
spi/dspi.c
spi/mmc.c
spi/sd_card.c
sys/BaS.c
sys/cache.c
sys/driver_mem.c
sys/exceptions.S
sys/fault_vectors.c
sys/init_fpga.c
sys/interrupts.c
sys/mmu.c
sys/startcf.S
sys/sysinit.c
usb/usb.c
usb/usb_mouse.c
util/bas_printf.c
util/bas_string.c
util/printf_helper.S
util/wait.c
video/fbmem.c
video/fbmodedb.c
video/fbmon.c
video/fnt_st_8x16.c
video/offscreen.c
video/vdi_fill.c
video/videl.c
video/video.c
x86emu/x86biosemu.c
x86emu/x86debug.c
x86emu/x86decode.c
x86emu/x86fpu.c
x86emu/x86ops.c
x86emu/x86ops2.c
x86emu/x86pcibios.c
x86emu/x86prim_ops.c
x86emu/x86sys.c
xhdi/xhdi_interface.c
xhdi/xhdi_sd.c
xhdi/xhdi_vec.S
bas.lk.in
bas_firebee.bdm
bas_m5484.bdm
basflash.lk.in
check.bdm
COPYING
COPYING.LESSER
dump.bdm
mcf5474.gdb
Makefile

2
BaS_gcc.includes Normal file
View File

@@ -0,0 +1,2 @@
include
/usr/m68k-elf/include

View File

@@ -32,20 +32,21 @@ NATIVECC=gcc
INCLUDE=-Iinclude INCLUDE=-Iinclude
CFLAGS=-mcpu=5474 \ CFLAGS=-mcpu=5474 \
-Wall \ -Wall \
-Os \ -g3 \
-fomit-frame-pointer \ -fomit-frame-pointer \
-ffreestanding \ -ffreestanding \
-fleading-underscore \ -fleading-underscore \
-Wa,--register-prefix-optional -Wa,--register-prefix-optional
CFLAGS_OPTIMIZED = -mcpu=5474 \ CFLAGS_OPTIMIZED = -mcpu=5474 \
-Wall \ -Wall \
-g3 \
-O2 \ -O2 \
-fomit-frame-pointer \ -fomit-frame-pointer \
-ffreestanding \ -ffreestanding \
-fleading-underscore \ -fleading-underscore \
-Wa,--register-prefix-optional -Wa,--register-prefix-optional
TRGTDIRS= ./firebee ./m5484lite TRGTDIRS= ./firebee ./m5484lite ./m54455
OBJDIRS=$(patsubst %, %/objs,$(TRGTDIRS)) OBJDIRS=$(patsubst %, %/objs,$(TRGTDIRS))
TOOLDIR=util TOOLDIR=util
@@ -170,32 +171,35 @@ clean:
# flags for targets # flags for targets
m5484lite/bas.$(EXE): MACHINE=MACHINE_M5484LITE m5484lite/bas.$(EXE): MACHINE=MACHINE_M5484LITE
m54455/bas.$(EXE): MACHINE=MACHINE_M54455
firebee/bas.$(EXE): MACHINE=MACHINE_FIREBEE firebee/bas.$(EXE): MACHINE=MACHINE_FIREBEE
m5484lite/ram.$(EXE): MACHINE=MACHINE_M5484LITE m5484lite/ram.$(EXE): MACHINE=MACHINE_M5484LITE
m54455/ram.$(EXE): MACHINE=MACHINE_M54455
firebee/ram.$(EXE): MACHINE=MACHINE_FIREBEE firebee/ram.$(EXE): MACHINE=MACHINE_FIREBEE
m5484lite/basflash.$(EXE): MACHINE=MACHINE_M5484LITE m5484lite/basflash.$(EXE): MACHINE=MACHINE_M5484LITE
m54455/basflash.$(EXE): MACHINE=MACHINE_M54455
firebee/basflash.$(EXE): MACHINE=MACHINE_FIREBEE firebee/basflash.$(EXE): MACHINE=MACHINE_FIREBEE
# #
# generate pattern rules for different object files # generate pattern rules for different object files
# #
define CC_TEMPLATE define CC_TEMPLATE
ifeq (firebee,$(1)) #ifeq (firebee,$(1))
MACHINE=MACHINE_FIREBEE #MACHINE=MACHINE_FIREBEE
else #else
MACHINE=MACHINE_M5484LITE #MACHINE=MACHINE_M5484LITE
endif #endif
# always optimize x86 emulator objects # always optimize x86 emulator objects
$(1)/objs/x86decode.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86decode.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86sys.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86sys.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86debug.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86debug.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86prim_ops.o:CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86prim_ops.o:CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86ops.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86ops.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86ops2.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86ops2.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86fpu.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86fpu.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86biosemu.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86biosemu.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/x86pcibios.o: CFLAGS=$(CFLAGS_OPTIMIZED) #$(1)/objs/x86pcibios.o: CFLAGS=$(CFLAGS_OPTIMIZED)
$(1)/objs/%.o:%.c $(1)/objs/%.o:%.c
$(CC) $$(CFLAGS) -D$$(MACHINE) $(INCLUDE) -c $$< -o $$@ $(CC) $$(CFLAGS) -D$$(MACHINE) $(INCLUDE) -c $$< -o $$@
@@ -257,7 +261,7 @@ endif
$(1)_MAPFILE_RAM=$(1)/$$(basename $$(RAM_EXEC)).map $(1)_MAPFILE_RAM=$(1)/$$(basename $$(RAM_EXEC)).map
$(1)/$$(RAM_EXEC): $(1)/$(LIBBAS) $(LDCSRC) $(1)/$$(RAM_EXEC): $(1)/$(LIBBAS) $(LDCSRC)
$(CPP) $(INCLUDE) -DCOMPILE_RAM -DOBJDIR=$(1)/objs -P -DFORMAT_ELF=$(FORMAT_ELF) -D$$(MACHINE) $(LDCSRC) -o $(1)/$$(LDRFILE) $(CPP) $(INCLUDE) -DCOMPILE_RAM -DOBJDIR=$(1)/objs -P -DFORMAT_ELF=$(FORMAT_ELF) -D$$(MACHINE) $(LDCSRC) -o $(1)/$$(LDRFILE)
$(LD) --oformat $$(FORMAT) -Map $$($(1)_MAPFILE_RAM) --cref -T $(1)/$$(LDRFILE) -o $$@ $(LD) -g --oformat $$(FORMAT) -Map $$($(1)_MAPFILE_RAM) --cref -T $(1)/$$(LDRFILE) -o $$@
ifeq ($(COMPILE_ELF),Y) ifeq ($(COMPILE_ELF),Y)
$(OBJCOPY) -O srec $$@ $$(basename $$@).s19 $(OBJCOPY) -O srec $$@ $$(basename $$@).s19
else else
@@ -291,7 +295,7 @@ printvars:
ifeq (MACHINE_M5484LITE,$$(MACHINE)) ifeq (MACHINE_M5484LITE,$$(MACHINE))
MNAME=m5484lite MNAME=m5484lite
else ifeq (MACHINE_FIREBEE,$(MACHINE)) else ifeq (MACHINE_FIREBEE,$(MACHINE))
MNAME=firebee MNAME=firebee
endif endif
tools: tools:

View File

@@ -1,9 +1,11 @@
#ifdef MACHINE_FIREBEE #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#endif /* MACHINE_FIREBEE */ #elif defined(MACHINE_M5484LITE)
#ifdef MACHINE_M5484LITE
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else
#error "unknown machine!"
#endif /* MACHINE_M5484LITE */ #endif /* MACHINE_M5484LITE */
/* make bas_rom access flags rx if compiling to RAM */ /* make bas_rom access flags rx if compiling to RAM */
@@ -177,6 +179,7 @@ SECTIONS
#else #else
__FASTRAM_END = TARGET_ADDRESS; __FASTRAM_END = TARGET_ADDRESS;
#endif #endif
__FASTRAM_SIZE = __FASTRAM_END - __FASTRAM;
/* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */ /* Init CS0 (BootFLASH @ E000_0000 - E07F_FFFF 8Mbytes) */
___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS; ___BOOT_FLASH = BOOTFLASH_BASE_ADDRESS;

View File

@@ -29,13 +29,17 @@
#include "cache.h" #include "cache.h"
#include "exceptions.h" #include "exceptions.h"
#if MACHINE_FIREBEE #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#elif MACHINE_M5484LITE #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else
#error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
//#define DBG_DMA #define DBG_DMA
#ifdef DBG_DMA #ifdef DBG_DMA
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
#else #else
@@ -592,11 +596,15 @@ int dma_interrupt_handler(void *arg1, void *arg2)
void *dma_memcpy(void *dst, void *src, size_t n) void *dma_memcpy(void *dst, void *src, size_t n)
{ {
int ret; int ret;
volatile int32_t time;
volatile int32_t start; #ifdef DBG_DMA
volatile int32_t end; int32_t time;
int32_t start;
int32_t end;
start = MCF_SLT0_SCNT; start = MCF_SLT0_SCNT;
#endif /* DBG_DMA */
ret = MCD_startDma(1, src, 4, dst, 4, n, 4, DMA_ALWAYS, 0, MCD_SINGLE_DMA, 0); ret = MCD_startDma(1, src, 4, dst, 4, n, 4, DMA_ALWAYS, 0, MCD_SINGLE_DMA, 0);
if (ret == MCD_OK) if (ret == MCD_OK)
{ {
@@ -640,8 +648,10 @@ void *dma_memcpy(void *dst, void *src, size_t n)
#endif #endif
} while (ret != MCD_DONE); } while (ret != MCD_DONE);
#ifdef DBG_DMA
end = MCF_SLT0_SCNT; end = MCF_SLT0_SCNT;
time = (start - end) / (SYSCLK / 1000) / 1000; time = (start - end) / (SYSCLK / 1000) / 1000;
#endif /* DBG_DMA */
dbg("%s: took %d ms (%f Mbytes/second)\r\n", __FUNCTION__, time, n / (float) time / 1000.0); dbg("%s: took %d ms (%f Mbytes/second)\r\n", __FUNCTION__, time, n / (float) time / 1000.0);
return dst; return dst;

View File

@@ -340,6 +340,17 @@ static err_t verify(uint8_t *dst, uint8_t *src, uint32_t length)
return OK; return OK;
} }
/*
* needed to avoid missing type cast warning below
*/
static inline err_t srec_memcpy(uint8_t *dst, uint8_t *src, size_t n)
{
err_t e = OK;
memcpy((void *) dst, (void *) src, n);
return e;
}
void srec_execute(char *flasher_filename) void srec_execute(char *flasher_filename)
{ {
DRESULT res; DRESULT res;
@@ -372,7 +383,7 @@ void srec_execute(char *flasher_filename)
{ {
/* next pass: copy data to destination */ /* next pass: copy data to destination */
xprintf("OK.\r\ncopy/flash data: "); xprintf("OK.\r\ncopy/flash data: ");
err = read_srecords(flasher_filename, &start_address, &length, memcpy); err = read_srecords(flasher_filename, &start_address, &length, srec_memcpy);
if (err == OK) if (err == OK)
{ {
/* next pass: verify data */ /* next pass: verify data */

View File

@@ -47,8 +47,8 @@ static struct xhdi_driver_interface xhdi_call_interface =
static struct dma_driver_interface dma_interface = static struct dma_driver_interface dma_interface =
{ {
.version = 0x0101, .version = 0x0101,
.magic = 'DMAC', .magic = 0x444d4143, /* 'DMAC' */
.dma_set_initiator = &dma_set_initiator, .dma_set_initiator = dma_set_initiator,
.dma_get_initiator = dma_get_initiator, .dma_get_initiator = dma_get_initiator,
.dma_free_initiator = dma_free_initiator, .dma_free_initiator = dma_free_initiator,
.dma_set_channel = dma_set_channel, .dma_set_channel = dma_set_channel,

View File

@@ -35,6 +35,7 @@ extern char *strncat(char *dst, const char *src, size_t max);
extern int atoi(const char *c); extern int atoi(const char *c);
extern void *memcpy(void *dst, const void *src, size_t n); extern void *memcpy(void *dst, const void *src, size_t n);
extern void *memset(void *s, int c, size_t n); extern void *memset(void *s, int c, size_t n);
extern int memcmp(const void *s1, const void *s2, size_t max);
extern void bzero(void *s, size_t n); extern void bzero(void *s, size_t n);
#define isdigit(c) (((c) >= '0') && ((c) <= '9')) #define isdigit(c) (((c) >= '0') && ((c) <= '9'))

View File

@@ -50,17 +50,17 @@ struct dma_driver_interface
{ {
int32_t version; int32_t version;
int32_t magic; int32_t magic;
int32_t (*dma_set_initiator)(int32_t initiator); int (*dma_set_initiator)(int initiator);
uint32_t (*dma_get_initiator)(int32_t requestor); uint32_t (*dma_get_initiator)(int requestor);
void (*dma_free_initiator)(int32_t requestor); void (*dma_free_initiator)(int requestor);
int32_t (*dma_set_channel)(int32_t requestor, void (*handler)(void)); int (*dma_set_channel)(int requestor, void (*handler)(void));
int32_t (*dma_get_channel)(int32_t requestor); int (*dma_get_channel)(int requestor);
void (*dma_free_channel)(int32_t requestor); void (*dma_free_channel)(int requestor);
void (*dma_clear_channel)(int32_t channel); void (*dma_clear_channel)(int channel);
int32_t (*MCD_startDma)(long channel, int (*MCD_startDma)(long channel,
int8_t *srcAddr, uint32_t srcIncr, int8_t *destAddr, uint32_t destIncr, int8_t *srcAddr, unsigned int srcIncr, int8_t *destAddr, unsigned int destIncr,
uint32_t dmaSize, uint32_t xferSize, uint32_t initiator, int32_t priority, unsigned int dmaSize, unsigned int xferSize, unsigned int initiator, int priority,
uint32_t flags, uint32_t funcDesc); unsigned int flags, unsigned int funcDesc);
int32_t (*MCD_dmaStatus)(int32_t channel); int32_t (*MCD_dmaStatus)(int32_t channel);
int32_t (*MCD_XferProgrQuery)(int32_t channel, MCD_XferProg *progRep); int32_t (*MCD_XferProgrQuery)(int32_t channel, MCD_XferProg *progRep);
int32_t (*MCD_killDma)(int32_t channel); int32_t (*MCD_killDma)(int32_t channel);

View File

@@ -27,7 +27,7 @@
* Author: Markus Fröschle * Author: Markus Fröschle
*/ */
#define SYSCLK 132000 #define SYSCLK 132000 /* NOTE: 132 _is_ correct. 133 _is_ wrong. Do not change! */
#define BOOTFLASH_BASE_ADDRESS 0xE0000000 #define BOOTFLASH_BASE_ADDRESS 0xE0000000
#define BOOTFLASH_SIZE 0x800000 /* FireBee has 8 MByte Flash */ #define BOOTFLASH_SIZE 0x800000 /* FireBee has 8 MByte Flash */

View File

@@ -79,11 +79,11 @@
#define INT_SOURCE_GPT0 62 // GPT0 timer interrupt #define INT_SOURCE_GPT0 62 // GPT0 timer interrupt
#define FEC0_INTC_LVL 5 /* interrupt level for FEC0 */ #define FEC0_INTC_LVL 1 /* interrupt level for FEC0 */
#define FEC0_INTC_PRI 7 /* interrupt priority for FEC0 */ #define FEC0_INTC_PRI 2 /* interrupt priority for FEC0 */
#define FEC1_INTC_LVL 5 /* interrupt level for FEC1 */ #define FEC1_INTC_LVL 1 /* interrupt level for FEC1 */
#define FEC1_INTC_PRI 7 /* interrupt priority for FEC1 */ #define FEC1_INTC_PRI 2 /* interrupt priority for FEC1 */
#define FEC_INTC_LVL(x) ((x == 0) ? FEC0_INTC_LVL : FEC1_INTC_LVL) #define FEC_INTC_LVL(x) ((x == 0) ? FEC0_INTC_LVL : FEC1_INTC_LVL)
#define FEC_INTC_PRI(x) ((x == 0) ? FEC0_INTC_PRI : FEC1_INTC_PRI) #define FEC_INTC_PRI(x) ((x == 0) ? FEC0_INTC_PRI : FEC1_INTC_PRI)
@@ -101,7 +101,7 @@ extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t pri
#define ISR_USER_ISR 0x02 #define ISR_USER_ISR 0x02
extern void isr_init(void); extern void isr_init(void);
extern int isr_register_handler(int type, int vector, int (*handler)(void *, void *), void *hdev, void *harg); extern int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg);
extern void isr_remove_handler(int type ,int (*handler)(void *, void *)); extern void isr_remove_handler(int (*handler)(void *, void *));
extern bool isr_execute_handler(int vector); extern bool isr_execute_handler(int vector);
#endif /* _INTERRUPTS_H_ */ #endif /* _INTERRUPTS_H_ */

View File

@@ -9,7 +9,6 @@
#ifndef _IP_H #ifndef _IP_H
#define _IP_H #define _IP_H
/********************************************************************/
/* 32-bit IP Addresses */ /* 32-bit IP Addresses */
typedef uint8_t IP_ADDR[4]; typedef uint8_t IP_ADDR[4];
@@ -57,7 +56,6 @@ typedef struct
#define IP_HDR_OFFSET ETH_HDR_LEN #define IP_HDR_OFFSET ETH_HDR_LEN
#define IP_HDR_SIZE 20 /* no options */ #define IP_HDR_SIZE 20 /* no options */
/********************************************************************/
typedef struct typedef struct
{ {
@@ -71,7 +69,6 @@ typedef struct
unsigned int err; unsigned int err;
} IP_INFO; } IP_INFO;
/********************************************************************/
extern void ip_handler(NIF *nif, NBUF *nbf); extern void ip_handler(NIF *nif, NBUF *nbf);
uint16_t ip_chksum(uint16_t *data, int num); uint16_t ip_chksum(uint16_t *data, int num);

49
include/m54455.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef _M54455_H_
#define _M54455_H_
/*
* m54455.h
*
* preprocessor definitions for the M54455 Freescale machine. This file should contain nothing but preprocessor
* definition that evaluate to numbers. It is intended for use in C sources as well as in linker control
* files, so care must be taken to not break the syntax of either one.
*
* 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 <http://www.gnu.org/licenses/>.
*
* Created on: 26.02.2013
* Author: Markus Fröschle
*/
#define SYSCLK 133000
#define BOOTFLASH_BASE_ADDRESS 0xe0000000
#define BOOTFLASH_SIZE 0x800000
#define BOOTFLASH_BAM (BOOTFLASH_SIZE - 1)
#define SDRAM_START 0x00000000 /* start at address 0 */
#define SDRAM_SIZE 0x8000000
#ifdef COMPILE_RAM
#define TARGET_ADDRESS (SDRAM_START + SDRAM_SIZE - 0x200000)
#else
#define TARGET_ADDRESS BOOTFLASH_BASE_ADDRESS
#endif /* COMPILE_RAM */
#define DRIVER_MEM_BUFFER_SIZE 0x100000
#define EMUTOS_BASE_ADDRESS 0xe0100000
#endif /* _M54455_H_ */

View File

@@ -26,8 +26,67 @@
#include "bas_types.h" #include "bas_types.h"
/*
* ACR register handling macros
*/
#define ACR_BA(x) ((x) & 0xffff0000)
#define ACR_ADMSK(x) (((x) & 0xffff) << 16)
#define ACR_E(x) (((x) & 1) << 15)
#define ACR_S(x) (((x) & 3) << 13)
#define ACR_S_USERMODE 0
#define ACR_S_SUPERVISOR_MODE 1
#define ACR_S_ALL 2
#define ACR_ADDRESS_MASK_MODE(x) (((x) & 1) << 10)
#define ACR_CACHE_MODE(x) (((x) & 3) << 5)
#define ACR_SUPERVISOR_PROTECT(x) (((x) & 1) << 3)
#define ACR_WRITE_PROTECT(x) (((x) & 1) << 2)
/*
* MMU register handling macros
*/
#define SCA_PAGE_ID 6 /* indicates video memory page */ #define SCA_PAGE_ID 6 /* indicates video memory page */
/*
* MMU page sizes
*/
#define MMU_PAGE_SIZE_1M 0
#define MMU_PAGE_SIZE_4K 1
#define MMU_PAGE_SIZE_8K 2
#define MMU_PAGE_SIZE_1K 3
/*
* cache modes
*/
#define CACHE_WRITETHROUGH 0
#define CACHE_COPYBACK 1
#define CACHE_NOCACHE_PRECISE 2
#define CACHE_NOCACHE_IMPRECISE 3
/*
* page flags
*/
#define SV_PROTECT 1
#define SV_USER 0
#define ACCESS_READ (1 << 0)
#define ACCESS_WRITE (1 << 1)
#define ACCESS_EXECUTE (1 << 2)
struct map_flags
{
unsigned cache_mode:2;
unsigned protection:1;
unsigned page_id:8;
unsigned access:3;
unsigned unused:18;
};
/* /*
* global variables from linker script * global variables from linker script
*/ */
@@ -35,6 +94,6 @@ extern long video_tlb;
extern long video_sbt; extern long video_sbt;
extern void mmu_init(void); extern void mmu_init(void);
extern void mmutr_miss(uint32_t addresss); extern void mmu_map_page(uint32_t virt, uint32_t phys, uint32_t map_size, struct map_flags flags);
#endif /* _MMU_H_ */ #endif /* _MMU_H_ */

View File

@@ -28,13 +28,17 @@
#ifndef __SYSINIT_H__ #ifndef __SYSINIT_H__
#define __SYSINIT_H__ #define __SYSINIT_H__
#include <stdbool.h>
/* function(s) from init_fpga.c */ /* function(s) from init_fpga.c */
extern void init_fpga(void); extern bool init_fpga(void);
extern void init_usb(void); extern void init_usb(void);
/* fault_vectors */ /* fault_vectors */
extern void setup_vectors(void); extern void setup_vectors(void);
extern bool fpga_configured;
#endif /* __SYSINIT_H__ */ #endif /* __SYSINIT_H__ */

View File

@@ -145,7 +145,7 @@ __extension__ \
__extension__ \ __extension__ \
({__asm__ volatile ("lea -60(sp),sp\n\t" \ ({__asm__ volatile ("lea -60(sp),sp\n\t" \
"movem.l d0-d7/a0-a6,(sp)"); \ "movem.l d0-d7/a0-a6,(sp)"); \
((void (*)(void))addr)(); \ ((void (*) (void)) addr)(); \
__asm__ volatile ("movem.l (sp),d0-d7/a0-a6\n\t" \ __asm__ volatile ("movem.l (sp),d0-d7/a0-a6\n\t" \
"lea 60(sp),sp"); \ "lea 60(sp),sp"); \
}) })

View File

@@ -29,7 +29,7 @@
*/ */
#define MAJOR_VERSION 0 #define MAJOR_VERSION 0
#define MINOR_VERSION 83 #define MINOR_VERSION 84
#endif /* VERSION_H_ */ #endif /* VERSION_H_ */

View File

@@ -29,55 +29,23 @@
#include <bas_types.h> #include <bas_types.h>
#if MACHINE_FIREBEE #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#elif MACHINE_M5484LITE #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else
#error "unknown machine"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
#include "MCF5475.h" #include "MCF5475.h"
typedef bool (*checker_func)(void); typedef bool (*checker_func)(void);
extern __inline__ void wait(uint32_t) __attribute__((always_inline)); extern void wait(uint32_t);
extern __inline__ bool waitfor(uint32_t us, checker_func condition) __attribute__((always_inline)); extern bool waitfor(uint32_t us, checker_func condition);
extern uint32_t get_timer(void);
extern void wait_ms(uint32_t ms);
extern __inline__ uint32_t get_timer(void)
{
return MCF_SLT_SCNT(0);
}
/*
* wait for the specified number of us on slice timer 0. Replaces the original routines that had
* the number of useconds to wait for hardcoded in their name.
*/
extern __inline__ void wait(uint32_t us)
{
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
while (MCF_SLT_SCNT(0) - target > 0);
}
/*
* same as above, but with milliseconds wait time
*/
extern __inline__ void wait_ms(uint32_t ms)
{
wait(ms * 1000);
}
/*
* the same as above, with a checker function which gets called while
* busy waiting and allows for an early return if it returns true
*/
extern __inline__ bool waitfor(uint32_t us, checker_func condition)
{
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
bool res;
do
{
if ((res = (*condition)()))
return res;
} while (MCF_SLT_SCNT(0) - target > 0);
return false;
}
#endif /* _WAIT_H_ */ #endif /* _WAIT_H_ */

View File

@@ -40,276 +40,300 @@ static unsigned char tx_queue[QUEUE_LEN];
static unsigned char wptr = 0, rptr = 0; static unsigned char wptr = 0, rptr = 0;
// structure to keep track of ikbd state // structure to keep track of ikbd state
static struct { static struct
unsigned char cmd; {
unsigned char state; unsigned char cmd;
unsigned char expect; unsigned char state;
unsigned char expect;
// joystick state // joystick state
unsigned char joystick[2]; unsigned char joystick[2];
// mouse state // mouse state
unsigned short mouse_pos_x, mouse_pos_y; unsigned short mouse_pos_x, mouse_pos_y;
unsigned char mouse_buttons; unsigned char mouse_buttons;
} ikbd; } ikbd;
// #define IKBD_DEBUG // #define IKBD_DEBUG
void ikbd_init() { void ikbd_init()
// reset ikbd state {
memset(&ikbd, 0, sizeof(ikbd)); // reset ikbd state
ikbd.state = IKBD_DEFAULT; memset(&ikbd, 0, sizeof(ikbd));
ikbd.state = IKBD_DEFAULT;
} }
static void enqueue(unsigned char b) { static void enqueue(unsigned char b)
if(((wptr + 1)&(QUEUE_LEN-1)) == rptr) { {
xprintf("IKBD: !!!!!!! tx queue overflow !!!!!!!!!\n"); if (((wptr + 1)&(QUEUE_LEN-1)) == rptr)
return; {
} xprintf("IKBD: !!!!!!! tx queue overflow !!!!!!!!!\n");
return;
}
tx_queue[wptr] = b; tx_queue[wptr] = b;
wptr = (wptr+1)&(QUEUE_LEN-1); wptr = (wptr + 1) & (QUEUE_LEN - 1);
} }
// convert internal joystick format into atari ikbd format // convert internal joystick format into atari ikbd format
static unsigned char joystick_map2ikbd(unsigned in) { static unsigned char joystick_map2ikbd(unsigned in)
unsigned char out = 0; {
unsigned char out = 0;
if(in & JOY_UP) out |= 0x01; if (in & JOY_UP) out |= 0x01;
if(in & JOY_DOWN) out |= 0x02; if (in & JOY_DOWN) out |= 0x02;
if(in & JOY_LEFT) out |= 0x04; if (in & JOY_LEFT) out |= 0x04;
if(in & JOY_RIGHT) out |= 0x08; if (in & JOY_RIGHT) out |= 0x08;
if(in & JOY_BTN1) out |= 0x80; if (in & JOY_BTN1) out |= 0x80;
return out; return out;
} }
// process inout from atari core into ikbd // process inout from atari core into ikbd
void ikbd_handle_input(unsigned char cmd) { void ikbd_handle_input(unsigned char cmd)
// expecting a second byte for command {
if(ikbd.expect) { // expecting a second byte for command
ikbd.expect--; if (ikbd.expect)
{
ikbd.expect--;
// last byte of command received // last byte of command received
if(!ikbd.expect) { if (!ikbd.expect)
switch(ikbd.cmd) { {
case 0x07: // set mouse button action switch(ikbd.cmd)
xprintf("IKBD: mouse button action = %x\n", cmd); {
case 0x07: // set mouse button action
xprintf("IKBD: mouse button action = %x\n", cmd);
// bit 2: Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75) // bit 2: Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
if(cmd & 0x04) ikbd.state |= IKBD_STATE_MOUSE_BUTTON_AS_KEY; if(cmd & 0x04) ikbd.state |= IKBD_STATE_MOUSE_BUTTON_AS_KEY;
else ikbd.state &= ~IKBD_STATE_MOUSE_BUTTON_AS_KEY; else ikbd.state &= ~IKBD_STATE_MOUSE_BUTTON_AS_KEY;
break; break;
case 0x80: // ibkd reset case 0x80: // ibkd reset
// reply "everything is ok" // reply "everything is ok"
enqueue(0xf0); enqueue(0xf0);
break; break;
default: default:
break; break;
} }
}
return;
} }
return; ikbd.cmd = cmd;
}
ikbd.cmd = cmd; switch(cmd)
{
case 0x07:
xprintf("IKBD: Set mouse button action");
ikbd.expect = 1;
break;
switch(cmd) { case 0x08:
case 0x07: xprintf("IKBD: Set relative mouse positioning");
xprintf("IKBD: Set mouse button action"); ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED;
ikbd.expect = 1; ikbd.state &= ~IKBD_STATE_MOUSE_ABSOLUTE;
break; break;
case 0x08: case 0x09:
xprintf("IKBD: Set relative mouse positioning"); xprintf("IKBD: Set absolute mouse positioning");
ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED; ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED;
ikbd.state &= ~IKBD_STATE_MOUSE_ABSOLUTE; ikbd.state |= IKBD_STATE_MOUSE_ABSOLUTE;
break; ikbd.expect = 4;
break;
case 0x09: case 0x0b:
xprintf("IKBD: Set absolute mouse positioning"); xprintf("IKBD: Set Mouse threshold");
ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED; ikbd.expect = 2;
ikbd.state |= IKBD_STATE_MOUSE_ABSOLUTE; break;
ikbd.expect = 4;
break;
case 0x0b: case 0x0f:
xprintf("IKBD: Set Mouse threshold"); xprintf("IKBD: Set Y at bottom");
ikbd.expect = 2; ikbd.state |= IKBD_STATE_MOUSE_Y_BOTTOM;
break; break;
case 0x0f: case 0x10:
xprintf("IKBD: Set Y at bottom"); xprintf("IKBD: Set Y at top");
ikbd.state |= IKBD_STATE_MOUSE_Y_BOTTOM; ikbd.state &= ~IKBD_STATE_MOUSE_Y_BOTTOM;
break; break;
case 0x10: case 0x12:
xprintf("IKBD: Set Y at top"); xprintf("IKBD: Disable mouse");
ikbd.state &= ~IKBD_STATE_MOUSE_Y_BOTTOM; ikbd.state |= IKBD_STATE_MOUSE_DISABLED;
break; break;
case 0x12: case 0x14:
xprintf("IKBD: Disable mouse"); xprintf("IKBD: Set Joystick event reporting");
ikbd.state |= IKBD_STATE_MOUSE_DISABLED; ikbd.state |= IKBD_STATE_JOYSTICK_EVENT_REPORTING;
break; break;
case 0x14: case 0x15:
xprintf("IKBD: Set Joystick event reporting"); xprintf("IKBD: Set Joystick interrogation mode");
ikbd.state |= IKBD_STATE_JOYSTICK_EVENT_REPORTING; ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
break; break;
case 0x15: case 0x16: // interrogate joystick
xprintf("IKBD: Set Joystick interrogation mode"); // send reply
ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING; enqueue(0xfd);
break; enqueue(joystick_map2ikbd(ikbd.joystick[0]));
enqueue(joystick_map2ikbd(ikbd.joystick[1]));
break;
case 0x16: // interrogate joystick case 0x1a:
// send reply xprintf("IKBD: Disable joysticks");
enqueue(0xfd); ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
enqueue(joystick_map2ikbd(ikbd.joystick[0])); break;
enqueue(joystick_map2ikbd(ikbd.joystick[1]));
break;
case 0x1a: case 0x1c:
xprintf("IKBD: Disable joysticks"); xprintf("IKBD: Interrogate time of day");
ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
break;
case 0x1c: enqueue(0xfc);
xprintf("IKBD: Interrogate time of day"); enqueue(0x13); // year bcd
enqueue(0x03); // month bcd
enqueue(0xfc); enqueue(0x07); // day bcd
enqueue(0x13); // year bcd enqueue(0x20); // hour bcd
enqueue(0x03); // month bcd enqueue(0x58); // minute bcd
enqueue(0x07); // day bcd enqueue(0x00); // second bcd
enqueue(0x20); // hour bcd break;
enqueue(0x58); // minute bcd
enqueue(0x00); // second bcd
break;
case 0x80: case 0x80:
xprintf("IKBD: Reset"); xprintf("IKBD: Reset");
ikbd.expect = 1; ikbd.expect = 1;
ikbd.state = IKBD_DEFAULT; ikbd.state = IKBD_DEFAULT;
break; break;
default: default:
xprintf("IKBD: unknown command: %x\n", cmd); xprintf("IKBD: unknown command: %x\n", cmd);
break; break;
} }
} }
void ikbd_poll(void) { void ikbd_poll(void) {
static int mtimer = 0; static int mtimer = 0;
if(CheckTimer(mtimer)) { if (CheckTimer(mtimer))
mtimer = GetTimer(10); {
mtimer = GetTimer(10);
// check for incoming ikbd data // check for incoming ikbd data
EnableIO();
SPI(UIO_IKBD_IN);
while(SPI(0))
ikbd_handle_input(SPI(0));
DisableIO();
}
// send data from queue if present
if(rptr == wptr) return;
// transmit data from queue
EnableIO(); EnableIO();
SPI(UIO_IKBD_IN); SPI(UIO_IKBD_OUT);
SPI(tx_queue[rptr]);
while(SPI(0))
ikbd_handle_input(SPI(0));
DisableIO(); DisableIO();
}
// send data from queue if present rptr = (rptr + 1) & (QUEUE_LEN - 1);
if(rptr == wptr) return;
// transmit data from queue
EnableIO();
SPI(UIO_IKBD_OUT);
SPI(tx_queue[rptr]);
DisableIO();
rptr = (rptr+1)&(QUEUE_LEN-1);
} }
void ikbd_joystick(unsigned char joystick, unsigned char map) { void ikbd_joystick(unsigned char joystick, unsigned char map)
// todo: suppress events for joystick 0 as long as mouse {
// is enabled? // todo: suppress events for joystick 0 as long as mouse
// is enabled?
if(ikbd.state & IKBD_STATE_JOYSTICK_EVENT_REPORTING) { if (ikbd.state & IKBD_STATE_JOYSTICK_EVENT_REPORTING)
{
#ifdef IKBD_DEBUG #ifdef IKBD_DEBUG
xprintf("IKBD: joy %d %x\n", joystick, map); xprintf("IKBD: joy %d %x\n", joystick, map);
#endif #endif
// only report joystick data for joystick 0 if the mouse is disabled // only report joystick data for joystick 0 if the mouse is disabled
if((ikbd.state & IKBD_STATE_MOUSE_DISABLED) || (joystick == 1)) { if ((ikbd.state & IKBD_STATE_MOUSE_DISABLED) || (joystick == 1))
enqueue(0xfe + joystick); {
enqueue(joystick_map2ikbd(map)); enqueue(0xfe + joystick);
} enqueue(joystick_map2ikbd(map));
}
if(!(ikbd.state & IKBD_STATE_MOUSE_DISABLED)) { if (!(ikbd.state & IKBD_STATE_MOUSE_DISABLED))
// the fire button also generates a mouse event if {
// mouse reporting is enabled // the fire button also generates a mouse event if
if((map & JOY_BTN1) != (ikbd.joystick[joystick] & JOY_BTN1)) { // mouse reporting is enabled
// generate mouse event (ikbd_joystick_buttons is evaluated inside if ((map & JOY_BTN1) != (ikbd.joystick[joystick] & JOY_BTN1))
// user_io_mouse) {
ikbd.joystick[joystick] = map; // generate mouse event (ikbd_joystick_buttons is evaluated inside
ikbd_mouse(0, 0, 0); // user_io_mouse)
} ikbd.joystick[joystick] = map;
ikbd_mouse(0, 0, 0);
}
}
} }
}
#ifdef IKBD_DEBUG #ifdef IKBD_DEBUG
else else
xprintf("IKBD: no monitor, drop joy %d %x\n", joystick, map); xprintf("IKBD: no monitor, drop joy %d %x\n", joystick, map);
#endif #endif
// save state of joystick for interrogation mode // save state of joystick for interrogation mode
ikbd.joystick[joystick] = map; ikbd.joystick[joystick] = map;
} }
void ikbd_keyboard(unsigned char code) { void ikbd_keyboard(unsigned char code)
{
#ifdef IKBD_DEBUG #ifdef IKBD_DEBUG
xprintf("IKBD: send keycode %x%s\n", code&0x7f, (code&0x80)?" BREAK":""); xprintf("IKBD: send keycode %x%s\n", code&0x7f, (code&0x80)?" BREAK":"");
#endif #endif
enqueue(code); enqueue(code);
} }
void ikbd_mouse(uint8_t b, int8_t x, int8_t y) { void ikbd_mouse(uint8_t b, int8_t x, int8_t y)
if(ikbd.state & IKBD_STATE_MOUSE_DISABLED) {
return; if (ikbd.state & IKBD_STATE_MOUSE_DISABLED)
return;
// joystick and mouse buttons are wired together in // joystick and mouse buttons are wired together in
// atari st // atari st
b |= (ikbd.joystick[0] & JOY_BTN1)?1:0; b |= (ikbd.joystick[0] & JOY_BTN1)?1:0;
b |= (ikbd.joystick[1] & JOY_BTN1)?2:0; b |= (ikbd.joystick[1] & JOY_BTN1)?2:0;
static unsigned char b_old = 0; static unsigned char b_old = 0;
// monitor state of two mouse buttons // monitor state of two mouse buttons
if(b != b_old) { if (b != b_old)
// check if mouse buttons are supposed to be treated like keys {
if(ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) { // check if mouse buttons are supposed to be treated like keys
// Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75) if (ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY)
{
// Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
// handle left mouse button // handle left mouse button
if((b ^ b_old) & 1) ikbd_keyboard(0x74 | ((b&1)?0x00:0x80)); if((b ^ b_old) & 1) ikbd_keyboard(0x74 | ((b&1)?0x00:0x80));
// handle right mouse button // handle right mouse button
if((b ^ b_old) & 2) ikbd_keyboard(0x75 | ((b&2)?0x00:0x80)); if((b ^ b_old) & 2) ikbd_keyboard(0x75 | ((b&2)?0x00:0x80));
}
b_old = b;
} }
b_old = b;
}
#if 0 #if 0
if(ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) { if(ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY)
b = 0; {
// if mouse position is 0/0 quit here b = 0;
if(!x && !y) return; // if mouse position is 0/0 quit here
} if(!x && !y) return;
}
#endif #endif
if(ikbd.state & IKBD_STATE_MOUSE_ABSOLUTE) { if (ikbd.state & IKBD_STATE_MOUSE_ABSOLUTE)
} else { {
// atari has mouse button bits swapped }
enqueue(0xf8|((b&1)?2:0)|((b&2)?1:0)); else
enqueue(x); {
enqueue((ikbd.state & IKBD_STATE_MOUSE_Y_BOTTOM)?-y:y); // atari has mouse button bits swapped
} enqueue(0xf8|((b&1)?2:0)|((b&2)?1:0));
enqueue(x);
enqueue((ikbd.state & IKBD_STATE_MOUSE_Y_BOTTOM)?-y:y);
}
} }

View File

@@ -61,6 +61,11 @@ define ib
setup-dram setup-dram
end end
define run
continue
end
tr tr
ib ib
load add-symbol-file ../emutos/emutos2.img 0xe00000
load firebee/ram.elf

View File

@@ -13,8 +13,10 @@
#include "firebee.h" #include "firebee.h"
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else #else
#error "unknown machine" #error "unknown machine!"
#endif #endif
//#define DBG_AM79 //#define DBG_AM79
@@ -63,6 +65,7 @@ int am79c874_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duple
if (!(settings & MII_AM79C874_CR_RESET)) if (!(settings & MII_AM79C874_CR_RESET))
break; break;
} }
if (timeout >= FEC_MII_TIMEOUT) if (timeout >= FEC_MII_TIMEOUT)
{ {
dbg("%s: PHY reset failed\r\n", __FUNCTION__); dbg("%s: PHY reset failed\r\n", __FUNCTION__);
@@ -88,11 +91,14 @@ int am79c874_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duple
if (timeout >= FEC_MII_TIMEOUT) if (timeout >= FEC_MII_TIMEOUT)
{ {
dbg("%s: PHY Set the default mode\r\n", __FUNCTION__); dbg("%s: Auto-negotiation failed (timeout). Set default mode (100Mbps, full duplex)\r\n", __FUNCTION__);
/* Set the default mode (Full duplex, 100 Mbps) */ /* Set the default mode (Full duplex, 100 Mbps) */
if (!fec_mii_write(fec_ch, phy_addr, MII_AM79C874_CR, MII_AM79C874_CR_100MB | MII_AM79C874_CR_DPLX)) if (!fec_mii_write(fec_ch, phy_addr, MII_AM79C874_CR, MII_AM79C874_CR_100MB | MII_AM79C874_CR_DPLX))
{
dbg("%s: forced setting 100Mbps/full failed.\r\n", __FUNCTION__);
return 0; return 0;
}
} }
#ifdef DBG_AM79 #ifdef DBG_AM79

View File

@@ -11,7 +11,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#define DBG_ARP //#define DBG_ARP
#ifdef DBG_ARP #ifdef DBG_ARP
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
#else #else

View File

@@ -18,13 +18,15 @@
#include "firebee.h" #include "firebee.h"
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else #else
#error "Unknown machine!" #error "Unknown machine!"
#endif #endif
#define DBG_BCM #define DBG_BCM
#ifdef DBG_BCM #ifdef DBG_BCM
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif /* DBG_BCM */ #endif /* DBG_BCM */
@@ -53,7 +55,7 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
/* Initialize the MII interface */ /* Initialize the MII interface */
fec_mii_init(fec_ch, SYSCLK / 1000); fec_mii_init(fec_ch, SYSCLK / 1000);
dbg("%s: PHY reset\r\n", __FUNCTION__); dbg("PHY reset\r\n");
/* Reset the PHY */ /* Reset the PHY */
if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, BCM5222_CTRL_RESET | BCM5222_CTRL_ANE)) if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, BCM5222_CTRL_RESET | BCM5222_CTRL_ANE))
@@ -69,7 +71,7 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
if(timeout >= FEC_MII_TIMEOUT) if(timeout >= FEC_MII_TIMEOUT)
return 0; return 0;
dbg("%s: PHY reset OK\r\n", __FUNCTION__); dbg("PHY reset OK\r\n");
settings = (BCM5222_AN_ADV_NEXT_PAGE | BCM5222_AN_ADV_PAUSE); settings = (BCM5222_AN_ADV_NEXT_PAGE | BCM5222_AN_ADV_PAUSE);
@@ -87,13 +89,13 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
if (!fec_mii_write(fec_ch, phy_addr, BCM5222_AN_ADV, settings)) if (!fec_mii_write(fec_ch, phy_addr, BCM5222_AN_ADV, settings))
return 0; return 0;
dbg("%s: PHY Enable Auto-Negotiation\r\n", __FUNCTION__); dbg("PHY Enable Auto-Negotiation\r\n");
/* Enable Auto-Negotiation */ /* Enable Auto-Negotiation */
if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, (BCM5222_CTRL_ANE | BCM5222_CTRL_RESTART_AN))) if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, (BCM5222_CTRL_ANE | BCM5222_CTRL_RESTART_AN)))
return 0; return 0;
dbg("%s: PHY Wait for auto-negotiation to complete\r\n", __FUNCTION__); dbg("PHY Wait for auto-negotiation to complete\r\n");
/* Wait for auto-negotiation to complete */ /* Wait for auto-negotiation to complete */
for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++) for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
@@ -106,7 +108,7 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
if (timeout < FEC_MII_TIMEOUT) if (timeout < FEC_MII_TIMEOUT)
{ {
dbg("%s: PHY auto-negociation complete\r\n", __FUNCTION__); dbg("PHY auto-negociation complete\r\n");
/* Read Auxiliary Control/Status Register */ /* Read Auxiliary Control/Status Register */
if (!fec_mii_read(fec_ch, phy_addr, BCM5222_ACSR, &settings)) if (!fec_mii_read(fec_ch, phy_addr, BCM5222_ACSR, &settings))
@@ -114,7 +116,7 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
} }
else else
{ {
dbg("%s: auto negotiation failed, PHY Set the default mode\r\n", __FUNCTION__); dbg("auto negotiation failed, PHY Set the default mode\r\n");
/* Set the default mode (Full duplex, 100 Mbps) */ /* Set the default mode (Full duplex, 100 Mbps) */
if (!fec_mii_write(fec_ch, phy_addr, BCM5222_ACSR, settings = (BCM5222_ACSR_100BTX | BCM5222_ACSR_FDX))) if (!fec_mii_write(fec_ch, phy_addr, BCM5222_ACSR, settings = (BCM5222_ACSR_100BTX | BCM5222_ACSR_FDX)))
@@ -127,17 +129,17 @@ int bcm5222_init(uint8_t fec_ch, uint8_t phy_addr, uint8_t speed, uint8_t duplex
else else
fec_duplex(fec_ch, FEC_MII_HALF_DUPLEX); fec_duplex(fec_ch, FEC_MII_HALF_DUPLEX);
dbg("%s: PHY Mode: ", __FUNCTION__); dbg("PHY Mode: ");
if (settings & BCM5222_ACSR_100BTX) if (settings & BCM5222_ACSR_100BTX)
dbg("%s: 100Mbps\r\n", __FUNCTION__); dbg("100Mbps\r\n");
else else
dbg("%s: 10Mbps\r\n", __FUNCTION__); dbg("10Mbps\r\n");
if (settings & BCM5222_ACSR_FDX) if (settings & BCM5222_ACSR_FDX)
dbg("%s: Full-duplex\r\n", __FUNCTION__); dbg("Full-duplex\r\n");
else else
dbg("%s: Half-duplex\r\n", __FUNCTION__); dbg("Half-duplex\r\n");
return 1; return 1;
} }

View File

@@ -13,7 +13,7 @@
#define DBG_BOOTP #define DBG_BOOTP
#ifdef DBG_BOOTP #ifdef DBG_BOOTP
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif /* DBG_BOOTP */ #endif /* DBG_BOOTP */
@@ -94,7 +94,7 @@ void bootp_handler(NIF *nif, NBUF *nbuf)
struct bootp_packet *rx_p; struct bootp_packet *rx_p;
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;
dbg("%s\n", __FUNCTION__); dbg("\r\n");
rx_p = (struct bootp_packet *) &nbuf->data[nbuf->offset]; rx_p = (struct bootp_packet *) &nbuf->data[nbuf->offset];
udpframe = (udp_frame_hdr *) &nbuf->data[nbuf->offset - UDP_HDR_SIZE]; udpframe = (udp_frame_hdr *) &nbuf->data[nbuf->offset - UDP_HDR_SIZE];

144
net/fec.c
View File

@@ -17,21 +17,24 @@
#include "bas_string.h" #include "bas_string.h"
#include "bas_printf.h" #include "bas_printf.h"
#include "util.h" #include "util.h"
#include "wait.h"
#include "am79c874.h" #include "am79c874.h"
#include "bcm5222.h" //#include "bcm5222.h"
#include <stdbool.h> #include <stdbool.h>
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else #else
#error Unknown machine! #error Unknown machine!
#endif #endif
//#define DBG_FEC #define DBG_FEC
#ifdef DBG_FEC #ifdef DBG_FEC
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif /* DBG_FEC */ #endif /* DBG_FEC */
@@ -91,11 +94,12 @@ int fec_mii_write(uint8_t ch, uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
*/ */
for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++) for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
{ {
wait(1);
if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII) if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII)
break; break;
} }
if(timeout == FEC_MII_TIMEOUT) if (timeout == FEC_MII_TIMEOUT)
return 0; return 0;
/* /*
@@ -156,11 +160,12 @@ int fec_mii_read(uint8_t ch, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data)
*/ */
for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++) for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
{ {
wait(1);
if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII) if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII)
break; break;
} }
if(timeout == FEC_MII_TIMEOUT) if (timeout == FEC_MII_TIMEOUT)
return 0; return 0;
/* /*
@@ -232,33 +237,33 @@ void fec_log_init(uint8_t ch)
*/ */
void fec_log_dump(uint8_t ch) void fec_log_dump(uint8_t ch)
{ {
dbg("%s: \r\n FEC%d Log\r\n", __FUNCTION__, ch); dbg("\r\n FEC%d Log\r\n", __FUNCTION__, ch);
dbg("%s: ---------------\r\n", __FUNCTION__); dbg(" ---------------\r\n", __FUNCTION__);
dbg("%s: Total: %4d\r\n", __FUNCTION__, fec_log[ch].total); dbg(" Total: %4d\r\n", fec_log[ch].total);
dbg("%s: hberr: %4d\r\n", __FUNCTION__, fec_log[ch].hberr); dbg(" hberr: %4d\r\n", fec_log[ch].hberr);
dbg("%s: babr: %4d\r\n", __FUNCTION__, fec_log[ch].babr); dbg(" babr: %4d\r\n", fec_log[ch].babr);
dbg("%s: babt: %4d\r\n", __FUNCTION__, fec_log[ch].babt); dbg(" babt: %4d\r\n", fec_log[ch].babt);
dbg("%s: gra: %4d\r\n", __FUNCTION__, fec_log[ch].gra); dbg(" gra: %4d\r\n", fec_log[ch].gra);
dbg("%s: txf: %4d\r\n", __FUNCTION__, fec_log[ch].txf); dbg(" txf: %4d\r\n", fec_log[ch].txf);
dbg("%s: mii: %4d\r\n", __FUNCTION__, fec_log[ch].mii); dbg(" mii: %4d\r\n", fec_log[ch].mii);
dbg("%s: lc: %4d\r\n", __FUNCTION__, fec_log[ch].lc); dbg(" lc: %4d\r\n", fec_log[ch].lc);
dbg("%s: rl: %4d\r\n", __FUNCTION__, fec_log[ch].rl); dbg(" rl: %4d\r\n", fec_log[ch].rl);
dbg("%s: xfun: %4d\r\n", __FUNCTION__, fec_log[ch].xfun); dbg(" xfun: %4d\r\n", fec_log[ch].xfun);
dbg("%s: xferr: %4d\r\n", __FUNCTION__, fec_log[ch].xferr); dbg(" xferr: %4d\r\n", fec_log[ch].xferr);
dbg("%s: rferr: %4d\r\n", __FUNCTION__, fec_log[ch].rferr); dbg(" rferr: %4d\r\n", fec_log[ch].rferr);
dbg("%s: dtxf: %4d\r\n", __FUNCTION__, fec_log[ch].dtxf); dbg(" dtxf: %4d\r\n", fec_log[ch].dtxf);
dbg("%s: drxf: %4d\r\n", __FUNCTION__, fec_log[ch].drxf); dbg(" drxf: %4d\r\n", fec_log[ch].drxf);
dbg("%s: \r\nRFSW:\r\n", __FUNCTION__); dbg(" \r\nRFSW:\r\n");
dbg("%s: inv: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_inv); dbg(" inv: %4d\r\n", fec_log[ch].rfsw_inv);
dbg("%s: m: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_m); dbg(" m: %4d\r\n", fec_log[ch].rfsw_m);
dbg("%s: bc: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_bc); dbg(" bc: %4d\r\n", fec_log[ch].rfsw_bc);
dbg("%s: mc: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_mc); dbg(" mc: %4d\r\n", fec_log[ch].rfsw_mc);
dbg("%s: lg: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_lg); dbg(" lg: %4d\r\n", fec_log[ch].rfsw_lg);
dbg("%s: no: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_no); dbg(" no: %4d\r\n", fec_log[ch].rfsw_no);
dbg("%s: cr: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_cr); dbg(" cr: %4d\r\n", fec_log[ch].rfsw_cr);
dbg("%s: ov: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_ov); dbg(" ov: %4d\r\n", fec_log[ch].rfsw_ov);
dbg("%s: tr: %4d\r\n", __FUNCTION__, fec_log[ch].rfsw_tr); dbg(" tr: %4d\r\n", fec_log[ch].rfsw_tr);
dbg("%s: ---------------\r\n\r\n", __FUNCTION__); dbg(" ---------------\r\n\r\n");
} }
/* /*
@@ -481,9 +486,7 @@ void fec_init(uint8_t ch, uint8_t mode, const uint8_t *pa)
*/ */
MCF_FEC_RCR(ch) = 0 MCF_FEC_RCR(ch) = 0
| MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM)
//#ifdef FEC_PROMISCUOUS
| MCF_FEC_RCR_PROM | MCF_FEC_RCR_PROM
//#endif
| MCF_FEC_RCR_FCE; | MCF_FEC_RCR_FCE;
if (mode == FEC_MODE_MII) if (mode == FEC_MODE_MII)
@@ -541,13 +544,13 @@ void fec_rx_start(uint8_t ch, int8_t *rxbd)
* Make the initiator assignment * Make the initiator assignment
*/ */
res = dma_set_initiator(DMA_FEC_RX(ch)); res = dma_set_initiator(DMA_FEC_RX(ch));
dbg("%s: dma_set_initiator(DMA_FEC_RX(%d)): %d\r\n", __FUNCTION__, ch, res); dbg("dma_set_initiator(DMA_FEC_RX(%d)): %d\r\n", ch, res);
/* /*
* Grab the initiator number * Grab the initiator number
*/ */
initiator = dma_get_initiator(DMA_FEC_RX(ch)); initiator = dma_get_initiator(DMA_FEC_RX(ch));
dbg("%s: dma_get_initiator(DMA_FEC_RX(%d)) = %d\r\n", __FUNCTION__, ch, initiator); dbg("dma_get_initiator(DMA_FEC_RX(%d)) = %d\r\n", ch, initiator);
/* /*
* Determine the DMA channel running the task for the * Determine the DMA channel running the task for the
@@ -555,7 +558,7 @@ void fec_rx_start(uint8_t ch, int8_t *rxbd)
*/ */
channel = dma_set_channel(DMA_FEC_RX(ch), channel = dma_set_channel(DMA_FEC_RX(ch),
(ch == 0) ? fec0_rx_frame : fec1_rx_frame); (ch == 0) ? fec0_rx_frame : fec1_rx_frame);
dbg("%s: DMA channel for FEC%1d: %d\r\n", __FUNCTION__, ch, channel); dbg("DMA channel for FEC%1d: %d\r\n", ch, channel);
/* /*
* Start the Rx DMA task * Start the Rx DMA task
@@ -580,7 +583,7 @@ void fec_rx_start(uint8_t ch, int8_t *rxbd)
| MCD_NO_CSUM | MCD_NO_CSUM
| MCD_NO_BYTE_SWAP | MCD_NO_BYTE_SWAP
); );
dbg("%s: Rx DMA task for FEC%1d started\r\n", __FUNCTION__, ch); dbg("Rx DMA task for FEC%1d started\r\n", ch);
} }
/* /*
@@ -604,13 +607,13 @@ void fec_rx_continue(uint8_t ch)
*/ */
channel = dma_get_channel(DMA_FEC_RX(ch)); channel = dma_get_channel(DMA_FEC_RX(ch));
dbg("%s: RX DMA channel for FEC%1d is %d\r\n", __FUNCTION__, ch, channel); dbg("RX DMA channel for FEC%1d is %d\r\n", ch, channel);
/* /*
* Continue/restart the DMA task * Continue/restart the DMA task
*/ */
MCD_continDma(channel); MCD_continDma(channel);
dbg("%s: RX dma on channel %d continued\r\n", __FUNCTION__, channel); dbg("RX dma on channel %d continued\r\n", channel);
} }
/* /*
@@ -668,7 +671,7 @@ void fec_rx_frame(uint8_t ch, NIF *nif)
NBUF *cur_nbuf, *new_nbuf; NBUF *cur_nbuf, *new_nbuf;
int keep; int keep;
dbg("%s: started\r\n", __FUNCTION__); dbg("started\r\n");
while ((pRxBD = fecbd_rx_alloc(ch)) != NULL) while ((pRxBD = fecbd_rx_alloc(ch)) != NULL)
{ {
@@ -730,7 +733,7 @@ void fec_rx_frame(uint8_t ch, NIF *nif)
new_nbuf = nbuf_alloc(); new_nbuf = nbuf_alloc();
if (new_nbuf == NULL) if (new_nbuf == NULL)
{ {
dbg("%s: nbuf_alloc() failed\n", __FUNCTION__); dbg("nbuf_alloc() failed\n");
/* /*
* Can't allocate a new network buffer, so we * Can't allocate a new network buffer, so we
@@ -786,7 +789,7 @@ void fec_rx_frame(uint8_t ch, NIF *nif)
else else
{ {
nbuf_free(cur_nbuf); nbuf_free(cur_nbuf);
dbg("%s: got unsupported packet %d, trashed it\r\n", __FUNCTION__, eth_hdr->type); dbg("got unsupported packet %d, trashed it\r\n", eth_hdr->type);
} }
} }
else else
@@ -850,13 +853,13 @@ void fec_tx_start(uint8_t ch, int8_t *txbd)
* Make the initiator assignment * Make the initiator assignment
*/ */
res = dma_set_initiator(DMA_FEC_TX(ch)); res = dma_set_initiator(DMA_FEC_TX(ch));
dbg("%s: dma_set_initiator(%d) = %d\r\n", __FUNCTION__, ch, res); dbg("dma_set_initiator(%d) = %d\r\n", ch, res);
/* /*
* Grab the initiator number * Grab the initiator number
*/ */
initiator = dma_get_initiator(DMA_FEC_TX(ch)); initiator = dma_get_initiator(DMA_FEC_TX(ch));
dbg("%s: dma_get_initiator(%d) = %d\r\n", __FUNCTION__, ch, initiator); dbg("dma_get_initiator(%d) = %d\r\n", ch, initiator);
/* /*
@@ -865,7 +868,7 @@ void fec_tx_start(uint8_t ch, int8_t *txbd)
*/ */
channel = dma_set_channel(DMA_FEC_TX(ch), channel = dma_set_channel(DMA_FEC_TX(ch),
(ch == 0) ? fec0_tx_frame : fec1_tx_frame); (ch == 0) ? fec0_tx_frame : fec1_tx_frame);
dbg("%s: dma_set_channel(%d, ...) = %d\r\n", __FUNCTION__, ch, channel); dbg("dma_set_channel(%d, ...) = %d\r\n", ch, channel);
/* /*
* Start the Tx DMA task * Start the Tx DMA task
@@ -890,7 +893,7 @@ void fec_tx_start(uint8_t ch, int8_t *txbd)
| MCD_NO_CSUM | MCD_NO_CSUM
| MCD_NO_BYTE_SWAP | MCD_NO_BYTE_SWAP
); );
dbg("%s: DMA tx task started\r\n", __FUNCTION__); dbg("DMA tx task started\r\n");
} }
/* /*
@@ -913,14 +916,13 @@ void fec_tx_continue(uint8_t ch)
* selected FEC * selected FEC
*/ */
channel = dma_get_channel(DMA_FEC_TX(ch)); channel = dma_get_channel(DMA_FEC_TX(ch));
dbg("%s: dma_get_channel(DMA_FEC_TX(%d)) = %d\r\n", dbg("dma_get_channel(DMA_FEC_TX(%d)) = %d\r\n", ch, channel);
__FUNCTION__, ch, channel);
/* /*
* Continue/restart the DMA task * Continue/restart the DMA task
*/ */
MCD_continDma(channel); MCD_continDma(channel);
dbg("%s: DMA TX task continue\r\n", __FUNCTION__); dbg("DMA TX task continue\r\n");
} }
/* /*
@@ -994,7 +996,7 @@ void fec_tx_frame(uint8_t ch)
NBUF *pNbuf; NBUF *pNbuf;
bool is_empty = true; bool is_empty = true;
dbg("%s:\r\n", __FUNCTION__); dbg("\r\n");
while ((pTxBD = fecbd_tx_free(ch)) != NULL) while ((pTxBD = fecbd_tx_free(ch)) != NULL)
{ {
fec_log[ch].dtxf++; fec_log[ch].dtxf++;
@@ -1008,7 +1010,7 @@ void fec_tx_frame(uint8_t ch)
* Free up the network buffer that was just transmitted * Free up the network buffer that was just transmitted
*/ */
nbuf_free(pNbuf); nbuf_free(pNbuf);
dbg("%s: free buffer %p from TX ring\r\n", __FUNCTION__, pNbuf); dbg("free buffer %p from TX ring\r\n", pNbuf);
/* /*
* Re-initialize the Tx BD * Re-initialize the Tx BD
@@ -1019,7 +1021,7 @@ void fec_tx_frame(uint8_t ch)
} }
if (is_empty) if (is_empty)
dbg("%s: transmit queue was empty!\r\n", __FUNCTION__); dbg("transmit queue was empty!\r\n");
} }
void fec0_tx_frame(void) void fec0_tx_frame(void)
@@ -1057,8 +1059,8 @@ int fec_send(uint8_t ch, NIF *nif, uint8_t *dst, uint8_t *src, uint16_t type, NB
/* Check the length */ /* Check the length */
if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU) if ((nbuf->length + ETH_HDR_LEN) > ETH_MTU)
{ {
dbg("%s: nbuf->length (%d) + ETH_HDR_LEN (%d) exceeds ETH_MTU (%d)\r\n", dbg("nbuf->length (%d) + ETH_HDR_LEN (%d) exceeds ETH_MTU (%d)\r\n",
__FUNCTION__, nbuf->length, ETH_HDR_LEN, ETH_MTU); nbuf->length, ETH_HDR_LEN, ETH_MTU);
return 0; return 0;
} }
@@ -1190,7 +1192,7 @@ static void fec_irq_handler(uint8_t ch)
event = eir & MCF_FEC_EIMR(ch); event = eir & MCF_FEC_EIMR(ch);
if (event != eir) if (event != eir)
dbg("%s: pending but not enabled: 0x%08x\r\n", __FUNCTION__, (event ^ eir)); dbg("pending but not enabled: 0x%08x\r\n", (event ^ eir));
/* /*
* Clear the event(s) in the EIR immediately * Clear the event(s) in the EIR immediately
@@ -1201,8 +1203,8 @@ static void fec_irq_handler(uint8_t ch)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].rferr++; fec_log[ch].rferr++;
dbg("%s: RFERR\r\n", __FUNCTION__); dbg("RFERR\r\n");
dbg("%s: FECRFSR%d = 0x%08x\r\n", __FUNCTION__, ch, MCF_FEC_FECRFSR(ch)); dbg("FECRFSR%d = 0x%08x\r\n", ch, MCF_FEC_FECRFSR(ch));
//fec_eth_stop(ch); //fec_eth_stop(ch);
} }
@@ -1210,14 +1212,14 @@ static void fec_irq_handler(uint8_t ch)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].xferr++; fec_log[ch].xferr++;
dbg("%s: XFERR\r\n", __FUNCTION__); dbg("XFERR\r\n");
} }
if (event & MCF_FEC_EIR_XFUN) if (event & MCF_FEC_EIR_XFUN)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].xfun++; fec_log[ch].xfun++;
dbg("%s: XFUN\r\n", __FUNCTION__); dbg("XFUN\r\n");
//fec_eth_stop(ch); //fec_eth_stop(ch);
} }
@@ -1225,54 +1227,54 @@ static void fec_irq_handler(uint8_t ch)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].rl++; fec_log[ch].rl++;
dbg("%s: RL\r\n", __FUNCTION__); dbg("RL\r\n");
} }
if (event & MCF_FEC_EIR_LC) if (event & MCF_FEC_EIR_LC)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].lc++; fec_log[ch].lc++;
dbg("%s: LC\r\n", __FUNCTION__); dbg("LC\r\n");
} }
if (event & MCF_FEC_EIR_MII) if (event & MCF_FEC_EIR_MII)
{ {
fec_log[ch].mii++; fec_log[ch].mii++;
dbg("%s: MII\r\n", __FUNCTION__); dbg("MII\r\n");
} }
if (event & MCF_FEC_EIR_TXF) if (event & MCF_FEC_EIR_TXF)
{ {
fec_log[ch].txf++; fec_log[ch].txf++;
dbg("%s: TXF\r\n", __FUNCTION__); dbg("TXF\r\n");
fec_log_dump(0); fec_log_dump(0);
} }
if (event & MCF_FEC_EIR_GRA) if (event & MCF_FEC_EIR_GRA)
{ {
fec_log[ch].gra++; fec_log[ch].gra++;
dbg("%s: GRA\r\n", __FUNCTION__); dbg("GRA\r\n");
} }
if (event & MCF_FEC_EIR_BABT) if (event & MCF_FEC_EIR_BABT)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].babt++; fec_log[ch].babt++;
dbg("%s: BABT\r\n", __FUNCTION__); dbg("BABT\r\n");
} }
if (event & MCF_FEC_EIR_BABR) if (event & MCF_FEC_EIR_BABR)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].babr++; fec_log[ch].babr++;
dbg("%s: BABR\r\n", __FUNCTION__); dbg("BABR\r\n");
} }
if (event & MCF_FEC_EIR_HBERR) if (event & MCF_FEC_EIR_HBERR)
{ {
fec_log[ch].total++; fec_log[ch].total++;
fec_log[ch].hberr++; fec_log[ch].hberr++;
dbg("%s: HBERR\r\n", __FUNCTION__); dbg("HBERR\r\n");
} }
} }
@@ -1342,9 +1344,9 @@ void fec_eth_setup(uint8_t ch, uint8_t trcvr, uint8_t speed, uint8_t duplex, con
*/ */
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
if (am79c874_init(0, 0, speed, duplex)) if (am79c874_init(0, 0, speed, duplex))
dbg("%s: PHY init completed\r\n", __FUNCTION__); dbg("PHY init completed\r\n");
else else
dbg("%s: PHY init failed\r\n", __FUNCTION__); dbg("PHY init failed\r\n");
#elif defined(MACHINE_M548X) #elif defined(MACHINE_M548X)
bcm_5222_init(0, 0, speed, duplex); bcm_5222_init(0, 0, speed, duplex);
#else #else
@@ -1397,7 +1399,7 @@ void fec_eth_stop(uint8_t ch)
*/ */
level = set_ipl(7); level = set_ipl(7);
dbg("%s: fec %d stopped\r\n", __FUNCTION__, ch); dbg("fec %d stopped\r\n", ch);
/* /*
* Gracefully disable the receiver and transmitter * Gracefully disable the receiver and transmitter
*/ */

View File

@@ -11,7 +11,7 @@
#include "bas_printf.h" #include "bas_printf.h"
#include <stddef.h> #include <stddef.h>
//#define DBG_FECBD #define DBG_FECBD
#ifdef DBG_FECBD #ifdef DBG_FECBD
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
#else #else
@@ -31,14 +31,14 @@
* *
*/ */
FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1]; static FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1];
/* /*
* These pointers are used to reference into the chunck of data set * These pointers are used to reference into the chunck of data set
* aside for buffer descriptors * aside for buffer descriptors
*/ */
FECBD *RxBD; static FECBD *RxBD;
FECBD *TxBD; static FECBD *TxBD;
/* /*
* Macros to easier access to the BD ring * Macros to easier access to the BD ring
@@ -65,7 +65,7 @@ void fecbd_init(uint8_t ch)
NBUF *nbuf; NBUF *nbuf;
int i; int i;
dbg("%s:\r\n", __FUNCTION__); dbg("\r\n");
/* /*
* Align Buffer Descriptors to 4-byte boundary * Align Buffer Descriptors to 4-byte boundary
@@ -73,7 +73,7 @@ void fecbd_init(uint8_t ch)
RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC); RxBD = (FECBD *)(((int) unaligned_bds + 3) & 0xFFFFFFFC);
TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD)); TxBD = (FECBD *)((int) RxBD + (sizeof(FECBD) * 2 * NRXBD));
dbg("%s: initialise RX buffer descriptor ring\r\n", __FUNCTION__); dbg("initialise RX buffer descriptor ring\r\n");
/* /*
* Initialize the Rx Buffer Descriptor ring * Initialize the Rx Buffer Descriptor ring
@@ -84,7 +84,7 @@ void fecbd_init(uint8_t ch)
nbuf = nbuf_alloc(); nbuf = nbuf_alloc();
if (nbuf == NULL) if (nbuf == NULL)
{ {
dbg("%s: could not allocate network buffer\r\n", __FUNCTION__); dbg("could not allocate network buffer\r\n");
return; return;
} }
@@ -102,7 +102,7 @@ void fecbd_init(uint8_t ch)
*/ */
RxBD(ch, i - 1).status |= RX_BD_W; RxBD(ch, i - 1).status |= RX_BD_W;
dbg("%s: initialise TX buffer descriptor ring\r\n", __FUNCTION__); dbg("initialise TX buffer descriptor ring\r\n");
/* /*
* Initialize the Tx Buffer Descriptor ring * Initialize the Tx Buffer Descriptor ring

View File

@@ -7,13 +7,15 @@
* Modifications: * Modifications:
*/ */
#include "net.h" #include "net.h"
#include "bas_printf.h"
#include "bas_string.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
//#define IP_DEBUG #define IP_DEBUG
#if defined(IP_DEBUG) #if defined(IP_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif #endif
@@ -42,7 +44,7 @@ uint8_t *ip_get_myip(IP_INFO *info)
{ {
return (uint8_t *) &info->myip[0]; return (uint8_t *) &info->myip[0];
} }
dbg("%s: info is NULL!\n\t", __FUNCTION__); dbg("info is NULL!\n\t");
return 0; return 0;
} }
@@ -72,9 +74,9 @@ uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
info = nif_get_protocol_info(nif, ETH_FRM_IP); info = nif_get_protocol_info(nif, ETH_FRM_IP);
if (memcmp(destip, bc) == 0) if (memcmp(destip, bc, 4) == 0)
{ {
dbg("%s: destip is broadcast address, no gateway needed\r\n", __FUNCTION__); dbg("destip is broadcast address, no gateway needed\r\n");
return destip; return destip;
} }
@@ -168,7 +170,7 @@ int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf
route = ip_resolve_route(nif, dest); route = ip_resolve_route(nif, dest);
if (route == NULL) if (route == NULL)
{ {
dbg("%s: Unable to locate %d.%d.%d.%d\r\n", __FUNCTION__, dbg("Unable to locate %d.%d.%d.%d\r\n",
dest[0], dest[1], dest[2], dest[3]); dest[0], dest[1], dest[2], dest[3]);
return 0; return 0;
} }
@@ -176,9 +178,9 @@ int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf
else else
{ {
route = bc; route = bc;
dbg("%s: route = broadcast\r\n", __FUNCTION__); dbg("route = broadcast\r\n");
dbg("%s: nif = %p\r\n", __FUNCTION__, nif); dbg("nif = %p\r\n", nif);
dbg("%s: nif->send = %p\r\n", __FUNCTION__, nif->send); dbg("nif->send = %p\r\n", nif->send);
} }
return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf); return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf);
@@ -280,7 +282,7 @@ void ip_handler(NIF *nif, NBUF *pNbuf)
*/ */
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
dbg("%s: packet received\r\n", __FUNCTION__); dbg("packet received\r\n");
ipframe = (ip_frame_hdr *) &pNbuf->data[pNbuf->offset]; ipframe = (ip_frame_hdr *) &pNbuf->data[pNbuf->offset];
@@ -289,6 +291,8 @@ void ip_handler(NIF *nif, NBUF *pNbuf)
*/ */
if (!validate_ip_hdr(nif, ipframe)) if (!validate_ip_hdr(nif, ipframe))
{ {
dbg("not a valid IP packet!\r\n");
nbuf_free(pNbuf); nbuf_free(pNbuf);
return; return;
} }
@@ -308,6 +312,8 @@ void ip_handler(NIF *nif, NBUF *pNbuf)
udp_handler(nif,pNbuf); udp_handler(nif,pNbuf);
break; break;
default: default:
dbg("no protocol handler registered for protocol %d\r\n",
__FUNCTION__, IP_PROTOCOL(ipframe));
nbuf_free(pNbuf); nbuf_free(pNbuf);
break; break;
} }

View File

@@ -24,6 +24,8 @@
#include "firebee.h" #include "firebee.h"
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else #else
#error unknown machine! #error unknown machine!
#endif #endif
@@ -152,8 +154,7 @@ bool timer_init(uint8_t ch, uint8_t lvl, uint8_t pri)
/* /*
* Register the timer interrupt handler * Register the timer interrupt handler
*/ */
if (!isr_register_handler(ISR_DBUG_ISR, if (!isr_register_handler(TIMER_VECTOR(ch),
TIMER_VECTOR(ch),
(int (*)(void *,void *)) timer_default_isr, (int (*)(void *,void *)) timer_default_isr,
NULL, NULL,
(void *) &net_timer[ch]) (void *) &net_timer[ch])

View File

@@ -39,6 +39,7 @@ void udp_init(void)
for (index = 0; index < UDP_MAX_PORTS; ++index) for (index = 0; index < UDP_MAX_PORTS; ++index)
{ {
udp_port_table[index].port = 0; udp_port_table[index].port = 0;
udp_port_table[index].handler = 0;
} }
udp_port = DEFAULT_UDP_PORT; /* next free port */ udp_port = DEFAULT_UDP_PORT; /* next free port */
@@ -88,7 +89,7 @@ static void *udp_port_handler(uint16_t port)
{ {
if (udp_port_table[index].port == port) if (udp_port_table[index].port == port)
{ {
return (void *)udp_port_table[index].handler; return (void *) udp_port_table[index].handler;
} }
} }
return NULL; return NULL;
@@ -116,7 +117,7 @@ int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
} }
/* /*
* This function takes data and creates a UDP frame and * This function takes data, creates a UDP frame from it and
* passes it onto the IP layer * passes it onto the IP layer
*/ */
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;

View File

@@ -74,7 +74,15 @@ extern void run_bios(struct radeonfb_info *rinfo);
#define MIN_MAPPED_VRAM (1024*768*4) #define MIN_MAPPED_VRAM (1024*768*4)
#define CHIP_DEF(id, family, flags) \ #define CHIP_DEF(id, family, flags) \
{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) } { \
PCI_VENDOR_ID_ATI, \
id, \
PCI_ANY_ID, \
PCI_ANY_ID, \
0, \
0, \
(flags) | (CHIP_FAMILY_##family) \
}
struct pci_device_id radeonfb_pci_table[] = struct pci_device_id radeonfb_pci_table[] =
{ {
@@ -231,7 +239,7 @@ extern struct fb_info *info_fb;
#define rinfo ((struct radeonfb_info *) info_fb->par) #define rinfo ((struct radeonfb_info *) info_fb->par)
static uint32_t inreg(uint32_t addr) static uint32_t inreg(uint32_t addr)
{ {
return(INREG(addr)); return INREG(addr);
} }
static void outreg(uint32_t addr, uint32_t val) static void outreg(uint32_t addr, uint32_t val)
@@ -332,12 +340,10 @@ static int round_div(int num, int den)
return(num + (den / 2)) / den; return(num + (den / 2)) / den;
} }
#ifndef MCF5445X
static uint32_t read_vline_crnt(struct radeonfb_info *rinfo) static uint32_t read_vline_crnt(struct radeonfb_info *rinfo)
{ {
return((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3FF); return((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3FF);
} }
#endif
static int radeon_map_ROM(struct radeonfb_info *rinfo) static int radeon_map_ROM(struct radeonfb_info *rinfo)
{ {
@@ -510,10 +516,12 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
hz = US_TO_TIMER(1000000.0) / (double)(stop_tv - start_tv); hz = US_TO_TIMER(1000000.0) / (double)(stop_tv - start_tv);
dbg("%s:hz %d\r\n", __FUNCTION__, (int32_t) hz); dbg("%s:hz %d\r\n", __FUNCTION__, (int32_t) hz);
hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8; hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1); vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
dbg("%s:hTotal=%d\r\n", __FUNCTION__, hTotal); dbg("%s:hTotal=%d\r\n", __FUNCTION__, hTotal);
dbg("%s:vTotal=%d\r\n", __FUNCTION__, vTotal); dbg("%s:vTotal=%d\r\n", __FUNCTION__, vTotal);
vclk = (double) hTotal * (double) vTotal * hz; vclk = (double) hTotal * (double) vTotal * hz;
dbg("%s:vclk=%d\r\n", __FUNCTION__, (int) vclk); dbg("%s:vclk=%d\r\n", __FUNCTION__, (int) vclk);
@@ -525,41 +533,52 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
num = 2 * n; num = 2 * n;
denom = 2 * m; denom = 2 * m;
break; break;
case 2: case 2:
n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff); n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff);
m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff); m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
num = 2 * n; num = 2 * n;
denom = 2 * m; denom = 2 * m;
break; break;
case 0: case 0:
default: default:
num = 1; num = 1;
denom = 1; denom = 1;
break; break;
} }
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3; ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
radeon_pll_errata_after_index(rinfo); radeon_pll_errata_after_index(rinfo);
n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff); n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
m = (INPLL(PPLL_REF_DIV) & 0x3ff); m = (INPLL(PPLL_REF_DIV) & 0x3ff);
num *= n; num *= n;
denom *= m; denom *= m;
switch((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) switch((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7)
{ {
case 1: case 1:
denom *= 2; denom *= 2;
break; break;
case 2: case 2:
denom *= 4; denom *= 4;
break; break;
case 3: case 3:
denom *= 8; denom *= 8;
break; break;
case 4: case 4:
denom *= 3; denom *= 3;
break; break;
case 6: case 6:
denom *= 6; denom *= 6;
break; break;
case 7: case 7:
denom *= 12; denom *= 12;
break; break;
@@ -567,6 +586,7 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
vclk *= (double) denom; vclk *= (double) denom;
vclk /= (double) (1000 * num); vclk /= (double) (1000 * num);
xtal = (int32_t) vclk; xtal = (int32_t) vclk;
if ((xtal > 26900) && (xtal < 27100)) if ((xtal > 26900) && (xtal < 27100))
xtal = 2700; /* 27 MHz */ xtal = 2700; /* 27 MHz */
else if ((xtal > 14200) && (xtal < 14400)) else if ((xtal > 14200) && (xtal < 14400))
@@ -578,6 +598,7 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
dbg("%s: xtal calculation failed: %d\r\n", __FUNCTION__, xtal); dbg("%s: xtal calculation failed: %d\r\n", __FUNCTION__, xtal);
return -1; /* error */ return -1; /* error */
} }
tmp = INPLL(M_SPLL_REF_FB_DIV); tmp = INPLL(M_SPLL_REF_FB_DIV);
ref_div = INPLL(PPLL_REF_DIV) & 0x3ff; ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
@@ -619,6 +640,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.sclk = 23000; rinfo->pll.sclk = 23000;
rinfo->pll.ref_clk = 2700; rinfo->pll.ref_clk = 2700;
break; break;
case PCI_DEVICE_ID_ATI_RADEON_QL: case PCI_DEVICE_ID_ATI_RADEON_QL:
case PCI_DEVICE_ID_ATI_RADEON_QN: case PCI_DEVICE_ID_ATI_RADEON_QN:
case PCI_DEVICE_ID_ATI_RADEON_QO: case PCI_DEVICE_ID_ATI_RADEON_QO:
@@ -630,6 +652,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.sclk = 27500; rinfo->pll.sclk = 27500;
rinfo->pll.ref_clk = 2700; rinfo->pll.ref_clk = 2700;
break; break;
case PCI_DEVICE_ID_ATI_RADEON_Id: case PCI_DEVICE_ID_ATI_RADEON_Id:
case PCI_DEVICE_ID_ATI_RADEON_Ie: case PCI_DEVICE_ID_ATI_RADEON_Ie:
case PCI_DEVICE_ID_ATI_RADEON_If: case PCI_DEVICE_ID_ATI_RADEON_If:
@@ -640,6 +663,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.sclk = 25000; rinfo->pll.sclk = 25000;
rinfo->pll.ref_clk = 2700; rinfo->pll.ref_clk = 2700;
break; break;
case PCI_DEVICE_ID_ATI_RADEON_ND: case PCI_DEVICE_ID_ATI_RADEON_ND:
case PCI_DEVICE_ID_ATI_RADEON_NE: case PCI_DEVICE_ID_ATI_RADEON_NE:
case PCI_DEVICE_ID_ATI_RADEON_NF: case PCI_DEVICE_ID_ATI_RADEON_NF:
@@ -650,6 +674,7 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.sclk = 27000; rinfo->pll.sclk = 27000;
rinfo->pll.ref_clk = 2700; rinfo->pll.ref_clk = 2700;
break; break;
case PCI_DEVICE_ID_ATI_RADEON_QD: case PCI_DEVICE_ID_ATI_RADEON_QD:
case PCI_DEVICE_ID_ATI_RADEON_QE: case PCI_DEVICE_ID_ATI_RADEON_QE:
case PCI_DEVICE_ID_ATI_RADEON_QF: case PCI_DEVICE_ID_ATI_RADEON_QF:
@@ -690,10 +715,12 @@ static void radeon_get_pllinfo(struct radeonfb_info *rinfo)
dbg("%s: Retreived PLL infos from registers\r\n", __FUNCTION__); dbg("%s: Retreived PLL infos from registers\r\n", __FUNCTION__);
goto found; goto found;
} }
/* /*
* Fall back to already-set defaults... * Fall back to already-set defaults...
*/ */
dbg("%s: Used default PLL infos\r\n", __FUNCTION__); dbg("%s: Used default PLL infos\r\n", __FUNCTION__);
found: found:
/* /*
* Some methods fail to retreive SCLK and MCLK values, we apply default * Some methods fail to retreive SCLK and MCLK values, we apply default
@@ -707,13 +734,15 @@ found:
dbg("%s: Reference=%d MHz (RefDiv=0x%x) Memory=%d MHz\r\n", __FUNCTION__, dbg("%s: Reference=%d MHz (RefDiv=0x%x) Memory=%d MHz\r\n", __FUNCTION__,
rinfo->pll.ref_clk / 100, rinfo->pll.ref_div, rinfo->pll.mclk / 100); rinfo->pll.ref_clk / 100, rinfo->pll.ref_div, rinfo->pll.mclk / 100);
dbg("%s: System=%d MHz PLL min %d, max %d\r\n", __FUNCTION__, rinfo->pll.sclk / 100, rinfo->pll.ppll_min, rinfo->pll.ppll_max); dbg("%s: System=%d MHz PLL min %d, max %d\r\n", __FUNCTION__,
rinfo->pll.sclk / 100, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
} }
static int var_to_depth(const struct fb_var_screeninfo *var) static int var_to_depth(const struct fb_var_screeninfo *var)
{ {
if (var->bits_per_pixel != 16) if (var->bits_per_pixel != 16)
return var->bits_per_pixel; return var->bits_per_pixel;
return(var->green.length == 5) ? 15 : 16; return(var->green.length == 5) ? 15 : 16;
} }
@@ -723,6 +752,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
struct fb_var_screeninfo v; struct fb_var_screeninfo v;
int nom, den; int nom, den;
uint32_t pitch; uint32_t pitch;
dbg("%s:\r\n", __FUNCTION__); dbg("%s:\r\n", __FUNCTION__);
/* clocks over 135 MHz have heat isues with DVI on RV100 */ /* clocks over 135 MHz have heat isues with DVI on RV100 */
@@ -742,9 +772,11 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
case 0 ... 8: case 0 ... 8:
v.bits_per_pixel = 8; v.bits_per_pixel = 8;
break; break;
case 9 ... 16: case 9 ... 16:
v.bits_per_pixel = 16; v.bits_per_pixel = 16;
break; break;
#if 0 /* Doesn't seem to work */ #if 0 /* Doesn't seem to work */
case 17 ... 24: case 17 ... 24:
v.bits_per_pixel = 24; v.bits_per_pixel = 24;
@@ -753,6 +785,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
case 25 ... 32: case 25 ... 32:
v.bits_per_pixel = 32; v.bits_per_pixel = 32;
break; break;
default: default:
return -1; //-EINVAL; return -1; //-EINVAL;
} }
@@ -765,6 +798,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.red.length = v.green.length = v.blue.length = 8; v.red.length = v.green.length = v.blue.length = 8;
v.transp.offset = v.transp.length = 0; v.transp.offset = v.transp.length = 0;
break; break;
case 15: case 15:
nom = 2; nom = 2;
den = 1; den = 1;
@@ -774,6 +808,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.red.length = v.green.length = v.blue.length = 5; v.red.length = v.green.length = v.blue.length = 5;
v.transp.offset = v.transp.length = 0; v.transp.offset = v.transp.length = 0;
break; break;
case 16: case 16:
nom = 2; nom = 2;
den = 1; den = 1;
@@ -785,6 +820,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.blue.length = 5; v.blue.length = 5;
v.transp.offset = v.transp.length = 0; v.transp.offset = v.transp.length = 0;
break; break;
case 24: case 24:
nom = 4; nom = 4;
den = 1; den = 1;
@@ -794,6 +830,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.red.length = v.blue.length = v.green.length = 8; v.red.length = v.blue.length = v.green.length = 8;
v.transp.offset = v.transp.length = 0; v.transp.offset = v.transp.length = 0;
break; break;
case 32: case 32:
nom = 4; nom = 4;
den = 1; den = 1;
@@ -804,6 +841,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.transp.offset = 24; v.transp.offset = 24;
v.transp.length = 8; v.transp.length = 8;
break; break;
default: default:
dbg("radeonfb: mode %d x %d x %d rejected, color depth invalid\r\n ", dbg("radeonfb: mode %d x %d x %d rejected, color depth invalid\r\n ",
var->xres, var->yres, var->bits_per_pixel); var->xres, var->yres, var->bits_per_pixel);
@@ -814,6 +852,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
v.yres_virtual = v.yres; v.yres_virtual = v.yres;
if (v.xres_virtual < v.xres) if (v.xres_virtual < v.xres)
v.xres_virtual = v.xres; v.xres_virtual = v.xres;
/* /*
* XXX I'm adjusting xres_virtual to the pitch, that may help XFree * XXX I'm adjusting xres_virtual to the pitch, that may help XFree
* with some panels, though I don't quite like this solution * with some panels, though I don't quite like this solution
@@ -848,6 +887,7 @@ int radeonfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
dbg("%s: using mode %d x %d \r\n", __FUNCTION__, v.xres, v.yres); dbg("%s: using mode %d x %d \r\n", __FUNCTION__, v.xres, v.yres);
memcpy(var, &v, sizeof(v)); memcpy(var, &v, sizeof(v));
return 0; return 0;
} }
@@ -857,16 +897,20 @@ int radeonfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
// DPRINT("radeonfb: radeonfb_pan_display\r\n"); // DPRINT("radeonfb: radeonfb_pan_display\r\n");
if ((var->xoffset + var->xres) > var->xres_virtual) if ((var->xoffset + var->xres) > var->xres_virtual)
return -1; //-EINVAL; return -1; //-EINVAL;
if (((var->yoffset * var->xres_virtual) + var->xoffset) >= if (((var->yoffset * var->xres_virtual) + var->xoffset) >=
(rinfo->mapped_vram - (var->yres * var->xres * (var->bits_per_pixel / 8)))) (rinfo->mapped_vram - (var->yres * var->xres * (var->bits_per_pixel / 8))))
return -1; //-EINVAL; return -1; //-EINVAL;
if (rinfo->asleep) if (rinfo->asleep)
return 0; return 0;
radeon_wait_for_fifo(rinfo, 2); radeon_wait_for_fifo(rinfo, 2);
rinfo->fb_offset = ((var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel / 8) & ~7; rinfo->fb_offset = ((var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel / 8) & ~7;
rinfo->dst_pitch_offset = (rinfo->pitch << 22) | ((rinfo->fb_local_base + rinfo->fb_offset) >> 10); rinfo->dst_pitch_offset = (rinfo->pitch << 22) | ((rinfo->fb_local_base + rinfo->fb_offset) >> 10);
OUTREG(CRTC_OFFSET, rinfo->fb_offset); OUTREG(CRTC_OFFSET, rinfo->fb_offset);
return 0;
return 0;
} }
short mirror; short mirror;
@@ -876,6 +920,7 @@ int radeonfb_ioctl(unsigned int cmd, unsigned long arg, struct fb_info *info)
struct radeonfb_info *rinfo = info->par; struct radeonfb_info *rinfo = info->par;
uint32_t tmp; uint32_t tmp;
uint32_t value = 0; uint32_t value = 0;
switch(cmd) switch(cmd)
{ {
/* /*
@@ -899,6 +944,7 @@ int radeonfb_ioctl(unsigned int cmd, unsigned long arg, struct fb_info *info)
tmp &= ~(LVDS_ON | LVDS_BLON); tmp &= ~(LVDS_ON | LVDS_BLON);
} }
OUTREG(LVDS_GEN_CNTL, tmp); OUTREG(LVDS_GEN_CNTL, tmp);
if (value & 0x02) if (value & 0x02)
{ {
tmp = INREG(CRTC_EXT_CNTL); tmp = INREG(CRTC_EXT_CNTL);
@@ -913,6 +959,7 @@ int radeonfb_ioctl(unsigned int cmd, unsigned long arg, struct fb_info *info)
} }
OUTREG(CRTC_EXT_CNTL, tmp); OUTREG(CRTC_EXT_CNTL, tmp);
return 0; return 0;
case FBIO_RADEON_GET_MIRROR: case FBIO_RADEON_GET_MIRROR:
if (!rinfo->is_mobility) if (!rinfo->is_mobility)
return -1; //-EINVAL; return -1; //-EINVAL;
@@ -923,6 +970,7 @@ int radeonfb_ioctl(unsigned int cmd, unsigned long arg, struct fb_info *info)
if (CRTC_CRT_ON & tmp) if (CRTC_CRT_ON & tmp)
value |= 0x02; value |= 0x02;
return 0; return 0;
default: default:
return -1; //-EINVAL; return -1; //-EINVAL;
} }
@@ -937,24 +985,30 @@ int32_t radeon_screen_blank(struct radeonfb_info *rinfo, int32_t blank, int32_t
if (rinfo->lock_blank) if (rinfo->lock_blank)
return 0; return 0;
dbg("radeonfb: radeon_screen_blank\r\n"); dbg("radeonfb: radeon_screen_blank\r\n");
radeon_engine_idle(); radeon_engine_idle();
val = INREG(CRTC_EXT_CNTL); val = INREG(CRTC_EXT_CNTL);
val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS); val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS);
switch(blank) switch(blank)
{ {
case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND:
val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS); val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
break; break;
case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND:
val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS); val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
break; break;
case FB_BLANK_POWERDOWN: case FB_BLANK_POWERDOWN:
val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS); val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS);
break; break;
case FB_BLANK_NORMAL: case FB_BLANK_NORMAL:
val |= CRTC_DISPLAY_DIS; val |= CRTC_DISPLAY_DIS;
break; break;
case FB_BLANK_UNBLANK: case FB_BLANK_UNBLANK:
default: default:
unblank = 1; unblank = 1;
@@ -974,6 +1028,7 @@ int32_t radeon_screen_blank(struct radeonfb_info *rinfo, int32_t blank, int32_t
OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN)); OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
} }
break; break;
case MT_LCD: case MT_LCD:
rinfo->lvds_timer = 0; rinfo->lvds_timer = 0;
val = INREG(LVDS_GEN_CNTL); val = INREG(LVDS_GEN_CNTL);
@@ -1007,15 +1062,19 @@ int32_t radeon_screen_blank(struct radeonfb_info *rinfo, int32_t blank, int32_t
/* We don't do a full switch-off on a simple mode switch */ /* We don't do a full switch-off on a simple mode switch */
if (mode_switch || blank == FB_BLANK_NORMAL) if (mode_switch || blank == FB_BLANK_NORMAL)
break; break;
/* Asic bug, when turning off LVDS_ON, we have to make sure /* Asic bug, when turning off LVDS_ON, we have to make sure
* RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
*/ */
tmp_pix_clks = INPLL(PIXCLKS_CNTL); tmp_pix_clks = INPLL(PIXCLKS_CNTL);
if (rinfo->is_mobility || rinfo->is_IGP) if (rinfo->is_mobility || rinfo->is_IGP)
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
val &= ~(LVDS_BL_MOD_EN); val &= ~(LVDS_BL_MOD_EN);
OUTREG(LVDS_GEN_CNTL, val); OUTREG(LVDS_GEN_CNTL, val);
wait(100); wait(100);
val &= ~(LVDS_ON | LVDS_EN); val &= ~(LVDS_ON | LVDS_EN);
OUTREG(LVDS_GEN_CNTL, val); OUTREG(LVDS_GEN_CNTL, val);
val &= ~LVDS_DIGON; val &= ~LVDS_DIGON;
@@ -1023,6 +1082,7 @@ int32_t radeon_screen_blank(struct radeonfb_info *rinfo, int32_t blank, int32_t
rinfo->lvds_timer = (int32_t)rinfo->panel_info.pwr_delay; rinfo->lvds_timer = (int32_t)rinfo->panel_info.pwr_delay;
rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
if (rinfo->is_mobility || rinfo->is_IGP) if (rinfo->is_mobility || rinfo->is_IGP)
OUTPLL(PIXCLKS_CNTL, tmp_pix_clks); OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
} }
@@ -1039,8 +1099,10 @@ int32_t radeon_screen_blank(struct radeonfb_info *rinfo, int32_t blank, int32_t
int radeonfb_blank(int blank, struct fb_info *info) int radeonfb_blank(int blank, struct fb_info *info)
{ {
struct radeonfb_info *rinfo = info->par; struct radeonfb_info *rinfo = info->par;
if (rinfo->asleep) if (rinfo->asleep)
return 0; return 0;
return radeon_screen_blank(rinfo, blank, 0); return radeon_screen_blank(rinfo, blank, 0);
} }
@@ -1049,14 +1111,18 @@ static int radeon_setcolreg(unsigned regno, unsigned red, unsigned green,
{ {
struct radeonfb_info *rinfo = info->par; struct radeonfb_info *rinfo = info->par;
uint32_t pindex; uint32_t pindex;
if (regno > 255) if (regno > 255)
return 1; return 1;
red >>= 8; red >>= 8;
green >>= 8; green >>= 8;
blue >>= 8; blue >>= 8;
rinfo->palette[regno].red = red; rinfo->palette[regno].red = red;
rinfo->palette[regno].green = green; rinfo->palette[regno].green = green;
rinfo->palette[regno].blue = blue; rinfo->palette[regno].blue = blue;
/* default */ /* default */
pindex = regno; pindex = regno;
if (!rinfo->asleep) if (!rinfo->asleep)
@@ -1069,7 +1135,9 @@ static int radeon_setcolreg(unsigned regno, unsigned red, unsigned green,
return 1; return 1;
if (rinfo->depth == 15 && regno > 31) if (rinfo->depth == 15 && regno > 31)
return 1; return 1;
/* For 565, the green component is mixed one order
/*
* For 565, the green component is mixed one order
* below * below
*/ */
if (rinfo->depth == 16) if (rinfo->depth == 16)
@@ -1095,6 +1163,7 @@ int radeonfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct radeonfb_info *rinfo = info->par; struct radeonfb_info *rinfo = info->par;
uint32_t dac_cntl2, vclk_cntl = 0; uint32_t dac_cntl2, vclk_cntl = 0;
int rc; int rc;
if (!rinfo->asleep) if (!rinfo->asleep)
{ {
if (rinfo->is_mobility) if (rinfo->is_mobility)
@@ -1102,6 +1171,7 @@ int radeonfb_setcolreg(unsigned regno, unsigned red, unsigned green,
vclk_cntl = INPLL(VCLK_ECP_CNTL); vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
} }
/* Make sure we are on first palette */ /* Make sure we are on first palette */
if (rinfo->has_CRTC2) if (rinfo->has_CRTC2)
{ {
@@ -1113,6 +1183,7 @@ int radeonfb_setcolreg(unsigned regno, unsigned red, unsigned green,
rc = radeon_setcolreg(regno, red, green, blue, transp, info); rc = radeon_setcolreg(regno, red, green, blue, transp, info);
if (!rinfo->asleep && rinfo->is_mobility) if (!rinfo->asleep && rinfo->is_mobility)
OUTPLL(VCLK_ECP_CNTL, vclk_cntl); OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
return rc; return rc;
} }
@@ -1129,6 +1200,7 @@ static void radeon_save_state(struct radeonfb_info *rinfo, struct radeon_regs *s
save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID); save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
save->crtc_pitch = INREG(CRTC_PITCH); save->crtc_pitch = INREG(CRTC_PITCH);
save->surface_cntl = INREG(SURFACE_CNTL); save->surface_cntl = INREG(SURFACE_CNTL);
/* FP regs */ /* FP regs */
save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP); save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP); save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
@@ -1143,6 +1215,7 @@ static void radeon_save_state(struct radeonfb_info *rinfo, struct radeon_regs *s
save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL); save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL); save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
/* PLL regs */ /* PLL regs */
save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f; save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
radeon_pll_errata_after_index(rinfo); radeon_pll_errata_after_index(rinfo);
save->ppll_div_3 = INPLL(PPLL_DIV_3); save->ppll_div_3 = INPLL(PPLL_DIV_3);
@@ -1152,8 +1225,10 @@ static void radeon_save_state(struct radeonfb_info *rinfo, struct radeon_regs *s
static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode) static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
{ {
int i; int i;
dbg("radeonfb: radeon_write_pll_regs\r\n"); dbg("radeonfb: radeon_write_pll_regs\r\n");
radeon_wait_for_fifo(rinfo, 20); radeon_wait_for_fifo(rinfo, 20);
#if 0 #if 0
/* Workaround from XFree */ /* Workaround from XFree */
if (rinfo->is_mobility) if (rinfo->is_mobility)
@@ -1180,22 +1255,27 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
} }
} }
#endif #endif
/* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/ /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK); OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
/* Reset PPLL & enable atomic update */ /* Reset PPLL & enable atomic update */
OUTPLLP(PPLL_CNTL, PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN, OUTPLLP(PPLL_CNTL, PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN)); ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
/* Switch to selected PPLL divider */ /* Switch to selected PPLL divider */
OUTREGP(CLOCK_CNTL_INDEX, mode->clk_cntl_index & PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK); OUTREGP(CLOCK_CNTL_INDEX, mode->clk_cntl_index & PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK);
radeon_pll_errata_after_index(rinfo); radeon_pll_errata_after_index(rinfo);
radeon_pll_errata_after_data(rinfo); radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */ /* Set PPLL ref. div */
if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_RS300 if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_RS300
|| rinfo->family == CHIP_FAMILY_R350 || rinfo->family == CHIP_FAMILY_RV350) || rinfo->family == CHIP_FAMILY_R350 || rinfo->family == CHIP_FAMILY_RV350)
{ {
if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK)
{ {
/* When restoring console mode, use saved PPLL_REF_DIV /*
* When restoring console mode, use saved PPLL_REF_DIV
* setting. * setting.
*/ */
OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0); OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
@@ -1216,17 +1296,22 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
/* Write update */ /* Write update */
while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W); OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
/* Wait read update complete */ /* Wait read update complete */
/* FIXME: Certain revisions of R300 can't recover here. Not sure of /* FIXME: Certain revisions of R300 can't recover here. Not sure of
the cause yet, but this workaround will mask the problem for now. the cause yet, but this workaround will mask the problem for now.
Other chips usually will pass at the very first test, so the Other chips usually will pass at the very first test, so the
workaround shouldn't have any effect on them. */ workaround shouldn't have any effect on them. */
for(i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++);
for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++);
OUTPLL(HTOTAL_CNTL, 0); OUTPLL(HTOTAL_CNTL, 0);
/* Clear reset & atomic update */ /* Clear reset & atomic update */
OUTPLLP(PPLL_CNTL, 0, ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN)); OUTPLLP(PPLL_CNTL, 0, ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
/* We may want some locking ... oh well */ /* We may want some locking ... oh well */
radeon_msleep(5); radeon_msleep(5);
/* Switch back VCLK source to PPLL */ /* Switch back VCLK source to PPLL */
OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK); OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
} }
@@ -1248,6 +1333,7 @@ static void radeon_timer_func(void)
#ifdef FIXME_LATER #ifdef FIXME_LATER
static int32_t start_timer; static int32_t start_timer;
/* delayed LVDS panel power up/down */ /* delayed LVDS panel power up/down */
if (rinfo->lvds_timer) if (rinfo->lvds_timer)
{ {
@@ -1263,10 +1349,11 @@ static void radeon_timer_func(void)
} }
else else
start_timer = 0; start_timer = 0;
#endif #endif /* FIXME_LATER */
if (rinfo->RenderCallback != NULL) if (rinfo->RenderCallback != NULL)
rinfo->RenderCallback(rinfo); rinfo->RenderCallback(rinfo);
if ((info->screen_mono != NULL) && info->update_mono) if ((info->screen_mono != NULL) && info->update_mono)
{ {
int32_t foreground = 255, background = 0; int32_t foreground = 255, background = 0;
@@ -1275,21 +1362,25 @@ static void radeon_timer_func(void)
int dst_x = 0; int dst_x = 0;
int w = (int)info->var.xres_virtual; int w = (int)info->var.xres_virtual;
int h = (int)info->var.yres_virtual; int h = (int)info->var.yres_virtual;
// info->fbops->SetClippingRectangle(info,0,0,w-1,h-1); // info->fbops->SetClippingRectangle(info,0,0,w-1,h-1);
src_buf = (uint8_t*)((int32_t)src_buf & ~3); src_buf = (uint8_t*)((int32_t)src_buf & ~3);
dst_x -= (int32_t)skipleft; dst_x -= (int32_t)skipleft;
w += (int32_t)skipleft; w += (int32_t)skipleft;
info->fbops->SetupForScanlineCPUToScreenColorExpandFill(info,(int)foreground,(int)background,3,0xffffffff); info->fbops->SetupForScanlineCPUToScreenColorExpandFill(info,(int)foreground,(int)background,3,0xffffffff);
info->fbops->SubsequentScanlineCPUToScreenColorExpandFill(info,(int)dst_x,0,w,h,skipleft); info->fbops->SubsequentScanlineCPUToScreenColorExpandFill(info,(int)dst_x,0,w,h,skipleft);
while (--h >= 0) while (--h >= 0)
{ {
info->fbops->SubsequentScanline(info, (unsigned long *) src_buf); info->fbops->SubsequentScanline(info, (unsigned long *) src_buf);
src_buf += (info->var.xres_virtual >> 3); src_buf += (info->var.xres_virtual >> 3);
} }
// info->fbops->DisableClipping(info); // info->fbops->DisableClipping(info);
if (info->update_mono > 0) if (info->update_mono > 0)
info->update_mono = 0; info->update_mono = 0;
} }
if ((info->var.xres_virtual != info->var.xres) if ((info->var.xres_virtual != info->var.xres)
|| (info->var.yres_virtual != info->var.yres)) || (info->var.yres_virtual != info->var.yres))
{ {
@@ -1310,6 +1401,7 @@ static void radeon_timer_func(void)
x -= 8; x -= 8;
chg = 1; chg = 1;
} }
if (((y + info->var.yres) < info->var.yres_virtual) && (rinfo->cursor_y >= (info->var.yres - 8))) if (((y + info->var.yres) < info->var.yres_virtual) && (rinfo->cursor_y >= (info->var.yres - 8)))
{ {
y += 8; y += 8;
@@ -1329,7 +1421,9 @@ static void radeon_timer_func(void)
disp = rinfo->cursor_show; disp = rinfo->cursor_show;
if (disp) if (disp)
info->fbops->HideCursor(info); info->fbops->HideCursor(info);
fb_pan_display(info,&var); fb_pan_display(info,&var);
if (disp) if (disp)
info->fbops->ShowCursor(info); info->fbops->ShowCursor(info);
} }
@@ -1345,14 +1439,19 @@ void radeon_write_mode(struct radeonfb_info *rinfo, struct radeon_regs *mode, in
{ {
int i; int i;
int primary_mon = PRIMARY_MONITOR(rinfo); int primary_mon = PRIMARY_MONITOR(rinfo);
dbg("radeonfb: radeon_write_mode\r\n"); dbg("radeonfb: radeon_write_mode\r\n");
if (!regs_only) if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
radeon_wait_for_fifo(rinfo, 31); radeon_wait_for_fifo(rinfo, 31);
for(i=0; i<10; i++)
for (i = 0; i < 10; i++)
OUTREG(common_regs[i].reg, common_regs[i].val); OUTREG(common_regs[i].reg, common_regs[i].val);
/* Apply surface registers */ /* Apply surface registers */
for(i=0; i<8; i++) for (i = 0; i < 8; i++)
{ {
OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]); OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]);
OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]); OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]);
@@ -1380,9 +1479,11 @@ void radeon_write_mode(struct radeonfb_info *rinfo, struct radeon_regs *mode, in
else else
#endif #endif
OUTREG(CRTC_OFFSET_CNTL, 0); OUTREG(CRTC_OFFSET_CNTL, 0);
OUTREG(CRTC_PITCH, mode->crtc_pitch); OUTREG(CRTC_PITCH, mode->crtc_pitch);
OUTREG(SURFACE_CNTL, mode->surface_cntl); OUTREG(SURFACE_CNTL, mode->surface_cntl);
radeon_write_pll_regs(rinfo, mode); radeon_write_pll_regs(rinfo, mode);
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
{ {
radeon_wait_for_fifo(rinfo, 10); radeon_wait_for_fifo(rinfo, 10);
@@ -1396,6 +1497,7 @@ void radeon_write_mode(struct radeonfb_info *rinfo, struct radeon_regs *mode, in
OUTREG(TMDS_CRC, mode->tmds_crc); OUTREG(TMDS_CRC, mode->tmds_crc);
OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl); OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
} }
if (!regs_only) if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
radeon_wait_for_fifo(rinfo, 2); radeon_wait_for_fifo(rinfo, 2);
@@ -1407,11 +1509,13 @@ void radeon_write_mode(struct radeonfb_info *rinfo, struct radeon_regs *mode, in
*/ */
static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, uint32_t freq) static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, uint32_t freq)
{ {
static const struct { static const struct
{
int divider; int divider;
int bitvalue; int bitvalue;
} *post_div, } *post_div,
post_divs[] = { post_divs[] =
{
{ 1, 0 }, { 1, 0 },
{ 2, 1 }, { 2, 1 },
{ 4, 2 }, { 4, 2 },
@@ -1424,6 +1528,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
}; };
int fb_div, pll_output_freq = 0; int fb_div, pll_output_freq = 0;
int uses_dvo = 0; int uses_dvo = 0;
/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm /* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
* not sure which model starts having FP2_GEN_CNTL, I assume anything more * not sure which model starts having FP2_GEN_CNTL, I assume anything more
* recent than an r(v)100... * recent than an r(v)100...
@@ -1443,9 +1548,11 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
uint32_t fp2_gen_cntl = INREG(FP2_GEN_CNTL); uint32_t fp2_gen_cntl = INREG(FP2_GEN_CNTL);
uint32_t disp_output_cntl; uint32_t disp_output_cntl;
int source; int source;
/* FP2 path not enabled */ /* FP2 path not enabled */
if ((fp2_gen_cntl & FP2_ON) == 0) if ((fp2_gen_cntl & FP2_ON) == 0)
break; break;
/* Not all chip revs have the same format for this register, /* Not all chip revs have the same format for this register,
* extract the source selection * extract the source selection
*/ */
@@ -1464,9 +1571,11 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
} }
else else
source = (fp2_gen_cntl >> 13) & 0x1; source = (fp2_gen_cntl >> 13) & 0x1;
/* sourced from CRTC2 -> exit */ /* sourced from CRTC2 -> exit */
if (source == 1) if (source == 1)
break; break;
/* so we end up on CRTC1, let's set uses_dvo to 1 now */ /* so we end up on CRTC1, let's set uses_dvo to 1 now */
uses_dvo = 1; uses_dvo = 1;
break; break;
@@ -1476,27 +1585,32 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
#endif #endif
if (freq > rinfo->pll.ppll_max) if (freq > rinfo->pll.ppll_max)
freq = rinfo->pll.ppll_max; freq = rinfo->pll.ppll_max;
if (freq*12 < rinfo->pll.ppll_min) if (freq * 12 < rinfo->pll.ppll_min)
freq = rinfo->pll.ppll_min / 12; freq = rinfo->pll.ppll_min / 12;
for(post_div = &post_divs[0]; post_div->divider; ++post_div) for (post_div = &post_divs[0]; post_div->divider; ++post_div)
{ {
pll_output_freq = post_div->divider * freq; pll_output_freq = post_div->divider * freq;
/* If we output to the DVO port (external TMDS), we don't allow an
/*
* If we output to the DVO port (external TMDS), we don't allow an
* odd PLL divider as those aren't supported on this path * odd PLL divider as those aren't supported on this path
*/ */
if (uses_dvo && (post_div->divider & 1)) if (uses_dvo && (post_div->divider & 1))
continue; continue;
if (pll_output_freq >= rinfo->pll.ppll_min && if (pll_output_freq >= rinfo->pll.ppll_min &&
pll_output_freq <= rinfo->pll.ppll_max) pll_output_freq <= rinfo->pll.ppll_max)
break; break;
} }
/* If we fall through the bottom, try the "default value" /* If we fall through the bottom, try the "default value"
given by the terminal post_div->bitvalue */ given by the terminal post_div->bitvalue */
if ( !post_div->divider ) if (!post_div->divider)
{ {
post_div = &post_divs[post_div->bitvalue]; post_div = &post_divs[post_div->bitvalue];
pll_output_freq = post_div->divider * freq; pll_output_freq = post_div->divider * freq;
} }
/* If we fall through the bottom, try the "default value" /* If we fall through the bottom, try the "default value"
given by the terminal post_div->bitvalue */ given by the terminal post_div->bitvalue */
if ( !post_div->divider ) if ( !post_div->divider )
@@ -1535,6 +1649,7 @@ int radeonfb_set_par(struct fb_info *info)
newmode = (struct radeon_regs *) driver_mem_alloc(sizeof(struct radeon_regs)); newmode = (struct radeon_regs *) driver_mem_alloc(sizeof(struct radeon_regs));
if (!newmode) if (!newmode)
return -1; //-ENOMEM; return -1; //-ENOMEM;
/* We always want engine to be idle on a mode switch, even /* We always want engine to be idle on a mode switch, even
* if we won't actually change the mode * if we won't actually change the mode
*/ */
@@ -1582,24 +1697,29 @@ int radeonfb_set_par(struct fb_info *info)
newmode->ppll_ref_div = rinfo->panel_info.ref_divider; newmode->ppll_ref_div = rinfo->panel_info.ref_divider;
} }
} }
dotClock = 1000000000 / pixClock; dotClock = 1000000000 / pixClock;
freq = dotClock / 10; /* x100 */ freq = dotClock / 10; /* x100 */
hsync_wid = (hSyncEnd - hSyncStart) / 8; hsync_wid = (hSyncEnd - hSyncStart) / 8;
if (hsync_wid == 0) if (hsync_wid == 0)
hsync_wid = 1; hsync_wid = 1;
else if (hsync_wid > 0x3f) /* max */ else if (hsync_wid > 0x3f) /* max */
hsync_wid = 0x3f; hsync_wid = 0x3f;
if (mode->vmode & FB_VMODE_DOUBLE) if (mode->vmode & FB_VMODE_DOUBLE)
{ {
vSyncStart <<= 1; vSyncStart <<= 1;
vSyncEnd <<= 1; vSyncEnd <<= 1;
vTotal <<= 1; vTotal <<= 1;
} }
vsync_wid = vSyncEnd - vSyncStart; vsync_wid = vSyncEnd - vSyncStart;
if (vsync_wid == 0) if (vsync_wid == 0)
vsync_wid = 1; vsync_wid = 1;
else if (vsync_wid > 0x1f) /* max */ else if (vsync_wid > 0x1f) /* max */
vsync_wid = 0x1f; vsync_wid = 0x1f;
// FIXME: this doesn't seem to be used anywhere hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; // FIXME: this doesn't seem to be used anywhere hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
// FIXME: this doesn't seem to be used anywhere vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; // FIXME: this doesn't seem to be used anywhere vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
// FIXME: this doesn't seem to be used anywhere cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; // FIXME: this doesn't seem to be used anywhere cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
@@ -1624,6 +1744,7 @@ int radeonfb_set_par(struct fb_info *info)
/* Clear auto-center etc... */ /* Clear auto-center etc... */
newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl; newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
newmode->crtc_more_cntl &= 0xfffffff0; newmode->crtc_more_cntl &= 0xfffffff0;
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
{ {
newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN; newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
@@ -1633,13 +1754,16 @@ int radeonfb_set_par(struct fb_info *info)
} }
else else
newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON; newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON;
newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN; newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN;
newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | (((mode->xres / 8) - 1) << 16)); newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | (((mode->xres / 8) - 1) << 16));
newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | (hsync_wid << 16) | (h_sync_pol << 23)); newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | (hsync_wid << 16) | (h_sync_pol << 23));
if (mode->vmode & FB_VMODE_DOUBLE) if (mode->vmode & FB_VMODE_DOUBLE)
newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | (((mode->yres << 1) - 1) << 16); newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | (((mode->yres << 1) - 1) << 16);
else else
newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | ((mode->yres - 1) << 16); newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | ((mode->yres - 1) << 16);
newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23)); newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23));
/* We first calculate the engine pitch */ /* We first calculate the engine pitch */
rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) & ~(0x3f)) >> 6; rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) & ~(0x3f)) >> 6;
@@ -1653,6 +1777,7 @@ int radeonfb_set_par(struct fb_info *info)
* swapper as well, so we leave it unset now. * swapper as well, so we leave it unset now.
*/ */
newmode->surface_cntl = 0; newmode->surface_cntl = 0;
if (rinfo->big_endian) if (rinfo->big_endian)
{ {
/* Setup swapping on both apertures, though we currently /* Setup swapping on both apertures, though we currently
@@ -1674,12 +1799,13 @@ int radeonfb_set_par(struct fb_info *info)
} }
/* Clear surface registers */ /* Clear surface registers */
for(i = 0; i < 8; i++) for (i = 0; i < 8; i++)
{ {
newmode->surf_lower_bound[i] = 0; newmode->surf_lower_bound[i] = 0;
newmode->surf_upper_bound[i] = 0x1f; newmode->surf_upper_bound[i] = 0x1f;
newmode->surf_info[i] = 0; newmode->surf_info[i] = 0;
} }
rinfo->bpp = mode->bits_per_pixel; rinfo->bpp = mode->bits_per_pixel;
rinfo->depth = depth; rinfo->depth = depth;
@@ -1724,6 +1850,7 @@ int radeonfb_set_par(struct fb_info *info)
& ~(FP_SEL_CRTC2 | FP_RMX_HVSYNC_CONTROL_EN | FP_DFP_SYNC_SEL | FP_CRT_SYNC_SEL & ~(FP_SEL_CRTC2 | FP_RMX_HVSYNC_CONTROL_EN | FP_DFP_SYNC_SEL | FP_CRT_SYNC_SEL
| FP_CRTC_LOCK_8DOT | FP_USE_SHADOW_EN | FP_CRTC_USE_SHADOW_VEND | FP_CRT_SYNC_ALT)); | FP_CRTC_LOCK_8DOT | FP_USE_SHADOW_EN | FP_CRTC_USE_SHADOW_VEND | FP_CRT_SYNC_ALT));
newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | FP_CRTC_DONT_SHADOW_HEND | FP_PANEL_FORMAT); newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | FP_CRTC_DONT_SHADOW_HEND | FP_PANEL_FORMAT);
if (IS_R300_VARIANT(rinfo) || (rinfo->family == CHIP_FAMILY_R200)) if (IS_R300_VARIANT(rinfo) || (rinfo->family == CHIP_FAMILY_R200))
{ {
newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
@@ -1734,10 +1861,12 @@ int radeonfb_set_par(struct fb_info *info)
} }
else else
newmode->fp_gen_cntl |= FP_SEL_CRTC1; newmode->fp_gen_cntl |= FP_SEL_CRTC1;
newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl; newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl; newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
newmode->tmds_crc = rinfo->init_state.tmds_crc; newmode->tmds_crc = rinfo->init_state.tmds_crc;
newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl; newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
if (primary_mon == MT_LCD) if (primary_mon == MT_LCD)
{ {
newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON); newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
@@ -1755,11 +1884,13 @@ int radeonfb_set_par(struct fb_info *info)
newmode->tmds_transmitter_cntl |= TMDS_PLL_EN; newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
newmode->crtc_ext_cntl &= ~CRTC_CRT_ON; newmode->crtc_ext_cntl &= ~CRTC_CRT_ON;
} }
newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) | (((mode->xres / 8) - 1) << 16)); newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) | (((mode->xres / 8) - 1) << 16));
newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) | ((mode->yres - 1) << 16); newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) | ((mode->yres - 1) << 16);
newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) | (hsync_wid << 16) | (h_sync_pol << 23)); newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) | (hsync_wid << 16) | (h_sync_pol << 23));
newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23)); newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23));
} }
/* do it! */ /* do it! */
if (!rinfo->asleep) if (!rinfo->asleep)
{ {
@@ -1778,10 +1909,12 @@ int radeonfb_set_par(struct fb_info *info)
/* (re)initialize the engine */ /* (re)initialize the engine */
radeon_engine_init(rinfo); radeon_engine_init(rinfo);
} }
/* Update fix */ /* Update fix */
info->fix.line_length = rinfo->pitch*64; info->fix.line_length = rinfo->pitch*64;
info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
driver_mem_free(newmode); driver_mem_free(newmode);
return 0; return 0;
} }

View File

@@ -48,6 +48,7 @@
#include "bootp.h" #include "bootp.h"
#include "interrupts.h" #include "interrupts.h"
#include "exceptions.h" #include "exceptions.h"
#include "net_timer.h"
//#define BAS_DEBUG //#define BAS_DEBUG
#if defined(BAS_DEBUG) #if defined(BAS_DEBUG)
@@ -251,7 +252,7 @@ static ARP_INFO arp_info;
void network_init(void) void network_init(void)
{ {
uint8_t mac[6] = {0x00, 0xcf, 0x54, 0x12, 0x34, 0x56}; uint8_t mac[6] = {0x00, 0xcf, 0x54, 0x85, 0xcf, 0x01}; /* this is the original MAC address dbug assigns */
uint8_t bc[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* this is our broadcast MAC address */ uint8_t bc[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* this is our broadcast MAC address */
IP_ADDR myip = {192, 168, 1, 100}; IP_ADDR myip = {192, 168, 1, 100};
IP_ADDR gateway = {192, 168, 1, 1}; IP_ADDR gateway = {192, 168, 1, 1};
@@ -264,7 +265,7 @@ void network_init(void)
isr_init(); /* need to call that explicitely, otherwise isr table might be full */ isr_init(); /* need to call that explicitely, otherwise isr table might be full */
if (!isr_register_handler(ISR_DBUG_ISR, vector, handler, NULL, (void *) &nif1)) if (!isr_register_handler(vector, handler, NULL, (void *) &nif1))
{ {
dbg("%s: unable to register handler for vector %d\r\n", __FUNCTION__, vector); dbg("%s: unable to register handler for vector %d\r\n", __FUNCTION__, vector);
return; return;
@@ -276,7 +277,7 @@ void network_init(void)
handler = dma_interrupt_handler; handler = dma_interrupt_handler;
vector = 112; vector = 112;
if (!isr_register_handler(ISR_DBUG_ISR, vector, handler, NULL,NULL)) if (!isr_register_handler(vector, handler, NULL,NULL))
{ {
dbg("%s: Error: Unable to register handler for vector %s\r\n", __FUNCTION__, vector); dbg("%s: Error: Unable to register handler for vector %s\r\n", __FUNCTION__, vector);
return; return;

View File

@@ -44,24 +44,24 @@ uint32_t cacr_get(void)
void flush_and_invalidate_caches(void) void flush_and_invalidate_caches(void)
{ {
__asm__ ( __asm__ __volatile__(
" clr.l d0\n\t" " clr.l d0 \n\t"
" clr.l d1\n\t" " clr.l d1 \n\t"
" move.l d0,a0\n\t" " move.l d0,a0 \n\t"
"cfa_setloop:\n\t" "cfa_setloop: \n\t"
" cpushl bc,(a0) | flush\n\t" " cpushl bc,(a0) | flush\n\t"
" lea 0x10(a0),a0 | index+1\n\t" " lea 0x10(a0),a0 | index+1\n\t"
" addq.l #1,d1 | index+1\n\t" " addq.l #1,d1 | index+1\n\t"
" cmpi.w #512,d1 | all sets?\n\t" " cmpi.w #512,d1 | all sets?\n\t"
" bne.s cfa_setloop | no->\n\t" " bne.s cfa_setloop | no->\n\t"
" clr.l d1\n\t" " clr.l d1 \n\t"
" addq.l #1,d0\n\t" " addq.l #1,d0 \n\t"
" move.l d0,a0\n\t" " move.l d0,a0 \n\t"
" cmpi.w #4,d0 | all ways?\n\t" " cmpi.w #4,d0 | all ways?\n\t"
" bne.s cfa_setloop | no->\n\t" " bne.s cfa_setloop | no->\n\t"
/* input */ : /* input */ :
/* output */ : /* output */ :
/* clobber */ : "d0", "d1", "a0" /* clobber */ : "d0", "d1", "a0"
); );
} }
@@ -81,25 +81,35 @@ void flush_icache_range(void *address, size_t size)
if (start_set > end_set) { if (start_set > end_set) {
/* from the begining to the lowest address */ /* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) { for (set = 0; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl ic,(%0)\n\t" __asm__ __volatile__(
"addq.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)\n\t" " addq.l #1,%[set] \n\t"
"addq.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)\n\t" " addq.l #1,%[set] \n\t"
"addq.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)" : "=a" (set) : "a" (set)); " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t"
: /* output parameters */
: [set] "a" (set) /* input parameters */
:
);
} }
/* next loop will finish the cache ie pass the hole */ /* next loop will finish the cache ie pass the hole */
end_set = LAST_ICACHE_ADDR; end_set = LAST_ICACHE_ADDR;
} }
for (set = start_set; set <= end_set; set += (0x10 - 3)) { for (set = start_set; set <= end_set; set += (0x10 - 3)) {
asm volatile("cpushl ic,(%0)\n\t" __asm__ __volatile__(
"addq.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)\n\t" " addq.l #1,%[set] \n\t"
"addq%.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)\n\t" " addq.l #1,%[set] \n\t"
"addq.l #1,%0\n\t" " cpushl ic,(%[set]) \n\t"
"cpushl ic,(%0)" : "=a" (set) : "a" (set)); " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set])"
: /* output parameters */
: [set] "a" (set)
:
);
} }
} }
@@ -121,25 +131,37 @@ void flush_dcache_range(void *address, size_t size)
if (start_set > end_set) { if (start_set > end_set) {
/* from the begining to the lowest address */ /* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) { for (set = 0; set <= end_set; set += (0x10 - 3))
asm volatile("cpushl dc,(%0)\n\t" {
"addq.l #1,%0\n\t" __asm__ __volatile__(
"cpushl dc,(%0)\n\t" " cpushl dc,(%[set]) \n\t"
"addq.l #1,%0\n\t" " addq.l #1,%[set] \n\t"
"cpushl dc,(%0)\n\t" " cpushl dc,(%[set]) \n\t"
"addq.l #1,%0\n\t" " addq.l #1,%[set] \n\t"
"cpushl dc,(%0)" : "=a" (set) : "a" (set)); " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t"
: /* output parameters */
: [set] "a" (set)
: /* clobbered registers */
);
} }
/* next loop will finish the cache ie pass the hole */ /* next loop will finish the cache ie pass the hole */
end_set = LAST_DCACHE_ADDR; end_set = LAST_DCACHE_ADDR;
} }
for (set = start_set; set <= end_set; set += (0x10 - 3)) { for (set = start_set; set <= end_set; set += (0x10 - 3))
asm volatile("cpushl dc,(%0)\n\t" {
"addq.l #1,%0\n\t" __asm__ __volatile__(
"cpushl dc,(%0)\n\t" " cpushl dc,(%[set]) \n\t"
"addq%.l #1,%0\n\t" " addq.l #1,%[set] \n\t"
"cpushl dc,(%0)\n\t" " cpushl dc,(%[set]) \n\t"
"addq.l #1,%0\n\t" " addq%.l #1,%[set] \n\t"
"cpushl dc,(%0)" : "=a" (set) : "a" (set)); " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t"
: /* output parameters */
: [set] "a" (set)
: /* clobbered registers */
);
} }
} }

View File

@@ -18,10 +18,14 @@
#include "usb.h" #include "usb.h"
#include "exceptions.h" /* set_ipl() */ #include "exceptions.h" /* set_ipl() */
#if MACHINE_FIREBEE #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#elif MACHINE_M5484LITE #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else
#error "unknown machine!"
#endif #endif
//#define DBG_DM //#define DBG_DM

File diff suppressed because it is too large Load Diff

View File

@@ -38,51 +38,41 @@ extern uint8_t _FPGA_FLASH_DATA[];
extern uint8_t _FPGA_FLASH_DATA_SIZE[]; extern uint8_t _FPGA_FLASH_DATA_SIZE[];
#define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_FLASH_DATA_SIZE[0]) #define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_FLASH_DATA_SIZE[0])
void config_gpio_for_fpga_config(void)
#ifdef _NOT_USED_
void test_longword(void)
{ {
uint32_t *fpga_data = (uint32_t *) FPGA_FLASH_DATA; #if defined(MACHINE_FIREBEE)
const uint32_t *fpga_flash_data_end = (uint32_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE; /*
do * Configure GPIO FEC1L port directions (needed to load FPGA configuration)
{ */
uint32_t value = *fpga_data++; MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value); 0 | /* bit 6 = input */
} while (fpga_data < fpga_flash_data_end); 0 | /* bit 5 = input */
xprintf("finished. \r\n"); MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
0; /* bit 0 => input */
#endif /* MACHINE_FIREBEE */
} }
void test_word(void) void config_gpio_for_jtag_config(void)
{ {
uint16_t *fpga_data = (uint16_t *) FPGA_FLASH_DATA; /*
const uint16_t *fpga_flash_data_end = (uint16_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE; * configure FEC1L port directions to enable external JTAG configuration download to FPGA
*/
do MCF_GPIO_PDDR_FEC1L = 0 |
{ MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
uint16_t value = *fpga_data++; /* all other bits = input */
xprintf("WORDS: addr=%p, value=%04x\r", fpga_data, value); /*
} while (fpga_data < fpga_flash_data_end); * unfortunately, the GPIO module cannot trigger interrupts. That means FPGA_CONFIG needs to be polled to detect
xprintf("finished. \r\n"); * external FPGA (re)configuration and reset the system in that case. Could be done from the OS as well...
*/
} }
void test_byte(void)
{
uint8_t *fpga_data = (uint8_t *) FPGA_FLASH_DATA;
const uint8_t *fpga_flash_data_end = (uint8_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
do
{
uint8_t value = *fpga_data++;
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
} while (fpga_data < fpga_flash_data_end);
xprintf("finished. \r\n");
}
#endif /* _NOT_USED_ */
/* /*
* load FPGA * load FPGA
*/ */
void init_fpga(void) bool init_fpga(void)
{ {
uint8_t *fpga_data; uint8_t *fpga_data;
volatile int32_t time, start, end; volatile int32_t time, start, end;
@@ -91,6 +81,7 @@ void init_fpga(void)
xprintf("FPGA load config... "); xprintf("FPGA load config... ");
start = MCF_SLT0_SCNT; start = MCF_SLT0_SCNT;
config_gpio_for_fpga_config();
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */ MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
/* pulling FPGA_CONFIG to low resets the FPGA */ /* pulling FPGA_CONFIG to low resets the FPGA */
@@ -109,7 +100,7 @@ void init_fpga(void)
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization. * configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
* While nCONFIG is low, the device is in reset. When the device comes out of reset, * While nCONFIG is low, the device is in reset. When the device comes out of reset,
* nCONFIG must be at a logic high level in order for the device to release the open-drain * nCONFIG must be at a logic high level in order for the device to release the open-drain
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA * nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
* is ready to receive configuration data. Before and during configuration, all user I/O pins * is ready to receive configuration data. Before and during configuration, all user I/O pins
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors * are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
* on the I/O pins which are on, before and during configuration. * on the I/O pins which are on, before and during configuration.
@@ -161,9 +152,10 @@ void init_fpga(void)
time = (start - end) / (SYSCLK / 1000) / 1000; time = (start - end) / (SYSCLK / 1000) / 1000;
xprintf("finished (took %f seconds).\r\n", time / 1000.0); xprintf("finished (took %f seconds).\r\n", time / 1000.0);
config_gpio_for_jtag_config();
return true;
} }
else xprintf("FAILED!\r\n");
{ config_gpio_for_jtag_config();
xprintf("FAILED!\r\n"); return false;
}
} }

View File

@@ -30,13 +30,16 @@
#include "exceptions.h" #include "exceptions.h"
#include "interrupts.h" #include "interrupts.h"
#include "bas_printf.h" #include "bas_printf.h"
#include "startcf.h"
#include "cache.h"
#include "util.h"
extern void (*rt_vbr[])(void); extern void (*rt_vbr[])(void);
#define VBR rt_vbr #define VBR rt_vbr
#define IRQ_DEBUG #define IRQ_DEBUG
#if defined(IRQ_DEBUG) #if defined(IRQ_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif #endif
@@ -57,7 +60,7 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
if (source < 1 || source > 63) if (source < 1 || source > 63)
{ {
dbg("%s: interrupt source %d not defined\r\n", __FUNCTION__, source); dbg("interrupt source %d not defined\r\n", source);
return -1; return -1;
} }
@@ -68,7 +71,7 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
{ {
if (ICR[i] == lp) if (ICR[i] == lp)
{ {
dbg("%s: level %d and priority %d already used for interrupt source %d!\r\n", __FUNCTION__, dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i); level, priority, i);
return -1; return -1;
} }
@@ -88,31 +91,29 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
return 0; return 0;
} }
#ifndef UIF_MAX_ISR_ENTRY #ifndef MAX_ISR_ENTRY
#define UIF_MAX_ISR_ENTRY (20) #define MAX_ISR_ENTRY (20)
#endif #endif
typedef struct typedef struct
{ {
int vector; int vector;
int type;
int (*handler)(void *, void *); int (*handler)(void *, void *);
void *hdev; void *hdev;
void *harg; void *harg;
} ISRENTRY; } ISRENTRY;
ISRENTRY isrtab[UIF_MAX_ISR_ENTRY]; ISRENTRY isrtab[MAX_ISR_ENTRY];
void isr_init(void) void isr_init(void)
{ {
int index; int index;
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
isrtab[index].vector = 0; isrtab[index].vector = 0;
isrtab[index].type = 0;
isrtab[index].handler = 0; isrtab[index].handler = 0;
isrtab[index].hdev = 0; isrtab[index].hdev = 0;
isrtab[index].harg = 0; isrtab[index].harg = 0;
@@ -120,8 +121,7 @@ void isr_init(void)
} }
int isr_register_handler(int type, int vector, int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg)
int (*handler)(void *, void *), void *hdev, void *harg)
{ {
/* /*
* This function places an interrupt handler in the ISR table, * This function places an interrupt handler in the ISR table,
@@ -133,28 +133,24 @@ int isr_register_handler(int type, int vector,
*/ */
int index; int index;
if ((vector == 0) || if ((vector == 0) || (handler == NULL))
((type != ISR_DBUG_ISR) && (type != ISR_USER_ISR)) ||
(handler == NULL))
{ {
dbg("%s: illegal type, vector or handler!\r\n", __FUNCTION__); dbg("illegal vector or handler!\r\n");
return false; return false;
} }
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if ((isrtab[index].vector == vector) && if (isrtab[index].vector == vector)
(isrtab[index].type == type))
{ {
/* only one entry of each type per vector */ /* one cross each, only! */
dbg("%s: already set handler with this type and vector (%d, %d)\r\n", __FUNCTION__, type, vector); dbg("already set handler with this vector (%d, %d)\r\n", vector);
return false; return false;
} }
if (isrtab[index].vector == 0) if (isrtab[index].vector == 0)
{ {
isrtab[index].vector = vector; isrtab[index].vector = vector;
isrtab[index].type = type;
isrtab[index].handler = handler; isrtab[index].handler = handler;
isrtab[index].hdev = hdev; isrtab[index].hdev = hdev;
isrtab[index].harg = harg; isrtab[index].harg = harg;
@@ -162,26 +158,24 @@ int isr_register_handler(int type, int vector,
return true; return true;
} }
} }
dbg("%s: no available slots to register handler for vector %d\n\r", __FUNCTION__, vector); dbg("no available slots to register handler for vector %d\n\r", vector);
return false; /* no available slots */ return false; /* no available slots */
} }
void isr_remove_handler(int type, int (*handler)(void *, void *)) void isr_remove_handler(int (*handler)(void *, void *))
{ {
/* /*
* This routine removes from the ISR table all * This routine removes from the ISR table all
* entries that matches 'type' and 'handler'. * entries that matches 'handler'.
*/ */
int index; int index;
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if ((isrtab[index].handler == handler) && if (isrtab[index].handler == handler)
(isrtab[index].type == type))
{ {
isrtab[index].vector = 0; isrtab[index].vector = 0;
isrtab[index].type = 0;
isrtab[index].handler = 0; isrtab[index].handler = 0;
isrtab[index].hdev = 0; isrtab[index].hdev = 0;
isrtab[index].harg = 0; isrtab[index].harg = 0;
@@ -189,7 +183,7 @@ void isr_remove_handler(int type, int (*handler)(void *, void *))
return; return;
} }
} }
dbg("%s: no such handler registered (type=%d, handler=%p\r\n", __FUNCTION__, type, handler); dbg("no such handler registered (handler=%p\r\n", handler);
} }
@@ -203,12 +197,11 @@ bool isr_execute_handler(int vector)
bool retval = false; bool retval = false;
/* /*
* First locate a BaS Interrupt Service Routine handler. * locate a BaS Interrupt Service Routine handler.
*/ */
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if ((isrtab[index].vector == vector) && if (isrtab[index].vector == vector)
(isrtab[index].type == ISR_DBUG_ISR))
{ {
retval = true; retval = true;
@@ -218,7 +211,202 @@ bool isr_execute_handler(int vector)
} }
} }
} }
dbg("%s: no BaS isr handler for vector %d found\r\n", __FUNCTION__, vector); dbg("no BaS isr handler for vector %d found\r\n", vector);
return retval; return retval;
} }
/*
* PIC interrupt handler for Firebee
*/
void pic_interrupt_handler(void)
{
uint8_t rcv_byte;
rcv_byte = MCF_PSC3_PSCRB_8BIT;
if (rcv_byte == 2) // PIC requests RTC data
{
uint8_t *rtc_reg= (uint8_t *) 0xffff8961;
uint8_t *rtc_data = (uint8_t *) 0xffff8963;
int index = 0;
xprintf("PIC interrupt requesting RTC data\r\n");
MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC
do
{
*rtc_reg = 0;
MCF_PSC3_PSCTB_8BIT = *rtc_data;
} while (index++ < 64);
}
}
extern int32_t video_sbt;
extern int32_t video_tlb;
void video_addr_timeout(void)
{
uint32_t addr = 0x0L;
uint32_t *src;
uint32_t *dst;
uint32_t asid;
dbg("video address timeout\r\n");
flush_and_invalidate_caches();
do
{
uint32_t tlb;
uint32_t page_attr;
/*
* search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm)
*/
MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/*
* retrieve tlb entry with the found TLB entry id
*/
MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */
{
addr += 0x100000;
continue; /* next page */
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA;
NOP();
dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
addr += 0x100000;
} while (addr < 0xd00000);
video_tlb = 0x2000;
video_sbt = 0;
}
/*
* blink the Firebee's LED to show we are still alive
*/
void blink_led(void)
{
static uint16_t blinker = 0;
if ((blinker++ & 0x80) > 0)
{
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
}
else
{
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
}
}
/*
* Atari MFP interrupt registers.
*
* TODO: should go into a header file
*/
#define FALCON_MFP_IERA *((volatile uint8_t *) 0xfffffa07)
#define FALCON_MFP_IERB *((volatile uint8_t *) 0xfffffa09)
#define FALCON_MFP_IPRA *((volatile uint8_t *) 0xfffffa0b)
#define FALCON_MFP_IPRB *((volatile uint8_t *) 0xfffffa0d)
#define FALCON_MFP_IMRA *((volatile uint8_t *) 0xfffffa13)
#define FALCON_MFP_IMRB *((volatile uint8_t *) 0xfffffa15)
bool irq6_acsi_dma_interrupt(void)
{
dbg("ACSI DMA interrupt\r\n");
/*
* TODO: implement handler
*/
return false;
}
bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
{
bool handled = false;
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{
video_addr_timeout();
handled = true;
}
/*
* check if ACSI DMA interrupt
*/
if (FALCON_MFP_IERA & (1 << 7))
{
/* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7))
{
irq6_acsi_dma_interrupt();
handled = true;
}
}
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{
blink_led();
}
return handled;
}

656
sys/mmu.c
View File

@@ -24,26 +24,6 @@
* Copyright 2013 M. Froeschle * Copyright 2013 M. Froeschle
*/ */
#define ACR_BA(x) ((x) & 0xffff0000)
#define ACR_ADMSK(x) (((x) & 0xffff) << 16)
#define ACR_E(x) (((x) & 1) << 15)
#define ACR_S(x) (((x) & 3) << 13)
#define ACR_S_USERMODE 0
#define ACR_S_SUPERVISOR_MODE 1
#define ACR_S_ALL 2
#define ACR_AMM(x) (((x) & 1) << 10)
#define ACR_CM(x) (((x) & 3) << 5)
#define ACR_CM_CACHEABLE_WT 0x0
#define ACR_CM_CACHEABLE_CB 0x1
#define ACR_CM_CACHE_INH_PRECISE 0x2
#define ACR_CM_CACHE_INH_IMPRECISE 0x3
#define ACR_SP(x) (((x) & 1) << 3)
#define ACR_W(x) (((x) & 1) << 2)
#include <stdint.h> #include <stdint.h>
#include "bas_printf.h" #include "bas_printf.h"
#include "bas_types.h" #include "bas_types.h"
@@ -56,16 +36,18 @@
#include "firebee.h" #include "firebee.h"
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else #else
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
//#define DEBUG_MMU #define DBG_MMU
#ifdef DEBUG_MMU #ifdef DBG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg);} while(0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg);} while(0)
#else #else
#define dbg(format, arg...) do {;} while (0) #define dbg(format, arg...) do {;} while (0)
#endif /* DEBUG_MMU */ #endif /* DBG_MMU */
/* /*
* set ASID register * set ASID register
@@ -77,11 +59,11 @@ inline uint32_t set_asid(uint32_t value)
uint32_t ret = rt_asid; uint32_t ret = rt_asid;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ASID\n\t" "movec %[value],ASID\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_asid = value; rt_asid = value;
@@ -99,11 +81,11 @@ inline uint32_t set_acr0(uint32_t value)
uint32_t ret = rt_acr0; uint32_t ret = rt_acr0;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR0\n\t" "movec %[value],ACR0\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr0 = value; rt_acr0 = value;
return ret; return ret;
@@ -119,11 +101,11 @@ inline uint32_t set_acr1(uint32_t value)
uint32_t ret = rt_acr1; uint32_t ret = rt_acr1;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR1\n\t" "movec %[value],ACR1\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr1 = value; rt_acr1 = value;
return ret; return ret;
@@ -140,11 +122,11 @@ inline uint32_t set_acr2(uint32_t value)
uint32_t ret = rt_acr2; uint32_t ret = rt_acr2;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR2\n\t" "movec %[value],ACR2\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr2 = value; rt_acr2 = value;
return ret; return ret;
@@ -160,11 +142,11 @@ inline uint32_t set_acr3(uint32_t value)
uint32_t ret = rt_acr3; uint32_t ret = rt_acr3;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR3\n\t" "movec %[value],ACR3\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr3 = value; rt_acr3 = value;
return ret; return ret;
@@ -176,264 +158,376 @@ inline uint32_t set_mmubar(uint32_t value)
uint32_t ret = rt_mmubar; uint32_t ret = rt_mmubar;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],MMUBAR\n\t" "movec %[value],MMUBAR\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: /* no clobber */ : /* no clobber */
); );
rt_mmubar = value; rt_mmubar = value;
NOP(); NOP();
return ret; return ret;
} }
/*
* TODO: this would be nicer in an include file
*/
extern uint8_t _SYS_SRAM[];
#define SYS_SRAM_ADDRESS ((uint32_t) &_SYS_SRAM[0])
extern uint8_t _SYS_SRAM_SIZE[];
extern uint8_t _FASTRAM_END[];
struct mmu_mapping
{
uint32_t phys;
uint32_t virt;
uint32_t length;
uint32_t pagesize;
struct map_flags flags;
};
static struct mmu_mapping locked_map[] =
{
{
/* Falcon video memory. Needs special care */
0x60d00000,
0xd00000,
0x100000,
MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, SCA_PAGE_ID, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
};
static int num_locked_mmu_maps = sizeof(locked_map) / sizeof(struct mmu_mapping);
static struct mmu_mapping memory_map[] =
{
/* map OS system vectors supervisor-protected */
{
0,
0,
0x800,
MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
0x800,
0x800,
0x800,
MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* when the first 4k are filled with 1k pages, we can switch to 8k pages */
0x1000,
0x1000,
0xff000,
MMU_PAGE_SIZE_8K,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* arrived at a 1Meg border, we can switch to 1Meg pages */
0x100000,
0x100000,
0xc00000,
MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
/* Falcon video ram left out intentionally here (see above) */
{
/* ROM */
0xe00000,
0xe00000,
0x100000,
MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_EXECUTE },
},
{
/* FASTRAM */
0x1000000,
0x1000000,
(uint32_t) _FASTRAM_END - 0x1000000,
MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* MBAR */
MBAR_ADDRESS,
MBAR_ADDRESS,
0x100000,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
},
{
/* RAMBAR0 */
RAMBAR0_ADDRESS,
RAMBAR0_ADDRESS,
(uint32_t) _RAMBAR0_SIZE,
MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* RAMBAR1 */
RAMBAR1_ADDRESS,
RAMBAR1_ADDRESS,
(uint32_t) _RAMBAR1_SIZE,
MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* SYSTEM SRAM */
SYS_SRAM_ADDRESS,
SYS_SRAM_ADDRESS,
(uint32_t) _SYS_SRAM_SIZE,
MMU_PAGE_SIZE_8K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
},
{
/* Firebee FPGA registers */
(uint32_t) 0xf0000000,
(uint32_t) 0xf0000000,
(uint32_t) 0x08000000,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
},
{
/* Falcon I/O registers */
(uint32_t) 0xfff00000,
(uint32_t) 0xfff00000,
(uint32_t) 0x100000,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
},
{
/* the same, but different virtual address */
(uint32_t) 0x00f00000,
(uint32_t) 0xfff00000,
(uint32_t) 0x100000,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
},
{
/* PCI memory */
(uint32_t) PCI_MEMORY_OFFSET,
(uint32_t) PCI_MEMORY_OFFSET,
(uint32_t) PCI_MEMORY_SIZE,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
},
{
/* PCI I/O */
(uint32_t) PCI_IO_OFFSET,
(uint32_t) PCI_IO_OFFSET,
(uint32_t) PCI_IO_SIZE,
MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
}
};
static int num_mmu_maps = sizeof(memory_map) / sizeof(struct mmu_mapping);
static struct mmu_mapping *lookup_mapping(uint32_t virt)
{
int i;
/*
* dumb, for now
*/
for (i = 0; i < num_mmu_maps; i++)
{
if (virt >= memory_map[i].virt && virt <= memory_map[i].virt + memory_map[i].length - 1)
return &memory_map[i];
}
return NULL;
}
void mmu_init(void) void mmu_init(void)
{ {
extern uint8_t _MMUBAR[]; extern uint8_t _MMUBAR[];
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0]; uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
extern uint8_t _TOS[]; int i;
uint32_t TOS = (uint32_t) &_TOS[0];
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */ set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
/* set data access attributes in ACR0 and ACR1 */ /*
set_acr0(ACR_W(0) | /* read and write accesses permitted */ * need to set data ACRs in a way that supervisor access to all memory regions
ACR_SP(0) | /* supervisor and user mode access permitted */ * becomes possible. Otherways it might be that the supervisor stack ends up in an unmapped
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */ * region when further MMU TLB entries force a page steal. This would lead to a double
ACR_AMM(0) | /* control region > 16 MB */ * fault since the CPU wouldn't be able to push its exception stack frame during an access
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */ * exception
ACR_E(1) | /* enable ACR */ */
#if MACHINE_FIREBEE
ACR_ADMSK(0x3f) | /* cover 1GB area from 0xc0000000 to 0xffffffff */
ACR_BA(0xc0000000)); /* (equals area from 3 to 4 GB */
#elif MACHINE_M5484LITE
ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */
ACR_BA(0x80000000));
#endif /* MACHINE_FIREBEE */
// set_acr1(0x601fc000); /* set data access attributes in ACR0 and ACR1 */
set_acr1(ACR_W(0) |
ACR_SP(0) | set_acr0(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */
ACR_CM(0) | ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */
#if MACHINE_FIREBEE ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */
ACR_CM(ACR_CM_CACHEABLE_WT) | /* video RAM on the Firebee */ ACR_ADDRESS_MASK_MODE(1) | /* region 13 MByte */
#elif MACHINE_M5484LITE ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */ ACR_E(1) | /* enable ACR */
#endif /* MACHINE_FIREBEE */ ACR_ADMSK(0x0a) | /* cover 12 MByte from 0x0 */
ACR_AMM(0) | ACR_BA(0)); /* start from 0x0 */
ACR_S(ACR_S_ALL) |
set_acr1(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */
ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */
ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */
ACR_ADDRESS_MASK_MODE(0) | /* region > 16 MByte */
ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */
ACR_E(1) | /* enable ACR */
ACR_ADMSK(0x1f) | /* cover 495 MByte from 0x1000000 */
ACR_BA(0x01000000)); /* all Fast RAM */
/*
* set instruction access attributes in ACR2 and ACR3. This is the same as above, basically:
* enable supervisor access to all SDRAM
*/
set_acr2(ACR_WRITE_PROTECT(0) |
ACR_SUPERVISOR_PROTECT(0) |
ACR_CACHE_MODE(CACHE_WRITETHROUGH) |
ACR_ADDRESS_MASK_MODE(1) |
ACR_S(ACR_S_SUPERVISOR_MODE) |
ACR_E(1) |
ACR_ADMSK(0x0c) |
ACR_BA(0x0));
set_acr3(ACR_WRITE_PROTECT(0) |
ACR_SUPERVISOR_PROTECT(0) |
ACR_CACHE_MODE(CACHE_WRITETHROUGH) |
ACR_ADDRESS_MASK_MODE(0) |
ACR_S(ACR_S_SUPERVISOR_MODE) |
ACR_E(1) | ACR_E(1) |
ACR_ADMSK(0x1f) | ACR_ADMSK(0x1f) |
ACR_BA(0x60000000)); ACR_BA(0x0f));
/* set instruction access attributes in ACR2 and ACR3 */
//set_acr2(0xe007c400);
set_acr2(ACR_W(0) |
ACR_SP(0) |
ACR_CM(0) |
ACR_CM(ACR_CM_CACHEABLE_WT) |
ACR_AMM(1) |
ACR_S(ACR_S_ALL) |
ACR_E(1) |
ACR_ADMSK(0x7) |
ACR_BA(0xe0000000));
/* disable ACR3 */
set_acr3(0x0);
set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */ set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */
/* clear all MMU TLB entries */ /* clear all MMU TLB entries */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA; MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA;
/* create locked TLB entries */ /* map locked TLB entries */
for (i = 0; i < num_locked_mmu_maps; i++)
/*
* 0x0000'0000 - 0x000F'FFFF (first MB of physical memory) locked virtual = physical
*/
MCF_MMU_MMUTR = 0x0 | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = 0x0 | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cacheable, copyback */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
/*
* 0x00d0'0000 - 0x00df'ffff (last megabyte of ST RAM = Falcon video memory) locked ID = 6
* mapped to physical address 0x60d0'0000 (FPGA video memory)
* video RAM: read write execute normal write true
*/
MCF_MMU_MMUTR = 0x00d00000 | /* virtual address */
#if defined(MACHINE_FIREBEE)
MCF_MMU_MMUTR_ID(SCA_PAGE_ID) |
#endif /* MACHINE_FIREBEE */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
#if defined(MACHINE_FIREBEE)
/* map FPGA video memory for FireBee only */
MCF_MMU_MMUDR = 0x60d00000 | /* physical address */
#elif defined(MACHINE_M5484LITE)
MCF_MMU_MMUDR = 0x00d00000 | /* physical address */
#endif /* MACHINE_FIREBEE */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x0) | /* cachable writethrough */
/* caveat: can't be supervisor protected since TOS puts the application stack there! */
//MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#if defined(MACHINE_FIREBEE)
video_tlb = 0x2000; /* set page as video page */
video_sbt = 0x0; /* clear time */
#endif /* MACHINE_FIREBEE */
/*
* Make the TOS (in SDRAM) read-only
* This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address
*/
MCF_MMU_MMUTR = TOS | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = TOS | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cachable copyback */
MCF_MMU_MMUDR_R | /* read access enable */
//MCF_MMU_MMUDR_W | /* write access enable (FIXME: for now) */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#if MACHINE_FIREBEE
/*
* Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O
* area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee
*/
MCF_MMU_MMUTR = 0x00f00000 | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = 0xfff00000 | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
#endif /* MACHINE_FIREBEE */
/*
* Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same
* virtual address. This is also used when BaS is in RAM
*/
MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x0) | /* cacheable writethrough */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
/*
* Map (locked) the very last MB of physical SDRAM (this is where the driver buffers reside) to the same
* virtual address. Used uncached for drivers.
*/
MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* virtual address */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */
MCF_MMU_MMUDR_SP | /* supervisor protect */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
//MCF_MMU_MMUDR_X | /* execute access enable */
MCF_MMU_MMUDR_LK; /* lock entry */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
}
void mmutr_miss(uint32_t address)
{
dbg("MMU TLB MISS at 0x%08x\r\n", address);
flush_and_invalidate_caches();
switch (address)
{ {
case keyctl: mmu_map_page(locked_map[i].virt, locked_map[i].phys, locked_map->pagesize, locked_map->flags);
case keybd:
/* do something to emulate the IKBD access */
dbg("IKBD access\r\n");
break;
case midictl: if (locked_map[i].flags.page_id == SCA_PAGE_ID)
case midi: {
/* do something to emulate MIDI access */ video_tlb = 0x2000;
dbg("MIDI ACIA access\r\n"); video_sbt = 0x0;
break; }
default:
/* add missed page to TLB */
MCF_MMU_MMUTR = (address & 0xfff00000) | /* virtual aligned to 1M */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (address & 0xfff00000) | /* physical aligned to 1M */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0x1) | /* cacheable copyback */
MCF_MMU_MMUDR_R | /* read access enable */
MCF_MMU_MMUDR_W | /* write access enable */
MCF_MMU_MMUDR_X; /* execute access enable */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
} }
} }
/*
* handle an access error
* upper level routine called from access_exception inside exceptions.S
*/
bool access_exception(uint32_t pc, uint32_t format_status)
{
int fault_status;
uint32_t fault_address;
uint32_t mmu_status;
/*
* extract fault status from format_status exception stack field
*/
fault_status = format_status & 0xc030000;
mmu_status = MCF_MMU_MMUSR;
/*
* determine if access fault was caused by a TLB miss
*/
switch (fault_status)
{
case 0x4010000: /* TLB miss on opword of instruction fetch */
case 0x4020000: /* TLB miss on extension word of instruction fetch */
//fault_address = pc;
//break;
case 0x8020000: /* TLB miss on data write */
case 0xc020000: /* TLB miss on data read or read-modify-write */
fault_address = MCF_MMU_MMUAR;
/*
* the following line must stay commented or we risk a double fault (debugging
* output requiring itself a page mapping):
*/
// dbg("access fault - TLB miss at %p. Fault status = 0x0%x\r\n", pc, fault_status);
break;
default:
return false;
}
if (mmu_status & MCF_MMU_MMUSR_HIT) /* did the last fault hit in TLB? */
{
/*
* if yes, then we already mapped that page during a previous turn and this is in fact a bus error
*/
return false;
}
else
{
struct mmu_mapping *map;
if ((map = lookup_mapping(fault_address)) != NULL)
{
uint32_t mask;
switch (map->pagesize)
{
case MMU_PAGE_SIZE_1M:
mask = ~(0x100000 - 1);
break;
case MMU_PAGE_SIZE_4K:
mask = ~(0x1000 - 1);
break;
case MMU_PAGE_SIZE_8K:
mask = ~(0x2000 - 1);
break;
case MMU_PAGE_SIZE_1K:
mask = ~(0x400 - 1);
break;
}
mmu_map_page(fault_address & mask, fault_address & mask, map->pagesize, map->flags);
return true;
}
}
return false;
}
void mmu_map_page(uint32_t virt, uint32_t phys, uint32_t map_size, struct map_flags flags)
{
/*
* add page to TLB
*/
MCF_MMU_MMUTR = virt | /* virtual address */
MCF_MMU_MMUTR_ID(flags.page_id) |
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = phys | /* physical address */
MCF_MMU_MMUDR_SZ(map_size) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(flags.cache_mode) |
(flags.access & ACCESS_READ ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags.access & ACCESS_WRITE ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags.access & ACCESS_EXECUTE ? MCF_MMU_MMUDR_X : 0); /* execute access enable */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
dbg("mapped virt=%p to phys=%p\r\n", virt, phys);
}

View File

@@ -1,3 +1,4 @@
/* /*
* This object file must be the first to be linked, * This object file must be the first to be linked,
* so it will be placed at the very beginning of the ROM. * so it will be placed at the very beginning of the ROM.
@@ -49,7 +50,8 @@ _rom_entry:
lea __SUP_SP,a7 lea __SUP_SP,a7
move.l #0,(sp) move.l #0,(sp)
/* Initialize the processor caches. /*
* Initialize the processor caches.
* The instruction cache is fully enabled. * The instruction cache is fully enabled.
* The data cache is enabled, but cache-inhibited by default. * The data cache is enabled, but cache-inhibited by default.
* Later, the MMU will fully activate the data cache for specific areas. * Later, the MMU will fully activate the data cache for specific areas.

View File

@@ -37,14 +37,17 @@
#include "wait.h" #include "wait.h"
#include "util.h" #include "util.h"
#include "version.h" #include "version.h"
#ifdef MACHINE_FIREBEE #if defined(MACHINE_FIREBEE)
#include "firebee.h" #include "firebee.h"
#endif /* MACHINE_FIREBEE */ #elif defined(MACHINE_M5484LITE)
#ifdef MACHINE_M5484LITE
#include "m5484l.h" #include "m5484l.h"
#elif defined(MACHINE_M54455)
#include "m54455.h"
#else
#error "unknown machine"
#endif /* MACHINE_M5484LITE */ #endif /* MACHINE_M5484LITE */
#
#include "dma.h" #include "dma.h"
#include "mod_devicetable.h" #include "mod_devicetable.h"
#include "pci_ids.h" #include "pci_ids.h"
@@ -52,7 +55,9 @@
#include "usb.h" #include "usb.h"
#include "video.h" #include "video.h"
#define UNUSED(x) (void)(x) /* Unused variable */ #define UNUSED(x) (void)(x) /* Unused variable */
bool fpga_configured = false; /* for FPGA JTAG configuration */
extern volatile long _VRAM; /* start address of video ram from linker script */ extern volatile long _VRAM; /* start address of video ram from linker script */
@@ -86,16 +91,16 @@ void init_gpio(void)
* configure all four 547x GPIO module DMA pins: * configure all four 547x GPIO module DMA pins:
* *
* /DACK1 - DMA acknowledge 1 * /DACK1 - DMA acknowledge 1
* /DACK0 - DMA acknowledge 0 * /DACK0 - DMA acknowledge 0
* /DREQ1 - DMA request 1 * /DREQ1 - DMA request 1
* /DREQ0 - DMA request 0 * /DREQ0 - DMA request 0
* *
* for DMA operation * for DMA operation
*/ */
MCF_PAD_PAR_DMA = MCF_PAD_PAR_DMA_PAR_DACK0(0b11) | MCF_PAD_PAR_DMA = MCF_PAD_PAR_DMA_PAR_DACK0(0x3) |
MCF_PAD_PAR_DMA_PAR_DACK1(0b11) | MCF_PAD_PAR_DMA_PAR_DACK1(0x3) |
MCF_PAD_PAR_DMA_PAR_DREQ1(0b11) | MCF_PAD_PAR_DMA_PAR_DREQ1(0x3) |
MCF_PAD_PAR_DMA_PAR_DREQ0(0b11); MCF_PAD_PAR_DMA_PAR_DREQ0(0x3);
/* /*
* configure FEC0 pin assignment on GPIO module as FEC0 * configure FEC0 pin assignment on GPIO module as FEC0
@@ -204,20 +209,6 @@ void init_gpio(void)
MCF_PAD_PAR_TIMER_PAR_TOUT3 | MCF_PAD_PAR_TIMER_PAR_TOUT3 |
MCF_PAD_PAR_TIMER_PAR_TIN2(MCF_PAD_PAR_TIMER_PAR_TIN2_IRQ2) | MCF_PAD_PAR_TIMER_PAR_TIN2(MCF_PAD_PAR_TIMER_PAR_TIN2_IRQ2) |
MCF_PAD_PAR_TIMER_PAR_TOUT2; MCF_PAD_PAR_TIMER_PAR_TOUT2;
#if defined(MACHINE_FIREBEE)
/*
* Configure GPIO FEC1L port directions (needed to load FPGA configuration)
*/
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
0 | /* bit 6 = input */
0 | /* bit 5 = input */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
0; /* bit 0 => input */
#endif /* MACHINE_FIREBEE */
} }
/* /*
@@ -427,27 +418,27 @@ void init_fbcs()
#if MACHINE_FIREBEE /* FBC setup for FireBee */ #if MACHINE_FIREBEE /* FBC setup for FireBee */
MCF_FBCS1_CSAR = 0xFFF00000; /* ATARI I/O ADRESS */ MCF_FBCS1_CSAR = 0xFFF00000; /* ATARI I/O ADRESS */
MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 /* 16BIT PORT */ MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 /* 16BIT PORT */
| MCF_FBCS_CSCR_WS(8) /* DEFAULT 8WS */ | MCF_FBCS_CSCR_WS(8) /* DEFAULT 8WS */
| MCF_FBCS_CSCR_AA; /* AA */ | MCF_FBCS_CSCR_AA; /* AA */
MCF_FBCS1_CSMR = MCF_FBCS_CSMR_BAM_1M | MCF_FBCS_CSMR_V; MCF_FBCS1_CSMR = MCF_FBCS_CSMR_BAM_1M | MCF_FBCS_CSMR_V;
MCF_FBCS2_CSAR = 0xF0000000; // NEUER I/O ADRESS-BEREICH MCF_FBCS2_CSAR = 0xF0000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_WS(8) // DEFAULT 4WS | MCF_FBCS_CSCR_WS(8) // DEFAULT 4WS
| MCF_FBCS_CSCR_AA; // AA | MCF_FBCS_CSCR_AA; // AA
MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M // F000'0000-F7FF'FFFF MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M // F000'0000-F7FF'FFFF
| MCF_FBCS_CSMR_V); | MCF_FBCS_CSMR_V);
MCF_FBCS3_CSAR = 0xF8000000; // NEUER I/O ADRESS-BEREICH MCF_FBCS3_CSAR = 0xF8000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_AA; // AA | MCF_FBCS_CSCR_AA; // AA
MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M // F800'0000-FBFF'FFFF MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M // F800'0000-FBFF'FFFF
| MCF_FBCS_CSMR_V); | MCF_FBCS_CSMR_V);
MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH, #FB_CS3 WIRD NICHT BENÜTZT, DECODE DIREKT AUF DEM FPGA MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH, #FB_CS3 WIRD NICHT BENÜTZT, DECODE DIREKT AUF DEM FPGA
MCF_FBCS4_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT MCF_FBCS4_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_BSTR // BURST READ ENABLE | MCF_FBCS_CSCR_BSTR // BURST READ ENABLE
| MCF_FBCS_CSCR_BSTW; // BURST WRITE ENABLE | MCF_FBCS_CSCR_BSTW; // BURST WRITE ENABLE
MCF_FBCS4_CSMR = MCF_FBCS_CSMR_BAM_1G // 4000'0000-7FFF'FFFF MCF_FBCS4_CSMR = MCF_FBCS_CSMR_BAM_1G // 4000'0000-7FFF'FFFF
| MCF_FBCS_CSMR_V; | MCF_FBCS_CSMR_V;
#elif MACHINE_M5484LITE #elif MACHINE_M5484LITE
@@ -666,7 +657,8 @@ static bool i2c_bus_free(void)
/* /*
* TFP410 (DVI) on * TFP410 (DVI) on
*/ */
void dvi_on(void) { void dvi_on(void)
{
uint8_t receivedByte; uint8_t receivedByte;
uint8_t dummyByte; /* only used for a dummy read */ uint8_t dummyByte; /* only used for a dummy read */
int num_tries = 0; int num_tries = 0;
@@ -675,9 +667,10 @@ void dvi_on(void) {
MCF_I2C_I2FDR = 0x3c; /* divide system clock by 1280: 100kHz standard */ MCF_I2C_I2FDR = 0x3c; /* divide system clock by 1280: 100kHz standard */
do { do
{
/* disable all i2c interrupt routing targets */ /* disable all i2c interrupt routing targets */
MCF_I2C_I2ICR = 0x0; //~(MCF_I2C_I2ICR_IE | MCF_I2C_I2ICR_RE | MCF_I2C_I2ICR_TE | MCF_I2C_I2ICR_BNBE); MCF_I2C_I2ICR = 0x0; // ~(MCF_I2C_I2ICR_IE | MCF_I2C_I2ICR_RE | MCF_I2C_I2ICR_TE | MCF_I2C_I2ICR_BNBE);
/* disable i2c, disable i2c interrupts, slave, receive, i2c = acknowledge, no repeat start */ /* disable i2c, disable i2c interrupts, slave, receive, i2c = acknowledge, no repeat start */
MCF_I2C_I2CR = 0x0; MCF_I2C_I2CR = 0x0;
@@ -817,7 +810,7 @@ void init_ac97(void) {
xprintf("AC97 sound chip initialization: "); xprintf("AC97 sound chip initialization: ");
MCF_PAD_PAR_PSC2 = MCF_PAD_PAR_PSC2_PAR_RTS2_RTS // PSC2=TX,RX BCLK,CTS->AC'97 MCF_PAD_PAR_PSC2 = MCF_PAD_PAR_PSC2_PAR_RTS2_RTS // PSC2=TX,RX BCLK,CTS->AC'97
| MCF_PAD_PAR_PSC2_PAR_CTS2_BCLK | MCF_PAD_PAR_PSC2_PAR_CTS2_BCLK
| MCF_PAD_PAR_PSC2_PAR_TXD2 | MCF_PAD_PAR_PSC2_PAR_TXD2
| MCF_PAD_PAR_PSC2_PAR_RXD2; | MCF_PAD_PAR_PSC2_PAR_RXD2;
MCF_PSC2_PSCMR1 = 0x0; MCF_PSC2_PSCMR1 = 0x0;
@@ -958,10 +951,10 @@ void initialize_hardware(void)
* (volatile uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */ * (volatile uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (volatile uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */ * (volatile uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* TT-RAM */ /* TT-RAM */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */ * (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */ * (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
/* Jump into FireTOS */ /* Jump into FireTOS */
typedef void void_func(void); typedef void void_func(void);
@@ -1052,7 +1045,7 @@ void initialize_hardware(void)
/* /*
* Determine the processor revision * Determine the processor revision
*/ */
xprintf(" (revision %d)\r\n",((MCF_SIU_JTAGID & MCF_SIU_JTAGID_REV) >> 28)); xprintf(" (revision %d)\r\n", ((MCF_SIU_JTAGID & MCF_SIU_JTAGID_REV) >> 28));
init_slt(); init_slt();
init_fbcs(); init_fbcs();
@@ -1090,6 +1083,7 @@ void initialize_hardware(void)
/* the following only makes sense _after_ DDRAM has been initialized */ /* the following only makes sense _after_ DDRAM has been initialized */
clear_bss_segment(); clear_bss_segment();
xprintf(".bss segment cleared\r\n");
if (BAS_LMA != BAS_IN_RAM) if (BAS_LMA != BAS_IN_RAM)
{ {
@@ -1103,34 +1097,12 @@ void initialize_hardware(void)
#if MACHINE_FIREBEE #if MACHINE_FIREBEE
if (coldboot) /* does not work with BDM */ if (coldboot) /* does not work with BDM */
; ;
init_fpga(); fpga_configured = init_fpga();
init_pll(); init_pll();
init_video_ddr(); init_video_ddr();
dvi_on(); dvi_on();
#ifdef _NOT_USED_
/* experimental */
{
int i;
uint32_t *scradr = (uint32_t *) 0xd00000;
for (i = 0; i < 100; i++)
{
uint32_t *p = scradr;
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0xffffffff;
}
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0x0;
}
}
}
#endif /* _NOT_USED_ */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
driver_mem_init(); driver_mem_init();
init_pci(); init_pci();

View File

@@ -48,7 +48,7 @@ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum);
int usb_mouse_deregister(struct usb_device *dev) int usb_mouse_deregister(struct usb_device *dev)
{ {
dev->irq_handle = NULL; dev->irq_handle = NULL;
if(new != NULL) if (new != NULL)
{ {
driver_mem_free(new); driver_mem_free(new);
new = NULL; new = NULL;
@@ -61,8 +61,9 @@ int usb_mouse_deregister(struct usb_device *dev)
/* registering the mouse */ /* registering the mouse */
int usb_mouse_register(struct usb_device *dev) int usb_mouse_register(struct usb_device *dev)
{ {
if(!mouse_installed && (dev->devnum != -1) && (usb_mouse_probe(dev, 0) == 1)) if (!mouse_installed && (dev->devnum != -1) && (usb_mouse_probe(dev, 0) == 1))
{ /* Ok, we found a mouse */ {
/* Ok, we found a mouse */
mse_printf("USB MOUSE found (USB: %d, devnum: %d)\r\n", dev->usbnum, dev->devnum); mse_printf("USB MOUSE found (USB: %d, devnum: %d)\r\n", dev->usbnum, dev->devnum);
mouse_installed = 1; mouse_installed = 1;
dev->deregister = usb_mouse_deregister; dev->deregister = usb_mouse_deregister;
@@ -76,12 +77,12 @@ int usb_mouse_register(struct usb_device *dev)
int drv_usb_mouse_init(void) int drv_usb_mouse_init(void)
{ {
int i, j; int i, j;
if(mouse_installed) if (mouse_installed)
return -1; return -1;
/* scan all USB Devices */ /* scan all USB Devices */
for(j = 0; j < USB_MAX_BUS; j++) for (j = 0; j < USB_MAX_BUS; j++)
{ {
for(i = 0; i < USB_MAX_DEVICE; i++) for (i = 0; i < USB_MAX_DEVICE; i++)
{ {
struct usb_device *dev = usb_get_dev_index(i, j); /* get device */ struct usb_device *dev = usb_get_dev_index(i, j); /* get device */
if (dev == NULL) if (dev == NULL)
@@ -109,27 +110,27 @@ static int usb_mouse_irq(struct usb_device *dev)
int level; int level;
#endif #endif
int i, change = 0; int i, change = 0;
if((dev->irq_status != 0) || (dev->irq_act_len < 3) || (dev->irq_act_len > 8)) if ((dev->irq_status != 0) || (dev->irq_act_len < 3) || (dev->irq_act_len > 8))
{ {
mse_printf("USB MOUSE error %lX, len %d\r\n", dev->irq_status, dev->irq_act_len); mse_printf("USB MOUSE error %lX, len %d\r\n", dev->irq_status, dev->irq_act_len);
return 1; return 1;
} }
for(i = 0; i < dev->irq_act_len; i++) for (i = 0; i < dev->irq_act_len; i++)
{ {
if(new[i] != old[i]) if (new[i] != old[i])
{ {
change = 1; change = 1;
break; break;
} }
} }
if(change) if (change)
{ {
char wheel = 0, buttons, old_buttons; char wheel = 0, buttons, old_buttons;
mse_printf("USB MOUSE len:%d %02X %02X %02X %02X %02X %02X\r\n", dev->irq_act_len, new[0], new[1], new[2], new[3], new[4], new[5]); mse_printf("USB MOUSE len:%d %02X %02X %02X %02X %02X %02X\r\n", dev->irq_act_len, new[0], new[1], new[2], new[3], new[4], new[5]);
#ifdef CONFIG_USB_INTERRUPT_POLLING #ifdef CONFIG_USB_INTERRUPT_POLLING
level = set_ipl(7); /* mask interrupts */ level = set_ipl(7); /* mask interrupts */
#endif #endif
if((dev->irq_act_len >= 6) && (new[0] == 1)) /* report-ID */ if ((dev->irq_act_len >= 6) && (new[0] == 1)) /* report-ID */
{ {
buttons = new[1]; buttons = new[1];
old_buttons = old[1]; old_buttons = old[1];
@@ -143,24 +144,24 @@ static int usb_mouse_irq(struct usb_device *dev)
buttons = new[0]; buttons = new[0];
old_buttons = old[0]; old_buttons = old[0];
new[0] = ((new[0] & 1) << 1) + ((new[0] & 2) >> 1) + 0xF8; new[0] = ((new[0] & 1) << 1) + ((new[0] & 2) >> 1) + 0xF8;
if(dev->irq_act_len >= 3) if (dev->irq_act_len >= 3)
wheel = new[3]; wheel = new[3];
} }
if((buttons ^ old_buttons) & 4) /* 3rd button */ if ((buttons ^ old_buttons) & 4) /* 3rd button */
{ {
if(buttons & 4) if (buttons & 4)
{ {
usb_kbd_send_code(0x72); /* ENTER */ usb_kbd_send_code(0x72); /* ENTER */
usb_kbd_send_code(0xF2); usb_kbd_send_code(0xF2);
} }
} }
if(wheel != 0) /* actually like Eiffel */ if (wheel != 0) /* actually like Eiffel */
{ {
#define REPEAT_WHEEL 3 #define REPEAT_WHEEL 3
int i; int i;
if(wheel > 0) if (wheel > 0)
{ {
for(i = 0; i < REPEAT_WHEEL; i++) for (i = 0; i < REPEAT_WHEEL; i++)
{ {
usb_kbd_send_code(0x48); /* UP */ usb_kbd_send_code(0x48); /* UP */
usb_kbd_send_code(0xC8); usb_kbd_send_code(0xC8);
@@ -168,7 +169,7 @@ static int usb_mouse_irq(struct usb_device *dev)
} }
else else
{ {
for(i = 0; i < REPEAT_WHEEL; i++) for (i = 0; i < REPEAT_WHEEL; i++)
{ {
usb_kbd_send_code(0x50); /* DOWN */ usb_kbd_send_code(0x50); /* DOWN */
usb_kbd_send_code(0xD0); usb_kbd_send_code(0xD0);
@@ -197,24 +198,24 @@ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum)
struct usb_interface_descriptor *iface; struct usb_interface_descriptor *iface;
struct usb_endpoint_descriptor *ep; struct usb_endpoint_descriptor *ep;
int pipe, maxp; int pipe, maxp;
if(dev->descriptor.bNumConfigurations != 1) if (dev->descriptor.bNumConfigurations != 1)
return 0; return 0;
iface = &dev->config.if_desc[ifnum]; iface = &dev->config.if_desc[ifnum];
if(iface->bInterfaceClass != 3) if (iface->bInterfaceClass != 3)
return 0; return 0;
if(iface->bInterfaceSubClass != 1) if (iface->bInterfaceSubClass != 1)
return 0; return 0;
if(iface->bInterfaceProtocol != 2) if (iface->bInterfaceProtocol != 2)
return 0; return 0;
if(iface->bNumEndpoints != 1) if (iface->bNumEndpoints != 1)
return 0; return 0;
ep = &iface->ep_desc[0]; ep = &iface->ep_desc[0];
if(!(ep->bEndpointAddress & 0x80)) if (!(ep->bEndpointAddress & 0x80))
return 0; return 0;
if((ep->bmAttributes & 3) != 3) if ((ep->bmAttributes & 3) != 3)
return 0; return 0;
new = (unsigned char *)driver_mem_alloc(8); new = (unsigned char *)driver_mem_alloc(8);
if(new == NULL) if (new == NULL)
return 0; return 0;
mse_printf("USB MOUSE found set protocol...\r\n"); mse_printf("USB MOUSE found set protocol...\r\n");
/* ok, we found a USB Mouse, install it */ /* ok, we found a USB Mouse, install it */

View File

@@ -55,14 +55,14 @@ void *memset(void *s, int c, size_t n)
} }
int memcmp(const char *s1, const char *s2, size_t max) int memcmp(const void *s1, const void *s2, size_t max)
{ {
int i; int i;
int cmp; int cmp;
for (i = 0; i < max; i++) for (i = 0; i < max; i++)
{ {
cmp = (*s1 - *s2); cmp = (* (const char *) s1 - * (const char *) s2);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
} }
return cmp; return cmp;
@@ -75,7 +75,7 @@ int strcmp(const char *s1, const char *s2)
for (i = 0; *s1++ && *s2++; i++) for (i = 0; *s1++ && *s2++; i++)
{ {
cmp * (*s1 - *s2); cmp = (*s1 - *s2);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
} }
return cmp; return cmp;

View File

@@ -34,3 +34,5 @@ printf_helper:
lea __MBAR+0x860C,a0 // PSCSTB0 transmitter buffer register lea __MBAR+0x860C,a0 // PSCSTB0 transmitter buffer register
move.b d0,(a0) // send byte move.b d0,(a0) // send byte
rts rts
// vim: set syntax=asm68k :

View File

@@ -27,5 +27,43 @@
#include <stdint.h> #include <stdint.h>
#include <MCF5475.h> #include <MCF5475.h>
#include <wait.h> #include <wait.h>
uint32_t get_timer(void)
{
return MCF_SLT_SCNT(0);
}
/*
* wait for the specified number of us on slice timer 0. Replaces the original routines that had
* the number of useconds to wait for hardcoded in their name.
*/
void wait(uint32_t us)
{
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
while (MCF_SLT_SCNT(0) - target > 0);
}
/*
* same as above, but with milliseconds wait time
*/
void wait_ms(uint32_t ms)
{
wait(ms * 1000);
}
/*
* the same as above, with a checker function which gets called while
* busy waiting and allows for an early return if it returns true
*/
bool waitfor(uint32_t us, checker_func condition)
{
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
bool res;
do
{
if ((res = (*condition)()))
return res;
} while (MCF_SLT_SCNT(0) - target > 0);
return false;
}

View File

@@ -61,3 +61,5 @@ _xhdi_sd_install:
move.l #_xhdi_vec,d0 // return our BaS vector to TOS move.l #_xhdi_vec,d0 // return our BaS vector to TOS
move.l d0,a0 // move.l d0,a0 //
rte rte
// vim: set syntax=asm68k :