aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Reber <adrian@lisas.de>2008-11-21 12:45:38 +0100
committerAdrian Reber <adrian@lisas.de>2008-11-21 12:45:38 +0100
commit1015f69140c36be1c56653075636be60ca433a6d (patch)
tree23c81fb82a757758186b8ad9adab8f48badd3a16
parent07ec038eec68116cbfcc42b4eea568fd334e8c88 (diff)
downloadSLOF-slof-JX-1.4.0-0.zip
SLOF-slof-JX-1.4.0-0.tar.gz
SLOF-slof-JX-1.4.0-0.tar.bz2
imported slof-JX-1.4.0-0 releaseslof-JX-1.4.0-0
-rw-r--r--.target1
-rw-r--r--FlashingSLOF.pdfbin0 -> 302593 bytes
-rw-r--r--INSTALL252
-rw-r--r--LICENSE8
-rw-r--r--Makefile189
-rw-r--r--Makefile.gen160
-rw-r--r--README217
-rw-r--r--board-js2x/Makefile110
-rw-r--r--board-js2x/Makefile.dirs41
-rw-r--r--board-js2x/config5
-rw-r--r--board-js2x/include/bmc.h29
-rw-r--r--board-js2x/include/hw.h27
-rw-r--r--board-js2x/include/nvramlog.h65
-rw-r--r--board-js2x/include/product.h31
-rw-r--r--board-js2x/include/southbridge.h28
-rw-r--r--board-js2x/llfw/Cboot.S18
-rw-r--r--board-js2x/llfw/Makefile77
-rw-r--r--board-js2x/llfw/board_io.S62
-rw-r--r--board-js2x/llfw/hw.c124
-rw-r--r--board-js2x/llfw/stage2.c271
-rw-r--r--board-js2x/llfw/stage2.h23
-rw-r--r--board-js2x/llfw/stage2.lds56
-rw-r--r--board-js2x/llfw/stage2_head.S91
-rw-r--r--board-js2x/llfw/stage_s.S43
-rw-r--r--board-js2x/llfw/stage_s.lds34
-rw-r--r--board-js2x/llfw/startup.S708
-rw-r--r--board-js2x/llfw/u4mem.c4071
-rw-r--r--board-js2x/romfs/boot_rom.ffs23
-rw-r--r--board-js2x/romfs/boot_rom_bimini.ffs23
-rw-r--r--board-js2x/rtas/Makefile89
-rw-r--r--board-js2x/rtas/rtas_board.c215
-rw-r--r--board-js2x/rtas/rtas_board.h45
-rw-r--r--board-js2x/rtas/rtas_flash.c613
-rw-r--r--board-js2x/rtas/rtas_flash.h18
-rw-r--r--board-js2x/rtas/rtas_i2c_bmc.h27
-rw-r--r--board-js2x/rtas/rtas_ipmi_bmc.h21
-rw-r--r--board-js2x/rtas/rtas_out.c114
-rw-r--r--board-js2x/rtas/rtas_pci.c111
-rw-r--r--board-js2x/rtas/rtas_table.c47
-rw-r--r--board-js2x/slof/Makefile106
-rw-r--r--board-js2x/slof/OF.fs580
-rw-r--r--board-js2x/slof/attu.fs126
-rw-r--r--board-js2x/slof/citrine-disk.fs79
-rw-r--r--board-js2x/slof/citrine-flash.fs36
-rw-r--r--board-js2x/slof/citrine.fs242
-rw-r--r--board-js2x/slof/copyright-oss.fs16
-rw-r--r--board-js2x/slof/cpu.fs59
-rw-r--r--board-js2x/slof/dart.fs32
-rw-r--r--board-js2x/slof/flash.fs43
-rw-r--r--board-js2x/slof/freq.fs25
-rw-r--r--board-js2x/slof/header.fs21
-rw-r--r--board-js2x/slof/helper.fs17
-rw-r--r--board-js2x/slof/ht.fs291
-rw-r--r--board-js2x/slof/i2c.fs77
-rw-r--r--board-js2x/slof/io.fs45
-rw-r--r--board-js2x/slof/ioapic.fs36
-rw-r--r--board-js2x/slof/ipmi-kcs.fs57
-rw-r--r--board-js2x/slof/ipmi-vpd.fs98
-rw-r--r--board-js2x/slof/memory.fs50
-rw-r--r--board-js2x/slof/mpic.fs37
-rw-r--r--board-js2x/slof/pci-aliases.fs85
-rw-r--r--board-js2x/slof/pci-bridge_1022_7460.fs153
-rw-r--r--board-js2x/slof/pci-capabilities.fs23
-rw-r--r--board-js2x/slof/pci-class_03.fs51
-rw-r--r--board-js2x/slof/pci-device_1002_515e.fs497
-rw-r--r--board-js2x/slof/pci-device_1014_028c.fs25
-rw-r--r--board-js2x/slof/pci-device_1014_02bd.fs24
-rw-r--r--board-js2x/slof/pci-device_1022_7451.fs129
-rw-r--r--board-js2x/slof/pci-device_1022_7468.fs50
-rw-r--r--board-js2x/slof/pci-device_1022_7469.fs23
-rw-r--r--board-js2x/slof/pci-interrupts.fs235
-rw-r--r--board-js2x/slof/rtas.fs236
-rw-r--r--board-js2x/slof/rtc.fs59
-rw-r--r--board-js2x/slof/serial.fs51
-rw-r--r--board-js2x/slof/sio.fs74
-rw-r--r--board-js2x/slof/tpm.fs63
-rw-r--r--board-js2x/slof/tree.fs194
-rw-r--r--board-js2x/slof/u4-mem.fs313
-rw-r--r--board-js2x/slof/vga-display.fs215
-rw-r--r--clients/Makefile29
-rw-r--r--clients/clients.mk13
-rw-r--r--clients/net-snk/Makefile57
-rw-r--r--clients/net-snk/app/Makefile44
-rw-r--r--clients/net-snk/app/main.c65
-rw-r--r--clients/net-snk/app/netapps/Makefile29
-rw-r--r--clients/net-snk/app/netapps/args.c142
-rw-r--r--clients/net-snk/app/netapps/args.h22
-rw-r--r--clients/net-snk/app/netapps/netapps.h19
-rw-r--r--clients/net-snk/app/netapps/netboot.c502
-rw-r--r--clients/net-snk/app/netapps/netflash.c190
-rw-r--r--clients/net-snk/app/netapps/ping.c198
-rw-r--r--clients/net-snk/app/netlib/Makefile31
-rw-r--r--clients/net-snk/app/netlib/arp.c231
-rw-r--r--clients/net-snk/app/netlib/arp.h20
-rw-r--r--clients/net-snk/app/netlib/bootp.c254
-rw-r--r--clients/net-snk/app/netlib/dhcp.c1049
-rw-r--r--clients/net-snk/app/netlib/dhcp.h14
-rw-r--r--clients/net-snk/app/netlib/dns.c522
-rw-r--r--clients/net-snk/app/netlib/dns.h21
-rw-r--r--clients/net-snk/app/netlib/icmp.c98
-rw-r--r--clients/net-snk/app/netlib/icmp.h75
-rw-r--r--clients/net-snk/app/netlib/netbase.c451
-rw-r--r--clients/net-snk/app/netlib/netbase.h138
-rw-r--r--clients/net-snk/app/netlib/netlib.h146
-rw-r--r--clients/net-snk/app/netlib/tftp.c658
-rw-r--r--clients/net-snk/client.lds51
-rw-r--r--clients/net-snk/include/crt0.h20
-rw-r--r--clients/net-snk/include/endian.h46
-rw-r--r--clients/net-snk/include/fcntl.h25
-rw-r--r--clients/net-snk/include/ioctl.h19
-rw-r--r--clients/net-snk/include/kernel.h32
-rw-r--r--clients/net-snk/include/macros.h72
-rw-r--r--clients/net-snk/include/net.h30
-rw-r--r--clients/net-snk/include/netdriver_int.h119
-rw-r--r--clients/net-snk/include/of.h56
-rw-r--r--clients/net-snk/include/pci.h26
-rw-r--r--clients/net-snk/include/rtas.h45
-rw-r--r--clients/net-snk/include/socket.h25
-rw-r--r--clients/net-snk/include/sys/socket.h28
-rw-r--r--clients/net-snk/include/systemcall.h148
-rw-r--r--clients/net-snk/include/time.h36
-rw-r--r--clients/net-snk/include/types.h34
-rw-r--r--clients/net-snk/kernel/Makefile43
-rw-r--r--clients/net-snk/kernel/crt0.c74
-rw-r--r--clients/net-snk/kernel/driver/Makefile40
-rw-r--r--clients/net-snk/kernel/driver/net/Makefile38
-rw-r--r--clients/net-snk/kernel/driver/net/netmodule.c138
-rw-r--r--clients/net-snk/kernel/driver/net_support.c534
-rw-r--r--clients/net-snk/kernel/endian.c30
-rw-r--r--clients/net-snk/kernel/entry.S167
-rw-r--r--clients/net-snk/kernel/init.c175
-rw-r--r--clients/net-snk/kernel/lowmem.S186
-rw-r--r--clients/net-snk/kernel/systemcall.c171
-rw-r--r--clients/net-snk/kernel/timer.c67
-rw-r--r--clients/net-snk/libc/Makefile48
-rw-r--r--clients/net-snk/libc/io.c53
-rw-r--r--clients/net-snk/libc/ioctl.c20
-rw-r--r--clients/net-snk/libc/sbrk.c37
-rw-r--r--clients/net-snk/libc/socket/Makefile41
-rw-r--r--clients/net-snk/libc/socket/send.c36
-rw-r--r--clients/net-snk/libc/time/Makefile43
-rw-r--r--clients/net-snk/libc/time/ftime.c38
-rw-r--r--clients/net-snk/libc/time/timer.c39
-rw-r--r--clients/net-snk/make.depend36
-rw-r--r--clients/net-snk/make.rules43
-rw-r--r--clients/net-snk/oflib/Makefile41
-rw-r--r--clients/net-snk/oflib/entry.S37
-rw-r--r--clients/net-snk/oflib/of.c357
-rw-r--r--clients/net-snk/oflib/pci.c97
-rw-r--r--clients/net-snk/oflib/rtas.c334
-rw-r--r--clients/net-snk/sec-client.lds50
-rw-r--r--clients/takeover/Makefile60
-rw-r--r--clients/takeover/client.lds60
-rw-r--r--clients/takeover/entry.S93
-rw-r--r--clients/takeover/main.c157
-rw-r--r--clients/takeover/ppc32wrap.S30
-rw-r--r--clients/takeover/takeover.h23
-rw-r--r--include/calculatecrc.h66
-rw-r--r--include/macros.h58
-rw-r--r--include/memmap.h26
-rw-r--r--include/pcd.h58
-rw-r--r--include/ppc970/cpu.h101
-rw-r--r--include/romfs.h60
-rw-r--r--include/rtas.h42
-rw-r--r--include/rtas_table.h32
-rw-r--r--include/termctrl.h62
-rw-r--r--include/types.h26
-rw-r--r--include/xvect.h21
-rw-r--r--lib/Makefile34
-rw-r--r--lib/libbases/Makefile42
-rw-r--r--lib/libbases/libbases.code42
-rw-r--r--lib/libbases/libbases.in17
-rw-r--r--lib/libbootmsg/Makefile59
-rw-r--r--lib/libbootmsg/bootmsg.code53
-rw-r--r--lib/libbootmsg/bootmsg.in18
-rw-r--r--lib/libbootmsg/bootmsg_lvl.S210
-rw-r--r--lib/libbootmsg/libbootmsg.h20
-rw-r--r--lib/libc/Makefile60
-rw-r--r--lib/libc/README.txt49
-rw-r--r--lib/libc/ctype/Makefile.inc20
-rw-r--r--lib/libc/ctype/isdigit.c25
-rw-r--r--lib/libc/ctype/isspace.c29
-rw-r--r--lib/libc/ctype/isxdigit.c21
-rw-r--r--lib/libc/ctype/tolower.c18
-rw-r--r--lib/libc/ctype/toupper.c21
-rw-r--r--lib/libc/include/ctype.h23
-rw-r--r--lib/libc/include/errno.h34
-rw-r--r--lib/libc/include/limits.h32
-rw-r--r--lib/libc/include/stdarg.h22
-rw-r--r--lib/libc/include/stddef.h25
-rw-r--r--lib/libc/include/stdint.h28
-rw-r--r--lib/libc/include/stdio.h63
-rw-r--r--lib/libc/include/stdlib.h31
-rw-r--r--lib/libc/include/string.h36
-rw-r--r--lib/libc/include/unistd.h26
-rw-r--r--lib/libc/stdio/Makefile.inc23
-rw-r--r--lib/libc/stdio/fileno.c19
-rw-r--r--lib/libc/stdio/fprintf.c26
-rw-r--r--lib/libc/stdio/fscanf.c26
-rw-r--r--lib/libc/stdio/printf.c27
-rw-r--r--lib/libc/stdio/putc.c25
-rw-r--r--lib/libc/stdio/putchar.c21
-rw-r--r--lib/libc/stdio/puts.c28
-rw-r--r--lib/libc/stdio/scanf.c26
-rw-r--r--lib/libc/stdio/setvbuf.c28
-rw-r--r--lib/libc/stdio/sprintf.c30
-rw-r--r--lib/libc/stdio/stdchnls.c23
-rw-r--r--lib/libc/stdio/vfprintf.c27
-rw-r--r--lib/libc/stdio/vfscanf.c256
-rw-r--r--lib/libc/stdio/vsnprintf.c242
-rw-r--r--lib/libc/stdio/vsprintf.c19
-rw-r--r--lib/libc/stdio/vsscanf.c131
-rw-r--r--lib/libc/stdlib/Makefile.inc22
-rw-r--r--lib/libc/stdlib/error.c15
-rw-r--r--lib/libc/stdlib/free.c26
-rw-r--r--lib/libc/stdlib/malloc.c157
-rw-r--r--lib/libc/stdlib/malloc_defs.h16
-rw-r--r--lib/libc/stdlib/memalign.c26
-rw-r--r--lib/libc/stdlib/rand.c24
-rw-r--r--lib/libc/stdlib/realloc.c40
-rw-r--r--lib/libc/stdlib/strtol.c114
-rw-r--r--lib/libc/stdlib/strtoul.c103
-rw-r--r--lib/libc/string/Makefile.inc22
-rw-r--r--lib/libc/string/memchr.c29
-rw-r--r--lib/libc/string/memcmp.c30
-rw-r--r--lib/libc/string/memcpy.c27
-rw-r--r--lib/libc/string/memmove.c42
-rw-r--r--lib/libc/string/memset.c25
-rw-r--r--lib/libc/string/strcasecmp.c28
-rw-r--r--lib/libc/string/strcat.c24
-rw-r--r--lib/libc/string/strchr.c28
-rw-r--r--lib/libc/string/strcmp.c28
-rw-r--r--lib/libc/string/strcpy.c25
-rw-r--r--lib/libc/string/strlen.c27
-rw-r--r--lib/libc/string/strncasecmp.c32
-rw-r--r--lib/libc/string/strncmp.c31
-rw-r--r--lib/libc/string/strncpy.c33
-rw-r--r--lib/libc/string/strstr.c37
-rw-r--r--lib/libipmi/Makefile28
-rw-r--r--lib/libipmi/libipmi.code105
-rw-r--r--lib/libipmi/libipmi.h32
-rw-r--r--lib/libipmi/libipmi.in23
-rw-r--r--llfw/boot_abort.S95
-rw-r--r--llfw/boot_abort.h37
-rw-r--r--llfw/clib/Makefile.inc42
-rw-r--r--llfw/clib/iolib.c65
-rw-r--r--llfw/clib/iolib.h42
-rw-r--r--llfw/clib/types.h27
-rw-r--r--llfw/io_generic/Makefile.inc38
-rw-r--r--llfw/io_generic/io_generic.S129
-rw-r--r--llfw/nvramlog.S340
-rw-r--r--llfw/romfs.S362
-rw-r--r--llfw/romfs_wrap.c22
-rw-r--r--make.rules41
-rw-r--r--other-licence/Makefile26
-rw-r--r--other-licence/bcm/Makefile57
-rw-r--r--other-licence/bcm/bcm57xx.c3410
-rw-r--r--other-licence/bcm/bcm57xx.h296
-rw-r--r--other-licence/bcm/types.h26
-rw-r--r--other-licence/common/Makefile45
-rw-r--r--other-licence/common/module.lds39
-rw-r--r--other-licence/common/module_entry.c59
-rw-r--r--other-licence/common/netdriver_int.h119
-rw-r--r--romfs/header.img1
-rw-r--r--romfs/tools/Makefile45
-rw-r--r--romfs/tools/build_ffs.c370
-rw-r--r--romfs/tools/cfg_parse.c383
-rw-r--r--romfs/tools/cfgparse.h42
-rw-r--r--romfs/tools/create_crc.c483
-rw-r--r--romfs/tools/create_flash.c87
-rw-r--r--romfs/tools/createcrc.h18
-rw-r--r--rtas/Makefile.inc89
-rw-r--r--rtas/flash/block_lists.c274
-rw-r--r--rtas/flash/block_lists.h23
-rw-r--r--rtas/reloc.S183
-rw-r--r--rtas/rtas.lds49
-rw-r--r--rtas/rtas_call.c89
-rw-r--r--rtas/rtas_common.S87
-rw-r--r--rtas/rtas_entry.S72
-rw-r--r--slof/Makefile.inc161
-rw-r--r--slof/OF.lds71
-rw-r--r--slof/default-font.c1653
-rw-r--r--slof/engine.in165
-rw-r--r--slof/entry.S230
-rw-r--r--slof/fs/accept.fs352
-rw-r--r--slof/fs/alloc-mem.fs86
-rw-r--r--slof/fs/available.fs72
-rw-r--r--slof/fs/banner.fs23
-rw-r--r--slof/fs/base.fs504
-rw-r--r--slof/fs/boot.fs247
-rw-r--r--slof/fs/bootmsg.fs74
-rw-r--r--slof/fs/claim.fs403
-rw-r--r--slof/fs/client.fs195
-rw-r--r--slof/fs/debug.fs346
-rw-r--r--slof/fs/devices/pci-class_02.fs35
-rw-r--r--slof/fs/devices/pci-class_0c.fs39
-rw-r--r--slof/fs/devices/pci-device_10de_0141.fs49
-rw-r--r--slof/fs/dictionary.fs74
-rw-r--r--slof/fs/display.fs124
-rw-r--r--slof/fs/dump.fs62
-rw-r--r--slof/fs/elf.fs181
-rw-r--r--slof/fs/envvar.fs401
-rw-r--r--slof/fs/exception.fs154
-rw-r--r--slof/fs/fbuffer.fs178
-rw-r--r--slof/fs/fcode/1275.fs353
-rw-r--r--slof/fs/fcode/big.fs45
-rw-r--r--slof/fs/fcode/core.fs169
-rw-r--r--slof/fs/fcode/evaluator.fs99
-rw-r--r--slof/fs/fcode/tokens.fs411
-rw-r--r--slof/fs/find-hash.fs37
-rw-r--r--slof/fs/generic-disk.fs68
-rw-r--r--slof/fs/ide.fs671
-rw-r--r--slof/fs/instance.fs168
-rw-r--r--slof/fs/little-endian.fs72
-rw-r--r--slof/fs/loaders.fs71
-rw-r--r--slof/fs/logging.fs41
-rw-r--r--slof/fs/node.fs663
-rw-r--r--slof/fs/nvram.fs259
-rw-r--r--slof/fs/packages.fs62
-rw-r--r--slof/fs/packages/bulk.fs87
-rw-r--r--slof/fs/packages/deblocker.fs61
-rw-r--r--slof/fs/packages/disk-label.fs265
-rw-r--r--slof/fs/packages/ext2-files.fs140
-rw-r--r--slof/fs/packages/fat-files.fs187
-rw-r--r--slof/fs/packages/filler.fs21
-rw-r--r--slof/fs/packages/iso-9660.fs307
-rw-r--r--slof/fs/packages/obp-tftp.fs55
-rw-r--r--slof/fs/packages/rom-files.fs85
-rw-r--r--slof/fs/packages/scsi.fs183
-rw-r--r--slof/fs/packages/sms.fs34
-rw-r--r--slof/fs/pci-bridge.fs62
-rw-r--r--slof/fs/pci-class-code-names.fs263
-rw-r--r--slof/fs/pci-config-bridge.fs85
-rw-r--r--slof/fs/pci-device.fs101
-rw-r--r--slof/fs/pci-properties.fs650
-rw-r--r--slof/fs/pci-scan.fs494
-rw-r--r--slof/fs/preprocessor.fs41
-rw-r--r--slof/fs/property.fs196
-rw-r--r--slof/fs/quiesce.fs48
-rw-r--r--slof/fs/rmove.fs53
-rw-r--r--slof/fs/romfs.fs123
-rw-r--r--slof/fs/root.fs57
-rw-r--r--slof/fs/rtas/rtas-cpu.fs39
-rw-r--r--slof/fs/rtas/rtas-flash.fs46
-rw-r--r--slof/fs/rtas/rtas-init.fs121
-rw-r--r--slof/fs/rtas/rtas-reboot.fs33
-rw-r--r--slof/fs/rtas/rtas-vpd.fs33
-rw-r--r--slof/fs/search.fs78
-rw-r--r--slof/fs/sms/sms-load.fs50
-rw-r--r--slof/fs/stack.fs57
-rw-r--r--slof/fs/start-up.fs85
-rw-r--r--slof/fs/term-io.fs57
-rw-r--r--slof/fs/terminal.fs196
-rw-r--r--slof/fs/timebase.fs19
-rw-r--r--slof/fs/translate.fs152
-rw-r--r--slof/fs/update_flash.fs101
-rw-r--r--slof/fs/usb/usb-enumerate.fs257
-rw-r--r--slof/fs/usb/usb-hub.fs468
-rw-r--r--slof/fs/usb/usb-kbd-device-support.fs105
-rw-r--r--slof/fs/usb/usb-keyboard.fs345
-rw-r--r--slof/fs/usb/usb-mouse.fs26
-rw-r--r--slof/fs/usb/usb-ohci.fs1109
-rw-r--r--slof/fs/usb/usb-static.fs85
-rw-r--r--slof/fs/usb/usb-storage-support.fs222
-rw-r--r--slof/fs/usb/usb-storage-wrapper.fs181
-rw-r--r--slof/fs/usb/usb-storage.fs464
-rw-r--r--slof/fs/usb/usb-support.fs628
-rw-r--r--slof/fs/vpd-bootlist.fs83
-rw-r--r--slof/lowmem.S67
-rw-r--r--slof/ofw.S182
-rw-r--r--slof/paflof.c47
-rw-r--r--slof/paflof.h57
-rw-r--r--slof/ppc64.c39
-rw-r--r--slof/ppc64.code166
-rw-r--r--slof/ppc64.h58
-rw-r--r--slof/ppc64.in71
-rw-r--r--slof/prep.h27
-rw-r--r--slof/prim.code218
-rw-r--r--slof/prim.in38
-rw-r--r--slof/ref.pl66
-rw-r--r--slof/types.h26
-rw-r--r--tools/Makefile33
-rwxr-xr-xtools/create_reloc_table.sh60
-rw-r--r--tools/gen_reloc_table.c95
384 files changed, 50279 insertions, 2001 deletions
diff --git a/.target b/.target
new file mode 100644
index 0000000..5356a3d
--- /dev/null
+++ b/.target
@@ -0,0 +1 @@
+js2x
diff --git a/FlashingSLOF.pdf b/FlashingSLOF.pdf
new file mode 100644
index 0000000..8e6e5b3
--- /dev/null
+++ b/FlashingSLOF.pdf
Binary files differ
diff --git a/INSTALL b/INSTALL
index 2e8c7f5..8adb27a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,228 +1,84 @@
-Slimline Open Firmware for JS20
+Slimline Open Firmware - SLOF
-Copyright (C) 2005, IBM Corporation
+Copyright (C) 2005, 2007 IBM Corporation
-In order to use SLOF, there are certain requirements on the build and
-target system.
+BUILD
+===============================================================================
- Target system:
+ To build SLOF you need:
+ - Recent GNU tools, configured for powerpc64-linux
+ - GCC: 3.3.3 and newer are known to work
+ - Binutils: use a version as new as possible
- - IBM BladeCenter JS20 1.6GHz or 2.2GHz machine
- - MAKE SURE you have the latest firmware revision
- installed, ALSO on the permanent side of the flash!
- - Linux 2.6.10 or newer
- - Older versions will not run correctly.
- - An example configuration file is provided.
- - ppc64-utils installed
- - Suitable Low Level Firmware. See BUILD for requirements.
+ - set the CROSS variable
+ - something like export CROSS="powerpc64-unknown-linux-gnu-"
+ when using a cross compiler
+ or
+ - export CROSS=""
+ when using a native compiler
- - Specific configuration
- - The blade server needs to have an ATA harddisk
- installed on the first connector; the disk needs
- to be partitioned with a PReP boot partition as
- the first physical partition on the system, i.e.,
- starting at sector 63. The root partition of your
- Linux system should be /dev/hda3. For example:
+ - four more files to build a bootable image:
+ - libipmi.oco
+ - takeover.oco
+ - i2c_bmc.oco
+ - ipmi_oem.oco
+ these files are also provided through developerworks and have to be
+ also downloaded just like the SLOF source code
- Disk /dev/hda: 16 heads, 63 sectors, 77520 cylinders
- Units = cylinders of 1008 * 512 bytes
-
- Device Boot Start End Blocks Id System
- /dev/hda1 * 1 7 3496+ 41 PPC PReP Boot
- /dev/hda2 8 2088 1048824 82 Linux swap
- /dev/hda3 2089 77520 38017728 83 Linux
-
- Build system:
-
- - Recent GNU tools, configured for powerpc64-linux
- - GCC: 3.3.3 and newer are known to work, but GCC 4.0
- and later do _not_ work.
- - Binutils: use a version as new as possible.
+ - make js2x
+INSTALL
+===============================================================================
-BUILD
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Detailed information about how to use SLOF on JS20 and JS21 can be found in
+ the document FlashingSLOF.pdf
- On the build system:
+ The JS20 and JS21 blades both have 2 "flashsides". They have a 8MB flash part
+ which is divided into a 4MB "temporary" side and a 4MB "permanent" side.
- - Edit the Makefile or set CROSS and/or CC in the environment to
- the right path to the tools, if the default tools do not satisfy
- the requirements mentioned above.
-
- - Two more files are required to build a boot-able image:
- + startup.o: Low Level Firmware
- + oco.o: Contains functions for reboot, halt, boot watchdog
- and other board specific functions.
- There is a description in the README file, how to implement your
- own board specific oco.o and startup.o.
- This files might be provided for test purposes on a JS20 board
- from a website which have to be defined.
+ The temporary side is the flashside used for the normal operation and the
+ permanent side is used as a backup if the temporary should ever fail.
- - make
+ Therefore it is important that the permanent flash side is not changed so
+ that if ever required the original firmware can be restored.
+ SLOF usually warns or in most cases does not easily allow to overwrite the
+ permanent side.
-INSTALL
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- Read [1] and [2] for documentation of flash handling and console support.
- The convention in this section for the commands to issue are:
- - 0 > : Firmware prompt
- - $ : Linux prompt
- - boot: : yaboot prompt
-
- On the target system:
-
- - make sure you are using the latest IBM provided firmware updates.
- This can be done on Linux by issuing
-
- $ cat /proc/device-tree/openprom/ibm,fw-temp-bank
- $ cat /proc/device-tree/openprom/ibm,fw-perm-bank
- $ cat /proc/device-tree/openprom/ibm,fw-bank
-
- The temp and perm bank should the same and the fw-bank need
- to be 'T'.
- If not, read the User's guide [1] how to achieve this state and see (1).
- This point is very important, since you might end with a broken
- firmware on the PERM side and SLOF on the TEMP side and no way
- to restore ther PERM side, since SLOF provides no flashing capability.
-
- - install a recent kernel (as discribed above) into /boot; a sample
- .config is included as linux.config.js20 in the SLOF distribution.
-
- To build a reference kernel boot-able with slof, download a kernel
- source tree from http://www.kernel.org/ and copy the linux.config.js20
- to the unpacked kernel source tree as .config as shown here:
-
- cp linux.config.js20 /usr/src/linux-2.6.XX/.config
- (NOTE: You have to set the right path to your kernel sources and
- the right revision number)
-
- Then compile the kernel as described in Linux Kernel Documentation
- and install it on a primary partition on the first hard drive.
-
- - change /etc/yaboot.conf appropriately
- The default yaboot.conf contains Open Firmware paths that can not be
- interpreted correctly by SLOF, so you have to make changes in
- /etc/yaboot.conf.
-
- Example:
- # header section
- timeout = 100 # set boot timeout to 10 seconds
- default = linux # set default bootimage to linux
-
- # image section
- image = disk:3,/boot/vmlinux # Specify correct kernel image here
- # as disk:(partno),(path)
- label = linux # Name of image
- root = /dev/hda3 # Set root device
- append = "selinux=0 elevator=cfq" # Kernel command line
- initrd = disk:3,/boot/initrd # Initrd if needed
-
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ! !
+ ! !
! WITH THE FOLLOWING STEPS YOU MIGHT DESTROY YOUR FIRMWARE !
- ! IMAGE AND LOOSE YOUR WARRANTY ! !
+ ! IMAGE AND LOOSE YOUR WARRANTY ! !
! YOU MAY NEED TO CALL SERVICE, IF THE FIRMWARE IMAGE IS !
! DESTROYED ! !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- $ update_flash -f slof.img
-
- This will put SLOF on the temp side of the flash and reboot the
- system to the firmware boot prompt. You will need to use a console
- connection (like, serial-over-lan) to interact with SLOF or yaboot.
-
- - After power up or reset, SLOF prints out a startup message and then
- enters the firmware prompt. Here you have to enter
-
- yaboot
-
- to start the secondary bootloader yaboot.
- (NOTE: SLOF does not start yaboot automatically due to lack of NVRAM
- support.)
-
- - On the SOL console (see [2]):
-
- 0 > boot
-
- otherwise type
-
- 0 > set-bootpart <partn>
- 0 > boot
-
- where <partn> is the number of the partition, yaboot.conf resides on.
+UNINSTALL
+===============================================================================
- - On yaboot prompt choose the right kernel
-
- boot: linux-slof
-
- - have a lot of fun...
-
- SLOF is a slimline Open Firmware and provides only a minimalistic
- device-tree and has no RTAS support. For example, you cannot
- check the flash-side or use update flash or reboot the system.
-
-Trouble-shooting
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- - update_flash does not end at the boot prompt
- -> It may take a couple minutes, if for some reason
- the SLOF image has a problem. In this case, the
- boot timer will start from the PERM side.
-
- $ update_flash -r
-
- will restore your system to the initial state. see (1)
-
- - boot does start yaboot, but does not find the config file.
- -> on the console type after yaboot / firmware prompt.
- boot: bye
- 0 > set-bootpart <partn>
-
- - Linux does not boot
- -> Compile the right kernel
- Reboot the blade
- 0 > other-firmware
-
- This will boot into the original firmware and OS
- In Linux start over again (building linux kernel, etc. ) see (1)
-
- Pull out blade out of the blade center to force the
- blade to boot from the TEMP side again
-
-Uninstall
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-If you want to boot the original firmware again, you need to
-boot the blade from the management module.
-On the SLOF command line, type:
+ If you want to boot the original firmware again, you need to boot the blade
+ from the management module. If auto-boot is enabled you have to press "s"
+ to reach the firmware prompt.
+ On the SLOF command line, type:
0 > other-firmware
-and it should get you back to running the original firmware.
-To permanently get it back, after booting Linux from there,
-type
+ and it should get you back to running the original firmware. To permanently
+ get it back, after booting Linux from there, type
$ update_flash -r
$ halt
-
-(1) You will boot on the PERM side. To boot from the TEMP side
- again, you need to restart the Blade System MGMT Processor.
-
- Following steps are needed on
- Management Module -> Blade Tasks -> Power/Restart
-
- Power Off Blade
- Restart Blade System Mgmt Processor
- Power On Blade
-
-Documentation
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-[1] Installation and User's Guide - IBM eServer BladeCenter JS20 :
-
-[2] IBM eServer BladeCenter JS20 quick set up guide : http://www-128.ibm.com/developerworks/linux/library/l-pow-js20quickstart/
+
+ You will boot on the PERM side. To boot from the TEMP side again, you need to
+ restart the Blade System MGMT Processor.
+
+ Following steps are needed on
+ Management Module -> Blade Tasks -> Power/Restart
+
+ Power Off Blade
+ Restart Blade System Mgmt Processor
+ Power On Blade
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..70896eb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,8 @@
+Copyright (c) 2004, 2007 IBM Corporation
+All rights reserved.
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+Neither the name of IBM nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
index ff967f5..fee1108 100644
--- a/Makefile
+++ b/Makefile
@@ -1,65 +1,124 @@
-# =============================================================================
-# * Copyright (c) 2004, 2005 IBM Corporation
-# * All rights reserved.
-# * This program and the accompanying materials
-# * are made available under the terms of the BSD License
-# * which accompanies this distribution, and is available at
-# * http://www.opensource.org/licenses/bsd-license.php
-# *
-# * Contributors:
-# * IBM Corporation - initial implementation
-# =============================================================================
-
-
-CROSS ?= powerpc64-linux-
-
-ifeq ($(origin CC), default)
- CC = $(CROSS)gcc
-endif
-ifeq ($(origin LD), default)
- LD = $(CROSS)ld
-endif
-OBJCOPY ?= $(CROSS)objcopy
-
-TARG = ppc64
-
-CFLAGS = -g -DTARG=$(TARG) -static -Wall -W -std=gnu99 -O2 -fno-gcse \
- -fno-crossjumping -fomit-frame-pointer -mcpu=970 -msoft-float
-LDFLAGS = -g -static -nostdlib
-
-DICT = prim.in engine.in $(TARG).in
-
-all: slof.img
-
-%.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@ && $(OBJCOPY) -R .note.GNU-stack $@
-
-dict.xt: $(DICT) ref.pl
- cat $(DICT) | perl ref.pl > dict.xt
-
-$(TARG).fs: fs/*.fs
- perl incs.pl main.fs > $@ || rm $@
-
-$(TARG).o: $(TARG).fs
- $(LD) -o $@ -r -bbinary $<
-
-payload-obj.o: payload
- $(LD) -o $@ -r -bbinary $<
-
-paflof.o: paflof.c prim.h prim.code $(TARG).h $(TARG).code dict.xt
-
-paflof: paflof.lds paflof.o entry.o oco.o payload-obj.o $(TARG).o
- $(LD) $(LDFLAGS) -T $^ -o $@
-
-slof: slof.lds startup.o loader.o paflof
- $(LD) -T $^ -o $@
-
-slof.bin: slof
- $(OBJCOPY) $< $@ -O binary
-
-slof.img: slof.bin
- ./package-firmware -l $^ -o $@
-
-clean:
- -rm -f paflof.o entry.o loader.o payload-obj.o $(TARG).fs $(TARG).o \
- dict.xt paflof slof slof.bin slof.img
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include make.rules
+
+STD_BOARDS = $(shell targets=""; \
+ for a in `echo board-*`; do \
+ if [ -e $$a/config ]; then \
+ targets="$$targets $$a"; \
+ else \
+ cd $$a; \
+ for b in `echo config* | sed -e s/config.//g`; do \
+ if [ "X$$b" != "Xsimics" ]; then \
+ if [ "X$$b" != "X`echo $$a|sed -e s/board-//g`" ]; then \
+ targets="$$targets $$a-$$b"; \
+ else \
+ targets="$$targets $$b"; \
+ fi fi \
+ done; \
+ cd ..; \
+ fi; \
+ done; \
+ echo $$targets | sed -e s/board-//g)
+
+all:
+ @if [ ! -f .target ]; then \
+ echo "Please specify a build target:"; \
+ echo " $(STD_BOARDS)"; \
+ exit 1; \
+ fi
+ @make `cat .target`
+
+rom:
+ @echo "******* Build $(BOARD) System ********"
+ @echo $(BOARD) > .target
+ @make -C board-$(BOARD)
+ @$(RM) -f .crc_flash
+rw:
+ @echo "******* Build $(BOARD) system (RISCWatch boot) ********"
+ @echo $(BOARD) > .target
+ @make -C board-$(BOARD) l2b
+ @$(RM) -f .crc_flash
+
+$(STD_BOARDS):
+ @echo "******** Building $@ system ********"
+ @if [ -f .target ]; then \
+ if [ `cat .target` != $@ ]; then \
+ echo "Configuration changed - cleaning up first..."; \
+ make distclean; \
+ echo $@ > .target; \
+ fi; \
+ else \
+ echo $@ > .target; \
+ fi
+ @b=`echo $@ | grep "-"`; \
+ if [ -n "$$b" ]; then \
+ subboard=$${b##*-}; \
+ board=$${b%%-*}; \
+ make -C board-$$board SUBBOARD=$$subboard; \
+ else \
+ make -C board-$@; \
+ fi
+ @$(RM) .crc_flash
+
+test_all:
+ @for i in $(STD_BOARDS); do make distclean $$i; done
+
+driver:
+ DRIVER=1 make -C board-$(BOARD) driver
+ @$(RM) -f .crc_flash .boot_xdr.ffs
+cli:
+ make -C clients
+
+# Rules for making clean:
+clean_here:
+ rm -f boot_rom.bin .boot_rom.ffs boot_xdr.bin .boot_xdr.ffs
+ rm -f boot_l2-dd2.ad boot_l2b.bin .crc_flash
+
+
+clean: clean_here
+ @if [ -e .target ]; then \
+ tar=`cat .target`; \
+ b=`echo $$tar | grep "-"`; \
+ if [ -n "$$b" ]; then \
+ subboard=$${b##*-}; \
+ board=$${b%%-*}; \
+ make -C board-$$board SUBBOARD=$$subboard clean; \
+ else \
+ pwd; \
+ make -C board-$$tar clean; \
+ fi \
+ fi
+
+distclean: clean_here
+ @if [ -e .target ]; then \
+ tar=`cat .target`; \
+ b=`echo $$tar | grep "-"`; \
+ if [ -n "$$b" ]; then \
+ subboard=$${b##*-}; \
+ board=$${b%%-*}; \
+ make -C board-$$board SUBBOARD=$$subboard distclean; \
+ else \
+ make -C board-$$tar distclean; \
+ fi; \
+ rm -f .target; \
+ fi
+
+distclean_all: clean_here
+ @for dir in board-* ; do \
+ $(MAKE) -C $$dir distclean || exit 1; \
+ done
+ rm -f .target
+
+cli-clean:
+ make -C clients clean
diff --git a/Makefile.gen b/Makefile.gen
new file mode 100644
index 0000000..ba6edc3
--- /dev/null
+++ b/Makefile.gen
@@ -0,0 +1,160 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+MAKEARG = BOARD=$(BOARD) PLATFORM=$(PLATFORM) FLAG=$(FLAG) TARG=$(TARG)
+
+BUILDS = tools_build romfs_build
+
+include ../make.rules
+
+ifdef DRIVER
+RELEASE=$(shell cat ../VERSION)
+export DRIVER_NAME=$(shell cat ../VERSION | sed -e "s/-/./g" | awk -F . '{ printf("%s%02x%02x%1x%02x",$$1,$$2,$$3,$$4,$$5); }')
+else
+RELEASE="$(USER)@$(HOSTNAME)(private build)"
+export DRIVER_NAME=HEAD
+endif
+
+DRVDATE=$(shell date +%Y-%h%d)
+
+FLASH_SIZE_MB = `echo $$[ $(FLASH_SIZE)/1024/1024 ]`
+
+
+llfw_disassembly:
+ make -C $(LLFWBRDDIR) stage1.dis stage2.dis stageS.dis
+
+clients_build:
+ @echo " ====== Building clients ======"
+ make -C ../clients $(MAKEARG)
+
+other_licence_build:
+ make -C ../other-licence $(MAKEARG)
+
+tools_build:
+ make -C ../tools
+
+romfs_build:
+ make -C ../romfs/tools $(MAKEARG)
+
+../build_info.img:
+ @echo "$(CC)" > ../build_info.img
+ @$(CC) -v >> ../build_info.img 2>&1
+ @$(LD) -V >> ../build_info.img 2>&1
+
+boot_rom.bin: $(BUILDS) ../romfs/copyright.img ../build_info.img
+ @echo " ====== Building $@ ======"
+ @if [ -e $(ROMFSBRDDIR)/boot_rom.$(SUBBOARD).ffs ]; then \
+ cat $(ROMFSBRDDIR)/boot_rom.$(SUBBOARD).ffs > ../.boot_rom.ffs; \
+ else \
+ cat $(ROMFSBRDDIR)/boot_rom.ffs > ../.boot_rom.ffs; \
+ fi
+ cat $(PCDBRDDIR)/pcdfiles.ffs >> ../.boot_rom.ffs
+ cat $(SLOFBRDDIR)/OF.ffs >> ../.boot_rom.ffs
+ @echo build_info.img build_info.img 0 0 >> ../.boot_rom.ffs
+ cd .. && ./romfs/tools/build_romfs .boot_rom.ffs boot_rom.bin
+ cd .. && if [ -f boot_rom.bin.gz ]; then rm -f boot_rom.bin.gz; gzip -9 boot_rom.bin; fi
+ rm -f ../.boot_rom.ffs
+
+boot_xdr.bin: $(BUILDS) ../romfs/copyright.img ../build_info.img
+ @echo " ====== Building $@ ======"
+ @if [ -e $(ROMFSBRDDIR)/boot_rom.$(SUBBOARD).ffs ]; then \
+ cat $(ROMFSBRDDIR)/boot_rom.$(SUBBOARD).ffs > ../.boot_xdr.ffs; \
+ else \
+ cat $(ROMFSBRDDIR)/boot_rom.ffs > ../.boot_xdr.ffs; \
+ fi
+ cat $(PCDBRDDIR)/pcdfiles.ffs >> ../.boot_xdr.ffs
+ @echo build_info.img build_info.img 0 0 >> ../.boot_xdr.ffs
+ cat ./slof/OF.ffs >> ../.boot_xdr.ffs
+ cd .. && ./romfs/tools/build_romfs .boot_xdr.ffs boot_xdr.bin
+ rm -f ../.boot_xdr.ffs
+
+../boot_l2b.bin: $(BUILDS) ../romfs/copyright.img
+ @if [ -e $(ROMFSBRDDIR)/boot_l2.$(SUBBOARD).ffs ]; then \
+ cd .. && ./romfs/tools/build_romfs $(ROMFSBRDDIR)/boot_l2.$(SUBBOARD).ffs boot_l2b.bin; \
+ else \
+ cd .. && ./romfs/tools/build_romfs $(ROMFSBRDDIR)/boot_l2.ffs boot_l2b.bin; \
+ fi
+
+boot_l2-dd2.ad: ../boot_l2b.bin
+ @cd ../tools && ./elf2l2 dd2 ../boot_l2b.bin 0 ../boot_l2-dd2.ad
+
+external_flasher: ../boot_rom.bin
+ ../tools/make-flasher-image.sh $(FLASH_SIZE) ../boot_rom.bin \
+ ../boot_rom-$(FLASH_SIZE_MB)MB-BigEndian.bin
+
+driver_dirs:
+ @rm -rf ../driver-$(RELEASE)
+ @mkdir -p ../driver-$(RELEASE)/{rom,l2b,disassemblies}
+
+driver_prep:
+ @echo "Building driver "$(RELEASE)" for $(BOARD)"
+
+copy_disassemblies: llfw_disassembly
+ cp $(LLFWBRDDIR)/stage1.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-stage1.dis
+ cp $(LLFWBRDDIR)/stage2.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-stage2.dis
+ cp $(LLFWBRDDIR)/stageS.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-stageS.dis
+ cp ../llfw/meminit.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-meminit.dis
+ @if [ -e ../clients/snk/client.dis ]; then cp ../clients/snk/client.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-client.dis; fi
+ @if [ -e ../llfw/meminit_l2b.dis ]; then cp ../llfw/meminit_l2b.dis \
+ ../driver-$(RELEASE)/disassemblies/$(RELEASE)-meminit_l2b.dis; \
+ fi
+
+copy_driver: copy_disassemblies external_flasher
+ mv ../boot_rom-$(FLASH_SIZE_MB)MB-BigEndian.bin \
+ ../driver-$(RELEASE)/rom/$(RELEASE)-boot_rom-$(FLASH_SIZE_MB)MB-BigEndian.bin
+ mv ../boot_rom.bin \
+ ../driver-$(RELEASE)/rom/$(RELEASE)-boot_rom.bin
+ mv ../boot_l2-dd2.ad \
+ ../driver-$(RELEASE)/l2b/
+ mv ../boot_xdr.bin \
+ ../driver-$(RELEASE)/l2b/
+ cp ../VERSION ../driver-$(RELEASE)
+ cd ../driver-$(RELEASE) && md5sum rom/*.bin > md5sum.txt
+
+tar_gz: copy_driver
+ @cp -a ../driver-$(RELEASE) ../driver-$(RELEASE)-$(DRVDATE)-devel
+ tar czf ../driver-$(RELEASE)-$(DRVDATE)-devel.tar.gz \
+ ../driver-$(RELEASE)-$(DRVDATE)-devel > /dev/null 2>&1
+ @rm -rf ../driver-$(RELEASE)-$(DRVDATE)-devel
+ @rm -rf ../driver-$(RELEASE)/disassemblies
+ @mv ../driver-$(RELEASE) ../driver-$(RELEASE)-$(DRVDATE)
+ tar czf ../driver-$(RELEASE)-$(DRVDATE).tar.gz \
+ ../driver-$(RELEASE)-$(DRVDATE) > /dev/null 2>&1
+ @rm -rf ../driver-$(RELEASE)-$(DRVDATE)
+
+clean_top:
+ @rm -f ../build_info.img
+ @rm -f ../.crc_flash
+
+clean_gen: clean_top
+ make -C ../romfs/tools BOARD=$(BOARD) clean
+ make -C ../tools clean
+ make -C ../other-licence clean
+ make -C ../clients clean
+ @for dir in $(COMMON_LIBS); do \
+ $(MAKE) -C ../lib/$$dir clean || exit 1; \
+ done
+
+distclean_gen: clean_top
+ make -C ../romfs/tools BOARD=$(BOARD) distclean
+ make -C ../tools distclean
+ make -C ../other-licence distclean
+ make -C ../clients distclean
+ @for dir in $(COMMON_LIBS); do \
+ $(MAKE) -C ../lib/$$dir distclean || exit 1; \
+ done
diff --git a/README b/README
index fee3f50..eee6e75 100644
--- a/README
+++ b/README
@@ -1,14 +1,12 @@
-Slimline Open Firmware for JS20
+Slimline Open Firmware - SLOF
-Copyright (C) 2004,2005 IBM Corporation
+Copyright (C) 2004, 2007 IBM Corporation
Index
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1.0 Introduction to Open Firmware
-1.1 Slimline Open Firmware
-1.2 Build process
-1.3 Load process
+1.1 Build process
2.0 Extension
3.0 Limitations
@@ -33,55 +31,8 @@ processor Instruction Set Architectures (ISAs) and buses.
The full documentation of this Standard can be found in [1].
-1.1 Overview
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-The Slimline Open Firmware (SLOF) is an implementation of the
-Open Firmware standard. Since the Open Firmware standard is
-quite extensive, the decision was made to keep focus on those
-parts of the standard which are required for booting Linux.
-As of today, it is possible to boot a recent Linux kernel (2.6.10)
-on a JS20 board and on a cell workstation. Booting SLOF on a
-machine requires a hardware-specific Low Level Firmware for
-doing the basic setup of the system which is not part of this
-package. The LLFW package as object code might be provided on
-a separate purposes for test purposes.
-
-The current restrictions and shortcomings regarding the
-Open Firmware Standard are listed here:
-
-+ User Interface
- - Command line editing: only the most basic command line editing
- (enter, backspace) is supported.
- - The assembler support words are not implemented. This is by design.
- - None of the administration group is provided; instead, there are some
- more minimalistic facilities.
- - There is no direct support for debugging client programs.
-+ Client Interface
- - "test" and "canon" are missing.
- - "boot", "enter", and "chain" are missing.
- - "interpret" doesn't actually do anything.
- - "set-callback" and "set-symbol-lookup" are missing.
- - "milliseconds" doesn't use anything resembling a real clock.
-+ Device Interface
- - FCode evaluator is under development and not available so-far.
- - Finding device nodes does not use the proper algorithm; instead, first
- all nodes are tried for an exact match on the full path; if that fails,
- all nodes are tried for an exact match on the short name.
- Arguments to a node are ignored. Nodes do not really have an address.
- - There is no terminal emulator. But then again, there is no graphics
- hardware either.
-
-
-As boot device currently only ATA disk is supported, by using yaboot
-as secondary boot loader. Netboot and USB boot support will not be made
-available and is not part of this package. It is possible to port external
-available secondary boot loader to the PowerPC64 architecture to support
-network boot based on existing Linux device drivers.
-
-
-
-1.2 Build process
+1.1 Build process
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Open Firmware (OF) is based on the programming language Forth.
@@ -136,65 +87,10 @@ Firmware to it's location in memory (see 1.3 Load process). Additionally
a secondary boot loader or any other client application can be bound
to the code as payload.
-The Open Firmware image will be bound together with the Low Level
-Firmware to the final slof.img.
-
The Low Level Firmware (LLFW) is responsible for setting up the
system in an initial state. This task includes the setup of the
CPUs, the system memory and all the buses as well as the serial port
-itself. The current distribution does not contain a LLFW image,
-which is hardware specific and has to be implemented for the each
-board SLOF should run on. Publication of an object code only LLFW
-for the JS20 board might be available in the future.
-
-Firmware image:
-
-0x2000000 +----------+
- | LLFW |
-X +----------+
- | Loader |
-X + 0x100 +----------+
- | Vector |
-X + 0x4100 +----------+
- | |
- | OF code |
- | |
-X + 0x6100 +----------+
- | |
- | OF data |
- | |
- +----------+
-
-
-1.3 Load process
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-This chapter describes the load process on the JS20 board.
-The whole firmware image resides in the flash. The reset is
-triggered by the service processor and both CPUs will jump into
-the LLFW code. After appropriate system setup, the LLFW will load the
-whole image into L2 cache at the link address of the image.
-The LLFW will jump into the OF loader in L2 cache, after it has
-ended it's task of doing base initialization of the system
-(e.g. probing memory and setting up the memory controller).
-The loader code will then move the system vectors, the OF
-core engine and the OF data to the location those parts are
-linked at.
-
-The current addresses and offsets are listed in the following table:
-
- | Runtime address | Link address | Offset in Image |
--------+-----------------+--------------+-----------------+
-LLFW | 0x2000000 | 0x2000000 | 0 |
-Loader | 0x200xxxx | any | + sizeof(LLFW) |
-Vector | 0x100 | 0x100 | + 0x100 |
-OFW | 0x1110000 | 0x1110000 | + 0x4000 |
-Dict | 0x1120000 | 0x1120000 | + 0x2000 |
--------+-----------------+--------------+-----------------+
-
-
-
-
+itself.
2.0 Extension
@@ -205,8 +101,6 @@ new primitive words (i.e., words implemented not by building
pre-existing Forth words together, but instead implemented in
C or assembler). With this, it is possible to adapt SLOF to
the specific needs of different hardware and architectures.
-We'll also discuss how to add an extra payload, and what is
-required of the LLFW to successfully run SLOF.
To add primitives:
@@ -230,103 +124,26 @@ To add primitives:
the Forth engine can be appropriately manipulated.
-To add an extra payload:
-
- It is possible to add client code (secondary boot loader, OS kernel)
- into the data section of SLOF. This will allow to execute a client
- without the need to load it from a device. Any client is required to
- be an ELF executable, and to adhere to the client interface as
- described in the standard, plus the PowerPC binding to the standard.
-
- The steps to add a new payload to SLOF are:
-
- + Add a rule in the SLOF Makefile to convert the client executable into
- a binary.
-
- - payloadbin.o: payload
- $(LD) -o $@ -r -bbinary $<
- paflof: .... payloadbin.o
- $(LD) .... payloadbin.o
-
-
- + Add in <arch>.h a line defining the entry point of the client.
- The name is generated by the linker by surrounding the input
- filename with "_binary_" and "_start".
-
- - extern char _binary_payload_start[];
-
- + Add in <arch>.in a line defining the Forth constant to access the
- start of the client.
-
- - con(PAYLOAD (type_u)_binary_payload_start)
-
- + Add in the main Forth file a colon definition to load and start
- the client.
-
- - : payload-exec payload dup load-elf-file start-elf ;
-
-
-Change Low Level Firmware:
-
- The low level firmware needs to setup the basic execution environment
- required by the rest of the system. The only link from
- LLFW to SLOF is the call to the SLOF loader, which itself is
- position independent. The last thing the LLFW should do is jump to
- the first instruction in the loader image. SLOF also has calls into
- code, that provides certain system specific information like the memory
- size or triggers for board specific actions, like reboot of the board.
- This code is currently implemented for JS20 as object code only module
- and not part of this distribution. For any different board this code
- needs to be provided.
-
-Change oco module:
-
- This file encapsulates functions supposed to be
- confidential and not made public.
- The prototype for this interface is
- type_u oco(cell p0, cell p1)
- p0 is the token and p1 the argument passed to the specific function.
- Current functions for the JS20 board are:
- Token 0: Start slave cpu
- Token 1: Reboot system
- Token 2: Halt system
- Token 3: Watchdog command
- Token 4: Get memory size
- Token 5: Enable ht apic space
- Token 6: Enable MPIC
- Token 7: Get own cpu number
- For other boards this might be different depending on the board
- specific requierements.
-
3.0 Limitations of this package
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- - RTAS is not available in this package. The client application
- has to manage hardware on its own. It is also not possible to
- power down the machine from linux. RTAS calls can be added if
- required.
+ On a JS20 the memory setup is very static and therefore there are
+ only very few combinations of memory DIMM placement actually work.
+
+ Known booting configurations:
- - SLOF has no support for NVRAM, so it is not possible to start the
- operating system without user interaction.
+ * 4x 256 MB (filling all slots) -- only "0.5 GB" reported.
+ * 2x 1 GB, slots 3/4 -- only "0.5 GB" reported.
- - The hardware real time clock is not correctly updated after system
- shutdown. That leads to problems restoring the right system time
- after booting. One possible solution is to set the system time early
- after the OS bootup from a network time server via the NTP protocol.
+ Known failing configurations
- - It is sometimes possible, that the "other-firmware" switchback
- function does not work properly. This is due to hardware limitations.
- The work around is to issue the command to the firmware until the
- original firmware starts. (Should take at most 3 tries to reactivate
- the old firmware)
+ * 2x 256 MB, slots 3/4
+ * 2x 256 MB, slots 1/2
- - The /etc/yaboot.conf file must reside on the 3rd partiton on the 1st
- hard drive in the system. If /etc/yaboot.conf is on another partition
- in fs/main.fs the line
- s" disk:3" encode-string s" bootpath" set-chosen
- has to be change accordanly. This also can be done temporaly by typing
- "set-bootpath x", where x is the partition number.
+ On a JS20 SLOF wil always report 0.5 GB even if there is much more memory
+ available.
+ On a JS21 all memory configurations should work.
Documentation
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/board-js2x/Makefile b/board-js2x/Makefile
new file mode 100644
index 0000000..27ce533
--- /dev/null
+++ b/board-js2x/Makefile
@@ -0,0 +1,110 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+JS2X_TARGETS = tools_build romfs_build stage1
+
+SUBDIRS = slof rtas
+COMMON_LIBS = libc libipmi libbootmsg libbases
+
+all: $(JS2X_TARGETS) subdirs clients_build bcm57xx boot_rom_js2x.bin boot_rom_bimini.bin
+
+.PHONY : subdirs $(SUBDIRS) clean distclean
+
+include config
+include Makefile.dirs
+include $(TOPCMNDIR)/make.rules
+include $(TOPCMNDIR)/Makefile.gen
+
+subdirs: $(SUBDIRS)
+
+$(SUBDIRS): libraries
+ @echo " ====== Building $@ ======"
+ $(MAKE) -C $@ $(MAKEARG)
+
+
+libraries:
+ $(MAKE) -C $(LIBCMNDIR) $(COMMON_LIBS)
+
+stage1:
+ make -C llfw RELEASE=-DRELEASE=\"\\\"$(RELEASE)\\\"\"
+
+boot_rom_js2x.bin: $(JS2X_TARGETS) subdirs clients_build bcm57xx ../build_info.img
+ @echo " ====== Building $@ ======"
+ cat $(ROMFSBRDDIR)/boot_rom.ffs > ../.boot_rom.ffs
+ cat $(SLOFBRDDIR)/OF.ffs >> ../.boot_rom.ffs
+ @echo build_info.img build_info.img 0 0 >> ../.boot_rom.ffs
+ cd .. && ./romfs/tools/build_romfs .boot_rom.ffs boot_rom.bin
+ cd .. && if [ -f boot_rom.bin.gz ]; then rm -f boot_rom.bin.gz; gzip -9 boot_rom.bin; fi
+ rm -f ../.boot_rom.ffs
+
+boot_rom_bimini.bin: $(JS2X_TARGETS) subdirs clients_build bcm57xx ../build_info.img
+ @echo " ====== Building $@ ======"
+ cat $(ROMFSBRDDIR)/boot_rom_bimini.ffs > ../.boot_rom.ffs
+ cat $(SLOFBRDDIR)/OF.ffs >> ../.boot_rom.ffs
+ @echo build_info.img build_info.img 0 0 >> ../.boot_rom.ffs
+ cd .. && ./romfs/tools/build_romfs .boot_rom.ffs boot_rom_bimini.bin
+ cd .. && if [ -f boot_rom_bimini.bin.gz ]; then rm -f boot_romi_bimini.bin.gz; gzip -9 boot_rom_bimini.bin; fi
+ rm -f ../.boot_rom.ffs
+
+bcm57xx:
+ make -C ../other-licence/bcm
+
+
+clean_here:
+ rm -f package-firmware
+ rm -f ../slof/OF.ffs
+ rm -f ../boot_rom.bin ../js2*.img ../ram.bin
+ rm -f ../bimini.img ../bimini.ram.bin
+ rm -rf ../boot_rom_bimini.bin
+
+clean: clean_here clean_gen
+ make -C ../other-licence/bcm clean
+ @for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir clean || exit 1; \
+ done
+ rm -f ../boot_rom.bin ../js2*.img
+ @make -C llfw clean
+ @make -C $(TOPCMNDIR)/clients/takeover clean
+
+distclean: clean_here distclean_gen
+ make -C ../other-licence/bcm clean
+ @for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir distclean || exit 1; \
+ done
+ rm -f ../boot_rom.bin ../js2*.img
+ make -C llfw clean
+ make -C $(TOPCMNDIR)/clients/takeover distclean
+
+takeover: all
+ $(MAKE) -C $(TOPCMNDIR)/clients/takeover
+
+.driver_dirs:
+ @rm -rf ../driver-$(RELEASE)
+ @mkdir -p ../driver-$(RELEASE)
+
+.tar_gz: .driver_dirs takeover
+ @mv ../boot_rom.bin \
+ ../driver-$(RELEASE)/$(RELEASE)-js2x.bin
+ @mv ../boot_rom_bimini.bin \
+ ../driver-$(RELEASE)/$(RELEASE)-bimini.bin
+ @mv $(TOPCMNDIR)/clients/takeover/takeover.elf \
+ ../driver-$(RELEASE)/$(RELEASE)-takeover.bin
+ @cp ../VERSION ../driver-$(RELEASE)
+ @cp changes.txt ../driver-$(RELEASE)
+ @cd ../driver-$(RELEASE) && md5sum * > md5sum.txt
+ @chmod 644 ../driver-$(RELEASE)/*
+ @mv ../driver-$(RELEASE) ../driver-$(RELEASE)-`date +%Y-%h%d`
+ @tar czf ../driver-$(RELEASE)-`date +%Y-%h%d`.tar.gz \
+ ../driver-$(RELEASE)-`date +%Y-%h%d` > /dev/null 2>&1
+ @rm -rf ../driver-$(RELEASE)-`date +%Y-%h%d`
+
+driver: driver_prep clean .tar_gz
diff --git a/board-js2x/Makefile.dirs b/board-js2x/Makefile.dirs
new file mode 100644
index 0000000..7d776af
--- /dev/null
+++ b/board-js2x/Makefile.dirs
@@ -0,0 +1,41 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+#
+# This sub-Makefile contains the directory configuration variables.
+# It can be included from all board specific subdirectories.
+#
+
+# The board specific top directory:
+export TOPBRDDIR ?= $(shell while ! test -e Makefile.dirs ; do cd .. ; done ; pwd )
+
+# The board specific directories:
+export INCLBRDDIR ?= $(TOPBRDDIR)/include
+export LLFWBRDDIR ?= $(TOPBRDDIR)/llfw
+export RTASBRDDIR ?= $(TOPBRDDIR)/rtas
+export SLOFBRDDIR ?= $(TOPBRDDIR)/slof
+export ROMFSBRDDIR ?= $(TOPBRDDIR)/romfs
+
+# The common top directory:
+export TOPCMNDIR ?= $(shell cd $(TOPBRDDIR)/.. && pwd)
+
+# The common directories:
+export INCLCMNDIR ?= $(TOPCMNDIR)/include
+export LLFWCMNDIR ?= $(TOPCMNDIR)/llfw
+export RTASCMNDIR ?= $(TOPCMNDIR)/rtas
+export SLOFCMNDIR ?= $(TOPCMNDIR)/slof
+export ROMFSCMNDIR ?= $(TOPCMNDIR)/romfs
+
+export LIBCMNDIR ?= $(TOPCMNDIR)/lib
+
+export TOOLSDIR ?= $(TOPCMNDIR)/tools
+export CLIENTSDIR ?= $(TOPCMNDIR)/clients
+export OTHERLICENCEDIR ?= $(TOPCMNDIR)/other-licence
diff --git a/board-js2x/config b/board-js2x/config
new file mode 100644
index 0000000..c9f76bc
--- /dev/null
+++ b/board-js2x/config
@@ -0,0 +1,5 @@
+PLATFORM=-DPLATFORM_ID=PPC970_PLATFORM
+BOARD=js2x
+TARG=ppc64
+export CPUARCH=ppc970
+export CPUARCHDEF=-DCPU_PPC970
diff --git a/board-js2x/include/bmc.h b/board-js2x/include/bmc.h
new file mode 100644
index 0000000..bc9a14c
--- /dev/null
+++ b/board-js2x/include/bmc.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __BMC_H
+#define __BMC_H
+
+void (*bmc_system_reboot) (void);
+void (*bmc_power_off) (void);
+
+short (*bmc_set_flashside) (short mode);
+short (*bmc_get_flashside) (void);
+int (*bmc_stop_bootwatchdog) (void);
+int (*bmc_set_bootwatchdog) (unsigned short);
+
+uint32_t(*bmc_read_vpd) (uint8_t * dst, uint32_t len, uint32_t offset);
+uint32_t(*bmc_write_vpd) (uint8_t * src, uint32_t len, uint32_t offset);
+
+uint32_t(*bmc_get_blade_descr) (uint8_t * dst, uint32_t maxlen, uint32_t * len);
+
+#endif /* __BMC_H */
diff --git a/board-js2x/include/hw.h b/board-js2x/include/hw.h
new file mode 100644
index 0000000..2b8342c
--- /dev/null
+++ b/board-js2x/include/hw.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+uint16_t bswap16_load(uint64_t addr) ;
+uint32_t bswap32_load(uint64_t addr) ;
+
+void bswap16_store(uint64_t addr, uint16_t val) ;
+void bswap32_store(uint64_t addr, uint32_t val) ;
+
+uint8_t load8_ci(uint64_t addr) ;
+uint16_t load16_ci(uint64_t addr) ;
+uint32_t load32_ci(uint64_t addr) ;
+uint64_t load64_ci(uint64_t addr) ;
+
+void store8_ci(uint64_t addr, uint8_t val) ;
+void store16_ci(uint64_t addr, uint16_t val) ;
+void store32_ci(uint64_t addr, uint32_t val) ;
+void store64_ci(uint64_t addr, uint64_t val) ;
diff --git a/board-js2x/include/nvramlog.h b/board-js2x/include/nvramlog.h
new file mode 100644
index 0000000..c086e61
--- /dev/null
+++ b/board-js2x/include/nvramlog.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef NVRAMLOG_H
+ #define NVRAMLOG_H
+
+/* ----------------------------------------------------------------------------
+ * NVRAM Log-Partition header design:
+ *
+ * Partition Header
+ * 00h - signature ( 1 byte)
+ * 01h - checksum ( 1 byte)
+ * 02h - length ( 2 byte) value = 1st_byte*256 + 2nd_byte
+ * 04h - name (12 byte)
+ * space for partiton header = 16 byte
+ *
+ * Log Header
+ * 10h - offset ( 2 byte) from Partition Header to Data Section
+ * 12h - flags ( 2 byte) control flags
+ * 14h - pointer ( 4 byte) pointer to first free byte in Data Section
+ * relative to the beginning of the data section
+ * 18h - zero ( 32 byte) reserved as stack for four 64 bit register
+ * 38h - reserved ( 8 byte) reserved for 64 bit CRC (not implemented yet)
+ * space for header = 64 byte
+ * Data Section
+ * 40h - cyclic data
+ * -------------------------------------------------------------------------------- */
+
+ // initial values
+ #define LLFW_LOG_BE0_SIGNATURE 0x51 // signature for general firmware usage
+ #define LLFW_LOG_BE0_NAME_PREFIX 0x69626D2C // first 4 bytes of name: "ibm,"
+ #define LLFW_LOG_BE0_NAME 0x435055306C6F6700 // remaining 8 bytes : "CPU0log\0"
+ #define LLFW_LOG_BE0_LENGTH 0x2000 // Partition length in block of 16 bytes
+ #define LLFW_LOG_BE0_DATA_OFFSET 0x40 // offset in bytes between header and data
+ #define LLFW_LOG_BE0_FLAGS 0 // unused
+
+ #define LLFW_LOG_BE1_SIGNATURE 0x51 // signature for general firmware usage
+ #define LLFW_LOG_BE1_NAME_PREFIX 0x69626D2C // first 4 bytes of name: "ibm,"
+ #define LLFW_LOG_BE1_NAME 0x435055316C6F6700 // remaining 8 bytes : "CPU1log\0\0"
+ #define LLFW_LOG_BE1_LENGTH 0x500 // Partition length in block of 16 bytes
+ #define LLFW_LOG_BE1_DATA_OFFSET 0x40 // offset in bytes between header and data
+ #define LLFW_LOG_BE1_FLAGS 0x0 // unused
+
+ // positions of the initial values
+ #define LLFW_LOG_POS_CHECKSUM 0x01 // 1
+ #define LLFW_LOG_POS_LENGTH 0x02 // 2
+ #define LLFW_LOG_POS_NAME 0x04 // 4
+ #define LLFW_LOG_POS_DATA_OFFSET 0x10 // 16
+ #define LLFW_LOG_POS_FLAGS 0x12 // 18
+ #define LLFW_LOG_POS_POINTER 0x14 // 20
+
+ // NVRAM info
+ #define MAMBO_NVRAM_BASE 0x100000 // NVRAM Base for MAMBO
+ #define NVRAM_EMPTY_PATTERN 0x0000000000000000 // Pattern (64-bit) used to overwrite NVRAM
+
+#endif
diff --git a/board-js2x/include/product.h b/board-js2x/include/product.h
new file mode 100644
index 0000000..4a95c70
--- /dev/null
+++ b/board-js2x/include/product.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _PRODUCT_H
+#define _PRODUCT_H
+
+/* This is also the name which is also put in the flash and should
+ * therefore not excedd the length of 32 bytes */
+#define PRODUCT_NAME "JS2XBlade"
+
+/* Generic identifier used in the flash */
+#define FLASHFS_MAGIC "magic123"
+
+/* Magic identifying the platform */
+#define FLASHFS_PLATFORM_MAGIC "JS2XBlade"
+
+/* also used in the flash */
+#define FLASHFS_PLATFORM_REVISION "1"
+
+#define BOOT_MESSAGE "Press \"s\" to enter Open Firmware.\r\n\r\n\0"
+
+#endif
diff --git a/board-js2x/include/southbridge.h b/board-js2x/include/southbridge.h
new file mode 100644
index 0000000..d10107b
--- /dev/null
+++ b/board-js2x/include/southbridge.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _SOUTHBRIDGE_H
+#define _SOUTHBRIDGE_H
+
+
+#define SB_FLASH_adr (0xff000000) // FLASH (EBC_CS0/Bank0)
+#define SB_NVRAM_adr (0xff800000) // NonVolatile mapping
+#define SB_NVRAM_FWONLY_adr (0xff8FF000) // NonVolatile mapping
+#define NVRAM_LENGTH 0x100000
+#define NVRAM_FWONLY_LENGTH 0x1000
+#define SB_MAILBOX_adr 0
+
+#define FLASH_LENGTH 0x400000
+
+#define SB_IPMI_KCS_adr 0xF4000CA8 // IPMI KCS
+
+#endif
diff --git a/board-js2x/llfw/Cboot.S b/board-js2x/llfw/Cboot.S
new file mode 100644
index 0000000..3e37984
--- /dev/null
+++ b/board-js2x/llfw/Cboot.S
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+ .org 0
+
+ /* Boot Information, hardcoded to ColdReset */
+ .quad 1
+ /* start address */
+ .quad 0x100
diff --git a/board-js2x/llfw/Makefile b/board-js2x/llfw/Makefile
new file mode 100644
index 0000000..fcb7eb4
--- /dev/null
+++ b/board-js2x/llfw/Makefile
@@ -0,0 +1,77 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include ../../make.rules
+
+CPPFLAGS = -I$(INCLBRDDIR) -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) \
+ -I$(LIBCMNDIR)/libc/include
+CFLAGS += -fno-builtin $(CPPFLAGS) -O2 -msoft-float $(MAMBO) $(PLATFORM)
+CFLAGS += $(BOOT) $(IOCONF) -Wa,-mregnames $(RELEASE) $(CPUARCHDEF) -Wall
+ASFLAGS = $(PLATFORM) $(BOOT) $(IOCONF) $(RELEASE)$(CPUARCHDEF) -Wa,-mregnames
+LDFLAGS1 = -nostdlib -e__start -Tstage2.lds -N -Ttext=0x100
+
+
+STG1OBJ = startup.o boot_abort.o romfs.o hw.o io_generic.o board_io.o
+#STG1OBJ += monitor.o ipmi_kcs.o mmu.o
+STG1OBJ += stage2_head.o stage2.o comlib.o \
+ romfs_wrap.o nvramlog.o
+
+all : stage1.js2x stage1.bimini stageS.bin
+
+stage1.js2x: $(STG1OBJ) Cboot.o u4maui.o $(LIBCMNDIR)/libc.a
+ $(LD) $(LDFLAGS1) -o stage1.elf $(STG1OBJ) u4maui.o $(LIBCMNDIR)/libc.a
+ $(OBJCOPY) -O binary stage1.elf stage1.js2x
+
+stage1.bimini: $(STG1OBJ) Cboot.o u4bimini.o $(LIBCMNDIR)/libc.a
+ $(LD) $(LDFLAGS1) -o stage1.elf $(STG1OBJ) u4bimini.o $(LIBCMNDIR)/libc.a
+ $(OBJCOPY) -O binary stage1.elf stage1.bimini
+
+stageS.bin: stage_s.o
+ $(LD) -nostdlib -N -Tstage_s.lds -o stage_s.elf stage_s.o
+ $(OBJCOPY) -O binary stage_s.elf stageS.bin
+
+u4bimini.o: u4mem.c
+ $(CC) $(CFLAGS) -DBOARD_BIMINI -o u4bimini.o -c u4mem.c
+
+u4maui.o: u4mem.c
+ $(CC) $(CFLAGS) -DBOARD_MAUI -o u4maui.o -c u4mem.c
+
+romfs.o: ../../llfw/romfs.S
+ $(CC) $(CFLAGS) -c ../../llfw/romfs.S
+
+ipmi_kcs.o: ../rtas/ipmi_kcs.c
+ $(CC) $(CFLAGS) -c ../rtas/ipmi_kcs.c
+
+boot_abort.o: ../../llfw/boot_abort.S
+ $(CC) $(CFLAGS) -c ../../llfw/boot_abort.S
+
+nvramlog.o: ../../llfw/nvramlog.S
+ $(CC) $(CFLAGS) -c ../../llfw/nvramlog.S
+
+include $(LLFWCMNDIR)/clib/Makefile.inc
+
+include $(LLFWCMNDIR)/io_generic/Makefile.inc
+
+romfs_wrap.o: ../../llfw/romfs_wrap.c
+ $(CC) $(CFLAGS) -c ../../llfw/romfs_wrap.c
+Cboot.o: Cboot.S
+ $(CC) $(CFLAGS) -c $^
+ $(OBJCOPY) -O binary Cboot.o Cboot.bin
+
+$(LIBCMNDIR)/libc.a:
+ $(MAKE) -C $(LIBCMNDIR) libc
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $^
+
+clean:
+ rm -f *.o *.bin *.elf *.js2x *.bimini
diff --git a/board-js2x/llfw/board_io.S b/board-js2x/llfw/board_io.S
new file mode 100644
index 0000000..6e39dfc
--- /dev/null
+++ b/board-js2x/llfw/board_io.S
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <macros.h>
+#include <cpu.h>
+
+ .text
+
+C_ENTRY(copy_from_flash)
+# size in GPR3 (multiple of 64), from GPR4, to GPR5
+ mflr 24 ; mtctr 3 ; addi 4,4,-64 ; addi 5,5,-64
+0: SETCI(r0)
+ ldu 16,64(4) ; ld 17,8(4) ; ld 18,16(4) ; ld 19,24(4)
+ ld 20,32(4) ; ld 21,40(4) ; ld 22,48(4) ; ld 23,56(4)
+ CLRCI(r0)
+ stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5)
+ std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5)
+ sync ; icbi 0,2 ; bdnz 0b ; sync ; isync ; mtlr 24 ; blr
+
+/****************************************************************************
+ * prints one character to serial console
+ *
+ * Input:
+ * R3 - character
+ *
+ * Returns: -
+ *
+ * Modifies Registers:
+ * R3, R4, R5, R6, R7
+ ****************************************************************************/
+ENTRY(io_putchar)
+ mflr r7
+
+ SETCI(r0)
+
+ # always use serial1
+ li 4,0x3f8 ; oris 4,4,0xf400
+
+ # print one char
+0: lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio
+
+ # also print char to serial2 if on a JS21
+ # read ID register: only if it is a PC87427 (JS21) also use serial2
+ addi 4,4,-0x3f8
+ li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4) ; cmpdi 5,0xf2 ; bne 1f
+
+ addi 4,4,0x2f8
+0: lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio
+
+1: CLRCI(r0)
+
+ mtlr r7
+ blr
diff --git a/board-js2x/llfw/hw.c b/board-js2x/llfw/hw.c
new file mode 100644
index 0000000..95888dc
--- /dev/null
+++ b/board-js2x/llfw/hw.c
@@ -0,0 +1,124 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
+#include <types.h>
+#include <hw.h>
+
+uint16_t
+bswap16_load(uint64_t addr)
+{
+ unsigned int val;
+ set_ci();
+ asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
+ clr_ci();
+ return val;
+}
+
+uint32_t
+bswap32_load(uint64_t addr)
+{
+ unsigned int val;
+ set_ci();
+ asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
+ clr_ci();
+ return val;
+}
+
+void
+bswap16_store(uint64_t addr, uint16_t val)
+{
+ set_ci();
+ asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
+ clr_ci();
+}
+
+void
+bswap32_store(uint64_t addr, uint32_t val)
+{
+ set_ci();
+ asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
+ clr_ci();
+}
+
+uint8_t
+load8_ci(uint64_t addr)
+{
+ uint8_t val;
+ set_ci();
+ val = *(uint8_t *) addr;
+ clr_ci();
+ return val;
+}
+
+uint16_t
+load16_ci(uint64_t addr)
+{
+ uint16_t val;
+ set_ci();
+ val = *(uint16_t *) addr;
+ clr_ci();
+ return val;
+}
+
+uint32_t
+load32_ci(uint64_t addr)
+{
+ uint32_t val;
+ set_ci();
+ val = *(uint32_t *) addr;
+ clr_ci();
+ return val;
+}
+
+uint64_t
+load64_ci(uint64_t addr)
+{
+ uint64_t val;
+ set_ci();
+ val = *(uint64_t *) addr;
+ clr_ci();
+ return val;
+}
+
+
+void
+store8_ci(uint64_t addr, uint8_t val)
+{
+ set_ci();
+ *(uint8_t *) addr = val;
+ clr_ci();
+}
+
+void
+store16_ci(uint64_t addr, uint16_t val)
+{
+ set_ci();
+ *(uint16_t *) addr = val;
+ clr_ci();
+}
+
+void
+store32_ci(uint64_t addr, uint32_t val)
+{
+ set_ci();
+ *(uint32_t *) addr = val;
+ clr_ci();
+}
+
+void
+store64_ci(uint64_t addr, uint64_t val)
+{
+ set_ci();
+ *(uint64_t *) addr = val;
+ clr_ci();
+}
diff --git a/board-js2x/llfw/stage2.c b/board-js2x/llfw/stage2.c
new file mode 100644
index 0000000..b529230
--- /dev/null
+++ b/board-js2x/llfw/stage2.c
@@ -0,0 +1,271 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <types.h>
+#include <xvect.h>
+#include <hw.h>
+#include <stdio.h>
+#include <romfs.h>
+#include "memmap.h"
+#include "stage2.h"
+#include <termctrl.h>
+#include "product.h"
+#include "calculatecrc.h"
+#include <cpu.h>
+#include <string.h>
+
+uint64_t uart;
+uint64_t gVecNum;
+uint8_t u4Flag;
+
+uint64_t exception_stack_frame;
+
+typedef void (*pInterruptFunc_t) (void);
+
+pInterruptFunc_t vectorTable[0x2E << 1];
+
+void c_memInit(uint64_t r3, uint64_t r4);
+
+void proceedInterrupt();
+
+void
+exception_forward(void)
+{
+ uint64_t val;
+
+ if (*(uint64_t *) XVECT_M_HANDLER) {
+ proceedInterrupt();
+ }
+
+ printf("\r\n exception %llx ", gVecNum);
+ asm volatile ("mfsrr0 %0":"=r" (val):);
+ printf("\r\nSRR0 = %08llx%08llx ", val >> 32, val);
+ asm volatile ("mfsrr1 %0":"=r" (val):);
+ printf(" SRR1 = %08llx%08llx ", val >> 32, val);
+
+ asm volatile ("mfsprg %0,2":"=r" (val):);
+ printf("\r\nSPRG2 = %08llx%08llx ", val >> 32, val);
+ asm volatile ("mfsprg %0,3":"=r" (val):);
+ printf(" SPRG3 = %08llx%08llx \r\n", val >> 32, val);
+ while (1);
+}
+
+void
+c_interrupt(uint64_t vecNum)
+{
+ gVecNum = vecNum;
+ if (vectorTable[vecNum >> 7]) {
+ vectorTable[vecNum >> 7] ();
+ } else {
+ exception_forward();
+ }
+}
+
+void
+set_exceptionVector(int num, void *func)
+{
+ vectorTable[num >> 7] = (pInterruptFunc_t) func;
+}
+
+static void
+io_init(void)
+{
+ // read ID register: only if it is a PC87427, enable serial2
+ store8_ci(0xf400002e, 0x20);
+ if (load8_ci(0xf400002f) != 0xf2) {
+ uart = 0xf40003f8;
+ u4Flag = 0;
+ } else {
+ uart = 0xf40002f8;
+ u4Flag = 1;
+ }
+}
+
+int
+io_getchar(char *ch)
+{
+ int retVal = 0;
+ if ((load8_ci(uart + 5) & 0x01)) {
+ *ch = load8_ci(uart);
+ retVal = 1;
+ }
+ return retVal;
+}
+
+uint64_t
+get_dec(void)
+{
+ return 0xdeadaffe;
+}
+
+void
+set_dec(uint64_t val)
+{
+}
+
+uint64_t
+tb_frequency(void)
+{
+ return 0;
+}
+
+void copy_from_flash(uint64_t cnt, uint64_t src, uint64_t dest);
+
+const uint32_t CrcTableHigh[16] = {
+ 0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90,
+ 0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7,
+ 0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E,
+ 0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09
+};
+const uint32_t CrcTableLow[16] = {
+ 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
+ 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
+ 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
+ 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
+};
+
+unsigned long
+check_flash_image(unsigned long rombase, unsigned long length,
+ unsigned long start_crc)
+{
+
+ uint32_t AccumCRC = start_crc;
+ char val;
+ uint32_t Temp;
+ while (length-- > 0) {
+ val = load8_ci(rombase++);
+ Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff;
+ AccumCRC <<= 8;
+ AccumCRC ^= CrcTableHigh[Temp / 16];
+ AccumCRC ^= CrcTableLow[Temp % 16];
+ }
+
+ return AccumCRC;
+}
+
+static void
+load_file(uint64_t destAddr, char *name, uint64_t maxSize, uint64_t romfs_base)
+{
+ uint64_t *src, *dest, cnt;
+ struct romfs_lookup_t fileInfo;
+ c_romfs_lookup(name, romfs_base, &fileInfo);
+ if (maxSize) {
+ cnt = maxSize / 8;
+ } else {
+ cnt = (fileInfo.size_data + 7) / 8;
+ }
+ dest = (uint64_t *) destAddr;
+ src = (uint64_t *) fileInfo.addr_data;
+ while (cnt--) {
+ store64_ci((uint64_t) dest, *src);
+ dest++;
+ src++;
+ }
+ flush_cache((void *) destAddr, fileInfo.size_data);
+}
+
+/***************************************************************************
+ * Function: early_c_entry
+ * Input : start_addr
+ *
+ * Description:
+ **************************************************************************/
+void
+early_c_entry(uint64_t start_addr)
+{
+ struct romfs_lookup_t fileInfo;
+ uint32_t crc;
+ void (*pofwStart) (uint64_t rombase);
+ uint64_t *boot_info;
+ uint64_t ofw_start = 0x80000;
+ exception_stack_frame = 0;
+ /* destination for the flash image; we copy it to RAM
+ * because from flash it is much too slow
+ * the flash is copied at 224MB - 4MB (max flash size)
+ * at 224MB starts SLOF
+ * at 256MB is the SLOF load-base */
+ uint64_t romfs_base = 0xe000000 - 0x400000;
+ // romfs header values
+ struct stH *header = (struct stH *) (start_addr + 0x28);
+ //since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory
+ uint64_t magic_val = 0;
+ uint64_t startVal = 0;
+ uint64_t flashlen = 0;
+
+ io_init();
+
+ flashlen = load64_ci((uint64_t) (&header->flashlen));
+
+ //copy fh_magic to magic_val since, we cannot use it as a string from flash
+ magic_val = load64_ci((uint64_t) (header->magic));
+
+ printf(" Check ROM = ");
+ if (strncmp((char *)&magic_val, FLASHFS_MAGIC, 8) == 0) {
+ // somehow, the first 8 bytes in flashfs are overwritten, if booting from drone...
+ // so if we find "IMG1" in the first 4 bytes, we skip the CRC check...
+ startVal = load64_ci((uint64_t) start_addr);
+ if (strncmp((char *)&startVal, "IMG1", 4) == 0) {
+ printf
+ ("start from RAM detected, skipping CRC check!\r\n");
+ // for romfs accesses (c_romfs_lookup) to work, we must fix the first uint64_t to the value we expect...
+ store64_ci((uint64_t) start_addr, 0xd8);
+ } else {
+ //checking CRC in flash, we must use cache_inhibit
+ // since the crc is included as the last 32 bits in the image, the resulting crc should be 0
+ crc =
+ check_flash_image((uint64_t) start_addr,
+ load64_ci((uint64_t)
+ (&header->flashlen)),
+ 0);
+ if (crc == 0) {
+ printf("OK\r\n");
+ } else {
+ printf("failed!\r\n");
+ while (1);
+ }
+ }
+ } else {
+ printf
+ ("failed (magic string is \"%.8s\" should be \"%.8s\")\r\n",
+ (char *)&magic_val, FLASHFS_MAGIC);
+ while (1);
+ }
+
+ printf(" Press \"s\" to enter Open Firmware.\r\n\r\n");
+
+ if ((start_addr > 0xF0000000) && u4Flag)
+ u4memInit();
+
+ /* here we have real ram avail -> hopefully
+ * copy flash to ram; size is in 64 byte blocks */
+ flashlen /= 64;
+ /* align it a bit */
+ flashlen += 7;
+ flashlen &= ~7;
+ copy_from_flash(flashlen, start_addr, romfs_base);
+ /* takeover sometimes fails if the image running on the system
+ * has a different size; flushing the cache helps, because it is
+ * the right thing to do anyway */
+ flush_cache((void *) romfs_base, flashlen * 64);
+
+ c_romfs_lookup("bootinfo", romfs_base, &fileInfo);
+ boot_info = (uint64_t *) fileInfo.addr_data;
+ boot_info[1] = start_addr;
+ load_file(0x100, "xvect", 0x100, romfs_base);
+ load_file(SLAVELOOP_LOADBASE, "stageS", 0, romfs_base);
+ load_file(ofw_start, "ofw_main", 0, romfs_base);
+ pofwStart = (void (*)(uint64_t)) &ofw_start;
+ // re-enable the cursor
+ printf("%s%s", TERM_CTRL_RESET, TERM_CTRL_CRSON);
+ // never return
+ pofwStart(romfs_base);
+}
diff --git a/board-js2x/llfw/stage2.h b/board-js2x/llfw/stage2.h
new file mode 100644
index 0000000..1c5205a
--- /dev/null
+++ b/board-js2x/llfw/stage2.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __STAGE2_H
+#define __STAGE2_H
+
+#ifndef __ASSEMBLER__
+
+#include <stddef.h>
+
+void u4memInit(void);
+
+#endif /* __ASSEMBLER__ */
+#endif /* __STAGE2_H */
diff --git a/board-js2x/llfw/stage2.lds b/board-js2x/llfw/stage2.lds
new file mode 100644
index 0000000..703ef9d
--- /dev/null
+++ b/board-js2x/llfw/stage2.lds
@@ -0,0 +1,56 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+
+/* set the entry point */
+ENTRY ( __start )
+
+SECTIONS {
+ .text : {
+ *(.text)
+ }
+
+ . = ALIGN(8);
+
+ .data : {
+ *(.data)
+ *(.rodata .rodata.*)
+ *(.got1)
+ *(.sdata)
+ *(.opd)
+ }
+
+ /* FIXME bss at end ??? */
+
+ . = ALIGN(8);
+ __bss_start = .;
+ .bss : {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ }
+
+ . = ALIGN(8);
+ __bss_end = .;
+ __bss_size = (__bss_end - __bss_start);
+
+ __toc_start = .;
+ .got :
+ {
+ *(.toc .got)
+ }
+ . = ALIGN(8);
+ __toc_end = .;
+ __stack_end = . ;
+}
diff --git a/board-js2x/llfw/stage2_head.S b/board-js2x/llfw/stage2_head.S
new file mode 100644
index 0000000..ea1cf59
--- /dev/null
+++ b/board-js2x/llfw/stage2_head.S
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "macros.h"
+#include "../../llfw/boot_abort.h"
+
+/*#################### defines #####################*/
+#define STACK_SIZE 0x4000
+
+/*#################### code ########################*/
+ .text
+ .globl .gluon_c_entry
+ .globl __toc_start
+ .globl __toc_end
+ .globl __stack_end
+ .globl __bss_start
+ .globl __bss_size
+ .globl __start
+
+ASM_ENTRY(__startC)
+ /* clear out bss section */
+ LOAD64(r3, (__bss_start - 8))
+ LOAD64(r4, __bss_size)
+
+ /* divide __bss_size by 8 to get number */
+ /* of dwords to clear */
+ srwi. r4, r4, 3
+ beq bsscdone
+ li r5, 0
+ mtctr r4
+bssc: stdu r5, 8(r3)
+ bdnz bssc
+bsscdone:
+ /* setup stack */
+ LOAD64(r1, __stack_end + STACK_SIZE)
+
+ /* save return address beside stack */
+ addi r3, r1, 128
+ mflr r0
+ std r0, 0(r3)
+
+ /* setup toc */
+ bl toc_init
+
+ /* ------------------------------------ */
+ /* jump to c-code */
+ /* r10 = cpu_init_slave address - r3 */
+ /* r11 = slave_setup address - r4 */
+ /* ------------------------------------ */
+ mr r3, r10
+ mr r4, r11
+ bl .early_c_entry
+
+ /* return to caller... */
+ LOAD64(r1, __stack_end + STACK_SIZE)
+ addi r1, r1, 128
+ ld r3, 0(r1)
+ mtlr r3
+ blr
+
+ /* #################################### */
+ /* Basic Additional Functions */
+ /* for extended lib functions see */
+ /* external library */
+ /* #################################### */
+ .align 2
+
+ /* ------------------------------------ */
+ /* updates toc in r2 */
+ /* ------------------------------------ */
+ASM_ENTRY(toc_init)
+ LOAD64(r2, __toc_start)
+ addi r2,r2,0x4000
+ addi r2,r2,0x4000
+ blr
+
+ /* ------------------------------------ */
+ /* stores arg#1 in r27 and stops */
+ /* ------------------------------------ */
+ENTRY(do_panic)
+ENTRY(halt_sys)
+ BOOT_ABORT_R3HINT(ABORT_CANIO, ALTBOOT, msg_e_ierror);
diff --git a/board-js2x/llfw/stage_s.S b/board-js2x/llfw/stage_s.S
new file mode 100644
index 0000000..15eed93
--- /dev/null
+++ b/board-js2x/llfw/stage_s.S
@@ -0,0 +1,43 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+ .text
+ .org 0 /* after loading to mem this is at slaveloop_base */
+# . = 0x3f00 loaded to this addr
+ .globl __stage_s_entry
+
+__stage_s_entry:
+ bl $+4
+ mflr r4
+ li r3, 0xff
+ not r3, r3
+ and r4, r4, r3
+ li 0,1 ; std 0,0xf8(4)
+ li 0,0 ; std 0,0xa0(4)
+slaveloop:
+ ori 28,28,0x100
+ lis 0,10
+ mtctr 0
+ bdnz $ # do some waiting, to prevent flooding the buses
+ lwz 0,0xa0(4)
+ cmpw 0,28
+ bne $-20 # wait for our flag
+
+ lwz 0,0x80(4)
+ lwz 3,0xc0(4)
+ mtctr 0
+ bctr # jump to specified address, with specified GPR3
+
+# .quad 0
+# .quad 0
+
+
+
diff --git a/board-js2x/llfw/stage_s.lds b/board-js2x/llfw/stage_s.lds
index d77a17e..989ca3d 100644
--- a/board-js2x/llfw/stage_s.lds
+++ b/board-js2x/llfw/stage_s.lds
@@ -1,24 +1,22 @@
-/* ============================================================================= */
-/* * Copyright (c) 2004, 2005 IBM Corporation
-/* * All rights reserved.
-/* * This program and the accompanying materials
-/* * are made available under the terms of the BSD License
-/* * which accompanies this distribution, and is available at
-/* * http://www.opensource.org/licenses/bsd-license.php
-/* *
-/* * Contributors:
-/* * IBM Corporation - initial implementation
-/* ============================================================================= */
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
OUTPUT_ARCH(powerpc:common64)
+ENTRY( __stage_s_entry )
+
SECTIONS {
- .startup 0x2000000 : { startup.o }
- image = ALIGN(128);
- .slof.loader image : { loader.o }
- .slof.vectors image + 0x100 : { *(.slof.vectors) }
- .slof.text image + 0x4100 : { *(.slof.text) }
- .slof.data image + 0x6100 : { *(.slof.data) }
+ .text : {
+ *(.text)
+ }
}
diff --git a/board-js2x/llfw/startup.S b/board-js2x/llfw/startup.S
new file mode 100644
index 0000000..59e1c3f
--- /dev/null
+++ b/board-js2x/llfw/startup.S
@@ -0,0 +1,708 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+# SLOF for JS20/JS21 -- ROM boot code.
+# Initial entry point, copy code from flash to cache, memory setup.
+# Also sets up serial console and optimizes some settings.
+
+#include "termctrl.h"
+#include <product.h>
+#include <xvect.h>
+#include <cpu.h>
+#include <macros.h>
+#include <southbridge.h>
+
+ .text
+ .globl __start
+__start:
+ /* put rombase in sprg1 ***********************/
+
+ bl postHeader
+ .long 0xDEADBEE0
+ .long 0x0 /* size */
+ .long 0x0 /* crc */
+ .long relTag - __start
+postHeader:
+ mflr r3
+ li r4, 0x7fff
+ not r4, r4
+ and r3, r3, r4
+ mtsprg 1, r3 /* romfs base */
+ bl _start
+
+ .org 0x150 - 0x100
+__startSlave:
+ bl setup_cpu
+ bl set_ci_bit
+# b slaveWithNumber
+ b slave
+
+ .org 0x180 - 0x100
+__startMaster:
+ li 3,0
+ mtsprg 1, r3 /* romfs base */
+ bl setup_cpu
+ bl set_ci_bit
+ b master
+
+
+ /* FIXME: Also need 0280, 0380, 0f20, etc. */
+
+ .irp i, 0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,0x0400,0x0500,0x0600,0x0700, \
+ 0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \
+ 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
+ 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
+ 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
+ 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00
+ . = \i
+
+ /* enable this if you get exceptions before the console works */
+ /* this will allow using the hardware debugger to see where */
+ /* it traps, and with what register values etc. */
+ // b $
+
+ mtsprg 0, r0
+ mfctr r0
+ mtsprg 2,r0
+ mflr r0
+// 10
+ mtsprg 3,r0
+ ld r0, (\i + 0x160)(0)
+ mtctr r0
+ li r0, \i + 0x100
+// 20
+ bctr
+
+ . = \i + 0x60
+
+ .quad intHandler2C
+
+ .endr
+
+
+ . = XVECT_M_HANDLER - 0x100
+ .quad 0x00
+ . = XVECT_S_HANDLER - 0x100
+
+ .quad 0
+
+
+
+ .org 0x4000 - 0x100
+_start:
+ # optimize HID register settings
+ bl setup_cpu
+ bl set_ci_bit
+
+ # read semaphore, run as slave if not the first to do so
+ li 3,0 ; oris 3,3,0xf800 ; lwz 3,0x60(3) ; andi. 3,3,1 ; beq slave
+master:
+ # setup flash, serial
+ bl setup_sio
+
+ # early greet
+ li r3, 10
+ bl putc
+ li 3,13 ; bl putc ; li 3,10 ; bl putc ; li 3,'S' ; bl putc
+
+
+ #do we run from ram ?
+ mfsprg r3, 1 /* rombase */
+ cmpdi r3,0 /* rombase is 0 when running from RAM */
+
+ bne copy_to_cache
+
+ # wait a bit, start scripts are slow... need to get all cores running!
+ lis 3,0x4000 ; mtctr 3 ; bdnz $
+
+ # copy 4MB from 0 to temp memory
+ lis 4,0x8 ; mtctr 4 ; lis 4,0x200 ; li 3,0 ; addi 4,4,-8 ; addi 3,3,-8
+0: ldu 5,8(3) ; stdu 5,8(4) ; bdnz 0b
+
+ lis 4,0x200
+ mtsprg 1, r4
+
+ lis 4,0x1
+ lis 3,0x20 ; addi 3,3,0x200-8 ;
+ FLUSH_CACHE(r3, r4)
+
+ lis 4,0x200
+ addi 4,4,copy_to_cache@l
+ mtctr 4
+ bctr
+
+# make all data accesses cache-inhibited
+set_ci_bit:
+ SETCI(r0)
+ blr
+
+# make all data accesses cacheable
+clr_ci_bit:
+ CLRCI(r0)
+ blr
+
+# write a character to the serial port
+putc:
+# always write to serial1
+0: lbz 0,5(13) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(13) ; eieio
+
+# read ID register: only if it is a PC87427 (JS21) also use serial2
+ li 4,0 ; oris 4,4,0xf400
+ li 5,0x20 ; stb 5,0x2e(4) ; lbz 5,0x2f(4); cmpdi 5,0xf2 ; bne 1f
+
+ addi 4,4,0x2f8
+0: lbz 0,5(4) ; andi. 0,0,0x20 ; beq 0b ; stb 3,0(4) ; eieio
+
+1: blr
+
+# transfer from running from flash to running from cache
+return_cacheable:
+ # find and set address to start running from cache, set msr value
+ mflr 3 ; rldicl 3,3,0,44
+jump_cacheable:
+ mtsrr0 3 ;
+ mfmsr 3 ; ori 3,3,0x1000 ; mtsrr1 3 # enable MCE, as well
+
+ # set cacheable insn fetches, jump to cache
+ mfspr 3,HID1 ; rldicl 3,3,32,0 ; oris 3,3,0x0020 ; rldicl 3,3,32,0
+ sync ; mtspr HID1,3 ; mtspr HID1,3 ; rfid ; b .
+
+
+
+
+copy_to_cache:
+ # zero the whole cache
+ # also, invalidate the insn cache, to clear parity errors
+ # 128kB @ 0MB (boot code and vectors from 0x0 up to 0x20000)
+ li 4,0x400 ; mtctr 4 ; li 5,0x0 ; bl clr_ci_bit
+0: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
+
+ # 0x2000 to 0x100000/0x80000 (smaller on 970/970FX)
+ li 4,0x1C00 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0xC00
+0:
+ mtctr 4 ; li 5,0x2000
+0: dcbz 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b ; bl set_ci_bit
+
+ # find base address
+ bcl 20,31,$+4 ; mflr 31 ; rldicr 31,31,0,43
+
+ # copy 1kB from 0x4000
+ li 4,0x80 ; mtctr 4 ;
+ li 5,0x3ff8
+ addi 3,31,0x3ff8
+0: ldu 4,8(3) ; bl clr_ci_bit ; stdu 4,8(5) ; bl set_ci_bit ; bdnz 0b
+ # now start executing from cache -- insn cache is huge speed boost
+
+ bl return_cacheable
+
+ li 3,'L' ; bl putc
+
+ # copy 128kB of flash to cache
+ li 4,0x800 ; mtctr 4 ; li 5,0x200-64 ; addi 3,31,0x200-64 ;
+0: ldu 16,64(3) ; ld 17,8(3) ; ld 18,16(3) ; ld 19,24(3)
+ ld 20,32(3) ; ld 21,40(3) ; ld 22,48(3) ; ld 23,56(3)
+ bl clr_ci_bit
+ stdu 16,64(5) ; std 17,8(5) ; std 18,16(5) ; std 19,24(5)
+ std 20,32(5) ; std 21,40(5) ; std 22,48(5) ; std 23,56(5)
+ icbi 0,5 ; bl set_ci_bit ; bdnz 0b ; isync
+
+
+ li 3,'O' ; bl putc
+
+ lis 4,0x20
+ mfsprg r3,1
+ cmpd r3,r4
+ beq 1f
+
+ // at 0xf8000000 we decide if it is u3 or u4
+ li 4,0 ; oris 4,4,0xf800 ; lwz 3,0(4) ; srdi 3,3,4 ; cmpdi 3,3 ; bne 0f
+ bl setup_mem_u3
+ bl setup_mem_size
+ b 1f
+0:
+
+1:
+ li 3,'F' ; bl putc
+
+ # setup nvram logging only when not running from RAM
+ mfsprg r3, 1 /* rombase */
+ cmpdi r3, 0 /* rombase is 0 when running from RAM */
+ beq 0f
+
+ // at 0xf8000000 we decide if it is u3 or u4
+ li r4, 0
+ oris r4, r4, 0xf800
+ lwz r3, 0(r4)
+ srdi r3, r3, 4
+ cmpdi r3, 3 /* 3 means js20; no nvram logging on js20 */
+ beq 0f
+
+ bl io_log_init
+0:
+
+ #bl print_mem
+
+ # data is cacheable by default from now on
+ bl clr_ci_bit
+
+
+ /* give live sign *****************************/
+ bl 0f
+ .ascii TERM_CTRL_RESET
+ .ascii TERM_CTRL_CRSOFF
+ .ascii " **********************************************************************"
+ .ascii "\r\n"
+ .ascii TERM_CTRL_BRIGHT
+ .ascii PRODUCT_NAME
+ .ascii " Starting\r\n"
+ .ascii TERM_CTRL_RESET
+ .ascii " Build Date = ", __DATE__, " ", __TIME__
+ .ascii "\r\n"
+ .ascii " FW Version = " , RELEASE
+ .ascii "\r\n\0"
+ .align 2
+0: mflr r3
+ bl io_print
+
+ # go!
+ li r3,__startC@l
+ mtctr r3
+ mfsprg r10, 1
+ bctrl
+
+relTag:
+ .ascii RELEASE
+ .ascii "\0"
+ .align 2
+
+slave:
+
+ # get cpu number
+ li 3,0 ; oris 3,3,0xf800 ; lwz 28,0x50(3)
+
+slaveWithNumber:
+ # create our slave loop address
+ sldi 3,28,24 ; oris 3,3,0x3000
+
+ # invalidate the insn cache, to clear parity errors
+ # clear the L2 cache as well, to get ECC right
+ li 4,0x2000 ; mfpvr 0 ; srdi 0,0,16 ; cmpdi 0,0x0044 ; bge 0f ; li 4,0x1000
+0: mtctr 4 ; mr 5,3 ; bl clr_ci_bit
+
+0: dcbz 0,5 ; sync ; icbi 0,5 ; sync ; isync ; addi 5,5,0x80 ; bdnz 0b
+
+
+ # write a "b $" insn in there
+ lis 4,0x4800 ; stw 4,0(3)
+/*
+ mr 5,3
+
+ # jump there
+ bl set_ci_bit
+ li 13,0 ; oris 13,13,0xf400
+ # device address
+ addi 13,13,0x2f8
+ li 3,'O' ; add 3,3,28 ; bl putc
+ bl clr_ci_bit
+ mr 3,5
+*/
+ b jump_cacheable
+
+
+
+
+# allow the flash chip to be accessed faster
+# initialize the 16550-compatible uart on serial port 1 of the sio
+setup_sio:
+
+ # i/o base address
+ li 3,0 ; oris 3,3,0xf400
+
+ # i/o base address
+ li 3,0 ; oris 3,3,0xf400
+
+ # put x-bus in turbo mode
+ li 4,0xf1 ; stb 4,0x400(3) ; eieio
+
+
+ # select sio serial1
+ li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
+
+ # set base address to 3f8
+ li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,3 ; stb 4,0x2f(3) ; eieio
+
+ # enable device
+ li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
+
+ # read ID register: only if it is a PC87427, enable serial2
+ li 4,0x20 ; stb 4,0x2e(3) ; eieio ; lbz 4,0x2f(3) ; cmpdi 4,0xf2 ; bne 0f
+
+ # select sio serial2
+ li 4,7 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
+
+ # set base address to 2f8
+ li 4,0x60 ; stb 4,0x2e(3) ; eieio ; li 4,2 ; stb 4,0x2f(3) ; eieio
+
+ # enable device
+ li 4,0x30 ; stb 4,0x2e(3) ; eieio ; li 4,1 ; stb 4,0x2f(3) ; eieio
+
+ # uart @0x2f8
+ addi 3,3,0x2f8
+
+ # disable interrupts, fifo off
+ li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
+
+ # set serial speed
+ li 4,0x80 ; stb 4,3(3) ; eieio
+ li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
+
+ # set 8-N-1, set RTS and DTR
+ li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
+
+ eieio
+
+ addi 3,3,-0x2f8
+
+ # uart @0x3f8
+0: addi 3,3,0x3f8
+
+ # disable interrupts, fifo off
+ li 4,0 ; stb 4,1(3) ; eieio ; stb 4,2(3) ; eieio
+
+ # set serial speed
+ li 4,0x80 ; stb 4,3(3) ; eieio
+ li 4,115200/19200 ; stb 4,0(3) ; eieio ; li 4,0 ; stb 4,1(3) ; eieio
+
+ # set 8-N-1, set RTS and DTR
+ li 4,3 ; stb 4,3(3) ; eieio ; stb 4,4(3) ; eieio
+
+ eieio
+
+ # save UART base for putc routine
+0: mr 13,3
+
+ blr
+
+
+
+
+# set the HID registers of the 970 for optimally executing from flash
+setup_cpu:
+
+ /* clear all the HV cruft */
+ li r0, 0
+ sync
+ mtspr HID4, r0
+ isync
+
+ /* enable dpm, disable attn insn, enable external mce
+ * first, try external time base; if clock doesn't run, switch to
+ * internal */
+ li r0, 1 /* do the setup for external timebase */
+ rldicl r0, r0, 44, 0 /* bit 19 has to be set */
+ oris r0, r0, 0x8000 /* Enable external machine check */
+ /* interrupts (preferred state */
+ /* equals `1'). */
+ sync
+ mtspr HID0, r0
+ isync
+
+ mftb r3 /* read the timebase */
+ li r1, 0x4000 /* wait long enough for the external */
+ mtctr r1 /* timebase (14MHz) to tick a bit */
+ bdnz $ /* 0x4000 seems to be enough (for now) */
+ mftb r4 /* read the timebase a second time */
+ cmpld r3, r4 /* see if it changed */
+ bne 0f
+ /* timebase did not change, do the setup for internal */
+ rldicl r0, r0, 19, 1
+ rldicl r0, r0, 45, 0
+ sync
+ mtspr HID0, r0
+ isync
+
+0:
+ /* enable insn prefetch, speculative table walks */
+ mfspr r0, HID1
+ rldicl r0, r0, 20, 0
+ ori r0, r0, 0x1002
+ mfsprg r3, 1 /* read rombase */
+ cmpdi r3, 0 /* check if running from ram */
+ bne 0f
+ /* running from ram */
+ /* Enable instruction fetch cacheability control */
+ ori r0, r0, 0x200
+0:
+ rldicl r0, r0, 44, 0
+ sync
+ mtspr HID1, r0
+ isync
+
+ /* enable cache parity */
+ mfspr r0, HID4
+ oris r0, r0, 0xfff0
+ xoris r0, r0, 0xfff0
+ sync
+ mtspr HID4, r0
+ isync
+
+ /* exception offset at 0 */
+ li r3, 0
+ mtspr HIOR, r3
+
+ blr
+
+C_ENTRY(proceedInterrupt)
+
+ ld r3,exception_stack_frame@got(r2)
+ ld r1,0(r3)
+
+ .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ ld r\i, 0x30+\i*8 (r1)
+ .endr
+
+ ld r14,0x138(r1);
+ mtsrr0 r14
+
+ ld r14,0x140(r1);
+ mtsrr1 r14
+
+ ld r14,0x148(r1);
+ mtcr r14
+
+
+ ld 0,XVECT_M_HANDLER(0)
+ mtctr 0
+
+ ld r0,0x30(r1); # restore vector number
+ ld r1,0x38(r1);
+
+ bctr
+
+intHandler2C:
+ mtctr r1 # save old stack pointer
+ lis r1,0x4
+ stdu r1, -0x160(r1)
+ .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ std r\i, 0x30+\i*8 (r1)
+ .endr
+
+ std r0,0x30(r1); # save vector number
+
+ mfctr r14
+ std r14,0x38(r1); # save old r1
+
+ mfsrr0 r14
+ std r14,0x138(r1);
+
+ mfsrr1 r14
+ std r14,0x140(r1);
+
+ mfcr r14
+ std r14,0x148(r1);
+
+ mfxer r14
+ std r14,0x150(r1);
+
+ bl toc_init
+
+ ld r3,exception_stack_frame@got(r2)
+ std r1,0(r3)
+
+
+ mr r3,r0
+ bl .c_interrupt
+
+ ld r14,0x138(r1);
+ mtsrr0 r14
+
+ ld r14,0x140(r1);
+ mtsrr1 r14
+
+ ld r14,0x148(r1);
+ mtcr r14
+
+ ld r14,0x150(r1);
+ mtxer r14
+
+
+ .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ ld r\i, 0x30+\i*8 (r1)
+ .endr
+
+ ld r1,0x38(r1);
+
+ mfsprg r0,2
+ mtctr r0
+ mfsprg r0,3
+ mtlr r0
+ mfsprg r0,0
+ rfid
+
+/* Set exception handler for given exception vector.
+ r3: exception vector offset
+ r4: exception handler
+*/
+ .globl .set_exception
+.set_exception:
+ .globl set_exception
+set_exception:
+ ld r4,0x0(r4)
+ .globl .set_exception_asm
+.set_exception_asm:
+ .globl set_exception_asm
+set_exception_asm:
+ std r4, 0x60(r3) # fixme diff 1f - 0b
+ blr
+
+
+setup_mem_u3:
+ li 4,0x2000 ; oris 4,4,0xf800
+
+ # MemTimingParam -- CAS lat 2.5 / 4 (read-to-read / read-to-write)
+ lis 3,0x49e1 ; ori 3,3,0xa000 ; stw 3,0x50(4)
+
+ # MRSRegCntl -- CAS lat 2.5
+ li 3,0x6a ; stw 3,0xf0(4)
+
+ # MemBusConfig -- 128 bit bus
+ lis 3,0x8500 ; stw 3,0x190(4)
+
+ # CKDelAdj -- clock delay 75
+ lis 3,0x12c3 ; ori 3,3,0x30cc ; stw 3,0x520(4)
+
+ # IOModeCntl -- no termination on differential and 3-state drivers
+ lis 3,0x0350 ; stw 3,0x530(4)
+
+ li 3,18 ; mtctr 3 ; addi 5,4,0x5f0
+0: # DQSDelAdj -- read delay offset -10
+ lis 3,0x3d8f ; ori 3,3,0x6000 ; stwu 3,0x10(5)
+
+ # DQSDataDelAdj -- write delay offset -32, write data delay offset +15
+ lis 3,0x380e ; ori 3,3,0x003c ; stwu 3,0x10(5)
+ bdnz 0b
+
+ # MemProgCntl -- set all
+ lis 3,0xc000 ; stw 3,0xe0(4)
+
+ eieio
+
+ blr
+
+
+# read dimm SPDs, program memory size and type
+setup_mem_size:
+ mflr 14
+
+ li 15,0 ; oris 15,15,0xf800 ; li 17,0
+ li 3,0xa0 ; li 4,3 ; li 5,3 ; bl i2c_read
+ mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
+0: li 3,0xa2 ; li 4,3 ; li 5,3 ; bl i2c_read
+ cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
+0: li 16,0x1e00
+1: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
+ #mr 3,16 ; bl print_hex
+
+ #li 3,0x20 ; bl print_byte
+ sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
+ stw 3,0x21c0(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x21e0(15)
+0: #bl print_hex
+ sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
+ # slw, not sld, so that empty/bad banks translate into size 0
+ stw 17,0x21d0(15) ; bl add17173 ; stw 17,0x21f0(15)
+ andi. 0,16,2 ; beq 0f ; bl add17173
+0: #bl print_hex
+
+ li 3,0xa4 ; li 4,3 ; li 5,3 ; bl i2c_read
+ mr 16,4 ; cmpdi 3,0 ; beq 0f ; li 16,0
+0: li 3,0xa6 ; li 4,3 ; li 5,3 ; bl i2c_read
+ cmpd 16,4 ; bne 0f ; cmpdi 3,0 ; beq 1f
+0: li 16,0x1e00
+1: #li 3,0xd ; bl print_byte ; li 3,0xa ; bl print_byte
+ #mr 3,16 ; bl print_hex
+
+ #li 3,0x20 ; bl print_byte
+ sldi 3,16,7 ; add 3,3,16 ; rlwinm 3,3,10,0,6 ; subis 3,3,0x3c00
+ stw 3,0x2200(15) ; andi. 0,16,2 ; beq 0f ; stw 3,0x2220(15)
+0: #bl print_hex
+ sldi 3,16,8 ; add 3,3,16 ; rldicl 3,3,48,56 ; li 0,8 ; slw 3,0,3
+ stw 17,0x2210(15) ; bl add17173 ; stw 17,0x2230(15)
+ andi. 0,16,2 ; beq 0f ; bl add17173
+0: #bl print_hex
+ #mr 3,17 ; bl print_hex
+ stw 17,0x2250(15) ; stw 17,0x2270(15)
+ stw 17,0x2290(15) ; stw 17,0x22b0(15)
+
+ mtlr 14
+ blr
+
+
+
+
+# print GPR3 as 8-digit hex. uses GPR18,19
+print_hex:
+ mflr 18 ; mr 19,3 ; li 3,8 ; mtctr 3
+1: rlwinm 3,19,4,28,31 ; sldi 19,19,4
+ cmpdi 3,0xa ; blt 0f ; addi 3,3,0x27
+0: addi 3,3,0x30 ; bl putc
+ bdnz 1b ; mtlr 18 ; blr
+
+
+# i2c stuff uses GPR20..GPR24
+
+# terminate any i2c transaction, at any point during that transaction
+i2c_stop:
+0: lwz 3,0x30(20) ; stw 3,0x30(20) ; andi. 3,3,4 ; beq 0b
+ mr 3,21 ; mr 4,22 ; mtlr 24 ; eieio ; blr
+
+# do a combined-mode read
+# in: GPR3 = addr, GPR4 = subaddr, GPR5 = len
+# out: GPR3 = error, GPR4 = result (right-aligned, msb)
+i2c_read:
+ mflr 24
+ li 20,0x1000 ; oris 20,20,0xf800 # uni-n i2c base
+ mr 21,3 ; mr 22,4 ; mr 23,5 # save params
+ li 4,0xc ; stw 4,0(20) # set mode (combined)
+ ori 4,21,1 ; stw 4,0x50(20) # set addr, read
+ stw 22,0x60(20) # set subaddr
+ li 4,2 ; stw 4,0x10(20) ; eieio # start address phase
+ li 21,1 # error
+ li 22,0 # result accumulator
+0: lwz 3,0x30(20) ; andi. 3,3,2 ; beq 0b # wait until sent
+ lwz 3,0x20(20) ; andi. 3,3,2 ; beq i2c_stop # check result
+ li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
+0: stw 4,0x10(20) # AAK for next byte (or not)
+ li 4,2 ; stw 4,0x30(20) ; eieio # ack address phase
+i2c_read_loop:
+ lwz 3,0x30(20) ; andi. 3,3,1 ; beq 1f # if byte recv'd:
+ subi 23,23,1 ; sldi 22,22,8 # shift byte accum
+ lwz 3,0x70(20) ; rlwimi 22,3,0,24,31 # get byte
+ cmpdi 23,0 ; bne 0f ; li 21,0 ; b i2c_stop # all done
+0: li 4,1 ; cmpdi 23,1 ; bne 0f ; li 4,0
+0: stw 4,0x10(20) # AAK for next byte (or not)
+ li 4,1 ; stw 4,0x30(20) ; eieio # ack data phase
+1: lwz 3,0x30(20) ; andi. 3,3,4 ; beq i2c_read_loop
+ li 4,0 ; stw 4,0x10(20) ; eieio ; b i2c_stop # stop bit received
+
+add17173: # add GPR3 into GPR17; if passing 2GB (0x10000000), add another 2GB.
+ lis 0,0x1000 ; cmpld 17,0 ; add 17,17,3 ; bgtlr
+ cmpld 17,0 ; blelr ; add 17,17,0 ; blr
+
+io_log_init:
+ LOAD64(r3, SB_NVRAM_adr)
+ b checkinitLog
diff --git a/board-js2x/llfw/u4mem.c b/board-js2x/llfw/u4mem.c
new file mode 100644
index 0000000..d0fc4cd
--- /dev/null
+++ b/board-js2x/llfw/u4mem.c
@@ -0,0 +1,4071 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <types.h>
+#include <hw.h>
+#include <stdio.h>
+#include "stage2.h"
+#include <cpu.h>
+#include <string.h>
+
+/*
+ * compiler switches
+ *******************************************************************************
+ */
+#define U4_DEBUG
+#define U4_INFO
+//#define U4_SHOW_REGS
+
+int io_getchar(char *);
+
+/*
+ * version info
+ */
+static const uint32_t VER = 2;
+static const uint32_t SUBVER = 1;
+
+/*
+ * local macros
+ *******************************************************************************
+ */
+// bit shifting in Motorola/IBM bit enumeration format (yaks...)
+#define IBIT( nr ) ( (uint32_t) 0x80000000 >> (nr) )
+#define BIT( nr ) ( (uint32_t) 0x1 << (nr) )
+
+/*
+ * macros to detect the current board layout
+ */
+#ifdef BOARD_BIMINI
+#define IS_MAUI 0 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 0 )
+#define IS_BIMINI 1 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 1 )
+#define IS_KAUAI 0 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 2 )
+#endif
+
+#ifdef BOARD_MAUI
+#define IS_MAUI 1 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 0 )
+#define IS_BIMINI 0 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 1 )
+#define IS_KAUAI 0 //( ( load8_ci( 0xf4000682 ) >> 4 ) == 2 )
+#endif
+
+/*
+ * local constants
+ *******************************************************************************
+ */
+
+/*
+ * u4 base address
+ */
+#define U4_BASE_ADDR ((uint64_t) 0xf8000000 )
+#define u4reg( reg ) (U4_BASE_ADDR + (uint64_t) (reg))
+
+/*
+ * I2C registers
+ */
+#define I2C_MODE_R u4reg(0x1000)
+#define I2C_CTRL_R u4reg(0x1010)
+#define I2C_STAT_R u4reg(0x1020)
+#define I2C_ISR_R u4reg(0x1030)
+#define I2C_ADDR_R u4reg(0x1050)
+#define I2C_SUBA_R u4reg(0x1060)
+#define I2C_DATA_R u4reg(0x1070)
+
+/*
+ * clock control registers & needed bits/masks
+ */
+#define ClkCntl_R u4reg(0x0800)
+#define PLL2Cntl_R u4reg(0x0860)
+
+/*
+ * clock control bits & masks
+ */
+#define CLK_DDR_CLK_MSK (IBIT(11) | IBIT(12) | IBIT(13))
+
+/*
+ * memory controler registers
+ */
+#define RASTimer0_R u4reg(0x2030)
+#define RASTimer1_R u4reg(0x2040)
+#define CASTimer0_R u4reg(0x2050)
+#define CASTimer1_R u4reg(0x2060)
+#define MemRfshCntl_R u4reg(0x2070)
+#define MemProgCntl_R u4reg(0x20b0)
+#define Dm0Cnfg_R u4reg(0x2200)
+#define Dm1Cnfg_R u4reg(0x2210)
+#define Dm2Cnfg_R u4reg(0x2220)
+#define Dm3Cnfg_R u4reg(0x2230)
+#define MemWrQCnfg_R u4reg(0x2270)
+#define MemArbWt_R u4reg(0x2280)
+#define UsrCnfg_R u4reg(0x2290)
+#define MemRdQCnfg_R u4reg(0x22a0)
+#define MemQArb_R u4reg(0x22b0)
+#define MemRWArb_R u4reg(0x22c0)
+#define MemBusCnfg_R u4reg(0x22d0)
+#define MemBusCnfg2_R u4reg(0x22e0)
+#define ODTCntl_R u4reg(0x23a0)
+#define MemModeCntl_R u4reg(0x2500)
+#define MemPhyModeCntl_R u4reg(0x2880)
+#define CKDelayL_R u4reg(0x2890)
+#define CKDelayU_R u4reg(0x28a0)
+#define IOPadCntl_R u4reg(0x29a0)
+#define ByteWrClkDelC0B00_R u4reg(0x2800)
+#define ByteWrClkDelC0B01_R u4reg(0x2810)
+#define ByteWrClkDelC0B02_R u4reg(0x2820)
+#define ByteWrClkDelC0B03_R u4reg(0x2830)
+#define ByteWrClkDelC0B04_R u4reg(0x2900)
+#define ByteWrClkDelC0B05_R u4reg(0x2910)
+#define ByteWrClkDelC0B06_R u4reg(0x2920)
+#define ByteWrClkDelC0B07_R u4reg(0x2930)
+#define ByteWrClkDelC0B16_R u4reg(0x2980)
+#define ByteWrClkDelC0B08_R u4reg(0x2a00)
+#define ByteWrClkDelC0B09_R u4reg(0x2a10)
+#define ByteWrClkDelC0B10_R u4reg(0x2a20)
+#define ByteWrClkDelC0B11_R u4reg(0x2a30)
+#define ByteWrClkDelC0B12_R u4reg(0x2b00)
+#define ByteWrClkDelC0B13_R u4reg(0x2b10)
+#define ByteWrClkDelC0B14_R u4reg(0x2b20)
+#define ByteWrClkDelC0B15_R u4reg(0x2b30)
+#define ByteWrClkDelC0B17_R u4reg(0x2b80)
+#define ReadStrobeDelC0B00_R u4reg(0x2840)
+#define ReadStrobeDelC0B01_R u4reg(0x2850)
+#define ReadStrobeDelC0B02_R u4reg(0x2860)
+#define ReadStrobeDelC0B03_R u4reg(0x2870)
+#define ReadStrobeDelC0B04_R u4reg(0x2940)
+#define ReadStrobeDelC0B05_R u4reg(0x2950)
+#define ReadStrobeDelC0B06_R u4reg(0x2960)
+#define ReadStrobeDelC0B07_R u4reg(0x2970)
+#define ReadStrobeDelC0B16_R u4reg(0x2990)
+#define ReadStrobeDelC0B08_R u4reg(0x2a40)
+#define ReadStrobeDelC0B09_R u4reg(0x2a50)
+#define ReadStrobeDelC0B10_R u4reg(0x2a60)
+#define ReadStrobeDelC0B11_R u4reg(0x2a70)
+#define ReadStrobeDelC0B12_R u4reg(0x2b40)
+#define ReadStrobeDelC0B13_R u4reg(0x2b50)
+#define ReadStrobeDelC0B14_R u4reg(0x2b60)
+#define ReadStrobeDelC0B15_R u4reg(0x2b70)
+#define ReadStrobeDelC0B17_R u4reg(0x2b90)
+#define MemInit00_R u4reg(0x2100)
+#define MemInit01_R u4reg(0x2110)
+#define MemInit02_R u4reg(0x2120)
+#define MemInit03_R u4reg(0x2130)
+#define MemInit04_R u4reg(0x2140)
+#define MemInit05_R u4reg(0x2150)
+#define MemInit06_R u4reg(0x2160)
+#define MemInit07_R u4reg(0x2170)
+#define MemInit08_R u4reg(0x2180)
+#define MemInit09_R u4reg(0x2190)
+#define MemInit10_R u4reg(0x21a0)
+#define MemInit11_R u4reg(0x21b0)
+#define MemInit12_R u4reg(0x21c0)
+#define MemInit13_R u4reg(0x21d0)
+#define MemInit14_R u4reg(0x21e0)
+#define MemInit15_R u4reg(0x21f0)
+#define CalConf0_R u4reg(0x29b0)
+#define CalConf1_R u4reg(0x29c0)
+#define MeasStatusC0_R u4reg(0x28f0)
+#define MeasStatusC1_R u4reg(0x29f0)
+#define MeasStatusC2_R u4reg(0x2af0)
+#define MeasStatusC3_R u4reg(0x2bf0)
+#define CalC0_R u4reg(0x28e0)
+#define CalC1_R u4reg(0x29e0)
+#define CalC2_R u4reg(0x2ae0)
+#define CalC3_R u4reg(0x2be0)
+#define RstLdEnVerniersC0_R u4reg(0x28d0)
+#define RstLdEnVerniersC1_R u4reg(0x29d0)
+#define RstLdEnVerniersC2_R u4reg(0x2ad0)
+#define RstLdEnVerniersC3_R u4reg(0x2bd0)
+#define ExtMuxVernier0_R u4reg(0x28b0)
+#define ExtMuxVernier1_R u4reg(0x28c0)
+#define OCDCalCmd_R u4reg(0x2300)
+#define OCDCalCntl_R u4reg(0x2310)
+#define MCCR_R u4reg(0x2440)
+#define MSRSR_R u4reg(0x2410)
+#define MSRER_R u4reg(0x2420)
+#define MSPR_R u4reg(0x2430)
+#define MSCR_R u4reg(0x2400)
+#define MEAR0_R u4reg(0x2460)
+#define MEAR1_R u4reg(0x2470)
+#define MESR_R u4reg(0x2480)
+#define MRSRegCntl_R u4reg(0x20c0)
+#define EMRSRegCntl_R u4reg(0x20d0)
+#define APIMemRdCfg_R u4reg(0x30090)
+#define APIExcp_R u4reg(0x300a0)
+
+/*
+ * common return values
+ */
+#define RET_OK 0
+#define RET_ERR -1
+#define RET_ACERR_CE -1
+#define RET_ACERR_UEWT -2
+#define RET_ACERR_UE -3
+
+/*
+ * 'DIMM slot populated' indicator
+ */
+#define SL_POP 1
+
+/*
+ * spd buffer size
+ */
+#define SPD_BUF_SIZE 0x40
+
+/*
+ * maximum number of DIMM banks & DIMM groups
+ */
+#define NUM_SLOTS 8
+#define NUM_BANKS ( NUM_SLOTS / 2 )
+#define MAX_DGROUPS ( NUM_SLOTS / 2 )
+#define SLOT_ADJ() ( ( IS_MAUI ) ? NUM_SLOTS / 4 : NUM_SLOTS / 2 )
+
+/*
+ * values needed for auto calibration
+ */
+#define MAX_DRANKS NUM_SLOTS
+#define MAX_BLANE 18
+#define MAX_RMD 0xf
+
+/*
+ * maximum number of supported CAS latencies
+ */
+#define NUM_CL 3
+
+/*
+ * min/max supported CL values by U4
+ */
+#define U4_MIN_CL 3
+#define U4_MAX_CL 5
+
+/*
+ * DIMM constants
+ */
+#define DIMM_TYPE_MSK BIT(0)
+#define DIMM_ORG_x4 BIT(0)
+#define DIMM_ORG_x8 BIT(1)
+#define DIMM_ORG_x16 BIT(2)
+#define DIMM_ORG_MIXx8x16 BIT(30)
+#define DIMM_ORG_UNKNOWN 0
+#define DIMM_WIDTH 72
+#define DIMM_BURSTLEN_4 BIT(2)
+
+/*
+ * L2 cache size
+ */
+#define L2_CACHE_SIZE (uint32_t) 0x100000
+
+/*
+ * scrub types
+ */
+#define IMMEDIATE_SCRUB IBIT(0)
+#define IMMEDIATE_SCRUB_WITH_FILL ( IBIT(0) | IBIT(1) )
+#define BACKGROUND_SCRUB ( IBIT(1) | ( 0x29 << 16 ) )
+
+/*
+ * I2C starting slave addresses of the DIMM banks
+ */
+#define I2C_START 0x50
+
+/*
+ * Index to the speed dependend DIMM settings
+ */
+enum
+{
+ SPEED_IDX_400 = 0,
+ SPEED_IDX_533,
+ SPEED_IDX_667,
+ NUM_SPEED_IDX
+};
+
+/*
+ * number of read/write strobes of the U4
+ */
+#define NUM_STROBES 18
+
+/*
+ * 2GB hole definition
+ */
+static const uint64_t _2GB = (uint64_t) 0x80000000;
+
+/*
+ * local types
+ *******************************************************************************
+ */
+/*
+ * DIMM definition
+ */
+typedef struct
+{
+ uint32_t m_pop_u32; // set if bank is populated
+ uint32_t m_bank_u32; // bank number
+ uint32_t m_clmsk_u32; // mask of supported CAS latencies
+ uint32_t m_clcnt_u32; // number of supporetd CAS latencies
+ uint32_t m_clval_pu32[NUM_CL]; // values of supporeted CAS latencies
+ uint32_t m_speed_pu32[NUM_CL]; // speed (Mhz) at CAS latency of same index
+ uint32_t m_size_u32; // chip size in Mb
+ uint32_t m_rank_u32; // # of ranks, total size = chip size*rank
+ uint32_t m_orgmsk_u32; // data organisation (x4, x8, x16) (mask)
+ uint32_t m_orgval_u32; // data organisation (value)
+ uint32_t m_width_u32; // data width
+ uint32_t m_ecc_u32; // set if ecc
+ uint32_t m_type_u32; // rdimm or udimm
+ uint32_t m_burst_u32; // supported burst lengths
+ uint32_t m_bankcnt_u32; // number of banks
+
+ /*
+ * the following timing values are all in 1/100ns
+ */
+ uint32_t m_tCK_pu32[NUM_CL];
+ uint32_t m_tRAS_u32;
+ uint32_t m_tRTP_u32;
+ uint32_t m_tRP_u32;
+ uint32_t m_tWR_u32;
+ uint32_t m_tRRD_u32;
+ uint32_t m_tRC_u32;
+ uint32_t m_tRCD_u32;
+ uint32_t m_tWTR_u32;
+ uint32_t m_tREF_u32;
+ uint32_t m_tRFC_u32;
+} dimm_t;
+
+/*
+ * DIMM group definition
+ */
+typedef struct
+{
+ uint32_t m_size_u32; // group size in MB
+ uint32_t m_start_u32; // in 128Mb granularity
+ uint32_t m_end_u32; // in 128Mb granularity
+ uint32_t m_ss_u32; // single sided/double sided
+ uint32_t m_csmode_u32; // selected CS mode for this group
+ uint32_t m_add2g_u32;
+ uint32_t m_sub2g_u32;
+ uint32_t m_memmd_u32; // selected mem mode for this group
+ uint32_t m_dcnt_u32; // number of DIMMs in group
+ dimm_t *m_dptr[NUM_SLOTS];
+} dgroup_t;
+
+/*
+ * auto calibration result structure
+ */
+typedef struct
+{
+ uint32_t m_MemBusCnfg_u32;
+ uint32_t m_MemBusCnfg2_u32;
+ uint32_t m_RstLdEnVerniers_pu32[4];
+} auto_calib_t;
+
+/*
+ * ECC error structure
+ */
+typedef struct
+{
+ int32_t m_err_i32;
+ uint32_t m_uecnt_u32; // number of uncorrectable errors
+ uint32_t m_cecnt_u32; // number of correctable errors
+ uint32_t m_rank_u32; // erroneous rank
+ uint32_t m_col_u32; // erroneous column
+ uint32_t m_row_u32; // erroneous row
+ uint32_t m_bank_u32; // erroneous bank
+} eccerror_t;
+
+/*
+ * U4 register setup structure
+ */
+typedef struct
+{
+ /*
+ * external MUX delays
+ */
+ uint32_t RRMux;
+ uint32_t WRMux;
+ uint32_t WWMux;
+ uint32_t RWMux;
+
+ /*
+ * default Wr/Rd Queue & Arbiter register settings
+ */
+ uint32_t MemRdQCnfg;
+ uint32_t MemWrQCnfg;
+ uint32_t MemQArb;
+ uint32_t MemRWArb;
+
+ /*
+ * misc fixed register values
+ */
+ uint32_t ODTCntl;
+ uint32_t IOPadCntl;
+ uint32_t MemPhyModeCntl;
+ uint32_t OCDCalCntl;
+ uint32_t OCDCalCmd;
+ uint32_t CKDelayL;
+ uint32_t CKDelayU;
+ uint32_t MemBusCnfg;
+ uint32_t CAS1Dly0;
+ uint32_t CAS1Dly1;
+ uint32_t ByteWrClkDel[NUM_STROBES];
+ uint32_t ReadStrobeDel[NUM_STROBES];
+} reg_statics_t;
+
+/*
+ * local variables
+ *******************************************************************************
+ */
+static dimm_t m_dimm[NUM_SLOTS];
+static dimm_t m_gendimm;
+static uint32_t m_dcnt_u32;
+static dimm_t *m_dptr[NUM_SLOTS];
+static uint32_t m_bankoff_u32;
+static uint32_t m_bankpop_u32[NUM_BANKS];
+static uint32_t m_dclidx_u32;
+static uint32_t m_dgrcnt_u32;
+static dgroup_t m_dgroup[MAX_DGROUPS];
+static dgroup_t *m_dgrptr[MAX_DGROUPS];
+static uint64_t m_memsize_u64; // memsize in bytes
+
+/*
+ * local functions
+ *******************************************************************************
+ */
+static void
+progbar( void )
+{
+ static uint8_t bar[] =
+ { '|', '/', '-', '\\', 0 };
+ static uint32_t idx = 0;
+
+ printf( "\b%c", bar[idx] );
+
+ if( bar[++idx] == 0 ) {
+ idx = 0;
+ }
+
+}
+
+static void
+or32_ci( uint64_t r, uint32_t m )
+{
+ uint32_t v;
+
+ v = load32_ci( r );
+ v |= m;
+ store32_ci( r, v );
+}
+
+static void
+and32_ci( uint64_t r, uint32_t m )
+{
+ uint32_t v;
+
+ v = load32_ci( r );
+ v &= m;
+ store32_ci( r, v );
+}
+
+static void
+dly( uint64_t volatile f_wait_u64 ) \
+{
+ while( f_wait_u64 ) {
+ f_wait_u64--;
+ }
+}
+
+/*
+ * local i2c access functions
+ */
+static void
+i2c_term( void )
+{
+ uint32_t l_stat_u32;
+
+ /*
+ * clear out all pending int's and wait
+ * for the stop condition to occur
+ */
+ do {
+ l_stat_u32 = load32_ci( I2C_ISR_R );
+ store32_ci( I2C_ISR_R, l_stat_u32 );
+ } while( ( l_stat_u32 & IBIT(29) ) == 0 );
+
+}
+
+static int32_t
+i2c_read( uint32_t f_addr_u32, uint32_t f_suba_u32, uint8_t *f_buf_pu08, uint32_t f_len_u32 )
+{
+ uint32_t l_val_u32;
+ int32_t l_ret_i32 = 1;
+
+ /*
+ * parameter check
+ */
+ if( ( f_addr_u32 > (uint32_t) 0x7f ) ||
+ ( f_suba_u32 > (uint32_t) 0xff ) ||
+ ( f_len_u32 == (uint32_t) 0x00 ) ) {
+ return RET_ERR;
+ }
+
+ /*
+ * set I2C Interface to combined mode
+ */
+ store32_ci( I2C_MODE_R, IBIT(28) | IBIT(29) );
+
+ /*
+ * set address, subaddress & read mode
+ */
+ store32_ci( I2C_ADDR_R, ( f_addr_u32 << 1 ) | (uint32_t) 0x1 );
+ store32_ci( I2C_SUBA_R, f_suba_u32 );
+
+ /*
+ * start address transmission phase
+ */
+ store32_ci( I2C_CTRL_R, IBIT(30) );
+
+ /*
+ * wait for address transmission to finish
+ */
+ do {
+ l_val_u32 = load32_ci( I2C_ISR_R );
+ } while( ( l_val_u32 & IBIT(30) ) == 0 );
+
+ /*
+ * check for success
+ */
+ if( ( load32_ci( I2C_STAT_R ) & IBIT(30) ) == 0 ) {
+ i2c_term();
+ return RET_ERR;
+ } else {
+ // send ack
+ store32_ci( I2C_CTRL_R, IBIT(31) );
+ // clear int
+ store32_ci( I2C_ISR_R, IBIT(30) );
+ }
+
+ /*
+ * read data
+ */
+ while( l_ret_i32 > 0 ) {
+ l_val_u32 = load32_ci( I2C_ISR_R );
+
+ if( ( l_val_u32 & IBIT(31) ) != 0 ) {
+ // data was received
+ *f_buf_pu08 = ( uint8_t ) load32_ci( I2C_DATA_R );
+
+ f_buf_pu08++;
+ f_len_u32--;
+
+ /*
+ * continue when there is more data to read or
+ * exit if not
+ */
+ if( f_len_u32 != 0 ) {
+ // send ack
+ store32_ci( I2C_CTRL_R, IBIT(31) );
+ // clear int
+ store32_ci( I2C_ISR_R, IBIT(31) );
+ } else {
+ // send nack
+ store32_ci( I2C_CTRL_R, 0 );
+ // set exit flag
+ l_ret_i32 = RET_OK;
+ }
+
+ } else if( ( l_val_u32 & IBIT(29) ) != 0 ) {
+ // early stop condition
+ // set exit flag
+ l_ret_i32 = RET_ERR;
+ }
+
+ };
+
+ i2c_term();
+
+ return( l_ret_i32 );
+}
+
+static uint32_t
+i2c_get_slot( uint32_t i2c_addr )
+{
+ uint32_t slot;
+
+ slot = ( i2c_addr - I2C_START ) / 2;
+
+ if( ( i2c_addr & 0x1 ) != 0 ) {
+ slot += SLOT_ADJ();
+ }
+
+ return slot;
+}
+
+/*
+ * 'serial presence detect' interpretation functions
+ */
+static uint32_t
+ddr2_get_dimm_rank( uint8_t *f_spd_pu08 )
+{
+ static const int RANK_IDX = (int) 5;
+
+ return (uint32_t) ( f_spd_pu08[RANK_IDX] & 0x3 ) + 1;
+}
+
+static uint32_t
+ddr2_get_dimm_size( uint8_t *f_spd_pu08 )
+{
+ static const int SIZE_IDX = (int) 31;
+ uint8_t l_smsk_u08;
+ uint32_t i;
+
+ l_smsk_u08 = ( f_spd_pu08[SIZE_IDX] << 3 ) |
+ ( f_spd_pu08[SIZE_IDX] >> 5 );
+
+ for( i = 0; ( ( l_smsk_u08 & ( (uint8_t) 0x1 << i ) ) == 0 ) ; i++ );
+
+ return (uint32_t) 0x80 << i;
+}
+
+static uint32_t
+ddr2_get_dimm_type( uint8_t *f_spd_pu08 )
+{
+ static const int TYPE_IDX = (int) 20;
+
+ return (uint32_t) f_spd_pu08[TYPE_IDX] & DIMM_TYPE_MSK;
+}
+
+static uint32_t
+ddr2_get_dimm_org( uint8_t *f_spd_pu08, uint32_t /*out*/ *f_omsk_pu32 )
+{
+ static const int ORG_IDX = (int) 13;
+ uint32_t l_ret_u32 = (uint32_t) f_spd_pu08[ORG_IDX];
+
+ if( l_ret_u32 == 4 ) {
+ *f_omsk_pu32 = DIMM_ORG_x4;
+ } else if( l_ret_u32 == 8 ) {
+ *f_omsk_pu32 = DIMM_ORG_x8;
+ *f_omsk_pu32 |= DIMM_ORG_MIXx8x16;
+ } else if( l_ret_u32 == 16 ) {
+ *f_omsk_pu32 = DIMM_ORG_x16;
+ *f_omsk_pu32 |= DIMM_ORG_MIXx8x16;
+ } else {
+ *f_omsk_pu32 = DIMM_ORG_UNKNOWN;
+ l_ret_u32 = (uint32_t) ~0;
+ }
+
+ return l_ret_u32;
+}
+
+static uint32_t
+ddr2_get_dimm_width( uint8_t *f_spd_pu08 )
+{
+ static const int WIDTH_IDX = (int) 6;
+
+ return (uint32_t) f_spd_pu08[WIDTH_IDX];
+}
+
+static uint32_t
+ddr2_get_dimm_ecc( uint8_t *f_spd_pu08 )
+{
+ static const int ECC_IDX = (int) 11;
+
+ return ( f_spd_pu08[ECC_IDX] & BIT(1) ) != 0;
+}
+
+static uint32_t
+ddr2_get_dimm_burstlen( uint8_t *f_spd_pu08 )
+{
+ static const int BURST_IDX = (int) 16;
+
+ return (uint32_t) f_spd_pu08[BURST_IDX];
+}
+
+static void
+ddr2_get_dimm_speed( dimm_t *f_dimm, uint8_t *f_spd_pu08 )
+{
+ static const int SPEED_IDX[] = { 25, 23, 9 };
+ static const uint32_t NS[] = { 25, 33, 66, 75 };
+ uint8_t l_tmp_u08;
+ uint32_t l_dspeed_u32;
+ uint32_t idx = 0;
+ uint32_t i;
+
+ for( i = NUM_CL - f_dimm->m_clcnt_u32; i < NUM_CL; i++ ) {
+ l_tmp_u08 = f_spd_pu08[SPEED_IDX[i]];
+ l_dspeed_u32 = (uint32_t) ( l_tmp_u08 >> 4 ) * 100;
+ l_tmp_u08 &= (uint8_t) 0xf;
+
+ if( l_tmp_u08 >= (uint8_t) 10 ) {
+ l_dspeed_u32 += NS[l_tmp_u08 - 10];
+ } else {
+ l_dspeed_u32 += (uint32_t) l_tmp_u08 * 10;
+ }
+
+ f_dimm->m_tCK_pu32[idx] = l_dspeed_u32;
+ f_dimm->m_speed_pu32[idx] = (uint32_t) 2000000 / l_dspeed_u32;
+ f_dimm->m_speed_pu32[idx] += (uint32_t) 5;
+ f_dimm->m_speed_pu32[idx] /= (uint32_t) 10;
+ idx++;
+ }
+
+}
+
+static void
+ddr2_get_dimm_timings( dimm_t *f_dimm, uint8_t *f_spd_pu08 )
+{
+ static const uint32_t NS[] = { 00, 25, 33, 50, 66, 75, 00, 00 };
+ static const uint32_t USMUL = (uint32_t) 390625;
+ static const int tREF_IDX = (int) 12;
+ static const int tRP_IDX = (int) 27;
+ static const int tRRD_IDX = (int) 28;
+ static const int tRCD_IDX = (int) 29;
+ static const int tRAS_IDX = (int) 30;
+ static const int tWR_IDX = (int) 36;
+ static const int tWTR_IDX = (int) 37;
+ static const int tRTP_IDX = (int) 38;
+ static const int tRC_IDX = (int) 41; // & 40
+ static const int tRFC_IDX = (int) 42; // & 40
+
+ uint32_t l_tmp_u32;
+
+ f_dimm->m_tRP_u32 = (uint32_t) f_spd_pu08[tRP_IDX] * 25;
+ f_dimm->m_tRRD_u32 = (uint32_t) f_spd_pu08[tRRD_IDX] * 25;
+ f_dimm->m_tRCD_u32 = (uint32_t) f_spd_pu08[tRCD_IDX] * 25;
+ f_dimm->m_tWR_u32 = (uint32_t) f_spd_pu08[tWR_IDX] * 25;
+ f_dimm->m_tWTR_u32 = (uint32_t) f_spd_pu08[tWTR_IDX] * 25;
+ f_dimm->m_tRTP_u32 = (uint32_t) f_spd_pu08[tRTP_IDX] * 25;
+ f_dimm->m_tRAS_u32 = (uint32_t) f_spd_pu08[tRAS_IDX] * 100;
+
+ l_tmp_u32 = (uint32_t) ( f_spd_pu08[tRC_IDX - 1] >> 4 );
+ l_tmp_u32 &= (uint32_t) 0x7;
+ f_dimm->m_tRC_u32 = (uint32_t) f_spd_pu08[tRC_IDX] * 100 +
+ NS[l_tmp_u32];
+
+ l_tmp_u32 = (uint32_t) f_spd_pu08[tRFC_IDX - 2];
+ l_tmp_u32 &= (uint32_t) 0xf;
+ f_dimm->m_tRFC_u32 = (uint32_t) 256 * ( l_tmp_u32 & (uint32_t) 0x1 );
+ f_dimm->m_tRFC_u32 += (uint32_t) f_spd_pu08[tRFC_IDX];
+ f_dimm->m_tRFC_u32 *= 100;
+ l_tmp_u32 >>= 1;
+ f_dimm->m_tRFC_u32 += NS[l_tmp_u32];
+
+ l_tmp_u32 = (uint32_t) f_spd_pu08[tREF_IDX];
+ l_tmp_u32 &= (uint32_t) 0x7f;
+
+ if( l_tmp_u32 == 0 ) {
+ l_tmp_u32 = (uint32_t) 2;
+ } else if( l_tmp_u32 <= (uint32_t) 2 ) {
+ l_tmp_u32--;
+ }
+
+ f_dimm->m_tREF_u32 = ( l_tmp_u32 + 1 ) * USMUL;
+}
+
+static uint32_t
+ddr2_get_banks( uint8_t *f_spd_pu08 )
+{
+ static const int BANK_IDX = (int) 17;
+
+ return (uint32_t) f_spd_pu08[BANK_IDX];
+}
+
+static uint32_t
+ddr2_get_cl_mask( uint8_t *f_spd_pu08 )
+{
+ static const int CL_IDX = (int) 18;
+
+ return (uint32_t) f_spd_pu08[CL_IDX];
+}
+
+static void
+ddr2_get_cl( dimm_t *f_dimm )
+{
+ uint32_t l_clcnt_u32 = 0;
+ uint32_t i;
+
+ for( i = 0; ( i < 8 ) && ( l_clcnt_u32 < NUM_CL ) ; i++ ) {
+
+ if( ( f_dimm->m_clmsk_u32 & ( (uint32_t) 0x1 << i ) ) != 0 ) {
+ f_dimm->m_clval_pu32[l_clcnt_u32] = i;
+ l_clcnt_u32++;
+ }
+
+ }
+
+ f_dimm->m_clcnt_u32 = l_clcnt_u32;
+}
+
+static uint32_t
+ddr2_cl2speed( dimm_t *f_dimm, uint32_t f_cl_u32, uint32_t *f_tCK_pu32 )
+{
+ uint32_t i;
+
+ for( i = 0; ( f_dimm->m_clval_pu32[i] != f_cl_u32 ) &&
+ ( i < NUM_CL ); i++ );
+
+ if( i == NUM_CL ) {
+ return (uint32_t) ~0;
+ }
+
+ *f_tCK_pu32 = f_dimm->m_tCK_pu32[i];
+
+ return f_dimm->m_speed_pu32[i];
+}
+
+static void
+ddr2_setupDIMM( dimm_t *f_dimm, uint32_t f_bank_u32, uint8_t *f_spd_pu08 )
+{
+ f_dimm->m_pop_u32 = SL_POP;
+ f_dimm->m_bank_u32 = f_bank_u32;
+ f_dimm->m_size_u32 = ddr2_get_dimm_size( f_spd_pu08 );
+ f_dimm->m_rank_u32 = ddr2_get_dimm_rank( f_spd_pu08 );
+ f_dimm->m_type_u32 = ddr2_get_dimm_type( f_spd_pu08 );
+ f_dimm->m_orgval_u32 = ddr2_get_dimm_org( f_spd_pu08, &f_dimm->m_orgmsk_u32 );
+ f_dimm->m_width_u32 = ddr2_get_dimm_width( f_spd_pu08 );
+ f_dimm->m_ecc_u32 = ddr2_get_dimm_ecc( f_spd_pu08 );
+ f_dimm->m_burst_u32 = ddr2_get_dimm_burstlen( f_spd_pu08 );
+ f_dimm->m_clmsk_u32 = ddr2_get_cl_mask( f_spd_pu08 );
+ f_dimm->m_bankcnt_u32 = ddr2_get_banks( f_spd_pu08 );
+
+ ddr2_get_cl( f_dimm );
+ ddr2_get_dimm_speed( f_dimm, f_spd_pu08 );
+ ddr2_get_dimm_timings( f_dimm, f_spd_pu08 );
+}
+
+static int32_t
+ddr2_checkSPD( uint8_t *f_spd_pu08 )
+{
+ uint8_t crc = 0;
+ uint32_t i;
+
+ for( i = 0; i < SPD_BUF_SIZE - 1; i++ ) {
+ crc += f_spd_pu08[i];
+ }
+
+ if( crc != f_spd_pu08[i] ) {
+ return RET_ERR;
+ }
+
+ return RET_OK;
+}
+
+static int32_t
+ddr2_readSPDs( void )
+{
+ static const uint32_t MAX_SPD_FAIL = 3;
+ uint8_t l_spdbuf_pu08[SPD_BUF_SIZE];
+ uint32_t l_bankfail_u32 = 0;
+ uint32_t l_spdfail_u32 = 0;
+ int32_t l_i2c_i32 = RET_OK;
+ int32_t l_spd_i32 = RET_OK;
+ int32_t ret = RET_OK;
+ uint32_t i;
+
+ /*
+ * read spd's and detect populated slots
+ */
+ for( i = 0; i < NUM_SLOTS; i++ ) {
+ /*
+ * indicate slot as empty
+ */
+ m_dimm[i].m_pop_u32 = 0;
+
+ /*
+ * check whether bank is switched off
+ */
+ if( ( m_bankoff_u32 & ( 0x1 << ( i / 2 ) ) ) != 0 ) {
+ continue;
+ }
+
+ /*
+ * read SPD data
+ */
+
+ /*
+ * reset SPD fail counter
+ */
+ l_spdfail_u32 = MAX_SPD_FAIL;
+ l_spd_i32 = RET_OK;
+
+ while( l_spdfail_u32 != 0 ) {
+ l_i2c_i32 = i2c_read( I2C_START + i, 0x0, l_spdbuf_pu08, SPD_BUF_SIZE );
+
+ if( l_i2c_i32 == RET_OK ) {
+ l_spd_i32 = ddr2_checkSPD( l_spdbuf_pu08 );
+
+ if( l_spd_i32 == RET_OK ) {
+ l_spdfail_u32 = 0;
+ } else {
+ l_spdfail_u32--;
+ }
+
+ } else {
+ l_spdfail_u32--;
+ }
+
+ }
+
+ if( l_spd_i32 != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "\r\n [ERROR -> SPD read failure in slot %u]",
+ i2c_get_slot( I2C_START + i ) );
+ #endif
+
+ l_bankfail_u32 |= ( 0x1 << ( i / 2 ) );
+ ret = RET_ERR;
+ } else if( l_i2c_i32 == RET_OK ) {
+ /*
+ * slot is populated
+ */
+ ddr2_setupDIMM( &m_dimm[i], i / 2, l_spdbuf_pu08 );
+
+ m_dptr[m_dcnt_u32] = &m_dimm[i];
+ m_dcnt_u32++;
+ }
+
+ }
+
+ if( ret != RET_OK ) {
+ m_bankoff_u32 |= l_bankfail_u32;
+ #ifdef U4_INFO
+ printf( "\r\n" );
+ #endif
+ }
+
+ return ret;
+}
+
+static int32_t
+ddr2_setupDIMMcfg( void )
+{
+ uint32_t l_tmp_u32;
+ uint32_t l_tmp0_u32;
+ uint32_t l_tmp1_u32;
+ uint32_t i, j, e, b;
+
+ /*
+ * check wether on board DIMM slot population is valid
+ */
+ e = 0;
+ b = 0;
+ for( i = 0; i < NUM_SLOTS; i += 2 ) {
+
+ switch( m_dimm[i].m_pop_u32 + m_dimm[i+1].m_pop_u32 ) {
+ case 0: {
+ m_bankpop_u32[i/2] = 0;
+ break;
+ }
+
+ case 2 * SL_POP: {
+ m_bankpop_u32[i/2] = !0;
+ b++;
+ break;
+ }
+
+ default: {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> only 1 DIMM installed in bank %u]", i/2 );
+ #endif
+ e++;
+ }
+
+ }
+
+ }
+
+ /*
+ * return on error
+ */
+ if( e != 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ if( b == 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> no (functional) memory installed]\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * check DIMM compatibility
+ * configuration is 128 bit data/128 bit bus
+ * -all DIMMs must be organized as x4
+ * -all DIMMs must be 72 bit wide with ECC
+ * -all DIMMs must be registered DIMMs (RDIMMs)
+ * -paired DIMMs must have the same # of ranks, size & organization
+ */
+
+ /*
+ * check DIMM ranks & sizes
+ */
+ e = 0;
+ for( i = 0; i < NUM_SLOTS; i += 2 ) {
+
+ if( ( m_bankpop_u32[i/2] != 0 ) &&
+ ( ( m_dimm[i].m_rank_u32 != m_dimm[i+1].m_rank_u32 ) ||
+ ( m_dimm[i].m_size_u32 != m_dimm[i+1].m_size_u32 ) ) ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> installed DIMMs in bank %u have different ranks/sizes]", i/2 );
+ #endif
+ e++;
+ }
+
+ }
+
+ /*
+ * return on error
+ */
+ if( e != 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * check valid DIMM organisation (must be x4)
+ */
+ e = 0;
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+
+ if( ( m_dptr[i]->m_orgmsk_u32 & DIMM_ORG_x4 ) == 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> wrong DIMM organisation in bank %u]",
+ m_dptr[i]->m_bank_u32 );
+ #endif
+ e++;
+ }
+
+ }
+
+ /*
+ * return on error
+ */
+ if( e != 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ e = (uint32_t) ~0;
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+ e &= m_dptr[i]->m_type_u32;
+ }
+
+ /*
+ * return on error
+ */
+ if( e == 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> installed DIMMs are of different type]\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * setup generic dimm
+ */
+ m_gendimm.m_type_u32 = e;
+
+ /*
+ * check valid width, ecc & burst length
+ */
+ e = 0;
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+
+ if( m_dptr[i]->m_width_u32 != DIMM_WIDTH ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> invalid DIMM width in bank %u]",
+ m_dptr[i]->m_bank_u32 );
+ #endif
+ e++;
+ }
+
+ if( m_dptr[i]->m_ecc_u32 == 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> DIMM(s) do not support ECC in bank %u]",
+ m_dptr[i]->m_bank_u32 );
+ #endif
+ e++;
+ }
+
+ if( ( m_dptr[i]->m_burst_u32 & DIMM_BURSTLEN_4 ) == 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> DIMM(s) have invalid burst length in bank %u]",
+ m_dptr[i]->m_bank_u32 );
+ #endif
+ e++;
+ }
+
+ }
+
+ /*
+ * return on error
+ */
+ if( e != 0 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * setup generic dimm
+ */
+ m_gendimm.m_width_u32 = m_dptr[0]->m_width_u32;
+ m_gendimm.m_ecc_u32 = m_dptr[0]->m_ecc_u32;
+ m_gendimm.m_burst_u32 = m_dptr[0]->m_burst_u32;
+
+ /*
+ * success
+ */
+ m_gendimm.m_pop_u32 = SL_POP;
+
+ /*
+ * setup timing parameters
+ */
+
+ /*
+ * find smallest common CL value
+ */
+ l_tmp_u32 = (uint32_t) ~0;
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+ l_tmp_u32 &= m_dptr[i]->m_clmsk_u32;
+ }
+
+ m_gendimm.m_clmsk_u32 = l_tmp_u32;
+ ddr2_get_cl( &m_gendimm );
+
+ /*
+ * find fastest common DIMM speed for all common CL values
+ */
+ for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) {
+ m_gendimm.m_speed_pu32[i] = (uint32_t) ~0;
+
+ for( j = 0; j < m_dcnt_u32; j++ ) {
+ l_tmp0_u32 =
+ ddr2_cl2speed( m_dptr[j],
+ m_gendimm.m_clval_pu32[i],
+ &l_tmp1_u32 );
+
+ if( m_gendimm.m_speed_pu32[i] > l_tmp0_u32 ) {
+ m_gendimm.m_speed_pu32[i] = l_tmp0_u32;
+ m_gendimm.m_tCK_pu32[i] = l_tmp1_u32;
+ }
+
+ }
+
+ }
+
+ /*
+ * check wether cl values are supported by U4
+ */
+ for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) {
+
+ if( ( m_gendimm.m_clval_pu32[i] >= U4_MIN_CL ) &&
+ ( m_gendimm.m_clval_pu32[i] <= U4_MAX_CL ) ) {
+ break;
+ }
+
+ }
+
+ if( i == m_gendimm.m_clcnt_u32 ) {
+ #ifdef U4_DEBUG
+ printf( "\r\n [ERROR -> DIMM's CL values not supported]\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * choose cl/speed values to use: prefer speed over CL
+ * i holds smallest supported cl value of u4 already
+ */
+ l_tmp_u32 = 0;
+ while( i < m_gendimm.m_clcnt_u32 ) {
+
+ if( l_tmp_u32 < m_gendimm.m_speed_pu32[i] ) {
+ l_tmp_u32 = m_gendimm.m_speed_pu32[i];
+ m_dclidx_u32 = i;
+ }
+
+ i++;
+ }
+
+ /*
+ * choose largest number of banks
+ */
+ m_gendimm.m_bankcnt_u32 = 0;
+
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+
+ if( m_gendimm.m_bankcnt_u32 < m_dptr[i]->m_bankcnt_u32 ) {
+ m_gendimm.m_bankcnt_u32 = m_dptr[i]->m_bankcnt_u32;
+ }
+
+ }
+
+ /*
+ * setup fastest possible timing parameters for all DIMMs
+ */
+ m_gendimm.m_tRP_u32 = 0;
+ m_gendimm.m_tRRD_u32 = 0;
+ m_gendimm.m_tRCD_u32 = 0;
+ m_gendimm.m_tWR_u32 = 0;
+ m_gendimm.m_tWTR_u32 = 0;
+ m_gendimm.m_tRTP_u32 = 0;
+ m_gendimm.m_tRAS_u32 = 0;
+ m_gendimm.m_tRC_u32 = 0;
+ m_gendimm.m_tRFC_u32 = 0;
+ m_gendimm.m_tREF_u32 = (uint32_t) ~0;
+
+ for( i = 0; i < m_dcnt_u32; i++ ) {
+
+ if( m_gendimm.m_tRP_u32 < m_dptr[i]->m_tRP_u32 ) {
+ m_gendimm.m_tRP_u32 = m_dptr[i]->m_tRP_u32;
+ }
+
+ if( m_gendimm.m_tRRD_u32 < m_dptr[i]->m_tRRD_u32 ) {
+ m_gendimm.m_tRRD_u32 = m_dptr[i]->m_tRRD_u32;
+ }
+
+ if( m_gendimm.m_tRCD_u32 < m_dptr[i]->m_tRCD_u32 ) {
+ m_gendimm.m_tRCD_u32 = m_dptr[i]->m_tRCD_u32;
+ }
+
+ if( m_gendimm.m_tWR_u32 < m_dptr[i]->m_tWR_u32 ) {
+ m_gendimm.m_tWR_u32 = m_dptr[i]->m_tWR_u32;
+ }
+
+ if( m_gendimm.m_tWTR_u32 < m_dptr[i]->m_tWTR_u32 ) {
+ m_gendimm.m_tWTR_u32 = m_dptr[i]->m_tWTR_u32;
+ }
+
+ if( m_gendimm.m_tRTP_u32 < m_dptr[i]->m_tRTP_u32 ) {
+ m_gendimm.m_tRTP_u32 = m_dptr[i]->m_tRTP_u32;
+ }
+
+ if( m_gendimm.m_tRAS_u32 < m_dptr[i]->m_tRAS_u32 ) {
+ m_gendimm.m_tRAS_u32 = m_dptr[i]->m_tRAS_u32;
+ }
+
+ if( m_gendimm.m_tRC_u32 < m_dptr[i]->m_tRC_u32 ) {
+ m_gendimm.m_tRC_u32 = m_dptr[i]->m_tRC_u32;
+ }
+
+ if( m_gendimm.m_tRFC_u32 < m_dptr[i]->m_tRFC_u32 ) {
+ m_gendimm.m_tRFC_u32 = m_dptr[i]->m_tRFC_u32;
+ }
+
+ if( m_gendimm.m_tREF_u32 > m_dptr[i]->m_tREF_u32 ) {
+ m_gendimm.m_tREF_u32 = m_dptr[i]->m_tREF_u32;
+ }
+
+ }
+
+ return RET_OK;
+}
+
+static void
+u4_group2dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -at least 2 slots are populated
+ * -the 2 DIMMs are equal
+ * -DIMMs are double sided (2 ranks)
+ *
+ * RESULT:
+ * 1 group of 2 ranks (2 ranks/2 DIMMs)
+ * -> CS mode 1 (one double sided DIMM pair)
+ */
+ l_dgr->m_size_u32 = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 0;
+ l_dgr->m_csmode_u32 = 1;
+ l_dgr->m_dcnt_u32 = 2;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+
+ m_dgrcnt_u32++;
+}
+
+static void
+u4_group2dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -at least 2 slots are populated
+ * -the 2 DIMMs are equal
+ * -DIMMs are single sided (1 rank)
+ *
+ * RESULT:
+ * 1 group of 1 rank (1 rank/2 DIMMs)
+ * -> CS mode 0 (one single sided DIMM pair)
+ */
+ l_dgr->m_size_u32 = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 1;
+ l_dgr->m_csmode_u32 = 0;
+ l_dgr->m_dcnt_u32 = 2;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+
+ m_dgrcnt_u32++;
+}
+
+static void
+u4_group4dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1,
+ dimm_t *f_dimm2, dimm_t *f_dimm3 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -4 slots are populated
+ * -all 4 DIMMs are equal
+ * -DIMMs are double sided (2 ranks)
+ *
+ * RESULT:
+ * 1 group of 4 ranks (2 ranks/2 DIMMs)
+ * -> CS mode 2 (two double sided DIMM pairs)
+ */
+ l_dgr->m_size_u32 = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 0;
+ l_dgr->m_csmode_u32 = 2;
+ l_dgr->m_dcnt_u32 = 4;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+ l_dgr->m_dptr[2] = f_dimm2;
+ l_dgr->m_dptr[3] = f_dimm3;
+
+ m_dgrcnt_u32++;
+}
+
+static void
+u4_group4dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1,
+ dimm_t *f_dimm2, dimm_t *f_dimm3 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -4 slots are populated
+ * -all 4 DIMMs are equal
+ * -DIMMs are single sided (1 rank)
+ *
+ * RESULT:
+ * 1 group of 2 ranks (1 rank/2 DIMMs)
+ * -> CS mode 1 (two single sided DIMM pairs)
+ */
+ l_dgr->m_size_u32 = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 1;
+ l_dgr->m_csmode_u32 = 1;
+ l_dgr->m_dcnt_u32 = 4;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+ l_dgr->m_dptr[2] = f_dimm2;
+ l_dgr->m_dptr[3] = f_dimm3;
+
+ m_dgrcnt_u32++;
+}
+
+static void
+u4_group8dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1,
+ dimm_t *f_dimm2, dimm_t *f_dimm3,
+ dimm_t *f_dimm4, dimm_t *f_dimm5,
+ dimm_t *f_dimm6, dimm_t *f_dimm7 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -8 slots are populated
+ * -all 8 DIMMs are equal
+ * -DIMMs are double sided (2 ranks)
+ *
+ * RESULT:
+ * 1 group of 8 ranks (2 ranks/2 DIMMs)
+ * -> CS mode 3 (four double sided DIMM pairs)
+ */
+ l_dgr->m_size_u32 = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 0;
+ l_dgr->m_csmode_u32 = 3;
+ l_dgr->m_dcnt_u32 = 8;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+ l_dgr->m_dptr[2] = f_dimm2;
+ l_dgr->m_dptr[3] = f_dimm3;
+ l_dgr->m_dptr[4] = f_dimm4;
+ l_dgr->m_dptr[5] = f_dimm5;
+ l_dgr->m_dptr[6] = f_dimm6;
+ l_dgr->m_dptr[7] = f_dimm7;
+
+ m_dgrcnt_u32++;
+}
+
+static void
+u4_group8dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1,
+ dimm_t *f_dimm2, dimm_t *f_dimm3,
+ dimm_t *f_dimm4, dimm_t *f_dimm5,
+ dimm_t *f_dimm6, dimm_t *f_dimm7 )
+{
+ dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32];
+
+ /*
+ * known conditions at this point:
+ * -8 slots are populated
+ * -all 8 DIMMs are equal
+ * -DIMMs are single sided (1 rank)
+ *
+ * RESULT:
+ * 1 group of 4 ranks (1 rank/2 DIMMs)
+ * -> CS mode 2 (four single sided DIMM pairs)
+ */
+ l_dgr->m_size_u32 = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 );
+ l_dgr->m_ss_u32 = 1;
+ l_dgr->m_csmode_u32 = 2;
+ l_dgr->m_dcnt_u32 = 8;
+ l_dgr->m_dptr[0] = f_dimm0;
+ l_dgr->m_dptr[1] = f_dimm1;
+ l_dgr->m_dptr[2] = f_dimm2;
+ l_dgr->m_dptr[3] = f_dimm3;
+ l_dgr->m_dptr[4] = f_dimm4;
+ l_dgr->m_dptr[5] = f_dimm5;
+ l_dgr->m_dptr[6] = f_dimm6;
+ l_dgr->m_dptr[7] = f_dimm7;
+
+ m_dgrcnt_u32++;
+}
+
+static int32_t
+u4_Dcmp( dimm_t *f_dimm0, dimm_t *f_dimm1 )
+{
+
+ if( ( f_dimm0->m_size_u32 == f_dimm1->m_size_u32 ) &&
+ ( f_dimm0->m_rank_u32 == f_dimm1->m_rank_u32 ) ) {
+ return RET_OK;
+ }
+
+ return RET_ERR;
+}
+
+static void
+u4_group1banks( uint32_t *bidx )
+{
+ uint32_t didx = 2 * bidx[0];
+
+ /*
+ * known conditions at this point:
+ * -either DIMMs 0 & 4 or
+ * DIMMs 1 & 5 or
+ * DIMMs 2 & 6 or
+ * DIMMs 3 & 7 are populated
+ * -3 (bimini)/1 (maui) pair of slots is empty
+ * -installed DIMMs are equal
+ */
+
+ /*
+ * double/single sided setup
+ */
+ if( m_dimm[didx].m_rank_u32 == 1 ) {
+ u4_group2dimmsSS( &m_dimm[didx], &m_dimm[didx+1] );
+ } else {
+ u4_group2dimmsDS( &m_dimm[didx], &m_dimm[didx+1] );
+ }
+
+}
+
+static void
+u4_group2banks( uint32_t *bidx )
+{
+ uint32_t didx0 = 2 * bidx[0];
+ uint32_t didx1 = 2 * bidx[1];
+
+ /*
+ * known conditions at this point:
+ * -4 slots are populated
+ */
+
+ /*
+ * check wether DIMM banks may be grouped
+ */
+ if( ( ( ( bidx[0] + bidx[1] ) & 0x1 ) != 0 ) &&
+ ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == 0 ) ) {
+ /*
+ * double/single sided setup
+ * NOTE: at this point all DIMMs have the same amount
+ * of ranks, therefore only the # of ranks on DIMM 0 is checked
+ */
+ if( m_dimm[didx0].m_rank_u32 == 1 ) {
+ u4_group4dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1],
+ &m_dimm[didx1], &m_dimm[didx1+1]);
+ } else {
+ u4_group4dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1],
+ &m_dimm[didx1], &m_dimm[didx1+1]);
+ }
+
+ } else {
+ u4_group1banks( &bidx[0] );
+ u4_group1banks( &bidx[1] );
+ }
+
+}
+
+static void
+u4_group3banks( uint32_t *bidx )
+{
+
+ if( ( bidx[0] == 0 ) && ( bidx[1] == 1 ) ) {
+ u4_group2banks( &bidx[0] );
+ u4_group1banks( &bidx[2] );
+ } else if( ( bidx[1] == 2 ) && ( bidx[2] == 3 ) ) {
+ u4_group2banks( &bidx[1] );
+ u4_group1banks( &bidx[0] );
+ }
+
+}
+
+static void
+u4_group4banks( uint32_t *bidx )
+{
+ uint32_t didx0 = 2 * bidx[0];
+ uint32_t didx1 = 2 * bidx[1];
+ uint32_t didx2 = 2 * bidx[2];
+ uint32_t didx3 = 2 * bidx[3];
+
+ if( ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == RET_OK ) &&
+ ( u4_Dcmp( &m_dimm[didx2], &m_dimm[didx3] ) == RET_OK ) &&
+ ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx2] ) == RET_OK ) ) {
+
+ if( m_dimm[didx0].m_rank_u32 == 1 ) {
+ u4_group8dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1],
+ &m_dimm[didx1], &m_dimm[didx1+1],
+ &m_dimm[didx2], &m_dimm[didx2+1],
+ &m_dimm[didx3], &m_dimm[didx3+1] );
+ } else {
+ u4_group8dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1],
+ &m_dimm[didx1], &m_dimm[didx1+1],
+ &m_dimm[didx2], &m_dimm[didx2+1],
+ &m_dimm[didx3], &m_dimm[didx3+1] );
+ }
+
+ } else {
+ u4_group2banks( &bidx[0] );
+ u4_group2banks( &bidx[2] );
+ }
+
+}
+
+static void
+u4_sortDIMMgroups( void )
+{
+ uint32_t i, j;
+
+ /*
+ * setup global group pointers
+ */
+ for( i = 0; i < m_dgrcnt_u32; i++ ) {
+ m_dgrptr[i] = &m_dgroup[i];
+ }
+
+ /*
+ * use a simple bubble sort to sort groups by size (descending)
+ */
+ for( i = 0; i < ( m_dgrcnt_u32 - 1 ); i++ ) {
+
+ for( j = i + 1; j < m_dgrcnt_u32; j++ ) {
+
+ if( m_dgrptr[i]->m_size_u32 < m_dgrptr[j]->m_size_u32 ) {
+ dgroup_t *l_sgr;
+
+ l_sgr = m_dgrptr[i];
+ m_dgrptr[i] = m_dgrptr[j];
+ m_dgrptr[j] = l_sgr;
+ }
+
+ }
+
+ }
+
+}
+
+static void
+u4_calcDIMMcnfg( void )
+{
+ static const uint32_t _2GB = (uint32_t) 0x00800;
+ static const uint32_t _4GB = (uint32_t) 0x01000;
+ static const uint32_t _64GB = (uint32_t) 0x10000;
+ uint32_t l_start_u32 = (uint32_t) 0;
+ uint32_t l_end_u32 = (uint32_t) 0;
+ uint32_t l_add2g_u32 = (uint32_t) 1;
+ uint32_t l_sub2g_u32 = (uint32_t) 1;
+ uint32_t i;
+
+ /*
+ * setup DIMM group parameters
+ */
+ for( i = 0; i < m_dgrcnt_u32; i++ ) {
+ l_end_u32 = l_start_u32 + m_dgrptr[i]->m_size_u32;
+
+ if( m_dgrptr[i]->m_size_u32 > _2GB ) {
+
+ if( l_end_u32 < _64GB ) {
+ l_add2g_u32 = ( l_end_u32 >> 11 );
+ } else {
+ l_add2g_u32 = 1;
+ }
+
+ if( l_start_u32 == 0 ) {
+ l_sub2g_u32 = 1;
+ } else {
+ l_sub2g_u32 = ( l_start_u32 >> 11 );
+ }
+
+ } else if( l_add2g_u32 != 1 ) {
+ l_start_u32 += _2GB;
+ l_end_u32 += _2GB;
+ l_add2g_u32 = 1;
+ l_sub2g_u32 = 1;
+ }
+
+ /*
+ * save values for the group
+ */
+ m_dgrptr[i]->m_start_u32 = ( l_start_u32 >> 7 ); // = /128
+ m_dgrptr[i]->m_end_u32 = ( l_end_u32 >> 7 );
+ m_dgrptr[i]->m_add2g_u32 = l_add2g_u32;
+ m_dgrptr[i]->m_sub2g_u32 = l_sub2g_u32;
+
+ /*
+ * continue with next group
+ */
+ if( l_end_u32 != _2GB ) {
+ l_start_u32 = l_end_u32;
+ } else {
+ l_start_u32 = _4GB;
+ }
+
+ }
+
+}
+
+static int32_t
+u4_calcDIMMmemmode( void )
+{
+ static const uint32_t MAX_ORG = (uint32_t) 0x10;
+ static const uint32_t MIN_BASE = (uint32_t) 0x80;
+ static const uint32_t MAX_MODE = (uint32_t) 0x10;
+ static const uint32_t MODE_ADD = (uint32_t) 0x04;
+ dimm_t *l_dptr;
+ uint32_t l_modeoffs_u32;
+ uint32_t l_sizebase_u32;
+ int32_t ret = RET_OK;
+ uint32_t i, j;
+
+ /*
+ * loop through all DIMM groups and calculate memmode setting
+ */
+ for( i = 0; i < m_dgrcnt_u32; i++ ) {
+ l_dptr = m_dgrptr[i]->m_dptr[0]; // all dimms in one group are equal!
+
+ l_modeoffs_u32 = MAX_ORG / l_dptr->m_orgval_u32;
+ l_modeoffs_u32 /= (uint32_t) 2;
+ l_sizebase_u32 = ( MIN_BASE << l_modeoffs_u32 );
+
+ j = 0;
+ while( ( l_sizebase_u32 != l_dptr->m_size_u32 ) &&
+ ( j < MAX_MODE ) ) {
+ l_sizebase_u32 <<= 1;
+ j += (uint32_t) MODE_ADD;
+ }
+
+ // return on error
+ if( j >= MAX_MODE ) {
+ #ifdef U4_INFO
+ uint32_t b, k, l;
+ printf( "\r\n [ERROR -> unsupported memory type in bank(s)" );
+
+ l = 0;
+ for( k = 0; k < m_dgrptr[i]->m_dcnt_u32; k++ ) {
+ b = m_dgrptr[i]->m_dptr[k]->m_bank_u32;
+
+ if( ( l & ( 1 << b ) ) == 0 ) {
+ printf( " %u", b );
+ l |= ( 1 << b );
+ }
+
+ }
+
+ printf( "]\r\n" );
+ #endif
+
+ ret = RET_ERR;
+ } else {
+ m_dgrptr[i]->m_memmd_u32 = l_modeoffs_u32 + j;
+ }
+
+ }
+
+ return ret;
+}
+
+static void
+u4_setupDIMMgroups( void )
+{
+ static const uint64_t _1MB = (uint64_t) 0x100000;
+ uint32_t l_bcnt_u32;
+ uint32_t l_bidx_u32[NUM_BANKS];
+ uint32_t i;
+
+ /*
+ * calculate number of populated banks
+ * IMPORTANT: array must be in ascending order!
+ */
+ l_bcnt_u32 = 0;
+ for( i = 0; i < NUM_BANKS; i++ ) {
+
+ if( m_bankpop_u32[i] != 0 ) {
+ l_bidx_u32[l_bcnt_u32] = i;
+ l_bcnt_u32++;
+ }
+
+ }
+
+ switch( l_bcnt_u32 ) {
+ case 4: u4_group4banks( &l_bidx_u32[0] ); break;
+ case 3: u4_group3banks( &l_bidx_u32[0] ); break;
+ case 2: u4_group2banks( &l_bidx_u32[0] ); break;
+ case 1: u4_group1banks( &l_bidx_u32[0] ); break;
+ }
+
+ /*
+ * sort DIMM groups by size (descending)
+ */
+ u4_sortDIMMgroups();
+
+ /*
+ * calculate overall memory size in bytes
+ * (group size is in MB)
+ */
+ m_memsize_u64 = 0;
+ for( i = 0; i < m_dgrcnt_u32; i++ ) {
+ m_memsize_u64 += (uint64_t) m_dgrptr[i]->m_size_u32 * _1MB;
+ }
+
+}
+
+static int32_t
+u4_setup_core_clock( void )
+{
+ static const uint32_t MCLK = (uint32_t) 266;
+ static const uint32_t CDIV = (uint32_t) 66;
+ static const uint32_t CMAX = (uint32_t) 7;
+ static const uint32_t MERR = (uint32_t) 10;
+ uint32_t volatile l_cclk_u32;
+ uint32_t volatile l_pll2_u32;
+ uint32_t i, s;
+
+ #ifdef U4_INFO
+ printf( " [core clock reset: ]" );
+ #endif
+
+ /*
+ * calculate speed value
+ */
+ s = m_gendimm.m_speed_pu32[m_dclidx_u32];
+ s -= MCLK;
+ s /= CDIV;
+
+ /*
+ * insert new core clock value
+ */
+ l_cclk_u32 = load32_ci( ClkCntl_R );
+ l_cclk_u32 &= ~CLK_DDR_CLK_MSK;
+ l_cclk_u32 |= ( s << 18 );
+
+
+ // return on error
+ if( s > CMAX ) {
+ #ifdef U4_INFO
+ printf( "\b\b\b\bERR\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * reset core clock
+ */
+ store32_ci( ClkCntl_R, l_cclk_u32 );
+ dly( 0x1000000 );
+ or32_ci( PLL2Cntl_R, IBIT(0) );
+ dly( 0x1000000 );
+
+ /*
+ * wait for reset to finish
+ */
+ do {
+ l_pll2_u32 = load32_ci( PLL2Cntl_R );
+ } while( ( l_pll2_u32 & IBIT(0) ) != 0 );
+
+ /*
+ * wait for stable PLL
+ */
+ s = 0;
+ do {
+ l_pll2_u32 = ( load32_ci( PLL2Cntl_R ) & IBIT(2) );
+
+ for( i = 0; i < 4; i++ ) {
+ l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) );
+ l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) );
+ l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) );
+ dly( 0x10000 );
+ }
+
+ } while( ( l_pll2_u32 == 0 ) && ( s++ < MERR ) );
+
+ if( s >= MERR ) {
+ #ifdef U4_INFO
+ printf( "\b\b\b\bERR\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+ #endif
+
+ return RET_OK;
+}
+
+static void
+u4_auto_calib_init( void )
+{
+ static const uint32_t SEQ[] = {
+ 0xb1000000, 0xd1000000, 0xd1000000, 0xd1000000,
+ 0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000,
+ 0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000,
+ 0xd1000000, 0xd1000000, 0xd1000400, 0x00000000,
+ };
+
+ uint64_t i;
+ uint32_t j;
+
+ for( i = MemInit00_R, j = 0; i <= MemInit15_R; i += 0x10, j++ ) {
+ store32_ci( i, SEQ[j] );
+ }
+
+}
+
+#if 0
+static uint32_t
+u4_RSL_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 )
+{
+ static const uint32_t MemProgCntl_V = (uint32_t) 0x80000500;
+ static const uint32_t CalConf0_V = (uint32_t) 0x0000aa10;
+ uint32_t l_MemProgCntl_u32;
+ uint32_t l_CalConf0_u32;
+ uint32_t l_MeasStat_u32;
+ uint32_t l_CalC_u32;
+ uint64_t MeasStat_R;
+ uint64_t CalC_R;
+ uint64_t VerC_R;
+ uint32_t shft;
+ uint32_t v;
+
+ if( f_BLane_u32 < 4 ) {
+ MeasStat_R = MeasStatusC0_R;
+ CalC_R = CalC0_R;
+ VerC_R = RstLdEnVerniersC0_R;
+ } else if( f_BLane_u32 < 8 ) {
+ f_BLane_u32 -= 4;
+ MeasStat_R = MeasStatusC1_R;
+ CalC_R = CalC1_R;
+ VerC_R = RstLdEnVerniersC1_R;
+ } else if( f_BLane_u32 < 12 ) {
+ f_BLane_u32 -= 8;
+ MeasStat_R = MeasStatusC2_R;
+ CalC_R = CalC2_R;
+ VerC_R = RstLdEnVerniersC2_R;
+ } else if( f_BLane_u32 == 16 ) {
+ f_BLane_u32 = 4;
+ MeasStat_R = MeasStatusC1_R;
+ CalC_R = CalC1_R;
+ VerC_R = RstLdEnVerniersC1_R;
+ } else if( f_BLane_u32 == 17 ) {
+ f_BLane_u32 = 4;
+ MeasStat_R = MeasStatusC3_R;
+ CalC_R = CalC3_R;
+ VerC_R = RstLdEnVerniersC3_R;
+ } else {
+ f_BLane_u32 -= 12;
+ MeasStat_R = MeasStatusC3_R;
+ CalC_R = CalC3_R;
+ VerC_R = RstLdEnVerniersC3_R;
+ }
+
+ shft = (uint32_t) 28 - ( f_BLane_u32 * 4 );
+
+ /*
+ * start auto calibration logic & wait for completion
+ */
+ or32_ci( MeasStat_R, IBIT(0) );
+
+ do {
+ l_MeasStat_u32 = load32_ci( MeasStat_R );
+ } while( ( l_MeasStat_u32 & IBIT(0) ) == 1 );
+
+ l_CalConf0_u32 = CalConf0_V;
+ store32_ci( CalConf0_R, l_CalConf0_u32 );
+
+ for( v = 0x000; v < (uint32_t) 0x100; v++ ) {
+ store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) );
+
+ l_MemProgCntl_u32 = MemProgCntl_V;
+ l_MemProgCntl_u32 |=
+ ( (uint32_t) 0x00800000 >> f_Rank_u32 );
+ store32_ci( MemProgCntl_R, l_MemProgCntl_u32 );
+
+ do {
+ l_MemProgCntl_u32 = load32_ci( MemProgCntl_R );
+ } while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 );
+
+ l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) &
+ (uint32_t) 0xf );
+
+ if( l_CalC_u32 != (uint32_t) 0xa ) {
+ v--;
+ break;
+ }
+
+ }
+
+ if( v == (uint32_t) 0x100 ) {
+ v = (uint32_t) ~1;
+ }
+
+ return v;
+}
+#endif
+
+static uint32_t
+u4_RMDF_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 )
+{
+ static const uint32_t MemProgCntl_V = (uint32_t) 0x80000f00;
+ static const uint32_t CalConf0_V = (uint32_t) 0x0000ac10;
+ uint32_t l_MemProgCntl_u32;
+ uint32_t l_CalConf0_u32;
+ uint32_t l_MeasStat_u32;
+ uint32_t l_CalC_u32;
+ uint64_t MeasStat_R;
+ uint64_t CalC_R;
+ uint64_t VerC_R;
+ uint32_t shft;
+ uint32_t v;
+
+ if( f_BLane_u32 < 4 ) {
+ MeasStat_R = MeasStatusC0_R;
+ CalC_R = CalC0_R;
+ VerC_R = RstLdEnVerniersC0_R;
+ } else if( f_BLane_u32 < 8 ) {
+ f_BLane_u32 -= 4;
+ MeasStat_R = MeasStatusC1_R;
+ CalC_R = CalC1_R;
+ VerC_R = RstLdEnVerniersC1_R;
+ } else if( f_BLane_u32 < 12 ) {
+ f_BLane_u32 -= 8;
+ MeasStat_R = MeasStatusC2_R;
+ CalC_R = CalC2_R;
+ VerC_R = RstLdEnVerniersC2_R;
+ } else if( f_BLane_u32 == 16 ) {
+ f_BLane_u32 = 4;
+ MeasStat_R = MeasStatusC1_R;
+ CalC_R = CalC1_R;
+ VerC_R = RstLdEnVerniersC1_R;
+ } else if( f_BLane_u32 == 17 ) {
+ f_BLane_u32 = 4;
+ MeasStat_R = MeasStatusC3_R;
+ CalC_R = CalC3_R;
+ VerC_R = RstLdEnVerniersC3_R;
+ } else {
+ f_BLane_u32 -= 12;
+ MeasStat_R = MeasStatusC3_R;
+ CalC_R = CalC3_R;
+ VerC_R = RstLdEnVerniersC3_R;
+ }
+
+ shft = (uint32_t) 28 - ( f_BLane_u32 * 4 );
+
+ /*
+ * start auto calibration logic & wait for completion
+ */
+ or32_ci( MeasStat_R, IBIT(0) );
+
+ do {
+ l_MeasStat_u32 = load32_ci( MeasStat_R );
+ } while( ( l_MeasStat_u32 & IBIT(0) ) == 1 );
+
+ l_CalConf0_u32 = CalConf0_V;
+ l_CalConf0_u32 |= ( f_BLane_u32 << 5 );
+ store32_ci( CalConf0_R, l_CalConf0_u32 );
+
+ for( v = 0x000; v < (uint32_t) 0x100; v++ ) {
+ store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) );
+
+ l_MemProgCntl_u32 = MemProgCntl_V;
+ l_MemProgCntl_u32 |=
+ ( (uint32_t) 0x00800000 >> f_Rank_u32 );
+ store32_ci( MemProgCntl_R, l_MemProgCntl_u32 );
+
+ do {
+ l_MemProgCntl_u32 = load32_ci( MemProgCntl_R );
+ } while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 );
+
+ l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) &
+ (uint32_t) 0xf );
+
+ if( l_CalC_u32 != (uint32_t) 0xa ) {
+ v--;
+ break;
+ }
+
+ }
+
+ if( v == (uint32_t) 0x100 ) {
+ v = (uint32_t) ~1;
+ }
+
+ return v;
+}
+
+static int32_t
+u4_RMDF_Rank( uint32_t f_Rank_u32,
+ uint32_t *f_Buf_pu32 )
+{
+ int32_t l_Err_pi32 = 0;
+ uint32_t b;
+
+ for( b = 0; ( b < MAX_BLANE ) && ( l_Err_pi32 == 0 ); b++ ) {
+ f_Buf_pu32[b] = u4_RMDF_BLane( f_Rank_u32, b );
+
+ if( f_Buf_pu32[b] == (uint32_t) ~0 ) {
+ f_Buf_pu32[b] = 0;
+ l_Err_pi32++;
+ } else if( f_Buf_pu32[b] == (uint32_t) ~1 ) {
+ f_Buf_pu32[b] = (uint32_t) 0xff;
+ l_Err_pi32++;
+ }
+
+ }
+
+ return l_Err_pi32;
+}
+
+static int32_t
+u4_auto_calib_MemBus( auto_calib_t *f_ac_pt )
+{
+ uint32_t RdMacDly, RdMacCnt;
+ uint32_t ResMuxDly, ResMuxCnt;
+ uint32_t RdPipeDly;
+ uint32_t l_Buf_pu32[MAX_DRANKS][MAX_BLANE];
+ uint32_t l_Rnk_pu32[MAX_DRANKS];
+ uint32_t l_Ver_u32;
+ int32_t l_Err_i32;
+ uint32_t bidx;
+ uint32_t n, r, b;
+
+ /*
+ * read starting delays out of the MemBus register
+ */
+ RdMacDly = ( load32_ci( MemBusCnfg_R ) >> 28 ) & 0xf;
+ ResMuxDly = ( load32_ci( MemBusCnfg_R ) >> 24 ) & 0xf;
+
+ /*
+ * initialize ranks as not populated
+ */
+ for( r = 0; r < MAX_DRANKS; r++ ) {
+ l_Rnk_pu32[r] = 0;
+ }
+
+ /*
+ * run through every possible delays of
+ * RdMacDly, ResMuxDly & RdPipeDly until
+ * the first working configuration is found
+ */
+ RdPipeDly = 0;
+ do {
+ and32_ci( MemBusCnfg2_R, ~0x3 );
+ or32_ci( MemBusCnfg2_R, RdPipeDly );
+
+ RdMacCnt = RdMacDly;
+ ResMuxCnt = ResMuxDly;
+
+ /*
+ * RdMacDly >= ResMuxDly
+ */
+ do {
+ and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 );
+ or32_ci( MemBusCnfg_R, ( RdMacCnt << 28 ) |
+ ( ResMuxCnt << 24 ) );
+ and32_ci( MemBusCnfg2_R, ( 1 << 28 ) - 1 );
+ or32_ci( MemBusCnfg2_R, ( RdMacCnt << 28 ) );
+
+ /*
+ * check the current value for every installed
+ * DIMM on each side for every bytelane
+ */
+ l_Err_i32 = 0;
+ for( n = 0;
+ ( n < NUM_SLOTS ) &&
+ ( l_Err_i32 == 0 );
+ n += 2 ) {
+
+ if( m_dimm[n].m_pop_u32 ) {
+ /*
+ * run through all 18 bytelanes of every rank
+ */
+ for( r = n;
+ ( r < n + m_dimm[n].m_rank_u32 ) &&
+ ( l_Err_i32 == 0 );
+ r++ ) {
+ l_Rnk_pu32[r] = 1;
+
+ l_Err_i32 =
+ u4_RMDF_Rank( r,
+ &l_Buf_pu32[r][0] );
+ }
+
+ }
+
+ }
+
+ /*
+ * decrementation before exit is wanted!
+ */
+ RdMacCnt--;
+ ResMuxCnt--;
+ } while( ( ResMuxCnt > 0 ) &&
+ ( l_Err_i32 != 0 ) );
+
+ if( l_Err_i32 != 0 ) {
+ RdPipeDly++;
+ }
+
+ } while( ( RdPipeDly < 4 ) &&
+ ( l_Err_i32 != 0 ) );
+
+ /*
+ * if l_Err_pi32 == 0 the auto calibration passed ok
+ */
+ if( l_Err_i32 != 0 ) {
+ return RET_ERR;
+ }
+
+ /*
+ * insert delay values into return struct
+ */
+ and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 );
+ or32_ci( MemBusCnfg_R, ( RdMacCnt << 28 ) |
+ ( ResMuxCnt << 24 ) );
+ and32_ci( MemBusCnfg2_R, ( ( 1 << 28 ) - 1 ) & ~0x3 );
+ or32_ci( MemBusCnfg2_R, ( RdMacCnt << 28 ) | RdPipeDly );
+
+ f_ac_pt->m_MemBusCnfg_u32 = load32_ci( MemBusCnfg_R );
+ f_ac_pt->m_MemBusCnfg2_u32 = load32_ci( MemBusCnfg2_R );
+
+ /*
+ * calculate the average vernier setting for the
+ * bytelanes which share one vernier
+ */
+ for( b = 0; b < MAX_BLANE - 2; b += 2 ) {
+ n = 0;
+ l_Ver_u32 = 0;
+
+ for( r = 0; r < MAX_DRANKS; r++ ) {
+ /*
+ * calculation is done or populated ranks only
+ */
+ if( l_Rnk_pu32[r] != 0 ) {
+ /*
+ * calculate average value
+ */
+ l_Ver_u32 += l_Buf_pu32[r][b];
+ l_Ver_u32 += l_Buf_pu32[r][b+1];
+ n += 2;
+
+ if( b == 4 ) {
+ l_Ver_u32 += l_Buf_pu32[r][16];
+ n++;
+ } else if( b == 12 ) {
+ l_Ver_u32 += l_Buf_pu32[r][17];
+ n++;
+ }
+
+ }
+
+ }
+
+ /*
+ * average the values
+ */
+ l_Ver_u32 /= n;
+
+ /*
+ * set appropiate vernier register for
+ * the current bytelane
+ */
+ bidx = ( b >> 2 );
+ if( ( b & (uint32_t) 0x3 ) == 0 ) {
+ l_Ver_u32 <<= 24;
+ f_ac_pt->m_RstLdEnVerniers_pu32[bidx] = l_Ver_u32;
+ } else {
+ l_Ver_u32 <<= 16;
+ f_ac_pt->m_RstLdEnVerniers_pu32[bidx] |= l_Ver_u32;
+ }
+
+ }
+
+ return RET_OK;
+}
+
+static int32_t
+u4_auto_calib( auto_calib_t *f_ac_pt )
+{
+ uint32_t l_MemBusCnfg_S;
+ uint32_t l_MemBusCnfg2_S;
+ uint32_t l_RstLdEnVerniers_S[4];
+ int32_t l_Ret_i32;
+
+ /*
+ * save manipulated registers
+ */
+ l_MemBusCnfg_S = load32_ci( MemBusCnfg_R );
+ l_MemBusCnfg2_S = load32_ci( MemBusCnfg2_R );
+ l_RstLdEnVerniers_S[0] = load32_ci( RstLdEnVerniersC0_R );
+ l_RstLdEnVerniers_S[1] = load32_ci( RstLdEnVerniersC1_R );
+ l_RstLdEnVerniers_S[2] = load32_ci( RstLdEnVerniersC2_R );
+ l_RstLdEnVerniers_S[3] = load32_ci( RstLdEnVerniersC3_R );
+
+ u4_auto_calib_init();
+ l_Ret_i32 = u4_auto_calib_MemBus( f_ac_pt );
+
+ /*
+ * restore manipulated registers
+ */
+ store32_ci( MemBusCnfg_R, l_MemBusCnfg_S );
+ store32_ci( MemBusCnfg2_R, l_MemBusCnfg2_S );
+ store32_ci( RstLdEnVerniersC0_R, l_RstLdEnVerniers_S[0] );
+ store32_ci( RstLdEnVerniersC1_R, l_RstLdEnVerniers_S[1] );
+ store32_ci( RstLdEnVerniersC2_R, l_RstLdEnVerniers_S[2] );
+ store32_ci( RstLdEnVerniersC3_R, l_RstLdEnVerniers_S[3] );
+
+ return l_Ret_i32;
+}
+
+static int32_t
+u4_checkeccerr( eccerror_t *f_ecc_pt )
+{
+ uint32_t l_val_u32;
+ int32_t ret = RET_OK;
+
+ l_val_u32 = load32_ci( MESR_R );
+ l_val_u32 >>= 29;
+
+ if( ( l_val_u32 & (uint32_t) 0x7 ) != 0 ) {
+
+ if( ( l_val_u32 & (uint32_t) 0x4 ) != 0 ) {
+ /* UE */
+ ret = RET_ACERR_UE;
+ } else if( ( l_val_u32 & (uint32_t) 0x1 ) != 0 ) {
+ /* UEWT */
+ ret = RET_ACERR_UEWT;
+ } else {
+ /* CE */
+ ret = RET_ACERR_CE;
+ }
+
+ }
+
+ f_ecc_pt->m_err_i32 = ret;
+
+ l_val_u32 = load32_ci( MEAR1_R );
+ f_ecc_pt->m_uecnt_u32 = ( ( l_val_u32 >> 24 ) & (uint32_t) 0xff );
+ f_ecc_pt->m_cecnt_u32 = ( ( l_val_u32 >> 16 ) & (uint32_t) 0xff );
+
+ l_val_u32 = load32_ci( MEAR0_R );
+ f_ecc_pt->m_rank_u32 = ( ( l_val_u32 >> 29 ) & (uint32_t) 0x7 );
+ f_ecc_pt->m_col_u32 = ( ( l_val_u32 >> 18 ) & (uint32_t) 0x7ff );
+ f_ecc_pt->m_row_u32 = ( ( l_val_u32 >> 0 ) & (uint32_t) 0x7fff );
+ f_ecc_pt->m_bank_u32 = ( ( l_val_u32 >> 15 ) & (uint32_t) 0x7 );
+
+ return ret;
+}
+
+static uint32_t
+u4_CalcScrubEnd( void )
+{
+ uint64_t l_scrend_u64 = m_memsize_u64;
+
+ /*
+ * check for memory hole at 2GB
+ */
+ if( l_scrend_u64 > _2GB ) {
+ l_scrend_u64 += _2GB;
+ }
+
+ l_scrend_u64 -= 0x40;
+ l_scrend_u64 /= 0x10;
+
+ return( (uint32_t) l_scrend_u64 );
+}
+
+static int32_t
+u4_Scrub( uint32_t f_scrub_u32, uint32_t f_pattern_u32, eccerror_t *f_eccerr_pt )
+{
+ uint32_t i;
+ int32_t ret;
+
+ /*
+ * setup scrub parameters
+ */
+ store32_ci( MSCR_R, 0 ); // stop scrub
+ store32_ci( MSRSR_R, 0x0 ); // set start
+ store32_ci( MSRER_R, u4_CalcScrubEnd() ); // set end
+ store32_ci( MSPR_R, f_pattern_u32 ); // set pattern
+
+ /*
+ * clear out ECC error registers
+ */
+ store32_ci( MEAR0_R, 0x0 );
+ store32_ci( MEAR1_R, 0x0 );
+ store32_ci( MESR_R, 0x0 );
+
+ /*
+ * Setup Scrub Type
+ */
+ store32_ci( MSCR_R, f_scrub_u32 );
+
+ if( f_scrub_u32 != BACKGROUND_SCRUB ) {
+ /*
+ * wait for scrub to complete
+ */
+ do {
+ progbar();
+ dly( 15000000 );
+ i = load32_ci( MSCR_R );
+ } while( ( i & f_scrub_u32 ) != 0 );
+
+ ret = u4_checkeccerr( f_eccerr_pt );
+ } else {
+ ret = RET_OK;
+ }
+
+ return ret;
+}
+
+static eccerror_t
+u4_InitialScrub( void )
+{
+ eccerror_t l_eccerr_st[2];
+ int32_t l_err_i32[2] = { 0, 0 };
+
+ l_err_i32[0] = u4_Scrub( IMMEDIATE_SCRUB_WITH_FILL, 0x0, &l_eccerr_st[0] );
+
+ if( l_err_i32[0] >= -1 /*CE*/ ) {
+ l_err_i32[1] = u4_Scrub( IMMEDIATE_SCRUB, 0x0, &l_eccerr_st[1] );
+ }
+
+ if( l_err_i32[0] < l_err_i32[1] ) {
+ return l_eccerr_st[0];
+ } else {
+ return l_eccerr_st[1];
+ }
+
+}
+
+/*
+ * RND: calculates Timer cycles from the given frequency
+ * devided by the clock frequency. Values are rounded
+ * up to the nearest integer value if the division is not even.
+ */
+#define RND( tXXX ) ( ( ( tXXX ) + tCK - 1 ) / tCK )
+
+static void
+u4_MemInitSequence( uint32_t tRP, uint32_t tWR, uint32_t tRFC, uint32_t CL,
+ uint32_t tCK, uint32_t TD )
+{
+ /*
+ * DIMM init sequence
+ */
+ static const uint32_t INI_SEQ[] = {
+ 0xa0000400, 0x80020000, 0x80030000, 0x80010404,
+ 0x8000100a, 0xa0000400, 0x90000000, 0x90000000,
+ 0x8ff0100a, 0x80010784, 0x80010404, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ };
+
+ uint32_t l_MemInit_u32;
+ uint64_t r;
+ uint32_t i;
+
+ for( r = MemInit00_R, i = 0; r <= MemInit15_R; r += 0x10, i++ ) {
+ l_MemInit_u32 = INI_SEQ[i];
+
+ switch( i ) {
+ case 0:
+ case 5: {
+ l_MemInit_u32 |= ( ( RND( tRP ) - TD ) << 20 );
+ break;
+ }
+ case 3: {
+ store32_ci( EMRSRegCntl_R, l_MemInit_u32 &
+ (uint32_t) 0xffff );
+ break;
+ }
+ case 4: {
+ l_MemInit_u32 |= IBIT(23);
+ }
+ case 8: {
+ l_MemInit_u32 |= ( ( RND( tWR ) - 1 ) << 9 );
+ l_MemInit_u32 |= ( CL << 4 );
+
+ store32_ci( MRSRegCntl_R, l_MemInit_u32 &
+ (uint32_t) 0xffff );
+ break;
+ }
+ case 6:
+ case 7: {
+ l_MemInit_u32 |= ( ( RND( tRFC ) - TD ) << 20 );
+ break;
+ }
+
+ }
+
+ store32_ci( r, l_MemInit_u32 );
+
+#ifdef U4_SHOW_REGS
+ printf( "\r\nMemInit%02d (0x%04X): 0x%08X", i, (uint16_t) r, l_MemInit_u32 );
+#endif
+ }
+#ifdef U4_SHOW_REGS
+ printf( "\r\n" );
+#endif
+ /*
+ * Kick off memory init sequence & wait for completion
+ */
+ store32_ci( MemProgCntl_R, IBIT(0) );
+
+ do {
+ i = load32_ci( MemProgCntl_R );
+ } while( ( i & IBIT(1) ) == 0 );
+
+}
+
+/*
+ * static DIMM configuartion settings
+ */
+static reg_statics_t reg_statics_maui[NUM_SPEED_IDX] = {
+ { /* 400 Mhz */
+ .RRMux = 1,
+ .WRMux = 1,
+ .WWMux = 1,
+ .RWMux = 1,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x60000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x34000000,
+ .CKDelayU = 0x34000000,
+
+ .MemBusCnfg = 0x00000050 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 2 ) << 24 ) ),
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 533 Mhz */
+ .RRMux = 1,
+ .WRMux = 1,
+ .WWMux = 1,
+ .RWMux = 1,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x60000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x18000000,
+ .CKDelayU = 0x18000000,
+
+ .MemBusCnfg = 0x00002070 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 3 ) << 24 ) ),
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+
+ 0x12000000, 0x12000000, 0x12000000 , 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000 , 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000 , 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000 , 0x12000000,
+ 0x12000000, 0x12000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000 , 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000 , 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000 , 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000 , 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 667 Mhz */
+ .RRMux = 1,
+ .WRMux = 1,
+ .WWMux = 1,
+ .RWMux = 3,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x60000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x0a000000,
+ .CKDelayU = 0x0a000000,
+
+ .MemBusCnfg = 0x000040a0 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 3 ) << 24 ) ),
+
+ .CAS1Dly0 = 2,
+ .CAS1Dly1 = 2,
+
+ .ByteWrClkDel = {
+
+ 0x12000000, 0x12000000, 0x12000000, 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000, 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000, 0x12000000,
+ 0x12000000, 0x12000000, 0x12000000, 0x12000000,
+ 0x12000000, 0x12000000
+/*
+ 0x31000000, 0x31000000, 0x31000000, 0x31000000,
+ 0x31000000, 0x31000000, 0x31000000, 0x31000000,
+ 0x31000000, 0x31000000, 0x31000000, 0x31000000,
+ 0x31000000, 0x31000000, 0x31000000, 0x31000000,
+ 0x31000000, 0x31000000
+*/
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ }
+};
+
+static reg_statics_t reg_statics_bimini[NUM_SPEED_IDX] = {
+ { /* 400 Mhz */
+ .RRMux = 2,
+ .WRMux = 2,
+ .WWMux = 2,
+ .RWMux = 2,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x40000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x00000000,
+ .CKDelayU = 0x28000000,
+
+ .MemBusCnfg = 0x00552070 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 2 ) << 24 ) ),
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 533 Mhz */
+ .RRMux = 3,
+ .WRMux = 3,
+ .WWMux = 3,
+ .RWMux = 3,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x40000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x00000000,
+ .CKDelayU = 0x20000000,
+
+ .MemBusCnfg = 0x00644190 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 3 ) << 24 ) ),
+
+ .CAS1Dly0 = 2,
+ .CAS1Dly1 = 2,
+
+ .ByteWrClkDel = {
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 667 Mhz */
+ .RRMux = 3,
+ .WRMux = 3,
+ .WWMux = 3,
+ .RWMux = 3,
+
+ .MemRdQCnfg = 0x20020820,
+ .MemWrQCnfg = 0x40041040,
+ .MemQArb = 0x00000000,
+ .MemRWArb = 0x30413cc0,
+
+ .ODTCntl = 0x40000000,
+ .IOPadCntl = 0x001a4000,
+ .MemPhyModeCntl = 0x00000000,
+ .OCDCalCntl = 0x00000000,
+ .OCDCalCmd = 0x00000000,
+
+ .CKDelayL = 0x00000000,
+ .CKDelayU = 0x00000000,
+
+ .MemBusCnfg = 0x00666270 |
+ ( ( MAX_RMD << 28 ) |
+ ( ( MAX_RMD - 3 ) << 24 ) ),
+
+ .CAS1Dly0 = 2,
+ .CAS1Dly1 = 2,
+
+ .ByteWrClkDel = {
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000, 0x14000000, 0x14000000,
+ 0x14000000, 0x14000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ }
+};
+
+static reg_statics_t reg_statics_kauai[NUM_SPEED_IDX] = {
+ { /* 400 Mhz */
+ .RRMux = 0,
+ .WRMux = 0,
+ .WWMux = 0,
+ .RWMux = 0,
+
+ .MemRdQCnfg = 0,
+ .MemWrQCnfg = 0,
+ .MemQArb = 0,
+ .MemRWArb = 0,
+
+ .ODTCntl = 0,
+ .IOPadCntl = 0,
+ .MemPhyModeCntl = 0,
+ .OCDCalCntl = 0,
+ .OCDCalCmd = 0,
+
+ .CKDelayL = 0,
+ .CKDelayU = 0,
+
+ .MemBusCnfg = 0,
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 533 Mhz */
+ .RRMux = 0,
+ .WRMux = 0,
+ .WWMux = 0,
+ .RWMux = 0,
+
+ .MemRdQCnfg = 0,
+ .MemWrQCnfg = 0,
+ .MemQArb = 0,
+ .MemRWArb = 0,
+
+ .ODTCntl = 0,
+ .IOPadCntl = 0,
+ .MemPhyModeCntl = 0,
+ .OCDCalCntl = 0,
+ .OCDCalCmd = 0,
+
+ .CKDelayL = 0,
+ .CKDelayU = 0,
+
+ .MemBusCnfg = 0,
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ },
+ { /* 667 Mhz */
+ .RRMux = 0,
+ .WRMux = 0,
+ .WWMux = 0,
+ .RWMux = 0,
+
+ .MemRdQCnfg = 0,
+ .MemWrQCnfg = 0,
+ .MemQArb = 0,
+ .MemRWArb = 0,
+
+ .ODTCntl = 0,
+ .IOPadCntl = 0,
+ .MemPhyModeCntl = 0,
+ .OCDCalCntl = 0,
+ .OCDCalCmd = 0,
+
+ .CKDelayL = 0,
+ .CKDelayU = 0,
+
+ .MemBusCnfg = 0,
+
+ .CAS1Dly0 = 0,
+ .CAS1Dly1 = 0,
+
+ .ByteWrClkDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ },
+ .ReadStrobeDel = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+ }
+
+ }
+};
+
+static int32_t
+u4_start( eccerror_t *f_ecc_pt )
+{
+ /*
+ * maximum runs for auto calibration
+ */
+ static const uint32_t MAX_ACERR = (uint32_t) 5;
+
+ /*
+ * fixed u4/DIMM timer/timing values for calculation
+ */
+ static const uint32_t TD = (uint32_t) 2; // u4 delay cycles for loading a timer
+ static const uint32_t AL = (uint32_t) 0; // additional latency (fix)
+ static const uint32_t BL = (uint32_t) 4; // burst length (fix)
+
+ uint32_t SPEED = m_gendimm.m_speed_pu32[m_dclidx_u32];
+ uint32_t CL = m_gendimm.m_clval_pu32[m_dclidx_u32];
+ uint32_t RL = AL + CL;
+ uint32_t WL = RL - 1;
+ uint32_t tCK = m_gendimm.m_tCK_pu32[m_dclidx_u32];
+ uint32_t tRAS = m_gendimm.m_tRAS_u32;
+ uint32_t tRTP = m_gendimm.m_tRTP_u32;
+ uint32_t tRP = m_gendimm.m_tRP_u32;
+ uint32_t tWR = m_gendimm.m_tWR_u32;
+ uint32_t tRRD = m_gendimm.m_tRRD_u32;
+ uint32_t tRC = m_gendimm.m_tRC_u32;
+ uint32_t tRCD = m_gendimm.m_tRCD_u32;
+ uint32_t tWTR = m_gendimm.m_tWTR_u32;
+ uint32_t tRFC = m_gendimm.m_tRFC_u32;
+ uint32_t tREF = m_gendimm.m_tREF_u32;
+
+ reg_statics_t *rst;
+
+ uint32_t l_RAS0_u32;
+ uint32_t l_RAS1_u32;
+ uint32_t l_CAS0_u32;
+ uint32_t l_CAS1_u32;
+ uint32_t l_MemRfshCntl_u32;
+ uint32_t l_UsrCnfg_u32;
+ uint32_t l_DmCnfg_u32;
+
+ uint32_t l_MemArbWt_u32;
+ uint32_t l_MemRWArb_u32;
+ uint32_t l_MemBusCnfg_u32;
+
+ auto_calib_t l_ac_st;
+ int32_t l_ac_i32;
+ uint32_t l_acerr_i32;
+ uint32_t sidx;
+ uint32_t i, j, t0, t1;
+
+ /*
+ * set index for different 400/533/667 Mhz setup
+ */
+ switch( SPEED ) {
+ case 400:
+ case 533:
+ case 667: {
+ sidx = SPEED;
+ sidx -= 400;
+ sidx /= 133;
+ break;
+ }
+
+ default: {
+ #ifdef U4_DEBUG2
+ printf( "\r\n-> DIMM speed of %03u not supported\r\n",
+ m_gendimm.m_speed_pu32[m_dclidx_u32] );
+ #endif
+ return RET_ERR;
+ }
+
+ }
+
+ /*
+ * setup pointer to the static register settings
+ */
+ if( IS_MAUI ) {
+ rst = &reg_statics_maui[sidx];
+ } else if( IS_BIMINI ) {
+ rst = &reg_statics_bimini[sidx];
+ } else if( IS_KAUAI ) {
+ rst = &reg_statics_kauai[sidx];
+ }
+
+ /*
+ * Switch off Fast Path by default for all DIMMs
+ * running with more than 400Mhz
+ */
+ if( SPEED == 400 ) {
+ or32_ci( APIMemRdCfg_R, IBIT(30) );
+ #ifdef U4_INFO
+ printf( " [fastpath : ON]\r\n" );
+ #endif
+ } else {
+ and32_ci( APIMemRdCfg_R, ~IBIT(30) );
+ #ifdef U4_INFO
+ printf( " [fastpath : OFF]\r\n" );
+ #endif
+ }
+
+
+ #ifdef U4_INFO
+ printf( " [register setup : ]" );
+ #endif
+
+ /*
+ * setup RAS/CAS timers2
+ * NOTE: subtract TD from all values because of the delay
+ * caused by reloading timers (see spec)
+ */
+
+ /*
+ * RAS Timer 0
+ */
+ // TiAtP = RND(tRAS) -> RAS0[0:4]
+ l_RAS0_u32 = ( ( RND( tRAS ) - TD ) << 27 );
+ // TiRtP = AL + BL/2 - 2 + RND(tRTP) -> RAS01[5:9]
+ l_RAS0_u32 |= ( ( AL + BL/2 - 2 + RND( tRTP ) - TD ) << 22 );
+ // TiWtP = WL + BL/2 + RND(tWR) -> RAS0[10:14]
+ l_RAS0_u32 |= ( ( WL + BL/2 + RND( tWR ) - TD ) << 17 );
+ // TiPtA = RND(tRP) -> RAS0[15:19]
+ l_RAS0_u32 |= ( ( RND( tRP ) - TD ) << 12 );
+ // TiPAtA = RND(tRP) or
+ // RND(tRP) + 1 for 8 bank devices -> RAS0[20:24]
+ if( m_gendimm.m_bankcnt_u32 <= 4 ) {
+ l_RAS0_u32 |= ( ( RND( tRP ) - TD ) << 7 );
+ } else {
+ l_RAS0_u32 |= ( ( RND( tRP ) + 1 - TD ) << 7 );
+ }
+
+ /*
+ * RAS Timer 1
+ */
+ // TiRAPtA = AL + BL/2 - 2 + RND(tRTP + tRP) -> RAS1[0:4]
+ l_RAS1_u32 = ( ( AL + BL/2 - 2 + RND( tRTP + tRP ) - TD ) << 27 );
+ // TiWAPtA = CL + AL + BL/2 - 1 + RND(tWR + tRP) -> RAS1[5:9]
+ l_RAS1_u32 |= ( ( CL + AL + BL/2 - 1 + RND( tWR + tRP ) - TD ) << 22 );
+ // TiAtARk = tRRD -> RAS1[10:14]
+ l_RAS1_u32 |= ( ( RND( tRRD ) - TD ) << 17 );
+ // TiAtABk = tRC -> RAS1[15:19]
+ l_RAS1_u32 |= ( ( RND( tRC ) - TD ) << 12 );
+ // TiAtRW = tRCD -> RAS1[20:24]
+ l_RAS1_u32 |= ( ( RND( tRCD ) - TD ) << 7 );
+ // TiSAtARk Win = 4 * tRRD + 2 -> RAS1[25:29]
+ l_RAS1_u32 |= ( ( RND( 4 * tRRD ) + 2 - TD ) << 2 );
+
+ /*
+ * CAS Timer 0
+ */
+ // TiRtRRk = BL/2 -> CAS0[0:4]
+ l_CAS0_u32 = ( ( BL/2 - TD ) << 27 );
+ // TiRtRDm = BL/2 + 1 -> CAS0[5:9]
+ l_CAS0_u32 |= ( ( BL/2 + 1 - TD ) << 22 );
+ // TiRtRSy = BL/2 + RRMux -> CAS0[10:14]
+ l_CAS0_u32 |= ( ( BL/2 + rst->RRMux - TD ) << 17 );
+ // TiWtRRk = CL - 1 + BL/2 + tWTR ->CAS0[15:19]
+ l_CAS0_u32 |= ( ( CL - 1 + BL/2 + RND( tWTR ) - TD ) << 12 );
+ // TiWtRDm = BL/2 + 1 -> CAS0[20:24]
+ l_CAS0_u32 |= ( ( BL/2 + 1 - TD ) << 7 );
+ // TiWtRSy = BL/2 + WRMux -> CAS0[25:29]
+ l_CAS0_u32 |= ( ( BL/2 + rst->WRMux - TD ) << 2 );
+
+ /*
+ * CAS Timer 1
+ */
+ // TiWtWRk = BL/2 -> CAS1[0:4]
+ l_CAS1_u32 = ( ( BL/2 - TD ) << 27 );
+ // TiWtWDm = BL/2 + 1 -> CAS1[5:9]
+ l_CAS1_u32 |= ( ( BL/2 + 1 - TD ) << 22 );
+ // TiWtWSy = BL/2 + WWMux -> CAS1[10:14]
+ l_CAS1_u32 |= ( ( BL/2 + rst->WWMux - TD ) << 17 );
+ // TiRtWRk = BL/2 + 2 -> CAS1[15:19]
+ l_CAS1_u32 |= ( ( BL/2 + 2 + rst->CAS1Dly0 - TD ) << 12 );
+ // TiRtWDm = BL/2 + 2 -> CAS1[20:24]
+ l_CAS1_u32 |= ( ( BL/2 + 2 + rst->CAS1Dly1 - TD ) << 7 );
+ // TiRtWSy = BL/2 + RWMux + 1 -> CAS1[25:29]
+ l_CAS1_u32 |= ( ( BL/2 + rst->RWMux + 1 - TD ) << 2 );
+
+ store32_ci( RASTimer0_R, l_RAS0_u32 );
+ store32_ci( RASTimer1_R, l_RAS1_u32 );
+ store32_ci( CASTimer0_R, l_CAS0_u32 );
+ store32_ci( CASTimer1_R, l_CAS1_u32 );
+
+ /*
+ * Mem Refresh Control register
+ */
+ l_MemRfshCntl_u32 = ( ( ( tREF / tCK ) / 16 ) << 23 );
+ l_MemRfshCntl_u32 |= ( ( RND( tRFC ) - TD ) << 8 );
+ store32_ci( MemRfshCntl_R, l_MemRfshCntl_u32 );
+
+ /*
+ * setup DmXCnfg registers
+ */
+ store32_ci( Dm0Cnfg_R, (uint32_t) 0x0 );
+ store32_ci( Dm1Cnfg_R, (uint32_t) 0x0 );
+ store32_ci( Dm2Cnfg_R, (uint32_t) 0x0 );
+ store32_ci( Dm3Cnfg_R, (uint32_t) 0x0 );
+
+ /*
+ * create DmCnfg & UsrCnfg values out of group data
+ */
+ l_UsrCnfg_u32 = 0;
+ for( i = 0; i < m_dgrcnt_u32; i++ ) {
+ l_DmCnfg_u32 = ( m_dgrptr[i]->m_add2g_u32 << 27 );
+ l_DmCnfg_u32 |= ( m_dgrptr[i]->m_sub2g_u32 << 19 );
+ l_DmCnfg_u32 |= ( m_dgrptr[i]->m_memmd_u32 << 12 );
+ l_DmCnfg_u32 |= ( m_dgrptr[i]->m_start_u32 << 3 );
+ l_DmCnfg_u32 |= ( m_dgrptr[i]->m_ss_u32 << 1 );
+ l_DmCnfg_u32 |= IBIT(31); // enable bit
+
+ /*
+ * write value into DmXCnfg registers
+ */
+ for( j = 0; j < m_dgrptr[i]->m_dcnt_u32; j++ ) {
+ t0 = m_dgrptr[i]->m_dptr[j]->m_bank_u32;
+ t1 = Dm0Cnfg_R + 0x10 * t0;
+
+ if( load32_ci( t1 ) == 0 ) {
+ store32_ci( t1, l_DmCnfg_u32 );
+ l_UsrCnfg_u32 |=
+ ( m_dgrptr[i]->m_csmode_u32 << ( 30 - 2 * t0 ) );
+ }
+
+ }
+
+ }
+
+ /*
+ * setup UsrCnfg register
+ *- cs mode is selected above
+ *- Interleave on L2 cache line
+ *- Usually closed page policy
+ */
+ l_UsrCnfg_u32 |= IBIT(8); // interleave on L2 cache line
+ l_UsrCnfg_u32 &= ~IBIT(9); // usually closed
+ l_UsrCnfg_u32 |= IBIT(10);
+ store32_ci( UsrCnfg_R, l_UsrCnfg_u32 );
+
+ /*
+ * Memory Arbiter Weight Register
+ */
+ // CohWt -> MemAWt[0:1]
+ l_MemArbWt_u32 = ( (uint32_t) 1 << 30 );
+ // NCohWt -> MemAWt[2:3]
+ l_MemArbWt_u32 |= ( (uint32_t) 1 << 28 );
+ // ScrbWt -> MemAWt[4:5]
+ l_MemArbWt_u32 |= ( (uint32_t) 0 << 26 );
+ store32_ci( MemArbWt_R, l_MemArbWt_u32 );
+
+ /*
+ * misc fixed register setup
+ */
+ store32_ci( ODTCntl_R, rst->ODTCntl );
+ store32_ci( IOPadCntl_R, rst->IOPadCntl );
+ store32_ci( MemPhyModeCntl_R, rst->MemPhyModeCntl );
+ store32_ci( OCDCalCntl_R, rst->OCDCalCntl );
+ store32_ci( OCDCalCmd_R, rst->OCDCalCmd );
+
+ /*
+ * CK Delay registers
+ */
+ store32_ci( CKDelayL_R, rst->CKDelayL );
+ store32_ci( CKDelayU_R, rst->CKDelayU );
+
+ /*
+ * read/write strobe delays
+ */
+ store32_ci( ByteWrClkDelC0B00_R, rst->ByteWrClkDel[ 0] );
+ store32_ci( ByteWrClkDelC0B01_R, rst->ByteWrClkDel[ 1] );
+ store32_ci( ByteWrClkDelC0B02_R, rst->ByteWrClkDel[ 2] );
+ store32_ci( ByteWrClkDelC0B03_R, rst->ByteWrClkDel[ 3] );
+ store32_ci( ByteWrClkDelC0B04_R, rst->ByteWrClkDel[ 4] );
+ store32_ci( ByteWrClkDelC0B05_R, rst->ByteWrClkDel[ 5] );
+ store32_ci( ByteWrClkDelC0B06_R, rst->ByteWrClkDel[ 6] );
+ store32_ci( ByteWrClkDelC0B07_R, rst->ByteWrClkDel[ 7] );
+ store32_ci( ByteWrClkDelC0B16_R, rst->ByteWrClkDel[16] );
+ store32_ci( ByteWrClkDelC0B08_R, rst->ByteWrClkDel[ 8] );
+ store32_ci( ByteWrClkDelC0B09_R, rst->ByteWrClkDel[ 9] );
+ store32_ci( ByteWrClkDelC0B10_R, rst->ByteWrClkDel[10] );
+ store32_ci( ByteWrClkDelC0B11_R, rst->ByteWrClkDel[11] );
+ store32_ci( ByteWrClkDelC0B12_R, rst->ByteWrClkDel[12] );
+ store32_ci( ByteWrClkDelC0B13_R, rst->ByteWrClkDel[13] );
+ store32_ci( ByteWrClkDelC0B14_R, rst->ByteWrClkDel[14] );
+ store32_ci( ByteWrClkDelC0B15_R, rst->ByteWrClkDel[15] );
+ store32_ci( ByteWrClkDelC0B17_R, rst->ByteWrClkDel[17] );
+ store32_ci( ReadStrobeDelC0B00_R, rst->ReadStrobeDel[ 0] );
+ store32_ci( ReadStrobeDelC0B01_R, rst->ReadStrobeDel[ 1] );
+ store32_ci( ReadStrobeDelC0B02_R, rst->ReadStrobeDel[ 2] );
+ store32_ci( ReadStrobeDelC0B03_R, rst->ReadStrobeDel[ 3] );
+ store32_ci( ReadStrobeDelC0B04_R, rst->ReadStrobeDel[ 4] );
+ store32_ci( ReadStrobeDelC0B05_R, rst->ReadStrobeDel[ 5] );
+ store32_ci( ReadStrobeDelC0B06_R, rst->ReadStrobeDel[ 6] );
+ store32_ci( ReadStrobeDelC0B07_R, rst->ReadStrobeDel[ 7] );
+ store32_ci( ReadStrobeDelC0B16_R, rst->ReadStrobeDel[16] );
+ store32_ci( ReadStrobeDelC0B08_R, rst->ReadStrobeDel[ 8] );
+ store32_ci( ReadStrobeDelC0B09_R, rst->ReadStrobeDel[ 9] );
+ store32_ci( ReadStrobeDelC0B10_R, rst->ReadStrobeDel[10] );
+ store32_ci( ReadStrobeDelC0B11_R, rst->ReadStrobeDel[11] );
+ store32_ci( ReadStrobeDelC0B12_R, rst->ReadStrobeDel[12] );
+ store32_ci( ReadStrobeDelC0B13_R, rst->ReadStrobeDel[13] );
+ store32_ci( ReadStrobeDelC0B14_R, rst->ReadStrobeDel[14] );
+ store32_ci( ReadStrobeDelC0B15_R, rst->ReadStrobeDel[15] );
+ store32_ci( ReadStrobeDelC0B17_R, rst->ReadStrobeDel[17] );
+
+ /*
+ * Mem Bus Configuration
+ * initial setup used in auto calibration
+ * final values will be written after
+ * auto calibration has finished
+ */
+ l_MemBusCnfg_u32 = rst->MemBusCnfg;
+
+/* values calculation has been dropped, static values are used instead
+ // WdbRqDly = 2 * (CL - 3) (registered DIMMs) -> MBC[16:19]
+ l_MemBusCnfg_u32 += ( ( 2 * ( CL - 3 ) ) << 12 );
+ // RdOEOnDly = 0 (typically)
+ l_MemBusCnfg_u32 += ( ( 0 ) << 8 );
+ // RdOEOffDly = (2 * CL) - 4 -> MBC[24:27]
+ // NOTE: formula is not working, changed to:
+ // RdOEOffDly = (2 * CL) - 1
+ l_MemBusCnfg_u32 += ( ( ( 2 * CL ) - 1 ) << 4 );
+*/
+
+ store32_ci( MemBusCnfg_R, l_MemBusCnfg_u32 );
+ store32_ci( MemBusCnfg2_R, rst->MemBusCnfg & (uint32_t) 0xf0000000 );
+
+ /*
+ * reset verniers registers
+ */
+ store32_ci( RstLdEnVerniersC0_R, 0x0 );
+ store32_ci( RstLdEnVerniersC1_R, 0x0 );
+ store32_ci( RstLdEnVerniersC2_R, 0x0 );
+ store32_ci( RstLdEnVerniersC3_R, 0x0 );
+ store32_ci( ExtMuxVernier0_R, 0x0 );
+ store32_ci( ExtMuxVernier1_R, 0x0 );
+
+ /*
+ * Queue Configuration
+ */
+ store32_ci( MemRdQCnfg_R, rst->MemRdQCnfg );
+ store32_ci( MemWrQCnfg_R, rst->MemWrQCnfg );
+ store32_ci( MemQArb_R, rst->MemQArb );
+ store32_ci( MemRWArb_R, rst->MemRWArb );
+
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+ #endif
+
+ /*
+ * start up clocks & wait for pll2 to stabilize
+ */
+ #ifdef U4_INFO
+ printf( " [start DDR clock : ]" );
+ #endif
+
+ store32_ci( MemModeCntl_R, IBIT(0) | IBIT(8) );
+ dly( 50000000 );
+
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+
+ #endif
+
+ /*
+ * memory initialization sequence
+ */
+ #ifdef U4_INFO
+ printf( " [memory init : ]" );
+ #endif
+ u4_MemInitSequence( tRP, tWR, tRFC, CL, tCK, TD );
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+ #endif
+
+ /*
+ * start ECC before auto calibration to enable ECC bytelane
+ */
+ store32_ci( MCCR_R, IBIT(0) );
+ dly( 15000000 );
+
+ /*
+ * start up auto calibration
+ */
+ #ifdef U4_INFO
+ printf( " [auto calibration: ]\b" );
+ #endif
+
+ /*
+ * start auto calibration
+ */
+ l_acerr_i32 = 0;
+ do {
+ progbar();
+
+ l_ac_i32 = u4_auto_calib( &l_ac_st );
+
+ if( l_ac_i32 != 0 ) {
+ l_acerr_i32++;
+ }
+
+ dly( 15000000 );
+ } while( ( l_ac_i32 != 0 ) &&
+ ( l_acerr_i32 <= MAX_ACERR ) );
+
+ if( l_acerr_i32 > MAX_ACERR ) {
+ #ifdef U4_INFO
+ printf( "\b\b\bERR\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * insert auto calibration results
+ */
+ store32_ci( MemBusCnfg_R, l_ac_st.m_MemBusCnfg_u32 );
+ store32_ci( MemBusCnfg2_R, l_ac_st.m_MemBusCnfg2_u32 );
+ store32_ci( RstLdEnVerniersC0_R, l_ac_st.m_RstLdEnVerniers_pu32[0] );
+ store32_ci( RstLdEnVerniersC1_R, l_ac_st.m_RstLdEnVerniers_pu32[1] );
+ store32_ci( RstLdEnVerniersC2_R, l_ac_st.m_RstLdEnVerniers_pu32[2] );
+ store32_ci( RstLdEnVerniersC3_R, l_ac_st.m_RstLdEnVerniers_pu32[3] );
+
+ /*
+ * insert final timing value into MemRWArb
+ */
+ l_MemRWArb_u32 = ( ( l_ac_st.m_MemBusCnfg_u32 >> 28 /*RdMacDel*/) + 1 );
+ l_MemRWArb_u32 *= 10; // needed for rounding
+ l_MemRWArb_u32 /= 2; // due to spec
+ l_MemRWArb_u32 += 9; // round up
+ l_MemRWArb_u32 /= 10; // value is rounded now
+ l_MemRWArb_u32 = l_MemRWArb_u32 + 6 - WL - TD;
+ l_MemRWArb_u32 |= rst->MemRWArb;
+ store32_ci( MemRWArb_R, l_MemRWArb_u32 );
+
+ progbar();
+ dly( 15000000 );
+
+ /*
+ * do initial scrubbing
+ */
+ *f_ecc_pt = u4_InitialScrub();
+
+ switch( f_ecc_pt->m_err_i32 ) {
+ case RET_OK: {
+ #ifdef U4_INFO
+ printf( "\b\bOK\r\n" );
+ #endif
+ break;
+ }
+
+ case RET_ACERR_CE: {
+ #ifdef U4_INFO
+ printf( "\b\b\b\bWEAK][correctable errors during scrub (%u)]\r\n",
+ f_ecc_pt->m_cecnt_u32 );
+ #endif
+ break;
+ }
+
+ case RET_ACERR_UEWT:
+ case RET_ACERR_UE: {
+ #ifdef U4_INFO
+ printf( "\b\b\bERR][uncorrectable errors during scrub (%u)]\r\n",
+ f_ecc_pt->m_uecnt_u32 );
+ #endif
+ return RET_ACERR_UE;
+ }
+
+ }
+
+ /*
+ * start continuous background scrub
+ */
+ #ifdef U4_INFO
+ printf( " [background scrub: ]" );
+ #endif
+
+ u4_Scrub( BACKGROUND_SCRUB, 0, NULL );
+
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+ #endif
+
+ /*
+ * finally clear API Exception register
+ * (read to clear)
+ */
+ load32_ci( APIExcp_R );
+
+ return RET_OK;
+}
+
+#undef RND
+
+void
+u4_memtest(uint8_t argCnt, char *pArgs[], uint64_t flags)
+
+{
+ #define TEND 99
+ #define TCHK 100
+ static const uint64_t _2GB = (uint64_t) 0x80000000;
+ static const uint64_t _start = (uint64_t) 0x08000000; // 128Mb
+ static const uint64_t _bsize = (uint64_t) 0x08000000; // 128MB
+ static const uint64_t _line = (uint64_t) 128;
+ static const uint64_t _256MB = (uint64_t) 0x10000000;
+
+ static const uint64_t PATTERN[] = {
+ 0x9090909090909090, 0x0020002000200020,
+ 0x0c0c0c0c0c0c0c0c, 0x8080808080808080,
+ 0x1004010004001041, 0x0000000000000000
+ };
+
+ uint64_t mend = (uint64_t) 0x200000000;//m_memsize_u64;
+ uint64_t numblocks = ( mend - _start ) / _bsize; // 128Mb blocks
+ uint64_t numlines = _bsize / _line;
+ uint64_t tstate = 0;
+ uint64_t tlast = 0;
+ uint64_t pidx = 0;
+ uint64_t rotr = 0;
+ uint64_t rotl = 0;
+ uint64_t block;
+ uint64_t line;
+ uint64_t addr;
+ uint64_t i;
+ uint64_t check = 0;
+ uint64_t dcnt;
+ uint64_t uerr = 0;
+ uint64_t cerr = 0;
+ uint64_t merr = 0;
+ char c;
+
+ printf( "\n\nU4 memory test" );
+ printf( "\n--------------" );
+
+ /*
+ * mask out UEC & CEC
+ */
+ or32_ci( MCCR_R, IBIT(6) | IBIT(7) );
+
+ while( PATTERN[pidx] ) {
+
+ switch( tstate )
+ {
+ case 0: {
+ printf( "\npattern fill 0x%08X%08X: ", (uint32_t) (PATTERN[pidx] >> 32), (uint32_t) PATTERN[pidx] );
+
+ /*
+ * first switch lines, then blocks. This way the CPU
+ * is not able to cache data
+ */
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ *( (uint64_t *) addr ) = PATTERN[pidx];
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+ printf( "*" );
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ check = PATTERN[pidx];
+ tlast = 0;
+ tstate = TCHK;
+ } break;
+
+ case 1: {
+ uint64_t one;
+
+ /*
+ * new check pattern
+
+ */
+ one = ( ( check & 0x1 ) != 0 );
+ check >>= 1;
+ if( one ) {
+ check |= 0x8000000000000000;
+ }
+
+ printf( "\nrotate right 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check );
+
+ /*
+ * first switch lines, then blocks. This way the CPU
+ * is not able to cache data
+ */
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ *( (uint64_t *) addr ) >>= 1;
+
+ if( one ) {
+ *( (uint64_t *) addr ) |=
+ (uint64_t) 0x8000000000000000;
+ }
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+ printf( "*" );
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ tlast = 1;
+ tstate = TCHK;
+ } break;
+
+ case 2: {
+
+ if( rotr < 6 ) {
+ rotr++;
+ tstate = 1;
+ } else {
+ rotr = 0;
+ tstate = 3;
+ }
+
+ } break;
+
+ case 3: {
+ /*
+ * new check pattern
+ */
+ check ^= (uint64_t) ~0;
+
+ printf( "\ninverting 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check );
+
+ /*
+ * first switch lines, then blocks. This way the CPU
+ * is not able to cache data
+ */
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ *( (uint64_t *) addr ) ^= (uint64_t) ~0;
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+ printf( "*" );
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ tlast = 3;
+ tstate = TCHK;
+ } break;
+
+ case 4: {
+ uint64_t one;
+
+ /*
+ * new check pattern
+ */
+ one = ( ( check & 0x8000000000000000 ) != 0 );
+ check <<= 1;
+ if( one ) {
+ check |= 0x1;
+ }
+
+ printf( "\nrotate left 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check );
+
+ /*
+ * first switch lines, then blocks. This way the CPU
+ * is not able to cache data
+ */
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ *( (uint64_t *) addr ) <<= 1;
+
+ if( one ) {
+ *( (uint64_t *) addr ) |=
+ (uint64_t) 0x1;
+ }
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+ printf( "*" );
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ tlast = 4;
+ tstate = TCHK;
+ } break;
+
+ case 5: {
+
+ if( rotl < 6 ) {
+ rotl++;
+ tstate = 4;
+ } else {
+ rotl = 0;
+ tstate = 6;
+ }
+
+ } break;
+
+ case 6: {
+ /*
+ * new check pattern
+ */
+ check *= ~check;
+ printf( "\nmultiply 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check );
+
+ /*
+ * first switch lines, then blocks. This way the CPU
+ * is not able to cache data
+ */
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ *( (uint64_t *) addr ) *= ~( *( (uint64_t *) addr ) );
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+ printf( "*" );
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ tlast = TEND - 1;
+ tstate = TCHK;
+ } break;
+
+ case TEND: {
+ pidx++;
+ tstate = 0;
+ } break;
+
+ case TCHK: {
+ uint64_t err;
+ /*
+ * check data
+ */
+ printf( "\nchecking : " );
+
+ for( line = 0, dcnt = 0; line < numlines; line++ ) {
+
+ for( block = 0; block < numblocks; block++ ) {
+
+ for( i = 0; i < _line; i += 8 ) {
+ addr = _start +
+ ( block * _bsize ) +
+ ( line * _line ) +
+ i;
+
+ if( addr >= _2GB ) {
+ addr += _2GB;
+ }
+
+ err = ( *( (uint64_t *) addr ) != check );
+
+ if( err ) {
+ merr++;
+ }
+
+ /*
+ * print out a dot every 256Mb
+ */
+ dcnt += 8;
+ if( dcnt == _256MB ) {
+ dcnt = 0;
+
+ if( err ) {
+ printf( "X" );
+ } else {
+ printf( "*" );
+ }
+
+ if( io_getchar( &c ) ) {
+ goto mtend;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ err = (uint64_t) load32_ci( MEAR1_R );
+ uerr += ( err >> 24 ) & (uint64_t) 0xff;
+ cerr += ( err >> 16 ) & (uint64_t) 0xff;
+
+ printf( " (UE: %02llX, CE: %02llX)", ( err >> 24 ) & (uint64_t) 0xff, ( err >> 16 ) & (uint64_t) 0xff );
+
+ tstate = tlast + 1;
+ tlast = TCHK;
+ } break;
+
+ }
+
+ }
+
+mtend:
+ printf( "\n\nmemory test results" );
+ printf( "\n-------------------" );
+ printf( "\nuncorrectable errors: %u", (uint32_t) uerr );
+ printf( "\ncorrectable errors : %u", (uint32_t) cerr );
+ printf( "\nread/write errors : %u\n", (uint32_t) merr );
+
+ and32_ci( MCCR_R, ~( IBIT(6) | IBIT(7) ) );
+}
+
+void
+u4_dump(uint8_t argCnt, char *pArgs[], uint64_t flags)
+{
+ printf( "\r\n*** u4 register dump ***\r\n\n" );
+ printf( "register (offset): value\r\n" );
+ printf( "----------------------------------\r\n" );
+ printf( "Clock Control (0x%04X): 0x%08X\r\n", (uint16_t) ClkCntl_R, load32_ci( ClkCntl_R ) );
+ printf( "PLL2 Control (0x%04X): 0x%08X\r\n", (uint16_t) PLL2Cntl_R, load32_ci( PLL2Cntl_R ) );
+ printf( "MemModeCntl (0x%04X): 0x%08X\r\n", (uint16_t) MemModeCntl_R, load32_ci( MemModeCntl_R ) );
+ printf( "RASTimer0 (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer0_R, load32_ci( RASTimer0_R ) );
+ printf( "RASTimer1 (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer1_R, load32_ci( RASTimer1_R ) );
+ printf( "CASTimer0 (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer0_R, load32_ci( CASTimer0_R ) );
+ printf( "CASTimer1 (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer1_R, load32_ci( CASTimer1_R ) );
+ printf( "MemRfshCntl (0x%04X): 0x%08X\r\n", (uint16_t) MemRfshCntl_R, load32_ci( MemRfshCntl_R ) );
+ printf( "Dm0Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm0Cnfg_R, load32_ci( Dm0Cnfg_R ) );
+ printf( "Dm1Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm1Cnfg_R, load32_ci( Dm1Cnfg_R ) );
+ printf( "Dm2Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm2Cnfg_R, load32_ci( Dm2Cnfg_R ) );
+ printf( "Dm3Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm3Cnfg_R, load32_ci( Dm3Cnfg_R ) );
+ printf( "UsrCnfg (0x%04X): 0x%08X\r\n", (uint16_t) UsrCnfg_R, load32_ci( UsrCnfg_R ) );
+ printf( "MemArbWt (0x%04X): 0x%08X\r\n", (uint16_t) MemArbWt_R, load32_ci( MemArbWt_R ) );
+ printf( "ODTCntl (0x%04X): 0x%08X\r\n", (uint16_t) ODTCntl_R, load32_ci( ODTCntl_R ) );
+ printf( "IOPadCntl (0x%04X): 0x%08X\r\n", (uint16_t) IOPadCntl_R, load32_ci( IOPadCntl_R ) );
+ printf( "MemPhyMode (0x%04X): 0x%08X\r\n", (uint16_t) MemPhyModeCntl_R, load32_ci( MemPhyModeCntl_R ) );
+ printf( "OCDCalCntl (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCntl_R, load32_ci( OCDCalCntl_R ) );
+ printf( "OCDCalCmd (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCmd_R, load32_ci( OCDCalCmd_R ) );
+ printf( "CKDelayL (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayL_R, load32_ci( CKDelayL_R ) );
+ printf( "CKDelayH (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayU_R, load32_ci( CKDelayU_R ) );
+ printf( "MemBusCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg_R, load32_ci( MemBusCnfg_R ) );
+ printf( "MemBusCnfg2 (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg2_R, load32_ci( MemBusCnfg2_R ) );
+ printf( "MemRdQCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemRdQCnfg_R, load32_ci( MemRdQCnfg_R ) );
+ printf( "MemWrQCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemWrQCnfg_R, load32_ci( MemWrQCnfg_R ) );
+ printf( "MemQArb (0x%04X): 0x%08X\r\n", (uint16_t) MemQArb_R, load32_ci( MemQArb_R ) );
+ printf( "MemRWArb (0x%04X): 0x%08X\r\n", (uint16_t) MemRWArb_R, load32_ci( MemRWArb_R ) );
+ printf( "ByteWrClkDel (0x%04X): 0x%08X\r\n", (uint16_t) ByteWrClkDelC0B00_R, load32_ci( ByteWrClkDelC0B00_R ) );
+ printf( "ReadStrobeDel (0x%04X): 0x%08X\r\n", (uint16_t) ReadStrobeDelC0B00_R, load32_ci( ReadStrobeDelC0B00_R ) );
+ printf( "RstLdEnVerC0 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC0_R, load32_ci( RstLdEnVerniersC0_R ) );
+ printf( "RstLdEnVerC1 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC1_R, load32_ci( RstLdEnVerniersC1_R ) );
+ printf( "RstLdEnVerC2 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC2_R, load32_ci( RstLdEnVerniersC2_R ) );
+ printf( "RstLdEnVerC3 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC3_R, load32_ci( RstLdEnVerniersC3_R ) );
+ printf( "APIMemRdCfg (0x%04X): 0x%08X\r\n", (uint16_t) APIMemRdCfg_R, load32_ci( APIMemRdCfg_R ) );
+ printf( "scrub start (0x%04X): 0x%08X\r\n", (uint16_t) MSRSR_R, load32_ci( MSRSR_R ) );
+ printf( "scrub end (0x%04X): 0x%08X\r\n", (uint16_t) MSRER_R, load32_ci( MSRER_R ) );
+}
+
+int32_t
+u4_memBegin( eccerror_t *f_ecc_pt )
+{
+ int32_t i;
+
+ #ifdef U4_INFO
+ printf( "\r\n" );
+ printf( "U4 DDR2 memory controller setup V%u.%u\r\n",
+ VER, SUBVER );
+ printf( "------------------------------------\r\n" );
+ printf( "> detected board : " );
+
+ if( IS_MAUI ) {
+ printf( "MAUI" );
+ } else if( IS_BIMINI ) {
+ printf( "BIMINI" );
+ } else if( IS_KAUAI ) {
+ printf( "KAUAI" );
+ } else {
+ printf( "unknown!" );
+ return RET_ERR;
+ }
+ #endif
+
+ do {
+ /*
+ * initialize variables
+ */
+ m_memsize_u64 = 0;
+ m_dcnt_u32 = 0;
+ m_dgrcnt_u32 = 0;
+ m_dclidx_u32 = 0;
+
+ for( i = 0; i < NUM_SLOTS; i++ ) {
+ m_dptr[i] = NULL;
+ memset( ( void * ) &m_dimm[i], 0, sizeof( dimm_t ) );
+ }
+
+ for( i = 0; i < MAX_DGROUPS; i++ ) {
+ m_dgrptr[i] = NULL;
+ memset( ( void * ) &m_dgroup[i], 0, sizeof( dimm_t ) );
+ }
+
+ /*
+ * start configuration
+ */
+ #ifdef U4_INFO
+ printf( "\r\n> detected DIMM configuration : " );
+ #endif
+
+ i = ddr2_readSPDs();
+
+ if( i != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "\r\n-------------------------------------------------------------" );
+ printf( "\r\n switching off memory bank(s) due to SPD integrity failure" );
+ printf( "\r\n-------------------------------------------------------------\r\n" );
+ #endif
+ }
+
+ } while( i != RET_OK );
+
+ /*
+ * check DIMM configuration
+ */
+ if( ddr2_setupDIMMcfg() != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "> initialization failure.\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ /*
+ * create DIMM groups
+ */
+ u4_setupDIMMgroups();
+
+ /*
+ * start configuration of u4
+ */
+ u4_calcDIMMcnfg();
+
+ if( u4_calcDIMMmemmode() != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "> initialization failure.\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ #ifdef U4_INFO
+ printf( "%uMb @ %uMhz, CL %u\r\n",
+ (uint32_t) ( m_memsize_u64 / 0x100000 ),
+ m_gendimm.m_speed_pu32[m_dclidx_u32],
+ m_gendimm.m_clval_pu32[m_dclidx_u32] );
+
+ printf( "> initializing memory :\r\n" );
+ #endif
+
+ if( u4_setup_core_clock() != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "> initialization failure.\r\n" );
+ #endif
+ return RET_ERR;
+ }
+
+ i = u4_start( f_ecc_pt );
+ if( i != RET_OK ) {
+ #ifdef U4_INFO
+ printf( "> initialization failure.\r\n" );
+ #endif
+ return i;
+ }
+
+ #ifdef U4_INFO
+ printf( " [flush cache : ]" );
+ #endif
+
+ flush_cache( 0x0, L2_CACHE_SIZE );
+
+ #ifdef U4_INFO
+ printf( "\b\b\bOK\r\n" );
+ printf( "> initialization complete.\r\n" );
+ #endif
+
+#ifdef U4_SHOW_REGS
+ u4_dump(0,0,0);
+#endif
+
+ return RET_OK;
+}
+
+static int32_t scrubstarted = 0;
+
+void
+u4_scrubStart(uint8_t argCnt, char *pArgs[], uint64_t flags )
+{
+ scrubstarted = 1;
+
+ /*
+ * setup scrub parameters
+ */
+ store32_ci( MSCR_R, 0 ); // stop scrub
+ store32_ci( MSRSR_R, 0x0 ); // set start
+ store32_ci( MSRER_R, 0x1c ); // set end
+ store32_ci( MSPR_R, 0x0 ); // set pattern
+
+ /*
+ * clear out ECC error registers
+ */
+ store32_ci( MEAR0_R, 0x0 );
+ store32_ci( MEAR1_R, 0x0 );
+ store32_ci( MESR_R, 0x0 );
+
+ /*
+ * Setup Scrub Type
+ */
+ store32_ci( MSCR_R, IBIT(1) );
+ printf( "\r\nscrub started\r\n" );
+}
+
+void
+u4_scrubEnd(uint8_t argCnt, char *pArgs[], uint64_t flags )
+{
+ store32_ci( MSCR_R, 0 ); // stop scrub
+ scrubstarted = 0;
+ printf( "\r\nscrub stopped\r\n" );
+}
+
+void
+u4_memwr(uint8_t argCnt, char *pArgs[], uint64_t flags )
+{
+ uint32_t i;
+ uint32_t v = 0;
+
+ for( i = 0; i < 0x200; i += 4 ) {
+
+ if( ( i & 0xf ) == 0 ) {
+ v = ~v;
+ }
+
+ store32_ci( i, v );
+ }
+
+}
+
+void
+u4memInit()
+{
+ static uint32_t l_isInit_u32 = 0;
+ eccerror_t l_ecc_t;
+ int32_t ret;
+
+ /*
+ * do not initialize memory more than once
+ */
+ if( l_isInit_u32 ) {
+ #ifdef U4_INFO
+ printf( "\r\n\nmemory already initialized\r\n" );
+ #endif
+ return;
+ } else {
+ l_isInit_u32 = 1;
+ }
+
+ /*
+ * enable all DIMM banks on first run
+ */
+ m_bankoff_u32 = 0;
+
+ do {
+ ret = u4_memBegin( &l_ecc_t );
+
+ if( ret < RET_ERR ) {
+ uint32_t l_bank_u32 = l_ecc_t.m_rank_u32 / 2;
+ printf( "\r\n-----------------------------------------------------" );
+ printf( "\r\n switching off memory bank %u due to memory failure", l_bank_u32 );
+ printf( "\r\n-----------------------------------------------------" );
+ m_bankoff_u32 |= ( 1 << l_bank_u32 );
+ }
+
+ } while( ret < RET_ERR );
+
+}
+
+void
+monitorDDR2( uint8_t argCnt, char *pArgs[], uint64_t flags )
+{
+ u4memInit();
+}
diff --git a/board-js2x/romfs/boot_rom.ffs b/board-js2x/romfs/boot_rom.ffs
new file mode 100644
index 0000000..ada0b62
--- /dev/null
+++ b/board-js2x/romfs/boot_rom.ffs
@@ -0,0 +1,23 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+# FFile-Name Real Filename Flags ROM-Offset i/a
+#--------------|-----------------------|-----------------------|--------------
+header romfs/header.img 0 0
+stage1 board-js2x/llfw/stage1.js2x 1 0x100
+xvect slof/xvect.bin 0 0
+ofw_main board-js2x/slof/slof.bin 0 0
+stageS board-js2x/llfw/stageS.bin 0 0
+bootinfo board-js2x/llfw/Cboot.bin 0 0
+rtas board-js2x/rtas/rtas.bin 0 0
+snk clients/net-snk.client 0 0
+net_bcm other-licence/bcm/net_bcm57xx.bin 0 0
diff --git a/board-js2x/romfs/boot_rom_bimini.ffs b/board-js2x/romfs/boot_rom_bimini.ffs
new file mode 100644
index 0000000..f89ddb8
--- /dev/null
+++ b/board-js2x/romfs/boot_rom_bimini.ffs
@@ -0,0 +1,23 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+# FFile-Name Real Filename Flags ROM-Offset i/a
+#--------------|-----------------------|-----------------------|--------------
+header romfs/header.img 0 0
+stage1 board-js2x/llfw/stage1.bimini 1 0x100
+xvect slof/xvect.bin 0 0
+ofw_main board-js2x/slof/slof.bin 0 0
+stageS board-js2x/llfw/stageS.bin 0 0
+bootinfo board-js2x/llfw/Cboot.bin 0 0
+rtas board-js2x/rtas/rtas.bin 0 0
+snk clients/net-snk.client 0 0
+net_bcm other-licence/bcm/net_bcm57xx.bin 0 0
diff --git a/board-js2x/rtas/Makefile b/board-js2x/rtas/Makefile
new file mode 100644
index 0000000..02fa2c7
--- /dev/null
+++ b/board-js2x/rtas/Makefile
@@ -0,0 +1,89 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include ../Makefile.dirs
+
+include $(TOPBRDDIR)/config
+include $(TOPCMNDIR)/make.rules
+
+
+LDFLAGS = -nostdlib
+CPPFLAGS = -I. -I$(LIBCMNDIR)/libc/include -I$(LIBCMNDIR)/libipmi -I$(INCLBRDDIR) \
+ -I$(INCLCMNDIR) -I$(RTASCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH)
+ASFLAGS = $(PLATFORM) -Wa,-mregnames $(FLAG)
+CFLAGS += -Wall -Wextra -O2 -msoft-float -ffreestanding $(PLATFORM) $(FLAG)
+
+# Board specific RTAS files:
+BOARD_SRC_ASM =
+BOARD_SRC_C = rtas_flash.c rtas_board.c rtas_pci.c \
+ rtas_out.c rtas_table.c
+BOARD_SRCS = $(BOARD_SRC_ASM) $(BOARD_SRC_C)
+BOARD_OBJ = $(BOARD_SRC_ASM:%.S=%.o) $(BOARD_SRC_C:%.c=%.o) $(BOARD_OCO:%.oco=%.o)
+BOARD_OCO = i2c_bmc.oco ipmi_oem.oco
+
+
+# Common RTAS files (from $(RTASCMNDIR) directory):
+RTAS_SRC_ASM = rtas_entry.S rtas_common.S reloc.S
+RTAS_SRC_C = rtas_call.c
+RTAS_SRCS = $(RTAS_SRC_ASM) $(RTAS_SRC_C)
+RTAS_OBJ = $(RTAS_SRC_ASM:%.S=%.o) $(RTAS_SRC_C:%.c=%.o)
+
+RTAS_FLASH_SRC = block_lists.c
+RTAS_FLASH_OBJ = $(RTAS_FLASH_SRC:%.c=$(RTASCMNDIR)/flash/%.o)
+
+# Additional object files:
+EXTRA_OBJ = ../llfw/hw.o ../../lib/libc.a ../../lib/libipmi.a
+
+OBJS = $(RTAS_OBJ:%=$(RTASCMNDIR)/%) $(BOARD_OBJ) $(EXTRA_OBJ) \
+ $(RTAS_FLASH_OBJ)
+
+
+all: Makefile.dep rtas.bin
+
+rtas.bin: rtas
+ $(OBJCOPY) -O binary $< $@
+
+rtas: $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o
+ $(LD) $(LDFLAGS) -o $@ -T $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o
+
+reloc_table.o: $(TOOLSDIR)/gen_reloc_table $(OBJS)
+ $(TOOLSDIR)/create_reloc_table.sh --ld "$(LD)" --ldflags "$(LDFLAGS)" \
+ --lds "$(RTASCMNDIR)/rtas.lds" --objcopy "$(OBJCOPY)" $(OBJS)
+
+$(TOOLSDIR)/gen_reloc_table: $(TOOLSDIR)/gen_reloc_table.c
+ $(MAKE) -C $(TOOLSDIR) gen_reloc_table
+
+../../lib/libc.a:
+ make -C ../../lib
+
+clean:
+ make -C ../../lib clean
+ rm -f $(OBJS) reloc_table.o rtas rtas.bin
+
+distclean : clean
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(BOARD_SRCS) > Makefile.dep
+ $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(RTAS_SRCS:%=$(RTASCMNDIR)/%) \
+ | sed -e '/:/s,^,$(RTASCMNDIR)/,' >> Makefile.dep
+Makefile.dep:
+ $(MAKE) depend
+
+# Include dependency file if available:
+ifneq (,$(wildcard Makefile.dep))
+include Makefile.dep
+endif
+%.o: %.oco
+ cp -f $< $@
diff --git a/board-js2x/rtas/rtas_board.c b/board-js2x/rtas/rtas_board.c
new file mode 100644
index 0000000..1a3c9e2
--- /dev/null
+++ b/board-js2x/rtas/rtas_board.c
@@ -0,0 +1,215 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <rtas.h>
+#include "rtas_board.h"
+#include <bmc.h>
+#include <rtas_i2c_bmc.h>
+#include <rtas_ipmi_bmc.h>
+#include "libipmi.h"
+#include <hw.h>
+
+void io_init(void);
+
+typedef struct {
+ uint64_t r3;
+ uint64_t addr;
+ volatile uint64_t id;
+} slave_t;
+
+volatile slave_t rtas_slave_interface;
+
+void
+rtas_slave_loop(volatile slave_t * pIface)
+{
+ uint64_t mask = pIface->id;
+ pIface->id = 0;
+ while (pIface->id != mask); {
+ int dly = 0x1000;
+ while (dly--);
+ }
+ pIface->id = 0;
+ asm(" mr 3,%0 ; mtctr %1 ; bctr "::"r"(pIface->r3), "r"(pIface->addr));
+
+}
+
+void
+rtas_fetch_slaves(rtas_args_t * pArgs)
+{
+ int retVal = 0;
+ int idx = 0;
+ uint32_t mask = pArgs->args[0] & 0xFFFFFFFE;
+ while (mask) {
+ if (mask & 0x1) {
+ rtas_slave_interface.id = idx | 0x100;
+ *(int *) 0x3fc0 = (int) &rtas_slave_interface; // r3
+ *(int *) 0x3f80 = *(uint64_t *) rtas_slave_loop; // addr
+ *(int *) 0x3fa0 = idx | 0x100; // pid
+ while (rtas_slave_interface.id);
+ }
+ mask >>= 1;
+ idx++;
+ }
+ pArgs->args[pArgs->nargs] = retVal;
+}
+
+void
+rtas_start_cpu(rtas_args_t * pArgs)
+{
+ int retVal = 0;
+ int idx = pArgs->args[0]; // pid
+ rtas_slave_interface.r3 = pArgs->args[2]; // r3
+ rtas_slave_interface.addr = pArgs->args[1]; // addr
+ asm(" sync ");
+ rtas_slave_interface.id = idx | 0x100; // pid
+ while (rtas_slave_interface.id);
+ pArgs->args[pArgs->nargs] = retVal;
+}
+
+void
+rtas_read_vpd(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] =
+ bmc_read_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1],
+ pArgs->args[0]);
+}
+
+void
+rtas_write_vpd(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] =
+ bmc_write_vpd((uint8_t *) (uint64_t) pArgs->args[2], pArgs->args[1],
+ pArgs->args[0]);
+}
+
+void
+rtas_set_indicator(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = -1;
+}
+
+void
+rtas_event_scan(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = -1;
+}
+
+void
+rtas_stop_bootwatchdog(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = bmc_stop_bootwatchdog();
+}
+
+void
+rtas_set_bootwatchdog(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = bmc_set_bootwatchdog(pArgs->args[0]);
+}
+
+void
+rtas_set_flashside(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = bmc_set_flashside(pArgs->args[0]);
+}
+
+void
+rtas_get_flashside(rtas_args_t * pArgs)
+{
+ int retVal = bmc_get_flashside();
+ pArgs->args[pArgs->nargs] = retVal;
+}
+
+void
+rtas_flash_test(rtas_args_t * pArgs)
+{
+ pArgs->args[pArgs->nargs] = -1;
+}
+
+void
+rtas_system_reboot(rtas_args_t * pArgs)
+{
+ bmc_system_reboot();
+ pArgs->args[pArgs->nargs] = -1;
+}
+
+void
+rtas_power_off(rtas_args_t * pArgs)
+{
+ bmc_power_off();
+ pArgs->args[pArgs->nargs] = -1;
+}
+
+void
+rtas_get_blade_descr(rtas_args_t * pArgs)
+{
+ uint8_t *buffer = (uint8_t *) (uint64_t) pArgs->args[0];
+ uint32_t maxlen = pArgs->args[1];
+ uint32_t retlen = 0;
+ uint32_t retval = bmc_get_blade_descr(buffer, maxlen, &retlen);
+ pArgs->args[pArgs->nargs] = retlen;
+ pArgs->args[pArgs->nargs + 1] = retval;
+}
+
+// for JS20 cannot read blade descr
+uint32_t
+dummy_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len)
+{
+ // to not have a warning we need to do _something_ with *dst and maxlen...
+ *dst = *dst;
+ maxlen = maxlen;
+ *len = 0;
+ return -1;
+}
+
+/* read flashside from register */
+short
+reg_get_flashside(void)
+{
+ short retVal;
+ uint8_t val = load8_ci(0xf4003fe3);
+ if (val & 0x80) {
+ // temp
+ retVal = 1;
+ } else {
+ // perm
+ retVal = 0;
+ }
+ return retVal;
+}
+
+void
+rtas_init(void)
+{
+ io_init();
+ if (u4Flag) {
+ bmc_system_reboot = ipmi_system_reboot;
+ bmc_power_off = ipmi_power_off;
+ bmc_set_flashside = ipmi_set_flashside;
+ bmc_get_flashside = reg_get_flashside;
+ bmc_stop_bootwatchdog = ipmi_oem_stop_bootwatchdog;
+ bmc_set_bootwatchdog = ipmi_oem_set_bootwatchdog;
+ bmc_read_vpd = ipmi_oem_read_vpd;
+ bmc_write_vpd = ipmi_oem_write_vpd;
+ bmc_get_blade_descr = ipmi_oem_get_blade_descr;
+ } else {
+ bmc_system_reboot = i2c_system_reboot;
+ bmc_power_off = i2c_power_off;
+ bmc_set_flashside = i2c_set_flashside;
+ bmc_get_flashside = i2c_get_flashside;
+ bmc_stop_bootwatchdog = i2c_stop_bootwatchdog;
+ bmc_set_bootwatchdog = i2c_set_bootwatchdog;
+ bmc_read_vpd = i2c_read_vpd;
+ bmc_write_vpd = i2c_write_vpd;
+ bmc_get_blade_descr = dummy_get_blade_descr;
+ }
+}
diff --git a/board-js2x/rtas/rtas_board.h b/board-js2x/rtas/rtas_board.h
new file mode 100644
index 0000000..107da45
--- /dev/null
+++ b/board-js2x/rtas/rtas_board.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __RTAS_BOARD_H
+#define __RTAS_BOARD_H
+
+#include <stddef.h>
+
+extern volatile unsigned char u4Flag;
+
+void rtas_ibm_read_pci_config(rtas_args_t * pArgs);
+void rtas_ibm_write_pci_config(rtas_args_t * pArgs);
+void rtas_read_pci_config(rtas_args_t * pArgs);
+void rtas_write_pci_config(rtas_args_t * pArgs);
+void rtas_system_reboot(rtas_args_t * pArgs);
+void rtas_power_off(rtas_args_t * pArgs);
+void rtas_display_character(rtas_args_t * pArgs);
+void rtas_flash_test(rtas_args_t * pArgs);
+void rtas_ibm_update_flash_64_and_reboot(rtas_args_t * pArgs);
+void rtas_set_indicator(rtas_args_t * pArgs);
+void rtas_event_scan(rtas_args_t * pArgs);
+void rtas_ibm_manage_flash_image(rtas_args_t * pArgs);
+void rtas_ibm_validate_flash_image(rtas_args_t * pArgs);
+void rtas_update_flash(rtas_args_t * pArgs);
+void rtas_set_flashside(rtas_args_t * pArgs);
+void rtas_get_flashside(rtas_args_t * pArgs);
+void rtas_dump_flash(rtas_args_t * pArgs);
+void rtas_start_cpu(rtas_args_t * pArgs);
+void rtas_read_vpd(rtas_args_t * pArgs);
+void rtas_write_vpd(rtas_args_t * pArgs);
+void rtas_fetch_slaves(rtas_args_t * pArgs);
+void rtas_stop_bootwatchdog(rtas_args_t * pArgs);
+void rtas_get_blade_descr(rtas_args_t * pArgs);
+void rtas_set_bootwatchdog(rtas_args_t * pArgs);
+
+#endif /* __RTAS_BOARD_H */
diff --git a/board-js2x/rtas/rtas_flash.c b/board-js2x/rtas/rtas_flash.c
new file mode 100644
index 0000000..2a21984
--- /dev/null
+++ b/board-js2x/rtas/rtas_flash.c
@@ -0,0 +1,613 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
+#include <string.h>
+#include <stdio.h>
+#include <types.h>
+#include <hw.h>
+#include <rtas.h>
+#include "rtas_board.h"
+#include <bmc.h>
+#include "rtas_flash.h"
+#include <flash/block_lists.h>
+#include "product.h"
+#include "calculatecrc.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define dprintf(_x...) printf(_x)
+#else
+#define dprintf(_x...)
+#endif
+
+static uint64_t size;
+static uint64_t flashOffset;
+
+unsigned short manage_flash_buffer[BUFSIZE];
+unsigned long check_flash_image(unsigned long rombase, unsigned long length,
+ unsigned long start_crc);
+
+#ifdef DEBUG
+void
+dump_blocklist(uint64_t * bl, int version)
+{
+ uint64_t bl_size;
+ uint8_t *addr = (uint8_t *) bl;
+ if (version == 1) {
+ // version 1 blocklist
+ bl_size = *bl & 0x00FFFFFFFFFFFFFFUL;
+
+ } else {
+ bl_size = *bl;
+ }
+
+ printf("\n\rblocklist_dump %lx", bl_size);
+ while (bl_size) {
+ unsigned int tmpCnt = bl_size;
+ unsigned char x;
+ if (tmpCnt > 8)
+ tmpCnt = 8;
+ printf("\n\r%08x: ", addr);
+ // print hex
+ while (tmpCnt--) {
+ set_ci();
+ x = *addr++;
+ clr_ci();
+ printf("%02x ", x);
+ }
+ tmpCnt = bl_size;
+ if (tmpCnt > 8)
+ tmpCnt = 8;
+ bl_size -= tmpCnt;
+ //reset addr ptr to print ascii
+ addr = addr - tmpCnt;
+ // print ascii
+ while (tmpCnt--) {
+ set_ci();
+ x = *addr++;
+ clr_ci();
+ if ((x < 32) || (x >= 127)) {
+ //non-printable char
+ x = '.';
+ }
+ printf("%c", x);
+ }
+ }
+ printf("\r\n");
+}
+#endif
+
+void
+rtas_dump_flash(rtas_args_t * rtas_args)
+{
+ int retVal = 0;
+ unsigned int size = rtas_args->args[0];
+ unsigned int offset = rtas_args->args[1];
+ unsigned char *flash = (unsigned char *) FLASH;
+ printf("\n\rflash_dump %x %x", size, offset);
+ flash += offset;
+ while (size) {
+ unsigned int tmpCnt = size;
+ unsigned char x;
+ if (tmpCnt > 16)
+ tmpCnt = 16;
+ printf("\n\r%p: ", flash);
+ // print hex
+ while (tmpCnt--) {
+ set_ci();
+ x = *flash++;
+ clr_ci();
+ printf("%02x ", x);
+ }
+ tmpCnt = size;
+ if (tmpCnt > 16)
+ tmpCnt = 16;
+ size -= tmpCnt;
+ //reset flash ptr to print ascii
+ flash = flash - tmpCnt;
+ // print ascii
+ while (tmpCnt--) {
+ set_ci();
+ x = *flash++;
+ clr_ci();
+ if ((x < 32) || (x >= 127)) {
+ //non-printable char
+ x = '.';
+ }
+ printf("%c", x);
+ }
+ }
+ printf("\r\n");
+ rtas_args->args[rtas_args->nargs] = retVal;
+}
+
+
+static void
+print_block(int i)
+{
+ int counter = 8;
+ while (counter--)
+ printf("\b");
+ printf("%08x", i);
+}
+
+
+
+/* To enter data mode after flash has been in programming mode
+ * a 0xFF has to be written */
+void
+enter_data_mode(void)
+{
+ unsigned char *flash = (unsigned char *) FLASH;
+ set_ci();
+ *flash = 0xFF;
+ eieio();
+ clr_ci();
+}
+
+
+static void
+erase_flash_block(unsigned long offset)
+{
+ volatile unsigned char *flash = (unsigned char *) FLASH;
+ flash += offset;
+ set_ci();
+ *flash = 0x20;
+ eieio();
+ *flash = 0xd0;
+ eieio();
+ while (!(*flash & 0x80));
+ clr_ci();
+}
+
+
+void
+write_flash(unsigned long offset, unsigned char *data)
+{
+ int cnt = 32;
+ volatile unsigned char *flash = (unsigned char *) FLASH;
+ flash += (offset + flashOffset);
+ set_ci();
+ while (cnt) {
+ if (!((uint64_t) flash & 0x1F)) {
+ while (cnt) {
+ uint64_t tmpcnt = cnt;
+ if (tmpcnt > 0x20)
+ tmpcnt = 0x20;
+ do {
+ *flash = 0xE8;
+ eieio();
+ } while (!(*flash & 0x80));
+ cnt -= tmpcnt;
+ *flash = tmpcnt - 1;
+ while (tmpcnt--) {
+ *flash++ = *data++;
+ }
+ *flash = 0xD0;
+ eieio();
+ while (!(*flash & 0x80));
+ }
+ break;
+ }
+ *flash = 0x40;
+ eieio();
+ *flash++ = *data++;
+ eieio();
+ while (!(*flash & 0x80));
+ cnt--;
+ }
+ clr_ci();
+}
+
+void
+write_flash_page(unsigned long offset, unsigned short *data)
+{
+ int i = 0;
+ for (i = 0; i < BUFSIZE; i += 32, offset += 32) {
+ write_flash(offset, ((unsigned char *) data + i));
+ }
+}
+
+/*
+ * 0 reject temporary image
+ * 1 commit temporary image
+ * */
+int
+copy_flash(short mode)
+{
+ unsigned char *flash = (unsigned char *) FLASH;
+ uint64_t blockCnt;
+ short notmode = mode ^ 0x1;
+ if (bmc_set_flashside(notmode) != notmode) {
+ return -1;
+ }
+ printf("\r\nErasing Flash: 0x ");
+
+ for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += FLASH_BLOCK_SIZE) {
+ print_block(blockCnt);
+ erase_flash_block(blockCnt);
+ }
+ enter_data_mode();
+ progress = FLASHSIZE / 38;
+ print_writing();
+
+ for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += BUFSIZE) {
+ uint64_t *srcPtr = (uint64_t *) (flash + blockCnt);
+ uint64_t *destPtr = (uint64_t *)((void*) manage_flash_buffer);
+ uint64_t cnt = BUFSIZE / 8;
+ if (bmc_set_flashside(mode) != mode) {
+ return -1;
+ }
+ enter_data_mode();
+ set_ci();
+ while (cnt--) {
+ *destPtr++ = *srcPtr++;
+ }
+ clr_ci();
+
+ if (bmc_set_flashside(notmode) != notmode) {
+ return -1;
+ }
+ write_flash_page(blockCnt,
+ (unsigned short *) manage_flash_buffer);
+ }
+ enter_data_mode();
+ if (bmc_set_flashside(mode) != mode) {
+ return -1;
+ }
+ printf("\b# ");
+ return 0;
+}
+
+/*
+Function: ibm_manage_flash_image
+ Input:
+ r3: rtas parm structure
+ token: 46
+ in: 1
+ out: 1
+ parm0: 0 reject temporary image
+ 1 commit temporary image
+ Output:
+ parm1: Status (hw -1, busy -2, parameter error -3
+ -9001 cannot overwrite the active firmware image)
+
+*/
+
+void
+rtas_ibm_manage_flash_image(rtas_args_t * rtas_args)
+{
+ int side;
+ int result = 0;
+ short mode = rtas_args->args[0];
+ if (mode < 0 || mode > 1) {
+ rtas_args->args[rtas_args->nargs] = -3;
+ return;
+ }
+ side = bmc_get_flashside();
+ if (side == 0) {
+ /* we are on the permanent side */
+ if (mode != 0) {
+ rtas_args->args[rtas_args->nargs] = -9001;
+ return;
+ }
+ } else if (side == 1) {
+ /* we are on the temporary side */
+ if (mode != 1) {
+ rtas_args->args[rtas_args->nargs] = -9001;
+ return;
+ }
+ } else {
+ rtas_args->args[rtas_args->nargs] = -1;
+ return;
+ }
+
+ result = copy_flash(mode);
+ bmc_set_flashside(mode);
+ enter_data_mode();
+ rtas_args->args[rtas_args->nargs] = 0;
+ return;
+}
+
+/**
+* check, if we find the FLASHFS_MAGIC token in bl
+**/
+static uint8_t
+check_magic(uint64_t * bl, int version)
+{
+ struct stH *pHeader;
+
+ if (version == 1) {
+ // version 1 blocklist
+ // if block list size <= 0x10, it is only block list header
+ // and address of block list extension, so look at the extension...
+ while ((*bl & 0x00FFFFFFFFFFFFFFUL) <= 0x10)
+ bl = (uint64_t *) bl[1];
+
+ //block list item 2 _should_ be the address of our flashfs image
+ pHeader = (struct stH *) (bl[2] + 0x28);
+ //printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic);
+ return strncmp(pHeader->magic, FLASHFS_MAGIC, 8);
+ } else {
+ //block list item 1 _should_ be the address of our flashfs image
+ pHeader = (struct stH *) (bl[1] + 0x28);
+ //printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic);
+ return strncmp(pHeader->magic, FLASHFS_MAGIC, 8);
+ }
+}
+
+static void
+get_image_name(char *buffer, int maxsize)
+{
+ struct stH *flash_header = (struct stH *) (SB_FLASH_adr + 0x28);
+ //since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory
+ uint64_t magic_val = 0;
+ uint64_t addr;
+
+ //copy fh_magic to magic_val since, we cannot use it as a string from flash
+ magic_val = load64_ci((uint64_t) (flash_header->magic));
+ if (strncmp((char *) &magic_val, FLASHFS_MAGIC, 8)) {
+ /* magic does not match */
+ sprintf(buffer, "Unknown");
+ buffer[maxsize - 1] = '\0';
+ return;
+ }
+ addr = (uint64_t) flash_header->version;
+ while (--maxsize) {
+ *buffer = load8_ci(addr++);
+ if (!*buffer++)
+ return;
+ }
+ *buffer = '\0';
+
+}
+
+/**
+ * validate_flash_image
+ * this function checks if the flash will be updated with the given image
+ * @param args[0] - buffer with minimum 4K of the image to flash
+ * @param args[1] - size of the buffer
+ * @param args[2] - status:
+ * 0 success
+ * -1 hw
+ * -2 busy
+ * -3 parameter error
+ * -9002 not authorized
+ * @param args[3] - update result token
+ */
+void
+rtas_ibm_validate_flash_image(rtas_args_t * rtas_args)
+{
+ dprintf("\nrtas_ibm_validate_flash_image\n");
+ unsigned long new_image = rtas_args->args[0];
+ char *ret_str = (char *) new_image;
+ struct stH *flash_header = (struct stH *) (new_image + 0x28);
+ char current_temp_version[16];
+ char current_perm_version[16];
+ char new_version[16];
+ int side = bmc_get_flashside();
+
+ /* fill args[0] with the current values which is needed
+ * in an error case */
+
+ bmc_set_flashside(0);
+ get_image_name(current_perm_version, sizeof(current_perm_version));
+ bmc_set_flashside(1);
+ get_image_name(current_temp_version, sizeof(current_temp_version));
+ bmc_set_flashside(side);
+ /* first check if we are running on P
+ * we do not flash on the permanent side */
+ if (side == 0) {
+ /* not authorized */
+ rtas_args->args[rtas_args->nargs] = -9002;
+ /* No update done, partition does not have
+ * authority to perform flash update */
+ rtas_args->args[rtas_args->nargs + 1] = 1;
+ sprintf(ret_str, "MI %s %s\xaMI %s %s",
+ current_temp_version, current_perm_version,
+ current_temp_version, current_perm_version);
+ return;
+ }
+
+ /* check if the candidate image if valid for this platform */
+ if (strncmp(flash_header->magic, FLASHFS_MAGIC, 8)) {
+ /* magic does not match */
+ rtas_args->args[rtas_args->nargs] = 0;
+ /* No update done, the candidate image is
+ * not valid for this platform */
+ rtas_args->args[rtas_args->nargs + 1] = 2;
+ sprintf(ret_str, "MI %s %s\xaMI %s %s",
+ current_temp_version, current_perm_version,
+ current_temp_version, current_perm_version);
+ return;
+ }
+
+ if (strncmp(flash_header->platform_name, (char *) sig_org, 32)) {
+ /* this image if for a different board */
+ rtas_args->args[rtas_args->nargs] = 0;
+ /* No update done, the candidate image is
+ * not valid for this platform */
+ rtas_args->args[rtas_args->nargs + 1] = 2;
+ sprintf(ret_str, "MI %s %s\xaMI %s %s",
+ current_temp_version, current_perm_version,
+ current_temp_version, current_perm_version);
+ return;
+ }
+
+ /* check header crc */
+ if (check_flash_image(rtas_args->args[0], 0x88, 0)) {
+ /* header crc failed */
+ rtas_args->args[rtas_args->nargs] = 0;
+ /* No update done, the candidate image is
+ * not valid for this platform */
+ rtas_args->args[rtas_args->nargs + 1] = 2;
+ sprintf(ret_str, "MI %s %s\xaMI %s %s",
+ current_temp_version, current_perm_version,
+ current_temp_version, current_perm_version);
+ return;
+ }
+ memcpy(new_version, flash_header->version, 16);
+ sprintf(ret_str, "MI %s %s\xaMI %s %s",
+ current_temp_version, current_perm_version,
+ side ? new_version : current_temp_version,
+ side ? current_perm_version : new_version);
+ rtas_args->args[rtas_args->nargs] = 0;
+ if (strncmp
+ (new_version, side ? current_temp_version : current_perm_version,
+ 16) >= 0) {
+ rtas_args->args[rtas_args->nargs + 1] = 0;
+ } else {
+ rtas_args->args[rtas_args->nargs + 1] = 6;
+ }
+ return;
+}
+
+/*
+Function: ibm_update_flash_64
+ Input:
+ r3: rtas parm structure
+ token: 7
+ in: 1
+ out: 1
+ parm0: A real pointer to a block list
+ Output:
+ parm1: Status (hw -1, bad image -3, programming failed -4)
+
+Decription: flash if addresses above 4GB have to be addressed
+*/
+void
+rtas_update_flash(rtas_args_t * rtas_args)
+{
+ void *bl = (void *) (uint64_t) rtas_args->args[0];
+ int version = get_block_list_version((unsigned char *) bl);
+ uint64_t erase_size;
+ uint64_t i;
+
+#ifdef DEBUG
+ dump_blocklist(bl, version);
+#endif
+
+ //first check if we are running on P
+ //we do not flash on the permanent side
+ if (bmc_get_flashside() == 0) {
+ rtas_args->args[rtas_args->nargs] = -9002; //not authorized
+ return;
+ }
+ //check magic string
+ printf("\r\nChecking magic string : ");
+ if (check_magic(bl, version) != 0) {
+ printf("failed!\n");
+ rtas_args->args[rtas_args->nargs] = -3; //bad image
+ return;
+ }
+ printf("succeeded!\n");
+
+ //check platform
+ printf("Checking platform : ");
+ if (check_platform(bl, 0x48, version) == -1) {
+ printf("failed!\n");
+ rtas_args->args[rtas_args->nargs] = -3; //bad image
+ return;
+ }
+ printf("succeeded!\n");
+
+ //checkcrc
+ printf("Checking CRC : ");
+ // the actual CRC is included at the end of the flash image, thus the resulting CRC must be 0!
+ if (image_check_crc(bl, version) != 0) {
+ printf("failed!\n");
+ rtas_args->args[1] = -3; //bad image
+ return;
+ }
+ printf("succeeded!\n");
+
+#ifdef DEBUG
+ rtas_args_t ra;
+ ra.args[0] = 0x100; //size;
+ ra.args[1] = flashOffset;
+ ra.nargs = 2;
+
+ rtas_dump_flash(&ra);
+ printf("\n");
+#endif
+
+ size = get_size(bl, version);
+ erase_size = (size + (FLASH_BLOCK_SIZE - 1)) & ~(FLASH_BLOCK_SIZE - 1);
+ dprintf("Erasing: size: %#x, erase_size: %#x, FLASH_BLOCK_SIZE: %#x\n",
+ size, erase_size, FLASH_BLOCK_SIZE);
+
+ progress = size / 39;
+ printf("Erasing : 0x%08x", 0);
+ for (i = 0; i < erase_size; i += FLASH_BLOCK_SIZE) {
+ print_block(i);
+ erase_flash_block(i);
+ }
+
+ enter_data_mode();
+#ifdef DEBUG
+ rtas_dump_flash(&ra);
+ printf("\n");
+#endif
+ print_writing();
+ write_block_list(bl, version);
+ printf("\b#\n");
+ enter_data_mode();
+
+#ifdef DEBUG
+ rtas_dump_flash(&ra);
+ printf("\n");
+#endif
+
+ //checkcrc
+ printf("Recheck CRC : ");
+ if (check_flash_image(FLASH + flashOffset, size, 0) != 0) {
+ //failed
+ printf("failed!\n\r");
+ dprintf("flash_addr: %#x, flashOffset: %#x, size: %#x\n", FLASH,
+ flashOffset, size);
+ dprintf("crc: %#x\n",
+ check_flash_image(FLASH + flashOffset, size, 0));
+ rtas_args->args[rtas_args->nargs] = -4; //programming failed
+ return;
+ }
+ printf("succeeded!\n");
+ rtas_args->args[rtas_args->nargs] = 0;
+
+ return;
+}
+
+/*
+Function: ibm_update_flash_64_and_reboot
+ Input:
+ r3: rtas parm structure
+ token: 27
+ in: 1
+ out: 1
+ parm0: A real pointer to a block list
+ Output:
+ parm1: Status (hw -1, bad image -3, programming failed -4)
+ Currently -4 and -1 are not returned
+
+Decription: flash and reboot if addresses above 4GB have to be addressed
+*/
+void
+rtas_ibm_update_flash_64_and_reboot(rtas_args_t * rtas_args)
+{
+ rtas_update_flash(rtas_args);
+ dprintf("rc: %#d\n", rtas_args->args[rtas_args->nargs]);
+ if (rtas_args->args[rtas_args->nargs] == 0) {
+ rtas_system_reboot(rtas_args);
+ }
+ return;
+}
diff --git a/board-js2x/rtas/rtas_flash.h b/board-js2x/rtas/rtas_flash.h
new file mode 100644
index 0000000..7efd925
--- /dev/null
+++ b/board-js2x/rtas/rtas_flash.h
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <southbridge.h>
+
+#define FLASHSIZE FLASH_LENGTH
+#define FLASH SB_FLASH_adr
+#define BUFSIZE 4096
+#define FLASH_BLOCK_SIZE 0x20000
diff --git a/board-js2x/rtas/rtas_i2c_bmc.h b/board-js2x/rtas/rtas_i2c_bmc.h
new file mode 100644
index 0000000..301e32c
--- /dev/null
+++ b/board-js2x/rtas/rtas_i2c_bmc.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __RTAS_I2C_BMC_H
+#define __RTAS_I2C_BMC_H
+
+#include <stddef.h>
+
+void i2c_system_reboot (void);
+void i2c_power_off (void);
+short i2c_set_flashside (short mode);
+short i2c_get_flashside (void);
+int i2c_stop_bootwatchdog (void);
+uint32_t i2c_read_vpd (uint8_t *dst, uint32_t len, uint32_t offset);
+uint32_t i2c_write_vpd (uint8_t *src, uint32_t len, uint32_t offset);
+int i2c_set_bootwatchdog(unsigned short seconds);
+
+#endif /* __RTAS_I2C_BMC_H */
diff --git a/board-js2x/rtas/rtas_ipmi_bmc.h b/board-js2x/rtas/rtas_ipmi_bmc.h
new file mode 100644
index 0000000..92cded6
--- /dev/null
+++ b/board-js2x/rtas/rtas_ipmi_bmc.h
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __RTAS_IPMI_BMC_H
+#define __RTAS_IPMI_BMC_H
+
+#include <stddef.h>
+
+short ipmi_set_flashside (short mode);
+short ipmi_get_flashside (void);
+
+#endif /* __RTAS_IPMI_BMC_H */
diff --git a/board-js2x/rtas/rtas_out.c b/board-js2x/rtas/rtas_out.c
new file mode 100644
index 0000000..fa704f4
--- /dev/null
+++ b/board-js2x/rtas/rtas_out.c
@@ -0,0 +1,114 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <types.h>
+#include <rtas.h>
+#include <hw.h>
+
+volatile unsigned char *uart;
+volatile unsigned char u4Flag;
+
+void
+io_init(void)
+{
+ // read ID register: only if it is a PC87427, enable serial2
+ store8_ci(0xf400002e, 0x20);
+ if (load8_ci(0xf400002f) != 0xf2) {
+ uart = (volatile unsigned char *) 0xf40003f8;
+ u4Flag = 0;
+ } else {
+ uart = (volatile unsigned char *) 0xf40002f8;
+ u4Flag = 1;
+ }
+}
+
+void
+display_char(char ch)
+{
+ volatile int i = 0;
+ volatile unsigned char *uart = (volatile unsigned char *) 0xf40002f8;
+ int cnt = 2;
+ while (cnt--) {
+ set_ci();
+ while (!(uart[5] & 0x20)) {
+ i++;
+ }
+ uart[0] = ch;
+ clr_ci();
+ uart += 0x100;
+ }
+}
+
+size_t
+write(int fd __attribute((unused)), const void *buf, size_t cnt)
+{
+ while (cnt--) {
+ display_char(*(char *) buf);
+ if (*(char *) buf++ == '\n')
+ display_char('\r');
+ }
+ return 0;
+}
+
+void *
+sbrk(int incr __attribute((unused)))
+{
+ return (void *) -1;
+}
+
+
+
+int
+rtas_display_character(rtas_args_t * pArgs)
+{
+ int retVal = 0;
+ display_char((char) pArgs->args[0]);
+ return retVal;
+}
+
+unsigned long
+check_flash_image(unsigned long rombase, unsigned long length,
+ unsigned long start_crc)
+{
+ const uint32_t CrcTableHigh[16] = {
+ 0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90,
+ 0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7,
+ 0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E,
+ 0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09
+ };
+ const uint32_t CrcTableLow[16] = {
+ 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
+ 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
+ 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
+ 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
+ };
+
+ char *Buffer = (char *) rombase;
+ uint32_t AccumCRC = start_crc;
+ char val;
+ uint32_t Temp;
+ while (length-- > 0) {
+ set_ci();
+ val = *Buffer;
+ clr_ci();
+ Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff;
+ AccumCRC <<= 8;
+ AccumCRC ^= CrcTableHigh[Temp / 16];
+ AccumCRC ^= CrcTableLow[Temp % 16];
+ ++Buffer;
+ }
+ return AccumCRC;
+}
diff --git a/board-js2x/rtas/rtas_pci.c b/board-js2x/rtas/rtas_pci.c
new file mode 100644
index 0000000..087b686
--- /dev/null
+++ b/board-js2x/rtas/rtas_pci.c
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <types.h>
+#include <rtas.h>
+#include <hw.h>
+
+int
+rtas_ibm_read_pci_config (rtas_args_t *rtas_args) {
+ int retVal = 0;
+ uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32; // high 32 bits of PHB UID
+ addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID
+ addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset
+ unsigned int size = rtas_args->args[3];
+
+ /* Check for bus != 0 on PCI/PCI-X (PHB UID = 0xf2000000) */
+ if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000))
+ addr += 0x1000000;
+
+ if (size == 1)
+ rtas_args->args[5] = load8_ci(addr);
+ else if (size == 2)
+ rtas_args->args[5] = bswap16_load(addr);
+ else if (size == 4)
+ rtas_args->args[5] = bswap32_load(addr);
+ else
+ retVal = -3; /* Bad arguments */
+
+ return retVal;
+}
+
+int
+rtas_ibm_write_pci_config (rtas_args_t *rtas_args) {
+ int retVal = 0;
+ uint64_t addr = ((uint64_t) rtas_args->args[1]) << 32; // high 32 bits of PHB UID
+ addr |= (rtas_args->args[2] & 0xFFFFFFFF); // low 32 bits of PHB UID
+ addr |= (rtas_args->args[0] & 0x00FFFFFF); // bus, devfn, offset
+ unsigned int size = rtas_args->args[3];
+
+ addr |= 0xf2000000;
+
+ /* Check for bus != 0 on PCI/PCI-X (PHB UID = 0xf2000000) */
+ if (((addr & 0xf2000000) == 0xf2000000) && (addr & 0xff0000))
+ addr += 0x1000000;
+
+ if (size == 1)
+ store8_ci(addr, rtas_args->args[4]);
+ else if (size == 2)
+ bswap16_store(addr, rtas_args->args[4]);
+ else if (size == 4)
+ bswap32_store(addr, rtas_args->args[4]);
+ else
+ retVal = -3; /* Bad arguments */
+
+ return retVal;
+}
+
+int
+rtas_read_pci_config (rtas_args_t *rtas_args) {
+ int retVal = 0;
+ unsigned long addr = rtas_args->args[0];
+ unsigned int size = rtas_args->args[1];
+ addr |= 0xf2000000;
+
+ /* Check for bus != 0 */
+ if (addr & 0xff0000)
+ addr += 0x1000000;
+
+ if (size == 1)
+ rtas_args->args[3] = load8_ci(addr);
+ else if (size == 2)
+ rtas_args->args[3] = bswap16_load(addr);
+ else if (size == 4)
+ rtas_args->args[3] = bswap32_load(addr);
+ else
+ retVal = -3; /* Bad arguments */
+
+ return retVal;
+}
+
+int
+rtas_write_pci_config (rtas_args_t *rtas_args) {
+ int retVal = 0;
+ unsigned long addr = rtas_args->args[0];
+ unsigned int size = rtas_args->args[1];
+
+ addr |= 0xf2000000;
+
+ /* Check for bus != 0 */
+ if (addr & 0xff0000)
+ addr += 0x1000000;
+
+ if (size == 1)
+ store8_ci(addr, rtas_args->args[2]);
+ else if (size == 2)
+ bswap16_store(addr, rtas_args->args[2]);
+ else if (size == 4)
+ bswap32_store(addr, rtas_args->args[2]);
+ else
+ retVal = -3; /* Bad arguments */
+
+ return retVal;
+}
diff --git a/board-js2x/rtas/rtas_table.c b/board-js2x/rtas/rtas_table.c
new file mode 100644
index 0000000..f45830b
--- /dev/null
+++ b/board-js2x/rtas/rtas_table.c
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <types.h>
+#include <rtas.h>
+#include "rtas_table.h"
+#include "rtas_board.h"
+
+const rtas_funcdescr_t rtas_func_tab[] = {
+ {"ibm,read-pci-config", rtas_ibm_read_pci_config, 0},
+ {"ibm,write-pci-config", rtas_ibm_write_pci_config, 0},
+ {"system-reboot", rtas_system_reboot, 0},
+ {"power-off", rtas_power_off, 0},
+ {"set-indicator", rtas_set_indicator, 0},
+ {"rtas-flash-test", rtas_flash_test, RTAS_TBLFLG_INTERNAL},
+ {"ibm,update-flash-64-and-reboot", rtas_ibm_update_flash_64_and_reboot, 0},
+ {"display-character", rtas_display_character, 0},
+ {"event-scan", rtas_event_scan, 0},
+ {"ibm,manage-flash-image", rtas_ibm_manage_flash_image, 0},
+ {"ibm,validate-flash-image", rtas_ibm_validate_flash_image, 0},
+ {"ibm,update-flash-64", rtas_update_flash, 0},
+ {"rtas-set-flashside", rtas_set_flashside, 0},
+ {"rtas-get-flashside", rtas_get_flashside, 0},
+ {"rtas-dump-flash", rtas_dump_flash, RTAS_TBLFLG_INTERNAL},
+ {"start-cpu", rtas_start_cpu, 0},
+ {"msg-read-vpd", rtas_read_vpd, RTAS_TBLFLG_INTERNAL},
+ {"msg-write-vpd", rtas_write_vpd, RTAS_TBLFLG_INTERNAL},
+ {"read-pci-config", rtas_read_pci_config, 0},
+ {"write-pci-config", rtas_write_pci_config, 0},
+ {"rtas-fetch-slaves", rtas_fetch_slaves, RTAS_TBLFLG_INTERNAL},
+ {"rtas-stop-bootwatchdog", rtas_stop_bootwatchdog, RTAS_TBLFLG_INTERNAL},
+ {"rtas-set-bootwatchdog", rtas_set_bootwatchdog, RTAS_TBLFLG_INTERNAL},
+ {"freeze-time-base", NULL, RTAS_TBLFLG_INTERNAL},
+ {"thaw-time-base", NULL, RTAS_TBLFLG_INTERNAL},
+ {"rtas-get-blade-descr", rtas_get_blade_descr, RTAS_TBLFLG_INTERNAL},
+};
+
+const int rtas_func_tab_size = sizeof(rtas_func_tab) / sizeof(rtas_func_tab[0]);
diff --git a/board-js2x/slof/Makefile b/board-js2x/slof/Makefile
new file mode 100644
index 0000000..911ad75
--- /dev/null
+++ b/board-js2x/slof/Makefile
@@ -0,0 +1,106 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+include ../Makefile.dirs
+
+include $(TOPBRDDIR)/config
+include $(TOPCMNDIR)/make.rules
+
+
+all: Makefile.dep OF.ffs slof.bin $(SLOFCMNDIR)/xvect.bin
+
+CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg
+SLOF_LIBS = $(LIBCMNDIR)/libbootmsg.a
+BOARD_SLOF_IN = \
+ $(LIBCMNDIR)/libbootmsg/bootmsg.in \
+ $(LIBCMNDIR)/libbases/libbases.in
+BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code)
+
+include $(SLOFCMNDIR)/Makefile.inc
+
+FPPINCLUDES = -I. -I$(SLOFCMNDIR)/fs -I$(SLOFCMNDIR)
+
+# FCode Evaluator files for the ROM fs:
+FCODE_FFS_FILES = \
+ $(SLOFCMNDIR)/fs/fcode/core.fs \
+ $(SLOFCMNDIR)/fs/fcode/evaluator.fs \
+ $(SLOFCMNDIR)/fs/fcode/big.fs \
+ $(SLOFCMNDIR)/fs/fcode/tokens.fs \
+ $(SLOFCMNDIR)/fs/fcode/1275.fs
+
+
+USB_FFS_FILES = \
+ $(SLOFCMNDIR)/fs/devices/pci-class_0c.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-ohci.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-support.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-hub.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-enumerate.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-storage.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-storage-support.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-storage-wrapper.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-keyboard.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-kbd-device-support.fs \
+ $(SLOFCMNDIR)/fs/usb/usb-mouse.fs
+
+
+# Files that should go into the ROM fs (and so have to be listed in OF.ffs):
+OF_FFS_FILES = \
+ $(SLOFBRDDIR)/u4-mem.fs \
+ $(SLOFBRDDIR)/attu.fs \
+ $(SLOFBRDDIR)/cpu.fs \
+ $(SLOFBRDDIR)/ioapic.fs \
+ $(SLOFBRDDIR)/pci-bridge_1022_7460.fs \
+ $(SLOFBRDDIR)/pci-device_1014_028c.fs \
+ $(SLOFBRDDIR)/pci-device_1014_02bd.fs \
+ $(SLOFBRDDIR)/pci-device_1022_7468.fs \
+ $(SLOFBRDDIR)/pci-device_1022_7469.fs \
+ $(SLOFBRDDIR)/pci-device_1022_7451.fs \
+ $(SLOFBRDDIR)/pci-class_03.fs \
+ $(SLOFBRDDIR)/vga-display.fs \
+ $(SLOFBRDDIR)/freq.fs \
+ $(SLOFBRDDIR)/pci-device_1002_515e.fs \
+ $(SLOFBRDDIR)/citrine.fs \
+ $(SLOFBRDDIR)/citrine-disk.fs \
+ $(SLOFBRDDIR)/sio.fs \
+ $(SLOFBRDDIR)/tpm.fs \
+ $(SLOFBRDDIR)/ipmi-kcs.fs \
+ $(SLOFCMNDIR)/fs/ide.fs \
+ $(SLOFCMNDIR)/fs/fbuffer.fs \
+ $(SLOFCMNDIR)/fs/generic-disk.fs \
+ $(SLOFCMNDIR)/fs/pci-device.fs \
+ $(SLOFCMNDIR)/fs/pci-bridge.fs \
+ $(SLOFCMNDIR)/fs/pci-properties.fs \
+ $(SLOFCMNDIR)/fs/pci-config-bridge.fs \
+ $(SLOFCMNDIR)/fs/update_flash.fs \
+ $(SLOFCMNDIR)/fs/devices/pci-device_10de_0141.fs \
+ $(SLOFCMNDIR)/fs/devices/pci-class_02.fs \
+ $(SLOFBRDDIR)/default-font.bin \
+ $(FCODE_FFS_FILES)
+
+# Uncomment the following line to enable the USB code:
+OF_FFS_FILES += $(USB_FFS_FILES)
+
+OF_FFS_FILES := $(OF_FFS_FILES:%.fs=%.fsi)
+
+OF.ffs: Makefile $(SLOFCMNDIR)/Makefile.inc $(OF_FFS_FILES)
+ $(MAKE) create_OF_ffs
+
+# Rules for cleaning up:
+.PHONY: clean_here clean distclean
+
+clean_here:
+ rm -f *.o OF.fsi OF.ffs
+
+clean: clean_here clean_slof
+
+distclean: clean_here distclean_slof
diff --git a/board-js2x/slof/OF.fs b/board-js2x/slof/OF.fs
index 3bfd90a..e99fa20 100644
--- a/board-js2x/slof/OF.fs
+++ b/board-js2x/slof/OF.fs
@@ -1,187 +1,467 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ The master file. Everything else is included into here.
hex
-\ Speed up compiling.
-INCLUDE find-hash.fs
+\ as early as possible we want to know if it is js20, js21 or bimini
+\ u3 = js20; u4 = js21/bimini
+\ the difference if bimini or js21 will be done later depending if
+\ obsidian or citrine is found
+\ f8000000 is probably the place of the u3/u4 version
+f8000000 rl@ CONSTANT uni-n-version
+uni-n-version 4 rshift dup 3 = CONSTANT u3? 4 = CONSTANT u4?
+false value bimini?
+
+\ to decide wether vga initialisation using bios emulation should be attempted,
+\ we need to know wether a vga-device was found during pci-scan.
+\ If it is found, this value will be set to the device's phandle
+0 value vga-device-node?
-\ Enable use of multiple wordlists and vocabularies.
-INCLUDE search.fs
+\ planar-id reads back GPIO 29 30 31 and returns it as one value
+\ if planar-id >= 5 it should be GA2 else it is GA1 (JS20 only)
+defer planar-id ( -- planar-id )
-\ Heap memory allocation.
-INCLUDE alloc-mem.fs
+: (planar-id) ( -- planar-id)
+ \ default implementation of planar-id just returns 8
+ \ the highest possible planar id for JS20 is 7
+ 8
+;
-\ First some very generic code.
-: d# parse-word base @ >r decimal evaluate r> base ! ; immediate
-: END-STRUCT drop ;
-: 0.r 0 swap <# 0 ?DO # LOOP #> type ;
+' (planar-id) to planar-id
-: zcount ( zstr -- str len ) dup BEGIN dup c@ WHILE char+ REPEAT over - ;
-: zplace ( str len buf -- ) 2dup + 0 swap c! swap move ;
+#include "header.fs"
-CREATE $catpad 100 allot
-\ First input string is allowed to already be on the pad; second is not.
-: $cat ( str1 len1 str2 len2 -- str3 len3 )
- >r >r dup >r $catpad swap move
- r> dup $catpad + r> swap r@ move
- r> + $catpad swap ;
+\ I/O accesses.
+#include "io.fs"
-: 2CONSTANT CREATE swap , , DOES> 2@ ;
-: $2CONSTANT $CREATE swap , , DOES> 2@ ;
+\ XXX: Enable first UART on JS20, scripts forget to do this. Sigh.
+3 7 siocfg! 1 30 siocfg!
-\ Memory and I/O hexdump.
-INCLUDE dump.fs
+#include "serial.fs"
-\ I/O accesses.
-INCLUDE hw/io.fs
+cr
+
+eregs 11 8 * + @ CONSTANT hsprg1
+
+#include "base.fs"
+
+\ Little-endian accesses. Also known as `wrong-endian'.
+#include <little-endian.fs>
+
+\ do not free-mem if address is not within the heap
+\ workaround for NVIDIA card
+: free-mem ( addr len -- )
+ over heap-start heap-end within IF
+ free-mem
+ ELSE
+ 2drop
+ THEN
+;
+
+: #join ( lo hi #bits -- x ) lshift or ;
+: #split ( x #bits -- lo hi ) 2dup rshift dup >r swap lshift xor r> ;
+
+: blink ;
+
+: reset-dual-emit ;
+
+: console-clean-fifo ;
+
+: bootmsg-nvupdate ;
-\ Start the serial console.
-INCLUDE hw/serial.fs
+: asm-cout 2drop drop ;
+
+#include "logging.fs"
+
+: log-string 2drop ;
+
+#include "bootmsg.fs"
+
+000 cp
+
+\ disable the nvram logging until we know if we are
+\ running from ram/takeover/js20 or in normal mode on js21
+: (nvramlog-write-byte) drop ;
+' (nvramlog-write-byte) to nvramlog-write-byte
+
+#include "exception.fs"
+
+: mm-log-warning 2drop ;
+
+: write-mm-log ( data length type -- status )
+ 3drop 0
+;
+
+080 cp
+
+#include "rtc.fs"
+
+100 cp
\ Input line editing.
-INCLUDE accept.fs
-
-\ Register frame layout.
-STRUCT
- cell FIELD >r0 cell FIELD >r1 cell FIELD >r2 cell FIELD >r3
- cell FIELD >r4 cell FIELD >r5 cell FIELD >r6 cell FIELD >r7
- cell FIELD >r8 cell FIELD >r9 cell FIELD >r10 cell FIELD >r11
- cell FIELD >r12 cell FIELD >r13 cell FIELD >r14 cell FIELD >r15
- cell FIELD >r16 cell FIELD >r17 cell FIELD >r18 cell FIELD >r19
- cell FIELD >r20 cell FIELD >r21 cell FIELD >r22 cell FIELD >r23
- cell FIELD >r24 cell FIELD >r25 cell FIELD >r26 cell FIELD >r27
- cell FIELD >r28 cell FIELD >r29 cell FIELD >r30 cell FIELD >r31
- cell FIELD >cr cell FIELD >xer cell FIELD >lr cell FIELD >ctr
- cell FIELD >srr0 cell FIELD >srr1 cell FIELD >dar cell FIELD >dsisr
-END-STRUCT
-
-1100000 CONSTANT eregs \ Exception register frame.
-1100400 CONSTANT ciregs \ Client (interface) register frame.
-
-\ Print out an exception frame, e.g., eregs .regs
-: .16 10 0.r 3 spaces ;
-: .8 8 spaces 8 0.r 3 spaces ;
-: .4regs cr 4 0 DO dup @ .16 8 cells+ LOOP drop ;
-: .fixed-regs
- cr ." R0 .. R7 R8 .. R15 R16 .. R23 R24 .. R31"
- dup 8 0 DO dup .4regs cell+ LOOP drop ;
-: .special-regs
- cr ." CR / XER LR / CTR SRR0 / SRR1 DAR / DSISR"
- cr dup >cr @ .8 dup >lr @ .16 dup >srr0 @ .16 dup >dar @ .16
- cr dup >xer @ .16 dup >ctr @ .16 dup >srr1 @ .16 >dsisr @ .8 ;
-: .regs
- cr .fixed-regs
- cr .special-regs
- cr cr ;
-
-\ Some low-level functions -- no source code provided, sorry.
-: reboot 0 1 oco ;
-: halt 0 2 oco ;
-: watchdog 3 oco ;
-: other-firmware 1 watchdog ;
-
-\ Get the second CPU into our own spinloop.
-0 VALUE slave?
-0 7 oco CONSTANT master-cpu
-cr .( The master cpu is #) master-cpu .
-: get-slave ( addr -- ) 0 oco 1 = IF true to slave? THEN ;
-: slave-report cr slave? IF ." Second CPU is running." ELSE
- ." Second CPU is NOT running!" THEN ;
-3f00 get-slave slave-report
-
-\ Packages, instances, properties, devices, methods -- the whole shebang.
-INCLUDE package.fs
-
-\ Environment variables. Not actually used right now.
-INCLUDE envvar.fs
+#include "accept.fs"
-\ Hook to help loading our secondary boot loader.
-DEFER disk-read ( lba cnt addr -- )
+120 cp
-\ Timebase frequency, in Hz.
--1 VALUE tb-frequency
--1 VALUE cpu-frequency
+#include "dump.fs"
-\ The device tree.
-INCLUDE js20-tree.fs
+cistack ciregs >r1 ! \ kernel wants a stack :-)
-\ The client interface.
-INCLUDE client.fs
+#include "romfs.fs"
-\ ELF binary file format.
-INCLUDE elf.fs
+140 cp
+#include "flash.fs"
-\ Give our client a stack.
-111f000 ciregs >r1 !
+\ claim the memory used by copy of the flash
+flash-header IF
+ romfs-base dup flash-image-size 0 claim drop
+THEN
-\ Run the client program.
-: start-elf ( entry-addr -- ) msr@ 7fffffffffffffff and 2000 or ciregs >srr1 !
- 0 0 rot call-client ;
-: start-elf64 ( entry-addr -- ) msr@ 2000 or ciregs >srr1 !
- 0 0 rot call-client ;
+s" bootinfo" romfs-lookup drop c + l@ CONSTANT start-addr
+start-addr flash-addr <> CONSTANT takeover?
-\ Where files are loaded. Not the same as where they are executed.
-10000 CONSTANT load-base
-\ Load secondary boot loader from disk @ sector 63. 512kB should be enough.
-: read-yaboot 3f 400 load-base disk-read ;
+takeover? u3? or 0= IF
+ \ we want nvram logging to work
+ ['] .nvramlog-write-byte to nvramlog-write-byte
+THEN
-: yaboot
- cr ." Reading..." read-yaboot
- ." relocating..." load-base load-elf-file
- ." go!" start-elf ;
+160 cp
-: set-bootpart ( -- )
- skipws 0 parse s" disk:" 2swap $cat
- encode-string s" bootpath" set-chosen ;
+u4? IF f8002100 rl@ 0= ELSE false THEN ?INCLUDE u4-mem.fs
+u3? IF
+ planar-id 5 >= IF
+ 40000 to nvram-size
+ ELSE
+ \ change nvram-size to 8000 for GA1 blades
+ 8000 to nvram-size
+ THEN
+THEN
-: set-bootargs
- skipws 0 parse dup 0= IF 2drop ELSE
- encode-string s" bootargs" set-chosen THEN ;
-: etherboot s" enet:" set-bootargs payload dup load-elf-file start-elf ;
-: go etherboot ;
-\ Default bootpath
+takeover? IF
+ \ potentially comming from phype
+ u4? IF
+ \ takeover on JS21 is using some nvram area
+ \ which might be available
+ \ on JS20 the nvram is too small and
+ \ we just overwrite the nvram
+ sec-nvram-base to nvram-base
+ THEN
+ sec-nvram-size to nvram-size
+ \ in takeover mode the nvram is probably not mapped
+ \ to the exact location where the nvram starts
+ \ doing a small check to see if we have a partition
+ \ starting with 70; this test is far from perfect but
+ \ takeover is not the most common mode of running slof
+ nvram-base rb@ 70 <> IF 0 nvram-base rb! THEN
+THEN
-s" disk:3" encode-string s" bootpath" set-chosen
+200 cp
-: boot set-bootargs yaboot ;
+#include <banner.fs>
-: auto
- key? IF clear c emit key drop QUIT THEN
- cr ." Netboot -- to drop into GUI instead, please hold a key while starting"
- cr
- payload dup load-elf-file start-elf ;
+\ Get the secondary CPUs into our own spinloop.
+f8000050 rl@ CONSTANT master-cpu
+\ cr .( The master cpu is #) master-cpu .
-: disable-boot-watchdog
- 0 watchdog IF cr ." Failed to disable boot watchdog." THEN ;
+VARIABLE cpu-mask
+: get-slave ( n -- online? )
+ 0 3ff8 ! 18 lshift 30000000 or 48003f02 over l! icbi 10000 0 DO LOOP 3ff8 @ ;
+: mark-online ( n -- ) 1 swap lshift cpu-mask @ or cpu-mask ! ;
+: get-slaves 40 0 DO i get-slave IF i mark-online THEN LOOP ;
+: cpu-report ( -- )
+ cpu-mask @ 40 0 DO dup 1 and IF ." #" i . THEN 1 rshift LOOP drop
+;
-disable-boot-watchdog
+220 cp
+master-cpu mark-online get-slaves
+DEFER disable-watchdog ( -- )
+DEFER find-boot-sector ( -- )
+
+
+240 cp
+\ Timebase frequency, in Hz.
+\ -1 VALUE tb-frequency
+d# 14318378 VALUE tb-frequency \ default value - needed for "ms" to work
+-1 VALUE cpu-frequency
+
+#include "helper.fs"
+260 cp
+
+\ #include <timebase.fs>
+
+: tb@ BEGIN tbu@ tbl@ tbu@ rot over <> WHILE 2drop REPEAT
+ 20 lshift swap ffffffff and or ;
+: milliseconds tb@ d# 1000 * tb-frequency / ;
+: ms milliseconds + BEGIN milliseconds over >= UNTIL drop ;
+: get-msecs ( -- n ) milliseconds ;
+\ : usecs tb@ d# 1000000 * tb-frequency / ;
+: us 999 + 1000 / ms ;
+
+280 cp
+#include "rtas.fs"
+290 cp
+s" update_flash.fs" included
+2a0 cp
+cpu-mask @ rtas-fetch-cpus drop
+
+: of-start-cpu rtas-start-cpu ;
+
+' power-off to halt
+' rtas-system-reboot to reboot
+
+: other-firmware rtas-get-flashside 0= IF 1 ELSE 0 THEN rtas-set-flashside reboot ;
+: disable-boot-watchdog rtas-stop-bootwatchdog drop ;
+' disable-boot-watchdog to disable-watchdog
+
+true value bmc?
+false value debug-boot?
+
+\ for JS21/Bimini try to detect BMC... if kcs (io @ca8) status is not ff...
+u4? IF ca8 4 + io-c@ ff = IF false to bmc? true to debug-boot? THEN THEN
+
+VARIABLE memnode
+
+\ Hook to help loading our secondary boot loader.
+DEFER disk-read ( lba cnt addr -- )
+0 VALUE disk-off
+
+create vpd-cb 24 allot
+create vpd-bootlist 4 allot
+2c0 cp
+#include "ipmi-vpd.fs"
+2e0 cp
+#include <quiesce.fs>
+300 cp
+#include <usb/usb-static.fs>
+320 cp
+#include <root.fs>
+360 cp
+#include "tree.fs"
+
+: .system-information ( -- )
+ s" " type cr
+ s" SYSTEM INFORMATION" type cr
+ s" Processor = " type s" cpu" get-chosen IF
+ drop l@ >r pvr@ s" pvr>name" r> $call-method type
+ s" @ " type cpu-frequency d# 1000000 /
+ decimal . hex s" MHz" type
+ THEN cr s" I/O Bridge = " type u3? IF
+ s" U3" ELSE s" U4" THEN type
+ f8000000 rl@ 4 rshift s" (" type 1 0.r s" ." type
+ f8000000 rl@ f and 1 0.r s" )" type cr
+ s" SMP Size = " type cpu-mask @ cnt-bits 1 0.r
+ s" (" type cpu-report 8 emit s" )" type
+ cr s" Boot-Date = " type .date cr
+ s" Memory = " type s" memory" get-chosen IF
+ drop l@ s" mem-report" rot $call-method THEN
+ cr s" Board Type = " type u3? IF
+ s" JS20(GA" type planar-id 5 >= IF
+ s" 2)" ELSE s" 1)" THEN type
+ ELSE bimini? IF s" Bimini" ELSE s" JS21" THEN type THEN
+ s" (" type .vpd-machine-type [char] / emit
+ .vpd-machine-serial [char] / emit
+ .vpd-hw-revision 8 emit s" )" type cr
+ s" MFG Date = " type .vpd-manufacturer-date cr
+ s" Part No. = " type .vpd-part-number cr
+ s" FRU No. = " type .vpd-fru-number cr
+ s" FRU Serial = " type .vpd-cardprefix-serial .vpd-card-serial cr
+ s" UUID = " type .vpd-uuid cr
+ s" Flashside = " type rtas-get-flashside 0= IF
+ ." 0 (permanent)"
+ ELSE
+ ." 1 (temporary)" THEN cr cr
+;
+
+800 cp
+
+#include "nvram.fs"
+takeover? not u4? and IF
+ \ if were are not in takeover mode the nvram should look
+ \ something like this:
+ \ type size name
+ \ ========================
+ \ 51 20000 ibm,CPU0log
+ \ 51 5000 ibm,CPU1log
+ \ 70 1000 common
+ \ 7f da000 <free-space>
+ \ the partition with the type 51 should have been added
+ \ by LLFW... if it does not exist then something went
+ \ wrong and we just destroy the whole thing
+ 51 get-header IF 0 nvram-base rb! ELSE 2drop THEN
+THEN
+
+880 cp
+
+\ dmesg/dmesg2 not available if running in takeover/ram mode or on js20
+: dmesg ( -- ) u3? takeover? or 0= IF dmesg THEN ;
+: dmesg2 ( -- ) u3? takeover? or 0= IF dmesg2 THEN ;
+
+#include "envvar.fs"
+check-for-nvramrc
+
+8a0 cp
+\ The client interface.
+#include "client.fs"
+\ ELF binary file format.
+#include "elf.fs"
+#include <loaders.fs>
+
+: bios-exec ( arg len -- rc )
+ s" bios-snk" romfs-lookup 0<> IF load-elf-file drop start-elf64
+ ELSE 2drop false THEN
+;
+
+\ check wether a VGA device was found during pci scan, if it was, and bios-snk is available
+\ try to initialize it and create the needed device-nodes
+s" bios-snk" romfs-lookup 0<> dup value biosemu-available? IF drop THEN
+0 value biosemu-vmem
+0 value screen-info
+
+vga-device-node? biosemu-available? AND 0<> IF
+ s" VGA Device found: " type vga-device-node? node>path type s" initializing..." type cr
+ \ claim virtual memory for biosemu of 1MB
+ 100000 4 claim to biosemu-vmem
+
+ \ claim memory for screen-info struct (140 bytes)
+ d# 140 4 claim to screen-info
+
+ \ remember current-node (it might be node 0 so we cannot use get-node)
+ current-node @
+ \ change into vga device node
+ vga-device-node? set-node
+ \ run biosemu to initialize the vga card
+ \ s" Time before biosemu:" type .date cr
+ vga-device-node? node>path ( pathstr len )
+ s" biosemu " biosemu-vmem $cathex ( pathstr len paramstr len )
+ 20 char-cat \ add a space
+ 2swap $cat ( paramstr len ) bios-exec
+ \ s" Time after biosemu:" type .date cr
+ s" VGA initialization: detecting displays..." type cr
+ \ try to get info for two monitors
+ 2 0 DO
+ \ setup screen-info struct as input to get_vbe_info
+ s" DDC" 0 char-cat screen-info swap move \ null-terminated "DDC" as signature
+ d# 140 screen-info 4 + w! \ reserved size in bytes (see claim above)
+ i screen-info 6 + c! \ monitor number
+ \ 320 screen-info 7 + w! \ max. screen width (800)
+ 500 screen-info 7 + w! \ max. screen width (1280)
+ \ following line would be the right thing to do, however environment seems not setup yet...
+ \ screen-#columns char-width * 500 min 280 max screen-info 7 + w! \ max. screen width, calculated from environment variable screen-#columns, but max. 1280, min. 640...
+ 8 screen-info 9 + c! \ requested color depth (8bpp)
+ \ d# 16 screen-info 9 + c! \ requested color depth (16bpp)
+ \ execute get_vbe_info from load-base
+ \ s" Time before client exec:" type .date cr
+ \ since node>path overwrites strings created with s"
+ \ we need to call it before assembling the parameter string
+ vga-device-node? node>path ( pathstr len )
+ s" get_vbe_info " biosemu-vmem $cathex ( pathstr len paramstr len )
+ 20 char-cat \ add a space
+ 2swap $cat ( paramstr len )
+ 20 char-cat
+ screen-info $cathex bios-exec
+ \ s" Time after client exec:" type .date cr
+ screen-info c@ 0<> IF
+ s" display " type i . s" found..." type
+ \ screen found
+ \ create device entry
+ get-node node>name \ get current nodes name (e.g. "vga") ( str len )
+ i \ put display-num on the stack ( str len displaynum )
+ new-device \ create new device
+ s" vga-display.fs" included
+ finish-device
+ s" created." type cr
+ THEN
+ LOOP
+ \ return to where we were before changing to vga device node
+ set-node
+ \ release the claimed memory
+ screen-info d# 140 release
+ biosemu-vmem 100000 release
+
+ s" VGA initialization done." type cr
+THEN \ vga-device-node? AND biosemu-available?
+
+\ enable output on framebuffer
+s" screen" find-alias ?dup IF
+ \ we need to open/close the screen device once before "ticking" display-emit to emit
+ open-dev close-node
+ s" display-emit" $find IF to emit ELSE 2drop THEN
+THEN
+8b0 cp
+
+\ do not let the usb scan overwrite the atapi cdrom alias
+pci-cdrom-num TO cdrom-alias-num
+
+s" Scanning USB..." type usb-scan s" done." type cr
+
+s" net" s" net1" find-alias ?dup IF set-alias ELSE 2drop THEN
+s" disk" s" disk0" find-alias ?dup IF set-alias ELSE 2drop THEN
+s" cdrom" s" cdrom0" find-alias ?dup IF set-alias ELSE 2drop THEN
+8ff cp
+
+.system-information
+
+: directserial
+u3? IF
+ s" /ht/isa/serial@3f8" io
+ELSE
+ s" direct-serial?" evaluate IF s" /ht/isa/serial@2f8" io ELSE s" /ht/isa/serial@3f8" io THEN
+THEN
+;
+
+directserial
+
+\ enable USB keyboard
+\ s" keyboard" input
+
+: .flashside
+ cr ." The currently active flashside is: "
+ rtas-get-flashside 0= IF ." 0 (permanent)" ELSE
+ ." 1 (temporary)" THEN
+;
+
+bmc? IF disable-watchdog THEN
+
+: flashsave ( "{filename}" -- rc )
+ (parse-line) dup 0> IF
+ s" netsave " \ command
+ get-flash-base $cathex \ Flash base addr
+ s" 400000 " $cat \ Flash size (4MB)
+ 2swap $cat \ add parameters from (parse-line)
+ evaluate
+ ELSE
+ cr
+ ." Usage: flashsave [bootp|dhcp,]filename[,siaddr][,ciaddr][,giaddr][,bootp-retries][,tftp-retries][,use_ci]"
+ cr 2drop
+ THEN
+;
+
+#include <vpd-bootlist.fs>
+
+\ for the blades we read the bootlist from the VPD
+bimini? takeover? or 0= IF ['] vpd-boot-import to read-bootlist THEN
+
+#include <start-up.fs>
+
+#include <boot.fs>
+
+cr .( Welcome to Open Firmware)
cr
-cr
-cr .( SLOF version 0.0 Copyright 2004,2005 IBM Corporation)
-cr .( Part of this code is:)
-cr
-cr .( Licensed Internal Code - Property of IBM)
-cr .( JS20 Licensed Internal Code)
-cr .( (C) char ) emit .( Copyright IBM Corp. 2004, 2005 All Rights Reserved.)
-cr .( US Government Users Restricted Rights - Use, duplication or)
-cr .( disclosure restricted by GSA ADP Schedule Contract with IBM)
-cr
+#include "copyright-oss.fs"
cr
-\ Enable this if you want your system to automatically boot by default:
-\ auto
+\ this CATCH is to ensure the code bellow always executes: boot may ABORT!
+' start-it CATCH drop
diff --git a/board-js2x/slof/attu.fs b/board-js2x/slof/attu.fs
new file mode 100644
index 0000000..91004a4
--- /dev/null
+++ b/board-js2x/slof/attu.fs
@@ -0,0 +1,126 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ U4 "Attu" PCIe root complex.
+
+\ See the PCI OF binding document.
+
+new-device
+
+s" pciex" device-name s" pci" device-type
+s" U4-pcie" compatible
+s" U4" encode-string s" model" property
+
+\ spare out 0xc0000000-0xefffffff for pcie
+f8070200 rl@ fffffff0 and f8070200 rl!
+\ enable io memory for pcie @ c0000000-efffffff
+70000003 f80903f0 rl!-le
+
+3 encode-int s" #address-cells" property
+2 encode-int s" #size-cells" property
+
+s" /mpic" find-node encode-int s" interrupt-parent" property
+\ XXX should have interrupt map, etc. this works for now though.
+
+: decode-unit 2 hex-decode-unit 3 #join 8 lshift 0 0 rot F00000 + ;
+: encode-unit nip nip ff00 and 8 rshift 3 #split
+ over IF 2 ELSE nip 1 THEN hex-encode-unit ;
+
+f1000000 CONSTANT my-puid
+\ Configuration space accesses.
+: >config f1000000 + ;
+: config-l! >config rl!-le ;
+: config-l@ >config rl@-le ;
+: config-w! >config rw!-le ;
+: config-w@ >config rw@-le ;
+: config-b! >config rb! ;
+: config-b@ >config rb@ ;
+
+: config-dump ( addr size -- ) ['] config-l@ 4 (dump) ;
+
+\ 16MB of configuration space
+f1000000 encode-64 1000000 encode-64+ s" reg" property
+
+\ 4MB of I/O space.
+01000000 encode-int 00000000 encode-int+ 00000000 encode-int+
+00000000 encode-int+ f0000000 encode-int+
+00000000 encode-int+ 00400000 encode-int+
+
+\ 1.75GB of memory space @ c0000000.
+02000000 encode-int+ c0000000 encode-64+
+c0000000 encode-64+ 30000000 encode-64+ s" ranges" property
+
+\ Host bridge, so full bus range.
+f0 encode-int ff encode-int+ s" bus-range" property
+
+\ cr .( Scanning Attu PCIe...)
+\ INCLUDE hw/pci-scan.fs
+
+\ INCLUDE pci-scan.fs
+
+
+: open true ;
+: close ;
+
+\ c0000000 next-pci-mem !
+\ e8000000 max-pci-mem !
+\ e8000000 next-pci-mmio !
+\ f0000000 max-pci-mmio !
+\ for x86emu io access must have 16 bit addresses, so start I/O space at 0xf000
+\ f000 next-pci-io !
+\ 100000000 max-pci-io !
+\ 0 next-pci-bus !
+
+\ 0 probe-pci
+\ : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- )
+0 my-puid pci-irq-init drop
+
+00fff1f0 18 config-l!
+
+ff F0 f0000000 e8000000 e8000000 c0000000 100000000 f000
+my-puid probe-pci-host-bridge
+
+
+\ \ PCIe debug / fixup
+ : find-pcie-cap ( devfn -- offset | 0 )
+ >r 34 BEGIN r@ + config-b@ dup ff <> over and WHILE
+ dup r@ + config-b@ 10 = IF r> drop EXIT THEN 1+ REPEAT r> 2drop 0 ;
+ : .pcie ( devfn -- )
+ dup find-pcie-cap ?dup IF cr over . ." cap @ " dup . +
+ dup 8 + config-w@ 5 rshift 7 and 80 swap lshift cr ." max payload size: " .d
+ dup 8 + config-w@ c rshift 7 and 80 swap lshift cr ." max read req: " .d
+ dup 12 + config-w@ 4 rshift 3f and cr ." link width: " .d
+ THEN drop ;
+ : .pcies ( -- )
+ cr cr ." PCIe:"
+ 10000 0 DO i 8 lshift .pcie LOOP ;
+
+ : (set-ps) ( ps addr -- )
+ 8 + >r 5 lshift r@ config-w@ ff1f and or r> config-w! ;
+ : set-ps ( ps -- )
+ log2 7 -
+ 10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF
+ + 2dup (set-ps) THEN drop LOOP drop ;
+
+ : (set-rr) ( rr addr -- )
+ 8 + >r c lshift r@ config-w@ 8fff and or r> config-w! ;
+ : set-rr ( rr -- )
+ log2 7 -
+ 10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF
+ + 2dup (set-rr) THEN drop LOOP drop ;
+
+80 set-ps 80 set-rr
+\ .pcies
+
+
+finish-device
+
diff --git a/board-js2x/slof/citrine-disk.fs b/board-js2x/slof/citrine-disk.fs
new file mode 100644
index 0000000..bfe43f5
--- /dev/null
+++ b/board-js2x/slof/citrine-disk.fs
@@ -0,0 +1,79 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+( max-#blocks rsrc id -- )
+
+new-device
+
+lwsplit swap wbsplit rot set-unit
+
+s" disk" device-name s" block" device-type
+
+CONSTANT resource-id
+CONSTANT max-#blocks
+get-parent CONSTANT ppack
+
+
+: our-disk-read ( lba count addr -- )
+ >r >r >r resource-id r> r> r> s" do-read" ppack $call-static ;
+
+0 pci-alias-disk
+
+\ Requiered interface for deblocker
+
+200 CONSTANT block-size
+40000 CONSTANT max-transfer
+
+: read-blocks ( addr block# #blocks -- #read )
+\ my-unit s" dev-read-blocks" $call-parent
+ \ check if the read is within max-#blocks
+ 2dup + max-#blocks 1 + > IF
+ \ 2drop drop 0 \ return 0
+ \ returning 0 would be correct (maybe?) but it confuses the deblocker...
+ \ so i erase whatever would have been read and return the "expected" #read
+ dup >r
+ swap drop \ drop block# (not needed)
+ block-size * erase \ erase at addr #blocks * block-size
+ r> \ return #read
+ ELSE
+ dup >r rot our-disk-read r>
+ THEN
+;
+
+INSTANCE VARIABLE deblocker
+
+: open ( -- okay? )
+ 0 0 s" deblocker" $open-package dup deblocker ! dup IF
+ s" disk-label" find-package IF
+ my-args rot interpose
+ THEN
+ THEN 0<> ;
+
+: close ( -- )
+ deblocker @ close-package ;
+
+: seek ( pos.lo pos.hi -- status )
+ 2dup lxjoin max-#blocks 1 + block-size * > IF
+ \ illegal seek, return -1
+ 2drop -1
+ ELSE
+ s" seek" deblocker @ $call-method
+ THEN
+;
+
+: read ( addr len -- actual )
+ s" read" deblocker @ $call-method ;
+
+
+finish-device
+
diff --git a/board-js2x/slof/citrine-flash.fs b/board-js2x/slof/citrine-flash.fs
new file mode 100644
index 0000000..f9b9b05
--- /dev/null
+++ b/board-js2x/slof/citrine-flash.fs
@@ -0,0 +1,36 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ we do all flash accesses as 8-bit
+
+9f000000 CONSTANT citrine-flash-addr
+
+: >citrine-flash citrine-flash-addr + ;
+: citrine-flash@ >citrine-flash rb@ ;
+: citrine-flash! >citrine-flash rb! ;
+: wait-for-citrine-flash-ready BEGIN 0 citrine-flash@ 80 and UNTIL ;
+: erase-citrine-flash-block ( offset -- )
+ cr dup 8 .r ." Erasing..."
+ 20 over citrine-flash! d0 swap citrine-flash! wait-for-citrine-flash-ready ;
+: write-citrine-flash ( data offset -- )
+ over ff = IF 2drop EXIT THEN
+ 40 over citrine-flash! citrine-flash! wait-for-citrine-flash-ready ;
+: write-citrine-flash-block ( addr offset -- ) \ always writes 128kB!
+ ." Writing..."
+ 20000 0 DO over i + c@ over i + write-citrine-flash LOOP 2drop
+ ." Done." ;
+: citrine-flash ( addr offset size -- )
+ BEGIN dup 0 > WHILE >r dup erase-citrine-flash-block
+ 2dup write-citrine-flash-block >r 20000 + r> 20000 + r> 20000 - REPEAT
+ drop 2drop -1 0 citrine-flash! ;
+
diff --git a/board-js2x/slof/citrine.fs b/board-js2x/slof/citrine.fs
new file mode 100644
index 0000000..d25c909
--- /dev/null
+++ b/board-js2x/slof/citrine.fs
@@ -0,0 +1,242 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Citrine storage controller.
+2dup type
+
+device-name s" ide" device-type
+
+
+3 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+: decode-unit 3 hex-decode-unit ;
+: encode-unit 3 hex-encode-unit ;
+
+
+: >ioa [ 10 config-l@ -10 and ] LITERAL + ;
+: ioa@ >ioa rl@-le ;
+: ioa! >ioa rl!-le ;
+
+
+\ Clear request completion doorbell.
+2 228 ioa!
+
+\ status
+CREATE ioasa 200 allot ioasa 200 erase \ can reduce to 8 later
+
+\ request/response queue
+CREATE rrq 100 allot rrq 100 erase \ can be smaller
+
+\ data descriptor
+CREATE ioadl 8 allot
+
+\ control block
+CREATE ioarcb 80 allot ioarcb 80 erase
+ioarcb dup l!
+60708090 ioarcb c + l! \ user handle
+ioadl ioarcb 2c + l! \ read ioadl
+ioasa ioarcb 34 + l! 200 ioarcb 38 + w!
+
+\ ioa config data (max. 16 devices)
+CREATE ioacfg 404 allot ioacfg 404 erase
+CREATE setsupbuff 2c allot setsupbuff 2c erase 2c setsupbuff w! 1 setsupbuff + 3 c!
+
+: wait-ready ( -- )
+ 82800000 214 ioa!
+ 80000000 BEGIN dup 224 ioa@ cr .s dup 8000000 and IF
+ cr ." Unit check on SAS-Controller detected"
+ cr 42c ioa@ .
+ 8 110 ioa!
+ BEGIN cr 0 config-l@ dup . ffffffff <> UNTIL
+\ ABORT" Unit check on SAS-Controller detected"
+ THEN
+ and
+ UNTIL drop
+;
+
+\ wait-ready
+
+: wait-ioa ( int-mask -- ) BEGIN dup 224 ioa@ and UNTIL drop ;
+: init-ioa ( -- ) 82800000 214 ioa! 80000000 wait-ioa ;
+: do-request ( -- ) ioasa 20 erase ioarcb 404 ioa!
+ 2 wait-ioa 2 228 ioa!
+;
+
+: setup-ioarcb ( rsrc type addr len -- )
+ tuck 49000000 or ioadl l! ioadl 4 + l! \ setup ioadl
+ ioarcb 20 + l! ioadl ioarcb 2c + l! 8 ioarcb 30 + l! \ set len, ioadl addr
+ ioarcb 3e + c! ioarcb 8 + l! \ set type and resource
+ ioarcb 40 + 40 erase ;
+
+: setup-wrioarcb ( rsrc type addr len -- )
+ tuck 49000000 or ioadl l! ioadl 4 + l! \ setup ioadl
+ ioarcb 1C + l! ioadl ioarcb 24 + l! 8 ioarcb 28 + l! \ set len, ioadl addr
+ ioarcb 3e + c! ioarcb 8 + l! \ set type and resource
+ ioarcb 40 + 40 erase ;
+
+: setup-idrrq ( rrq len -- )
+ c4 ioarcb 42 + c! 8 lshift ioarcb 48 + l! ioarcb 44 + l! ;
+: do-idrrq ( -- ) -1 1 0 0 setup-ioarcb rrq 100 setup-idrrq do-request ;
+
+: setup-query ( len -- ) c5 ioarcb 42 + c! 8 lshift ioarcb 48 + l! ;
+: do-query ( -- ) -1 1 ioacfg 404 setup-ioarcb 404 setup-query do-request ;
+
+: setup-startUnit ( -- ) 1b ioarcb 42 + c! 3 ioarcb 46 + c! ;
+: do-startUnit ( hndl -- ) 0 0 0 setup-ioarcb setup-startUnit do-request ;
+
+: setup-setsupported ( len -- ) 80 ioarcb 40 + c! fb ioarcb 42 + c! 8 lshift ioarcb 48 + l! ;
+: do-setsupported ( -- ) -1 1 setsupbuff 2c setup-wrioarcb 2c setup-setsupported do-request ;
+
+\ ********************************
+\ read capacity
+\ ********************************
+CREATE cap 8 allot
+
+: setup-cap ( -- ) 25 ioarcb 42 + c! cap 8 erase ;
+: do-cap ( rsrc addr -- )
+ >r 0 r> 8 setup-ioarcb setup-cap do-request ;
+
+: .id ( id -- ) ." @" lwsplit 2 0.r ." ," wbsplit 2 0.r ." ," 2 0.r ;
+
+: .cap ( rsrc -- )
+ cap do-cap cap l@ cap 4 + l@ * d# 50000000 + d# 100000000 /
+ base @ >r decimal d# 10 /mod 4 .r ." ." 0 .r ." GB" r> base ! ;
+
+\ ********************************
+\ Test Unit Ready
+\ ********************************
+: setup-test-unit-ready ( -- )
+ 00 ioarcb 42 + c! \ SCSI cmd: Test-Unit-Ready
+;
+
+: do-test-unit-ready ( rsrc -- )
+ 0 0 0 setup-ioarcb ( rsrc type addr len -- )
+ setup-test-unit-ready
+ do-request
+;
+
+\ ********************************
+\ Check devices
+\ ********************************
+: check-device ( ioacfg-entry -- )
+ dup 2 + w@ 2001 and 0<> \ generic or raid disk
+ IF \ is an IOA resource ?
+ dup 8 + l@ ( ioacfg-entry rsrc ) \ get resource handle
+ 8 0
+ DO ( ioacfg-entry rsrc )
+ dup do-test-unit-ready ( ioacfg-entry rsrc )
+ ioasa l@ 0= \ read returned status
+ IF
+ LEAVE
+ THEN
+ LOOP
+ drop ( ioacfg-entry )
+ THEN
+ drop ( )
+;
+
+: check-devices ( -- )
+ ioacfg 4 + ( ioacfg-entry ) \ config block for 16 devices
+ ioacfg c@ 0 \ amount of detected devices
+ ?DO
+ dup
+ check-device ( ioacfg-entry )
+ 40 +
+ LOOP
+ drop
+;
+
+\ ********************************
+\ Show Devices
+\ ********************************
+: show-device ( ioacfg-entry -- )
+ cr ." " dup 2 + w@
+ dup 8000 and IF ." Controller :" THEN
+ dup 2000 and IF ." Disk (RAID Member):" THEN
+ dup 0002 and IF ." Disk (Volume Set) :" THEN
+ 0001 and IF ." Disk (Generic) :" THEN
+ space dup 4 + l@ ffffff and dup ffffff <> IF
+ .id
+ ELSE drop 9 spaces THEN space
+ dup 1c + 8 type space dup 24 + 10 type
+ dup 2 + w@ 8000 and 0= IF
+ space dup 8 + l@ .cap
+ THEN drop
+;
+
+: show-devices ( -- )
+ ioacfg 4 + ioacfg c@ 0
+ ?DO dup show-device 40 + LOOP drop
+;
+
+: setup-read ( lba len -- ) \ len is in blocks
+ 28 ioarcb 42 + c!
+ swap ioarcb 44 + l!
+ 8 lshift ioarcb 48 + l!
+;
+
+: do-read ( hndl lba len addr -- ) \ len is in blocks
+ over >r rot >r swap 0 -rot 200 * ( 0 hndl addr len* )
+ setup-ioarcb r> r> ( lba len )
+ setup-read do-request
+;
+
+: make-subnode ( rsrc-type rsrc-handle id -- )
+ rot 2 and IF \ only device which are part of a RAID should be started
+ over do-startUnit \ at least on citrine there are problems starting
+ \ Generic SCSI devices
+ THEN do-setsupported
+ dup ffffff <> IF
+ \ we need max-#blocks for citrine-disk.fs
+ ( rsrc id )
+ over cap do-cap cap l@ ( rsrc id max-#blocks )
+ swap rot swap ( max-#block rsrc id ) \ this is what citrine-disk.fs expects...
+ s" citrine-disk.fs" included
+ ELSE
+ 2drop
+ THEN
+;
+
+: make-subnodes ( -- )
+ ioacfg 4 + ioacfg c@ 0 ?DO dup 2 + w@ dup ( ioacfg rsrc-type rsrc-type )
+ A000 \ 8000 = Resource Subtype is IOA Focal Point.
+ \ 2000 = Device is a member of a data redundancy group (eg. RAID).
+ \ (1000 = Device is designated for use as a hot spare.
+ \ Unfortunately obsidian reports disk which are not part of
+ \ of a RAID also as hot space even if they are not.)
+ \ all these devices should not appeat in DT
+ \ SIS40 page 60
+ and 0= IF
+ swap dup ( rsrc-type ioacfg ioacfg )
+ 8 + l@ over 4 + l@ ( rsrc-type ioacfg rsrc-handle rsrc-addr )
+ ffffff and 2swap swap 2swap ( ioacfg rsrc-type rsrc-handle rsrc-addr )
+ make-subnode ELSE drop THEN 40 + LOOP drop ;
+
+: do-it ( -- )
+ init-ioa do-idrrq
+ do-query
+ check-devices
+ show-devices
+;
+
+: setup-shutdown ( -- )
+ f7 ioarcb 42 + c! 0 ioarcb 48 + l! 0 ioarcb 44 + l! ;
+: do-shutdown ( -- ) -1 1 0 0 setup-ioarcb setup-shutdown do-request ;
+
+: open true ;
+: close ;
+
+: start ['] do-it CATCH IF cr ." Citrine disabled" ELSE make-subnodes THEN ;
+
+cr start cr cr
diff --git a/board-js2x/slof/copyright-oss.fs b/board-js2x/slof/copyright-oss.fs
new file mode 100644
index 0000000..813d997
--- /dev/null
+++ b/board-js2x/slof/copyright-oss.fs
@@ -0,0 +1,16 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+cr .( Copyright (c) char ) emit .( 2004, 2007 IBM Corporation All rights reserved.)
+cr .( This program and the accompanying materials are made available)
+cr .( under the terms of the BSD License available at)
+cr .( http://www.opensource.org/licenses/bsd-license.php)
diff --git a/board-js2x/slof/cpu.fs b/board-js2x/slof/cpu.fs
index a73dec4..3f5977e 100644
--- a/board-js2x/slof/cpu.fs
+++ b/board-js2x/slof/cpu.fs
@@ -1,31 +1,44 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ CPU node. Pretty minimal...
-: create-cpu-node ( cpu# -- )
- new-device
- dup s" /cpus/cpu@" rot (u.) $cat full-name
+( cpu# -- )
+new-device set-space
- s" cpu" 2dup device-name device-type
- encode-int s" reg" property
+: pvr>name s" PowerPC," rot 10 rshift CASE
+ 39 OF s" 970" ENDOF
+ 3c OF s" 970FX" ENDOF
+ 44 OF 1 my-space 1 xor lshift cpu-mask @ and IF
+ s" 970MP" ELSE s" 970GX" THEN ENDOF
+ \ On GX CPUs, the sibling is missing, numbering is the same.
+ dup dup OF 0 <# # # # # [char] # hold #> ENDOF ENDCASE $cat ;
- tb-frequency encode-int s" timebase-frequency" property
- cpu-frequency encode-int s" clock-frequency" property
+pvr@ pvr>name device-name
+s" cpu" device-type
- 8000 encode-int s" d-cache-size" property
- 80 encode-int s" d-cache-line-size" property
- 10000 encode-int s" i-cache-size" property
- 80 encode-int s" i-cache-line-size" property
+my-space encode-int s" reg" property
- finish-device ;
+tb-frequency encode-int s" timebase-frequency" property
+cpu-frequency encode-int s" clock-frequency" property
+
+ 8000 encode-int s" d-cache-size" property
+ 80 encode-int s" d-cache-line-size" property
+10000 encode-int s" i-cache-size" property
+ 80 encode-int s" i-cache-line-size" property
+
+: open true ;
+: close ;
+
+
+finish-device
diff --git a/board-js2x/slof/dart.fs b/board-js2x/slof/dart.fs
index 405d33e..be65421 100644
--- a/board-js2x/slof/dart.fs
+++ b/board-js2x/slof/dart.fs
@@ -1,22 +1,23 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
-\ CPC925 DART.
+\ CPC9x5 DART.
-new-device s" /dart" full-name
+new-device
s" dart" 2dup device-name device-type
-s" u3-dart" compatible
+u3? IF s" u3-dart" compatible THEN
+u4? IF s" u4-dart" compatible THEN
0 encode-int f8033000 encode-int+
0 encode-int+ 7000 encode-int+ s" reg" property
@@ -24,4 +25,7 @@ s" u3-dart" compatible
: open true ;
: close ;
+\ Now clear and disable the DART.
+20000000 f8033000 rl!
+
finish-device
diff --git a/board-js2x/slof/flash.fs b/board-js2x/slof/flash.fs
new file mode 100644
index 0000000..19b59bf
--- /dev/null
+++ b/board-js2x/slof/flash.fs
@@ -0,0 +1,43 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ we do all flash accesses as 8-bit
+
+ff000000 CONSTANT flash-addr
+
+: >flash flash-addr + ;
+: flash@ >flash rb@ ;
+: flash! >flash rb! ;
+: wait-for-flash-ready BEGIN 0 flash@ 80 and UNTIL ;
+: erase-flash-block ( offset -- )
+ cr dup 8 .r ." Erasing..."
+ 20 over flash! d0 swap flash! wait-for-flash-ready ;
+: write-flash ( data offset -- )
+ 40 over flash! flash! wait-for-flash-ready ;
+: write-flash-buffer ( addr offset -- )
+ e8 over flash! wait-for-flash-ready 1f over flash!
+ 20 0 DO over i + c@ over i + flash! LOOP
+ d0 over flash! wait-for-flash-ready 2drop ;
+: write-flash-block ( addr offset -- ) \ always writes 128kB!
+ ." Writing..."
+ 20000 0 DO over i + over i + write-flash-buffer 20 +LOOP 2drop
+ ." Done." ;
+: flash ( addr offset size -- )
+ BEGIN dup 0 > WHILE >r dup erase-flash-block 2dup write-flash-block
+ >r 20000 + r> 20000 + r> 20000 - REPEAT drop 2drop -1 0 flash! ;
+
+: flash-it load-base 0 e0000 flash ;
+: flash4 load-base 0 400000 flash ;
+
+\ for update-flash
+: flash-image-size ( addr -- size ) 30 + rx@ ;
diff --git a/board-js2x/slof/freq.fs b/board-js2x/slof/freq.fs
index 38a0033..c226c85 100644
--- a/board-js2x/slof/freq.fs
+++ b/board-js2x/slof/freq.fs
@@ -1,14 +1,14 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ Use the HPET to calculate various frequencies.
@@ -33,8 +33,7 @@ d# 1000000000000000 4 hpet@ / CONSTANT hpet-freq
hpet-freq * r> / ;
: round-to tuck 2/ + over / * ;
-calibrate ( d# 1000000 round-to) TO tb-frequency
- ( d# 10000000 round-to) TO cpu-frequency
+calibrate TO tb-frequency d# 100000000 round-to TO cpu-frequency
\ Stop HPET.
0 10 hpet!
diff --git a/board-js2x/slof/header.fs b/board-js2x/slof/header.fs
new file mode 100644
index 0000000..9c17ffb
--- /dev/null
+++ b/board-js2x/slof/header.fs
@@ -0,0 +1,21 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+get-flash-base VALUE flash-addr
+
+get-nvram-base CONSTANT nvram-base
+get-nvram-size CONSTANT nvram-size
+ff8f9000 CONSTANT sec-nvram-base \ save area from phype.... not really known
+2000 CONSTANT sec-nvram-size
+
+nvram-base 20000 + CONSTANT nvram-log-be1-base
diff --git a/board-js2x/slof/helper.fs b/board-js2x/slof/helper.fs
new file mode 100644
index 0000000..4c36a45
--- /dev/null
+++ b/board-js2x/slof/helper.fs
@@ -0,0 +1,17 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: slof-build-id ( -- str len )
+ flash-header 10 + a
+;
+
+: slof-revision s" 001" ;
diff --git a/board-js2x/slof/ht.fs b/board-js2x/slof/ht.fs
index 837280b..31a8de3 100644
--- a/board-js2x/slof/ht.fs
+++ b/board-js2x/slof/ht.fs
@@ -1,21 +1,22 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ Hypertransport.
\ See the PCI OF binding document.
-new-device s" /ht" full-name
+new-device
+
s" ht" 2dup device-name device-type
s" u3-ht" compatible
@@ -24,6 +25,36 @@ s" U3" encode-string s" model" property
3 encode-int s" #address-cells" property
2 encode-int s" #size-cells" property
+s" /mpic" find-node encode-int s" interrupt-parent" property
+\ XXX should have interrupt map, etc. this works for now though.
+\ linux gets the PCI irqs right; only need to tell it the lpc irqs are edge.
+
+: decode-unit 2 hex-decode-unit 3 lshift or
+ 8 lshift 0 0 rot ;
+: encode-unit nip nip ff00 and 8 rshift dup 7 and swap 3 rshift
+ over IF 2 ELSE nip 1 THEN hex-encode-unit ;
+
+f2000000 CONSTANT my-puid
+\ Configuration space accesses.
+: >config dup ffff > IF 1000000 + THEN f2000000 + ;
+
+\ : config-l! >config cr ." config-l! " 2dup . space . rl!-le ;
+\ : config-l@ >config cr ." config-l@ " dup . rl@-le space dup . ;
+\ : config-w! >config cr ." config-w! " 2dup . space . rw!-le ;
+\ : config-w@ >config cr ." config-w@ " dup . rw@-le space dup . ;
+\ : config-b! >config cr ." config-b! " 2dup . space . rb! ;
+\ : config-b@ >config cr ." config-b@ " dup . rb@ space dup . ;
+
+: config-l! >config rl!-le ;
+: config-l@ >config rl@-le ;
+: config-w! >config rw!-le ;
+: config-w@ >config rw@-le ;
+: config-b! >config rb! ;
+: config-b@ >config rb@ ;
+
+: config-dump ( addr size -- ) ['] config-l@ 4 (dump) ;
+
+
\ 16MB of configuration space, seperate for type 0 and type 1.
00000000 encode-int f2000000 encode-int+
00000000 encode-int+ 02000000 encode-int+ s" reg" property
@@ -36,27 +67,243 @@ s" U3" encode-string s" model" property
\ 1.75GB of memory space @ 80000000.
02000000 encode-int+ 00000000 encode-int+ 80000000 encode-int+
00000000 encode-int+ 80000000 encode-int+
-00000000 encode-int+ 70000000 encode-int+ s" ranges" property
+00000000 encode-int+ 4000000 encode-int+ s" ranges" property
\ Host bridge, so full bus range.
0 encode-int ff encode-int+ s" bus-range" property
-: enable-ht-apic-space 0 5 oco drop ;
+: enable-ht-apic-space 3c0300fe f8070200 rl! ;
enable-ht-apic-space
-\ This works for the AMD devices; should walk PCI capabilities list
-\ to be more portable.
+\ spare out 0xc0000000-0xefffffff for pcie
+f8070200 rl@ fffffff0 and f8070200 rl!
+\ enable io memory for pcie @ c0000000-efffffff
+70000003 f80903f0 rl!-le
+
+
+\ Workaround for "takeover" boot on JS20: the top 8131 is programmed to be
+\ device #1f, while it should be #01.
+u3? IF f800 config-l@ 74501022 = IF 41 f8c2 config-w! THEN THEN
+
+\ Assign BUIDs.
+
+: find-ht-primary
+ 34 BEGIN config-b@ dup 0= ABORT" No HT capability block found!"
+ dup config-l@ e00000ff and 8 = IF 2 + EXIT THEN 1 + AGAIN ;
+
: assign-buid ( this -- next )
- 00c2 config-w@ 5 rshift over 00c2 config-w! + ;
-: assign-buids
+ find-ht-primary dup >r config-w@ 5 rshift 1f and over r> config-b! + ;
+
+: assign-buids ( -- )
1 BEGIN 0 config-l@ ffffffff <> WHILE assign-buid REPEAT drop ;
-assign-buids
+
+assign-buids
+
+: ldtstop f8000840 rl@ 40000 or f8000840 rl! ;
+: delay 100000 0 DO LOOP ;
+: wait-for-done BEGIN f8070110 rl@ 30 and UNTIL
+ BEGIN 8b4 config-l@ 30 and UNTIL ;
+: ldtstop1 f8000840 rl@ dup 20000 or f8000840 rl! delay
+ f8000840 rl! wait-for-done ;
+: warm 400000 f8070300 rl! 0 f8070300 rl! ;
+
+: dumpht cr f8070110 rl@ 8 0.r space 8b4 config-l@ 8 0.r
+ space f8070122 rb@ 2 0.r space 8bd config-b@ 2 0.r ;
+
+: clearht f8070110 dup rl@ swap rl!
+ f8070120 dup rl@ swap rl!
+ 08b4 dup config-l@ swap config-l!
+ 08bc dup config-l@ swap config-l! ;
+
+: setwidth dup f8070110 rb! 8b7 config-b! ;
+: set8 00 setwidth ;
+: set16 11 setwidth ;
+
+: setfreq dup f8070122 rb! 8bd config-b! ;
+: set200 0 setfreq ;
+: set300 1 setfreq ;
+: set400 2 setfreq ;
+: set500 3 setfreq ;
+: set600 4 setfreq ;
+: set800 5 setfreq ;
+: set1000 6 setfreq ;
+: set1200 7 setfreq ;
+: set1400 8 setfreq ;
+: set1600 9 setfreq ;
+
+: ht>freq 2 + dup 6 > IF 2* 6 - THEN d# 100 * ;
+\ XXX: looks only at the U3/U4 side for max. link speed and width.
+clearht f8070111 rb@ setwidth
+f8070120 rw@ 2log dup .( Switching top HT bus to ) ht>freq 0 d# .r .( MHz...) cr
+setfreq u3? IF ldtstop THEN u4? IF ldtstop1 THEN
+
+
+\ #include <pci-scan.fs>
+
: open true ;
: close ;
-\ The devices on our HT chain
-INCLUDE hw/8131.fs
-INCLUDE hw/8111.fs
+
+\ 80000000 next-pci-mem !
+\ b8000000 max-pci-mem !
+\ b8000000 next-pci-mmio !
+\ c0000000 max-pci-mmio !
+\ 10000 next-pci-io !
+\ 100000000 max-pci-io !
+\ 0 next-pci-bus !
+
+\ 0 probe-pci
+\ : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- )
+s" /mpic" find-node my-puid pci-irq-init drop
+1f 0 c0000000 b8000000 b8000000 80000000 100000000 10000
+my-puid probe-pci-host-bridge
+
+
+
+
+: msi
+\ \ on citrine (pass2)
+\ f8005000 101054 config-l! 0 101058 config-l!
+\ f 10105c config-w! 81 101052 config-b!
+
+\ \ on citrine (pass4)
+\ f8005000 010854 config-l! 0 010858 config-l!
+\ f 01085c config-w! 81 010852 config-b!
+
+ \ on citrine (pass4), using old vector
+ f80040f0 010854 config-l! 0 010858 config-l!
+ ffff 01085c config-w! 81 010852 config-b!
+
+ \ on pxb1
+\ f8000000 08a4 config-l! 0 08a8 config-l! 1 08a2 config-b! ;
+\ f8000000 08a4 config-l! fd 08a8 config-l! 1 08a2 config-b! ;
+
+;
+
+
+
+\ This works. Needs cleaning up though; and we need to communicate the
+\ MSI address range to the client program. (We keep the default range
+\ at fee00000 for now).
+: msi-on 7 1 DO 10000 i 800 * a0 + config-l! LOOP ;
+msi-on
+
+
+
+\ \ \
+\ \ \ IRQ DEBUG CODE
+\ \ \
+
+: >mpic0 f8041000 + ;
+: mpic0@ >mpic0 rl@ ;
+: mpic0! >mpic0 rl! ;
+
+: >mpic f8050000 + ;
+: mpic@ >mpic rl@ ;
+: mpic! >mpic rl! ;
+
+: mpic-on dup 20 * 00880000 rot + over mpic! 1 swap 10 + mpic! ;
+: mpic-all-on 7c 0 DO i mpic-on LOOP ;
+
+: mpic-cpu-on 0 f8060080 rl! ;
+: mpic-cur cr ." pending: " 4 0 DO f80600a0 i c lshift + rl@ . LOOP ;
+: mpic-eoi 0 f80600b0 rl! ;
+
+: one-by-one 7c 0 DO cr i . i mpic-on mpic-cur mpic-eoi LOOP ;
+
+CREATE pcie-cnfg-space 24 allot
+
+: .pci-express-capabilites-reg ( val -- )
+ cr ." Cap ID :" dup ff and u.
+ cr ." Next Cap :" dup 8 rshift ff and u.
+ cr ." Type :" dup 14 rshift f and
+ CASE
+ 0 OF ." PCI Express Endpoint" ENDOF
+ 1 OF ." Legacy PCI Express Endpoint" ENDOF
+ 4 OF ." Root Port" ENDOF
+ 5 OF ." Switch upstream port" ENDOF
+ 6 OF ." Switch downstream port" ENDOF
+ 7 OF ." Express-to-PCI/PCI-X bridge" ENDOF
+ 8 OF ." PCI/PCI-X to Express bridge" ENDOF
+ dup OF 0 ENDOF ." Reserved" ENDCASE
+ drop
+;
+
+: .pci-device-capabilites-reg ( val -- )
+ cr ." MaxPS :" dup 7 and u.
+ drop
+;
+
+: .pci-device-control-reg ( val -- )
+ cr ." MaxPS act:" dup 5 rshift 7 and u.
+ cr ." MaxRS act:" dup c rshift 7 and u.
+ cr ." ERROR :" dup 10 rshift 3f and u.
+ drop
+;
+
+: .pci-link-capabilites-reg ( val -- )
+ cr ." Max linkW:" dup 4 rshift 3f and u.
+ drop
+;
+
+: .pci-link-control-reg ( val -- )
+ cr ." Neg linkW:" dup 4 10 + rshift 3f and u.
+ cr ." Train ERR:" dup a 10 + rshift 1 and u.
+ cr ." Train act:" dup b 10 + rshift 1 and u.
+ drop
+;
+
+: .pcie-ext
+ 8 0 DO dup i 4 * dup >r + config-l@ r> pcie-cnfg-space + l! LOOP
+\ pcie-cnfg-space 24 dump
+ pcie-cnfg-space l@ .pci-express-capabilites-reg
+ pcie-cnfg-space 4 + l@ .pci-device-capabilites-reg
+ pcie-cnfg-space 8 + l@ .pci-device-control-reg
+ pcie-cnfg-space c + l@ .pci-link-capabilites-reg
+ pcie-cnfg-space 10 + l@ .pci-link-control-reg
+;
+
+
+\ PCIe debug / fixup
+: find-pcie-cap ( devfn -- offset | 0 )
+ >r 34 BEGIN r@ + config-b@ dup ff <> over and WHILE
+ dup r@ + config-b@ 10 = IF r> drop EXIT THEN 1+ REPEAT r> 2drop 0 ;
+: .pcie ( devfn -- )
+ dup find-pcie-cap ?dup IF cr over . ." cap @ " dup . +
+\ .pcie-ext
+ dup 8 + config-w@ 5 rshift 7 and 80 swap lshift cr ." max payload size: " .d
+ dup 8 + config-w@ c rshift 7 and 80 swap lshift cr ." max read req: " .d
+ dup 12 + config-w@ 4 rshift 3f and cr ." link width: " .d
+ THEN drop ;
+: .pcies ( -- )
+ cr cr ." PCIe:"
+ 10000 0 DO i 8 lshift .pcie LOOP ;
+
+: (set-ps) ( ps addr -- )
+ 8 + >r 5 lshift r@ config-w@ ff1f and or r> config-w! ;
+: set-ps ( ps -- )
+ log2 7 -
+ 10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF
+ + 2dup (set-ps) THEN drop LOOP drop ;
+
+: (set-rr) ( rr addr -- )
+ 8 + >r c lshift r@ config-w@ 8fff and or r> config-w! ;
+: set-rr ( rr -- )
+ log2 7 -
+ 10000 0 DO i 8 lshift dup find-pcie-cap ?dup IF
+ + 2dup (set-rr) THEN drop LOOP drop ;
+
+bimini? IF
+ 100 set-ps 200 set-rr
+\ .pcies
+ELSE
+ 100 set-ps 200 set-rr
+\ .pcies
+THEN
+
+: set-ps set-ps .pcies ;
+: set-rr set-rr .pcies ;
+
finish-device
diff --git a/board-js2x/slof/i2c.fs b/board-js2x/slof/i2c.fs
new file mode 100644
index 0000000..16a2145
--- /dev/null
+++ b/board-js2x/slof/i2c.fs
@@ -0,0 +1,77 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+new-device
+
+s" i2c" 2dup device-name device-type
+s" u4-i2c" compatible
+
+0 encode-int f8001000 encode-int+
+0 encode-int+ 1000 encode-int+ s" reg" property
+
+: >i2c f8001000 + ;
+: i2c@ >i2c rl@ ;
+: i2c! >i2c rl! ;
+
+: .i2c 80 0 DO i i2c@ . 10 +LOOP ;
+
+\ 0 mode 1 ctrl 2 stat 3 isr 4 ier 5 addr 6 suba 7 data
+\ 8 rev 9 risetime a bittime
+
+\ 0 mode: 08
+\ 1 ctrl: 8 = start 4 = stop 2 = xaddr 1 = aak
+\ 2 stat: 2 = lastaak 1 = busy
+\ 3 isr: 8 = istart 4 = istop 2 = iaddr 1 = idata
+\ 4 ier: --
+\ 5 addr: a1..a7
+\ 6 suba: offset
+\ 7 data: data
+
+: i2c-addr ( addr -- ) 50 i2c! 2 10 i2c! BEGIN 30 i2c@ 2 and UNTIL ;
+: i2c-subaddr ( suba -- ) 60 i2c! ;
+: i2c-stop ( -- ) BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ;
+: i2c-nak? ( -- failed? ) 20 i2c@ 2 and 0= dup IF i2c-stop THEN ;
+: i2c-short? ( -- failed? ) 30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ;
+: i2c-aak-if-more ( n -- ) 1 <> 1 and 10 i2c! ;
+
+: (read) ( buf len addr -- error? )
+ 1 or i2c-addr i2c-nak? IF 2drop true EXIT THEN
+ dup i2c-aak-if-more 2 30 i2c!
+ BEGIN
+ 30 i2c@ 1 and IF
+ 1- >r 70 i2c@ over c! char+ r>
+ dup 0= IF i2c-stop 2drop false EXIT THEN
+ dup i2c-aak-if-more 1 30 i2c! THEN
+ i2c-short? IF 2drop true EXIT THEN
+ AGAIN ;
+
+: i2c-read ( buf len addr -- error? )
+ 4 0 i2c! (read) ;
+: i2c-sub-read ( buf len addr suba -- error? )
+ c 0 i2c! i2c-subaddr (read) ;
+
+: i2c-write ( buf len addr -- error? )
+ 4 0 i2c! i2c-addr i2c-nak? IF 2drop true EXIT THEN
+ over c@ 70 i2c! 2 30 i2c!
+ BEGIN
+ 30 i2c@ 1 and IF
+ 1- >r char+ r> i2c-nak? IF 2drop true EXIT THEN
+ dup 0= IF 4 10 i2c! i2c-stop nip EXIT THEN
+ over c@ 70 i2c! 1 30 i2c! THEN
+ i2c-short? IF 2drop true EXIT THEN
+ AGAIN ;
+
+: open true ;
+: close ;
+
+finish-device
diff --git a/board-js2x/slof/io.fs b/board-js2x/slof/io.fs
index 3d55493..a607767 100644
--- a/board-js2x/slof/io.fs
+++ b/board-js2x/slof/io.fs
@@ -1,31 +1,17 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ I/O accesses.
-\ Little-endian accesses. Also known as `wrong-endian'.
-: l!-le >r lbflip r> l! ;
-: l@-le l@ lbflip ;
-
-: w!-le >r wbflip r> w! ;
-: w@-le w@ wbflip ;
-
-: rl!-le >r lbflip r> rl! ;
-: rl@-le rl@ lbflip ;
-
-: rw!-le >r wbflip r> rw! ;
-: rw@-le rw@ wbflip ;
-
\ Legacy I/O accesses.
: >io f4000000 + ;
@@ -38,12 +24,3 @@
\ Accessing the SIO config registers.
: siocfg! 2e io-c! 2f io-c! ;
: siocfg@ 2e io-c! 2f io-c@ ;
-
-\ Configuration space accesses.
-: >config dup ffff > IF 1000000 + THEN f2000000 + ;
-: config-l! >config rl!-le ;
-: config-l@ >config rl@-le ;
-: config-w! >config rw!-le ;
-: config-w@ >config rw@-le ;
-: config-b! >config rb! ;
-: config-b@ >config rb@ ;
diff --git a/board-js2x/slof/ioapic.fs b/board-js2x/slof/ioapic.fs
new file mode 100644
index 0000000..8519413
--- /dev/null
+++ b/board-js2x/slof/ioapic.fs
@@ -0,0 +1,36 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ ( ioapic-addr -- )
+\ IO-APIC setup.
+
+CONSTANT ioapic
+
+: ioapic@ ( offset -- x ) ioapic rb! ioapic 10 + rl@-le ;
+: ioapic! ( x offset -- ) ioapic rb! ioapic 10 + rl!-le ;
+
+: init-ioapic ( irq# -- )
+ 1a000 or 1 ioapic@ 10 rshift 1+ 0 ?DO
+ 0 i 2* 11 + ioapic! dup
+ \ move all ISA IRQs to 40 and higher,
+ \ as to not conflict with U3/U4 internal
+ \ IRQs. ISA IRQs are positive edge.
+ dup ff and 0c < IF a000 - 40 + THEN
+ i 2* 10 + ioapic! 1+ LOOP drop
+;
+
+: dump-ioapic ( -- )
+ 1 ioapic@ 10 rshift 1+
+ dup cr . ." irqs" 0 ?DO
+ cr i 2 0.r space i 2* 11 + ioapic@ 8 0.r
+ i 2* 10 + ioapic@ 8 0.r LOOP
+;
diff --git a/board-js2x/slof/ipmi-kcs.fs b/board-js2x/slof/ipmi-kcs.fs
new file mode 100644
index 0000000..edf939e
--- /dev/null
+++ b/board-js2x/slof/ipmi-kcs.fs
@@ -0,0 +1,57 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ IPMI KCS interface to the BMC.
+
+new-device
+ ca8 1 set-unit
+
+ : open true ;
+ : close ;
+
+ create descr-buf 100 allot
+
+ : rtas-get-bmc-version ( -- adr len )
+ descr-buf 100 rtas-get-blade-descr ( len status )
+ IF
+ drop 0 0
+ ELSE
+ descr-buf 9 + swap 11 - ( adr len )
+ THEN
+ ;
+
+ ' rtas-get-bmc-version to bmc-version
+
+ s" system-controller" 2dup device-name device-type
+ \ s" IBM,BMC." get-build-name $cat encode-string s" model" property
+ \ s" IBM,BMC.12345" encode-string s" model" property
+ s" IBM,BMC." bmc-version $cat encode-string s" model" property
+ 0 0 s" ranges" property
+
+ new-device
+
+ : open true ;
+ : close ;
+
+ s" ipmi" 2dup device-name device-type
+ s" ipmi-kcs" compatible
+
+ 1 encode-int ca8 encode-int+ 1 encode-int+ s" reg" property
+ 4 encode-int s" reg-spacing" property
+ s" IBM,BMC." bmc-version $cat encode-string s" model" property
+
+ s" ipmi" get-node node>path set-alias
+
+ finish-device
+
+finish-device
diff --git a/board-js2x/slof/ipmi-vpd.fs b/board-js2x/slof/ipmi-vpd.fs
new file mode 100644
index 0000000..9b1f564
--- /dev/null
+++ b/board-js2x/slof/ipmi-vpd.fs
@@ -0,0 +1,98 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: vpd-read-bootlist ( -- )
+ 837 4 vpd-bootlist rtas-read-vpd IF vpd-bootlist 4 erase THEN
+;
+
+: vpd-write-bootlist ( offset len data -- )
+ 837 4 vpd-bootlist rtas-write-vpd
+;
+
+: .vpd-machine-type
+ e 7 vpd-cb rtas-read-vpd drop
+ 0 vpd-cb 7 + c!
+ vpd-cb zcount type
+;
+
+: .vpd-machine-serial
+ 15 7 vpd-cb rtas-read-vpd drop
+ 0 vpd-cb 7 + c!
+ vpd-cb zcount type
+;
+
+: .vpd-card-serial
+ 54 6 vpd-cb rtas-read-vpd drop
+ 0 vpd-cb 6 + c!
+ vpd-cb zcount type
+;
+: .vpd-cardprefix-serial
+ 5a 6 vpd-cb rtas-read-vpd drop
+ 0 vpd-cb 6 + c!
+ vpd-cb zcount type
+;
+
+: .vpd-hw-revision
+ 65 1 vpd-cb rtas-read-vpd drop
+ vpd-cb c@ .
+;
+
+: .vpd-part-number
+ 3c c vpd-cb rtas-read-vpd drop
+ vpd-cb c type
+;
+
+: .vpd-fru-number
+ 48 c vpd-cb rtas-read-vpd drop
+ vpd-cb c type
+;
+
+: .vpd-manufacturer-date
+ 6b 4 vpd-cb rtas-read-vpd drop
+ 0 vpd-cb 4 + c!
+ vpd-cb zcount type
+;
+
+: .vpd-uuid
+ 9f 10 vpd-cb rtas-read-vpd drop
+ 10 0 do i vpd-cb + c@ 2 0.r loop
+;
+
+: vpd-read-model ( -- addr len )
+ 60 4 vpd-cb rtas-read-vpd drop vpd-cb 4 -leading s" ," $cat
+ e 7 vpd-cb rtas-read-vpd drop vpd-cb 4 $cat s" -" $cat vpd-cb 4 + 3 $cat
+;
+
+: .vpd
+ ." ===================== VPD ====================="
+ cr ." Machine Type : " .vpd-machine-type
+ cr ." Machine Serial No. : " .vpd-machine-serial
+ cr ." Hardware Revision : " .vpd-hw-revision
+ cr ." Manuf. Date : " .vpd-manufacturer-date
+ cr ." Part Number : " .vpd-part-number
+ cr ." FRU Number : " .vpd-fru-number
+ cr ." FRU Serial No. : " .vpd-cardprefix-serial .vpd-card-serial
+ cr ." UUID : " .vpd-uuid
+;
+
+: vpd-write-revision-and-build-id ( -- )
+ 406 24 vpd-cb rtas-read-vpd drop 0
+ vpd-cb 1a + zcount bdate2human drop a string=ci 0=
+ IF bdate2human drop a vpd-cb 1a + zplace drop 1 THEN
+ vpd-cb zcount slof-revision string=ci 0=
+ IF slof-revision vpd-cb zplace drop 1 THEN
+ vpd-cb 4 + zcount slof-build-id string=ci 0=
+ IF slof-build-id vpd-cb 4 + zplace drop 1 THEN
+ 1 = IF 406 24 vpd-cb rtas-write-vpd drop THEN
+;
+
+vpd-write-revision-and-build-id
diff --git a/board-js2x/slof/memory.fs b/board-js2x/slof/memory.fs
index b9383da..ae3002e 100644
--- a/board-js2x/slof/memory.fs
+++ b/board-js2x/slof/memory.fs
@@ -1,24 +1,33 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ The /memory node.
\ See 3.7.6.
-new-device s" /memory" full-name
+new-device
s" memory" 2dup device-name device-type
-: mem-size 0 4 oco ;
+: mem-size-u3 20000000 ;
+: (mem-size-u4) ( # -- size )
+ 4 lshift f8002200 + rl@ dup 1 and 0= IF drop 0 EXIT THEN
+ dup c000 and e rshift over 3000 and c rshift + 10000000 swap lshift
+ swap 2 and 0= IF 2* THEN ;
+: mem-size-u4 0 4 0 DO i (mem-size-u4) + LOOP ;
+: mem-size u3? IF mem-size-u3 THEN u4? IF mem-size-u4 THEN ;
+: mem-speed-u4 f8000800 rl@ 12 rshift 7 and 4 + d# 200 * 3 / ;
+: mem-speed-u3 f8000f60 rl@ c rshift f and d# 100 * 3 / ;
+: mem-speed u3? IF mem-speed-u3 THEN u4? IF mem-speed-u4 THEN ;
+
: encode-our-reg
0 encode-int 0 encode-int+
@@ -27,10 +36,17 @@ s" memory" 2dup device-name device-type
1 encode-int+ 0 encode-int+ r> 80000000 - >r THEN
r@ 20 rshift encode-int+ r> ffffffff and encode-int+ ;
encode-our-reg s" reg" property
+0 mem-size release \ Make our memory available
+
: mem-report
- base @ decimal cr mem-size 1e rshift 0 .r
- mem-size 3fffffff and IF ." .5" THEN ." GB of RAM detected." base ! ;
-mem-report
+ base @ decimal mem-size 1e rshift 0 .r
+ mem-size 3fffffff and IF ." .5" THEN ." GB of RAM @ "
+ mem-speed . ." MHz" base ! ;
+
+get-node memnode !
+
+: open true ;
+: close ;
finish-device
diff --git a/board-js2x/slof/mpic.fs b/board-js2x/slof/mpic.fs
index 5b46004..abba585 100644
--- a/board-js2x/slof/mpic.fs
+++ b/board-js2x/slof/mpic.fs
@@ -1,25 +1,28 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
-
-new-device s" /mpic" full-name
-
-s" mpic" device-name s" interrupt-controller" device-type
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+new-device
+
+s" mpic" device-name s" interrupt-controller" device-type
s" open-pic" compatible
+0 0 s" interrupt-controller" property
+
+2 encode-int s" #interrupt-cells" property
0 encode-int f8040000 encode-int+
0 encode-int+ 30000 encode-int+ s" reg" property
-: enable-mpic 0 6 oco drop ;
+: enable-mpic 6 f80000e0 rl! ;
enable-mpic
: open true ;
diff --git a/board-js2x/slof/pci-aliases.fs b/board-js2x/slof/pci-aliases.fs
new file mode 100644
index 0000000..f685487
--- /dev/null
+++ b/board-js2x/slof/pci-aliases.fs
@@ -0,0 +1,85 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ Starting alias number for net devices after the onboard devices.
+2 VALUE pci-net-num
+\ Starting alias number for disks after the onboard devices.
+0 VALUE pci-disk-num
+\ Starting alias number for cdroms after the onboard devices.
+0 VALUE pci-cdrom-num
+
+\ define a new alias for this device
+: pci-set-alias ( str-addr str-len num -- )
+ $cathex strdup \ create alias name
+ get-node node>path \ get path string
+ set-alias \ and set the alias
+;
+
+\ define a new net alias
+: unknown-enet ( -- pci-net-num )
+ pci-net-num dup 1+ TO pci-net-num
+;
+: pci-alias-net ( config-addr -- )
+ u3? IF
+ pci-device-vec c@ CASE
+ 2 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 1 OF dup pci-addr2fn 1 >= IF 1 ELSE 0 THEN ENDOF
+ dup OF unknown-enet ENDOF
+ ENDCASE
+ ELSE
+ unknown-enet
+ THEN
+ ENDOF
+ dup OF unknown-enet ENDOF
+ ENDCASE
+ ELSE
+ pci-device-vec c@ CASE
+ 2 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 4 OF dup pci-addr2fn 1 >= IF 1 ELSE 0 THEN ENDOF
+ dup OF unknown-enet ENDOF
+ ENDCASE
+ ELSE
+ unknown-enet
+ THEN
+ ENDOF
+ dup OF unknown-enet ENDOF
+ ENDCASE
+ THEN
+ swap drop \ forget the config address
+
+ s" net" rot pci-set-alias \ create the alias
+;
+
+\ define a new disk alias
+: pci-alias-disk ( config-addr -- )
+ drop \ forget the config address
+ pci-disk-num dup 1+ TO pci-disk-num \ increase the pci-disk-num
+ s" disk" rot pci-set-alias \ create the alias
+;
+\ define a new cdrom alias
+: pci-alias-cdrom ( config-addr -- )
+ drop \ forget the config address
+ pci-cdrom-num dup 1+ TO pci-cdrom-num \ increase the pci-cdrom-num
+ s" cdrom" rot pci-set-alias \ create the alias
+;
+
+\ define the alias for the calling device
+: pci-alias ( config-addr -- )
+ dup pci-class@
+ 10 rshift CASE
+ 01 OF pci-alias-disk ENDOF
+ 02 OF pci-alias-net ENDOF
+ dup OF drop ENDOF
+ ENDCASE
+;
diff --git a/board-js2x/slof/pci-bridge_1022_7460.fs b/board-js2x/slof/pci-bridge_1022_7460.fs
index a570419..3e4a9d1 100644
--- a/board-js2x/slof/pci-bridge_1022_7460.fs
+++ b/board-js2x/slof/pci-bridge_1022_7460.fs
@@ -1,114 +1,77 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ AMD 8111 I/O hub.
\ See the documentation at http://www.amd.com ; the datasheet for this chip is
\ document #24674.
-
\ First, some master config. Not all of this logically belongs to just
\ one function, and certainly not to the LPC bridge; also, we'll
\ initialize all functions in "downstream" order, and this code has to be
\ run first. So do it now.
-00 2042 config-b!
-03 2048 config-b! \ Enable LPC, IDE; disable I2C, SMM, AC'97 functions.
-00 2049 config-b! \ Disable everything on second bus (USB, 100Mb enet).
-
-01 204b config-b! \ Enable IO-APIC.
-30 fec00000 rb! 0000a010 fec00010 rl!-le
-31 fec00000 rb! ff000000 fec00010 rl!-le
-32 fec00000 rb! 0000a011 fec00010 rl!-le
-33 fec00000 rb! ff000000 fec00010 rl!-le
-34 fec00000 rb! 0000a012 fec00010 rl!-le
-35 fec00000 rb! ff000000 fec00010 rl!-le
-36 fec00000 rb! 0000a013 fec00010 rl!-le
-37 fec00000 rb! ff000000 fec00010 rl!-le \ Set PCI IRQs as 10..13.
- \ Leave ISA IRQs disabled.
-
-
-\ Device A, function 0: PCI bridge.
-
-\ We show this bridge in the device-tree, for completeness, as it is
-\ impossible to completely disable this device; we don't assign any
-\ address space to it though, or enable any transactions through it.
-\ Maybe later we want to support the USB functions on its secondary
-\ side; but not now.
-
-new-device s" /ht/pci@3" full-name
-
-s" pci" 2dup device-name device-type
-
-: open true ;
-: close ;
-
-finish-device
-
-
-\ Device B, function 0: LPC bridge.
-
-new-device s" /ht/isa@4" full-name
-
-\ See the "ISA/EISA/ISA-PnP" OF binding document.
-
-s" isa" 2dup device-name device-type
-\ We have to say it's ISA i.s.o. LPC, as otherwise Linux can't find
-\ the serial port for its console. Linux uses the name instead of the
-\ device type (and it completely ignores any "compatible" property).
-
-\ 64kB of ISA I/O space, at PCI devfn 4:0.
-1 encode-int 0 encode-int+
-01002000 encode-int+ 0 encode-int+ 0 encode-int+
-10000 encode-int+ s" ranges" property
-
-: open true ;
-: close ;
-
-\ There's a SIO chip on the LPC bus.
-INCLUDE hw/sio.fs
-
-finish-device
-
-
-\ Device B, function 1: ATA controller.
-
-new-device s" /ht/ata@4,1" full-name
-
-s" ata" 2dup device-name device-type
-s" ide" compatible
-
-2108 dup config-l@ 500 or swap config-l! \ Enable native PCI mode.
-2104 dup config-l@ 5 or swap config-l! \ Enable I/O, bus master.
-2140 dup config-l@ 03 or swap config-l! \ Enable both ports.
-10 213c config-b! \ Set IRQ#.
-
-: open true ;
-: close ;
-
-\ Just assume there is always one disk.
-INCLUDE hw/disk.fs
-
-\ Enable HPET at address fe000000.
-fe000001 20a0 config-l!
+00 842 config-b! \ Disable 8237 & 8254 & 8259's. We're not a PC.
+80 847 config-b! \ Disable EHCI, as it is terminally broken.
+03 848 config-b! \ Enable LPC, IDE; disable I2C, SMM, AC'97 functions.
+01 849 config-b! \ Enable USB, disable 100Mb enet.
+01 84b config-b! \ Enable IO-APIC.
+
+fec00000 s" ioapic.fs" included
+00 init-ioapic
+
+\ Program PNPIRQ[0,1,2] as IRQ #D,E,F; switch those GPIOs to low-active.
+ 0b 848 config-b! \ enable devB:3
+7000 b58 config-l! \ map PMxx at pci i/o 7000
+ d1 b41 config-b! \ enable access to PMxx space
+
+\ on JS20 the planar id is encoded in GPIO 29, 30 and 31
+\ >=5 is GA2 else it is GA1
+: (planar-id) ( -- planar-id)
+ [ 70dd io-c@ 5 rshift 1 and ] LITERAL
+ [ 70de io-c@ 5 rshift 2 and ] LITERAL
+ [ 70df io-c@ 5 rshift 4 and ] LITERAL
+ + + 7 xor
+;
+
+u3? IF ['] (planar-id) to planar-id THEN
+
+8 70d3 io-c! 8 70d4 io-c! 8 70d5 io-c! \ set the pins to low-active
+ bimini? IF 5 70c4 io-c! THEN \ on bimini set gpio4 as output and high to power up USB
+ fec b44 config-w! \ set PNPIRQ pnpirq2 -> f , pnpirq1 -> e pnpirq0 -> c
+ 51 b41 config-b! \ disable access to PMxx space
+ 03 848 config-b! \ disable devB:3
+
+\ The function of the PCI controller BARs change depending on the mode the
+\ controller is in.
+\ And the default is legacy mode. Gross.
+05 909 config-b! \ Enable native PCI mode.
+03 940 config-b! \ Enable both ports.
+
+\ Enable HPET on 8111, at address fe000000.
+fe000001 8a0 config-l!
: >hpet fe000000 + ;
: hpet@ >hpet rl@-le ;
: hpet! >hpet rl!-le ;
-INCLUDE hw/freq.fs
+INCLUDE freq.fs
\ Disable HPET.
-0 20a0 config-l!
+0 8a0 config-l!
+
+\ 8111 has only 16 bits of PCI I/O space. Get the address in range.
+8000 next-pci-io !
-finish-device
+my-space pci-class-name type cr
+my-space pci-bridge-generic-setup
+s" pci" device-name
diff --git a/board-js2x/slof/pci-capabilities.fs b/board-js2x/slof/pci-capabilities.fs
new file mode 100644
index 0000000..8f9998e
--- /dev/null
+++ b/board-js2x/slof/pci-capabilities.fs
@@ -0,0 +1,23 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ -----------------------------------------------------------------------------
+\ Set the msi address for a device
+: pci-set-msi ( cap-addr -- )
+ drop
+;
+
+\ Set up all known capabilities for this board to the plugged devices
+: pci-set-capabilities ( config-addr -- )
+ dup 05 pci-cap-find ?dup IF pci-set-msi THEN
+ drop
+;
diff --git a/board-js2x/slof/pci-class_03.fs b/board-js2x/slof/pci-class_03.fs
new file mode 100644
index 0000000..833c8eb
--- /dev/null
+++ b/board-js2x/slof/pci-class_03.fs
@@ -0,0 +1,51 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space pci-class-name type
+
+my-space pci-device-generic-setup
+
+my-space pci-class-name device-type
+
+\ add legacy I/O Ports / Memory regions to assigned-addresses
+\ see PCI Bus Binding Revision 2.1 Section 7.
+s" reg" get-my-property
+IF
+ \ "reg" does not exist, create new
+ encode-start
+ELSE
+ \ "reg" does exist, copy it
+ encode-bytes
+THEN
+\ I/O Range 0x3B0-0x3BB
+my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space
+3b0 encode-64+ \ addr
+c encode-64+ \ size
+\ I/O Range 0x3C0-0x3DF
+my-space a1000000 or encode-int+ \ non-relocatable, aliased I/O space
+3c0 encode-64+ \ addr
+20 encode-64+ \ size
+\ the U4 does not support memory accesses to this region... so we dont put it into "reg"
+\ maybe with some clever hacking of the address map registers it will be possible to access
+\ these regions??
+\ Memory Range 0xA0000-0xBFFFF
+\ my-space a2000000 or encode-int+ \ non-relocatable, <1MB Memory space
+\ a0000 encode-64+ \ addr
+\ 20000 encode-64+ \ size
+
+s" reg" property \ store "reg" property
+
+\ remember this vga device's phandle
+get-node to vga-device-node?
+
+cr
+
diff --git a/board-js2x/slof/pci-device_1002_515e.fs b/board-js2x/slof/pci-device_1002_515e.fs
new file mode 100644
index 0000000..ebbd9a2
--- /dev/null
+++ b/board-js2x/slof/pci-device_1002_515e.fs
@@ -0,0 +1,497 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space pci-class-name type
+
+my-space assign-all-device-bars
+my-space pci-device-props
+my-space pci-set-irq-line
+
+7 4 config-w!
+
+\ Special notice from ATI:
+\ ATI TECHNOLOGIES INC. ("ATI") HAS NOT ASSISTED IN THE CREATION OF,
+\ AND DOES NOT ENDORSE THE USE OF, THIS SOFTWARE. ATI WILL NOT BE
+\ RESPONSIBLE OR LIABLE FOR ANY ACTUAL OR ALLEGED DAMAGE OR LOSS
+\ CAUSED BY OR IN CONNECTION WITH THE USE OF, OR RELIANCE ON,
+\ THIS SOFTWARE.
+
+\ Description: This FCODE driver initializes the RN50 (ES1000) ATI
+\ adaptor.
+
+-1 value mem-addr
+-1 value regs-addr
+false value is_installed
+
+: >rn [ 18 config-l@ -10 and ] LITERAL + ;
+: rn! >rn rl!-le ;
+: rn@ >rn rl@-le ;
+: reg-rl@ rn@ ;
+: reg-rl! rn! ;
+: map-in " map-in" $call-parent ;
+: map-out " map-out" $call-parent ;
+: pc@ ( offset -- byte ) >rn rb@ ;
+: pc! ( byte offset -- ) >rn rb! ;
+
+0 value phys_low
+0 value phys_mid
+0 value phys_high
+0 value phys_len
+
+: MAP-CSR-BASE ( -- )
+ " assigned-addresses" get-my-property 0= if
+ begin dup 0> while ( prop-addr len )
+ \ Get the phys-hi mid low and the low order 32 bits of the length
+
+ decode-phys to phys_high to phys_mid to phys_low decode-int drop decode-int to phys_len
+
+ phys_high H# FF and \ See which BAR this refers to
+ case
+ h# 10 of phys_low phys_mid phys_high h# 1000000 map-in to mem-addr endof
+ h# 18 of phys_low phys_mid phys_high phys_len map-in to regs-addr endof
+ endcase
+ repeat
+ ( prop-addr 0 ) 2drop
+ then
+
+ ;
+
+: enable-card my-space 4 + dup config-b@ 3 or swap config-b! ;
+
+: EARLY-MAP ( -- )
+
+ " reg" get-my-property 0= if
+ begin dup 0> while ( prop-addr len )
+
+ \ Get the phys-hi mid low and the low order 32 bits of the length
+
+ decode-phys to phys_high to phys_mid to phys_low decode-int drop decode-int to phys_len
+
+ phys_high H# FF and \ See which BAR this refers to
+ case
+ h# 10 of phys_low phys_mid phys_high H# 1000000 map-in to mem-addr endof
+ h# 18 of phys_low phys_mid phys_high h# 1000 map-in to regs-addr endof
+ endcase
+ repeat
+ ( prop-addr 0 ) 2drop
+ then
+ ;
+
+: EARLY-UNMAP ( -- )
+
+ mem-addr -1 <> if
+ mem-addr h# 1000000 map-out
+ -1 to mem-addr
+ then
+
+ regs-addr -1 <> if
+ regs-addr h# 1000 map-out
+ -1 to regs-addr
+ then
+
+ ;
+
+CREATE INIT1_ARRAY
+H# 0F8 ( CONFIG_MEMSIZE ) L, H# 00000000 L, H# 01000000 L,
+H# 1C0 ( MPP_TB_CONFIG ) L, H# 00FFFFFF L, H# 07000000 L,
+H# 030 ( BUS_CNTL ) L, H# 00000000 L, H# 5133A3B0 L,
+H# 0EC ( RBBM_CNTL ) L, H# 00000000 L, h# 00004443 L,
+H# 1D0 ( DEBUG_CNTL ) L, H# FFFFFFFD L, H# 00000002 L,
+H# 050 ( CRTC_GEN_CNTL ) L, H# 00000000 L, H# 04000000 L,
+H# 058 ( DAC_CNTL ) L, H# 00000000 L, H# FF604102 L,
+H# 168 ( PAD_CTLR_STRENGTH ) L, H# FFFEFFFF L, H# 00001200 L,
+H# 178 ( MEM_REFRESH_CNTL ) L, H# 00000000 L, H# 88888888 L,
+H# 17C ( MEM_READ_CNTL ) L, H# 00000000 L, H# B7C20000 L,
+H# 188 ( MC_DEBUG ) L, H# FFFFFFFF L, H# 00000000 L,
+H# D00 ( DISP_MISC_CNTL) L, H# 00FFFFFF L, H# 5B000000 L,
+H# 88C ( TV_DAC_CNTL ) L, H# F800FCEF L, H# 00490200 L,
+H# D04 ( DAC_MACRO_CNTL) L, H# 00000000 L, H# 00000905 L,
+H# 284 ( FP_GEN_CNTL ) L, H# FFFFFFFF L, H# 00000008 L,
+H# 030 ( BUS_CNTL ) L, H# FFFFFFEF L, H# 00000000 L,
+
+here INIT1_ARRAY - /L / CONSTANT INIT1_LENGTH
+
+
+CREATE INIT2_ARRAY
+
+H# 140 ( MEM_CNTL ) L, H# 00000000 L, H# 38001A01 L, 0 L,
+H# 158 ( MEM_SDRAM_MODE_REG ) L, H# E0000000 L, H# 08320032 L, 0 L,
+H# 144 ( MEM_TIMING_CNTL ) L, H# 00000000 L, H# 20123833 L, 0 L,
+H# 14C ( MC_AGP_LOCATION ) L, H# 00000000 L, H# 000FFFF0 L, 0 L,
+H# 148 ( MC_FB_LOCATION ) L, H# 00000000 L, H# FFFF0000 L, 0 L,
+H# 154 ( MEM_INIT_LAT_TIMER ) L, H# 00000000 L, H# 34444444 L, 0 L,
+H# 18C ( MC_CHP_IO_OE_CNTL ) L, H# 00000000 L, H# 0A540002 L, 0 L,
+H# 910 ( FCP_CNTL ) L, H# 00000000 L, H# 00000004 L, 0 L,
+H# 010 ( BIOS_0_SCRATCH ) L, H# FFFFFFFB L, H# 00000004 L, 0 L,
+H# D64 ( DISP_OUTPUT_CNTL ) L, H# FFFFFBFF L, H# 00000000 L, 0 L,
+H# 2A8 ( TMDS_PLL_CNTL ) L, H# 00000000 L, H# 00000A1B L, 0 L,
+H# 800 ( TV_MASTER_CNTL ) L, H# BFFFFFFF L, H# 40000000 L, 0 L,
+H# D10 ( DISP_TEST_DBUG_CTL ) L, H# EFFFFFFF L, H# 10000000 L, 0 L,
+H# 4DC ( OV0_FLAG_CNTRL ) L, H# FFFFFEFF L, H# 00000100 L, 0 L,
+H# 034 ( BUS_CNTL1 ) L, H# 73FFFFFF L, H# 84000000 L, 0 L,
+H# 174 ( AGP_CNTL ) L, H# FFEFFF00 L, H# 001E0000 L, 0 L,
+H# 18C ( MC_CHP_IO_OE_CNTL ) L, H# FFFFFFF9 L, H# 00000006 L, h# 000A L,
+H# 18C ( MC_CHP_IO_OE_CNTL ) L, H# FFFFFFFB L, H# 00000000 L, H# 000A L,
+H# 18C ( MC_CHP_IO_OE_CNTL ) L, H# FFFFFFFD L, H# 00000000 L, 0 L,
+
+here INIT2_ARRAY - /L / CONSTANT INIT2_LENGTH
+
+CREATE PLLINIT_ARRAY
+
+H# 0D L, H# FFFFFFFF L, H# FFFF8000 L, 0 L,
+H# 12 L, H# FFFFFFFF L, H# 00350000 L, 0 L,
+H# 08 L, H# FFFFFFFF L, H# 00000000 L, 0 L,
+H# 2D L, H# FFFFFFFF L, H# 00000000 L, 0 L,
+H# 1F L, H# FFFFFFFF L, H# 0000000A L, 5 L,
+H# 03 L, H# FFFFFFFF L, H# 0000003C L, 0 L,
+H# 0A L, H# FFFFFFFF L, H# 00252504 L, 0 L,
+H# 25 L, H# FFFFFFFF L, H# 00000005 L, 0 L,
+H# 0E L, H# FFFFFFFF L, H# 04756400 L, 0 L,
+H# 0C L, H# FFFFFFFF L, H# 04006401 L, 0 L,
+H# 02 L, H# FFFFFFFF L, H# 0000A703 L, 0 L,
+H# 0F L, H# FFFFFFFF L, H# 0000051C L, 0 L,
+H# 10 L, H# FFFFFFFF L, H# 04000400 L, 5 L,
+H# 0E L, H# FFFFFFFD L, H# 00000000 L, 5 L,
+H# 0E L, H# FFFFFFFE L, H# 00000000 L, 5 L,
+H# 12 L, H# FFFFFFFF L, H# 00350012 L, 5 L,
+H# 0F L, H# FFFFFFFE L, H# 00000000 L, 6 L,
+H# 10 L, H# FFFFFFFE L, H# 00000000 L, 5 L,
+H# 10 L, H# FFFEFFFF L, H# 00000000 L, 6 L,
+H# 0F L, H# FFFFFFFD L, H# 00000000 L, 5 L,
+H# 10 L, H# FFFFFFFD L, H# 00000000 L, 5 L,
+H# 10 L, H# FFFDFFFF L, H# 00000000 L, d# 10 L,
+H# 0C L, H# FFFFFFFE L, H# 00000000 L, 6 L,
+H# 0C L, H# FFFFFFFD L, H# 00000000 L, 5 L,
+h# 0D L, H# FFFFFFFF L, H# FFFF8007 L, 5 L,
+H# 08 L, H# FFFFFF3C L, H# 00000000 L, 0 L,
+H# 02 L, H# FFFFFFFF L, H# 00000003 L, 0 L,
+H# 04 L, H# FFFFFFFF L, H# 000381C0 L, 0 L,
+H# 05 L, H# FFFFFFFF L, H# 000381F7 L, 0 L,
+H# 06 L, H# FFFFFFFF L, H# 000381C0 L, 0 L,
+H# 07 L, H# FFFFFFFF L, H# 000381F7 L, 0 L,
+H# 02 L, H# FFFFFFFD L, H# 00000000 L, 6 L,
+H# 02 L, H# FFFFFFFE L, H# 00000000 L, 5 L,
+h# 08 L, H# FFFFFF3C L, H# 00000003 L, 5 L,
+H# 0B L, H# FFFFFFFF L, H# 78000800 L, 0 L,
+H# 0B L, H# FFFFFFFF L, H# 00004000 L, 0 L,
+h# 01 L, h# FFFFFFFF L, H# 00000010 L, 0 L,
+
+here PLLINIT_ARRAY - /L / CONSTANT PLLINIT_LENGTH
+
+CREATE MEMINIT_ARRAY
+h# 6FFF0000 L, H# 00004000 L, H# 6FFF0000 L, H# 80004000 L,
+h# 6FFF0000 L, H# 00000132 L, H# 6FFF0000 L, H# 80000132 L,
+h# 6FFF0000 L, H# 00000032 L, H# 6FFF0000 L, H# 80000032 L,
+h# 6FFF0000 L, H# 10000032 L,
+here MEMINIT_ARRAY - /L / CONSTANT MEMINIT_LENGTH
+: L@+ ( addr -- value addr' )
+
+dup l@ swap la1+
+;
+
+0 VALUE _len
+
+: ENCODE-ARRAY ( array len -- )
+ dup to _len 0 do l@+ swap encode-int rot loop
+ drop _len 1 - 0 ?do encode+ loop
+;
+
+: andorset ( reg and or -- )
+ 2 pick regs-addr + dup rn@
+ 3 pick AND 2 pick OR swap rn! 3drop
+;
+
+: INIT1
+H# 0F8 ( CONFIG_MEMSIZE ) H# 00000000 H# 01000000 andorset \ Set 16Mb memory size
+H# 1C0 ( MPP_TB_CONFIG ) H# 00FFFFFF H# 07000000 andorset
+H# 030 ( BUS_CNTL ) H# 00000000 H# 5133A3B0 andorset
+H# 0EC ( RBBM_CNTL ) H# 00000000 h# 00004443 andorset
+H# 1D0 ( DEBUG_CNTL ) H# FFFFFFFD H# 00000002 andorset
+H# 050 ( CRTC_GEN_CNTL ) H# 00000000 H# 04000000 andorset
+H# 058 ( DAC_CNTL ) H# 00000000 H# FF604102 andorset
+H# 168 ( PAD_CTLR_STRENGTH ) H# FFFEFFFF H# 00001200 andorset
+H# 178 ( MEM_REFRESH_CNTL ) H# 00000000 H# 88888888 andorset
+H# 17C ( MEM_READ_CNTL ) H# 00000000 H# B7C20000 andorset
+H# 188 ( MC_DEBUG ) H# FFFFFFFF H# 00000000 andorset
+H# D00 ( DISP_MISC_CNTL) H# 00FFFFFF H# 5B000000 andorset
+H# 88C ( TV_DAC_CNTL ) H# F800FCEF H# 00490200 andorset
+H# D04 ( DAC_MACRO_CNTL) H# 00000000 H# 00000905 andorset
+H# 284 ( FP_GEN_CNTL ) H# FFFFFFFF H# 00000008 andorset
+H# 030 ( BUS_CNTL ) H# FFFFFFEF H# 00000000 andorset
+;
+
+
+: INIT2
+H# 140 ( MEM_CNTL ) H# 00000000 H# 38001A01 andorset
+H# 158 ( MEM_SDRAM_MODE_REG ) H# E0000000 H# 08320032 andorset
+H# 144 ( MEM_TIMING_CNTL ) H# 00000000 H# 20123833 andorset
+H# 14C ( MC_AGP_LOCATION ) H# 00000000 H# 000FFFF0 andorset
+H# 148 ( MC_FB_LOCATION ) H# 00000000 H# FFFF0000 andorset
+H# 154 ( MEM_INIT_LAT_TIMER ) H# 00000000 H# 34444444 andorset
+H# 18C ( MC_CHP_IO_OE_CNTL ) H# 00000000 H# 0A540002 andorset
+H# 910 ( FCP_CNTL ) H# 00000000 H# 00000004 andorset
+H# 010 ( BIOS_0_SCRATCH ) H# FFFFFFFB H# 00000004 andorset
+H# D64 ( DISP_OUTPUT_CNTL ) H# FFFFFBFF H# 00000000 andorset
+H# 2A8 ( TMDS_PLL_CNTL ) H# 00000000 H# 00000A1B andorset
+H# 800 ( TV_MASTER_CNTL ) H# BFFFFFFF H# 40000000 andorset
+H# D10 ( DISP_TEST_DEBUG_CTL ) H# EFFFFFFF H# 10000000 andorset
+H# 4DC ( OV0_FLAG_CNTRL ) H# FFFFFEFF H# 00000100 andorset
+H# 034 ( BUS_CNTL1 ) H# 73FFFFFF H# 84000000 andorset
+H# 174 ( AGP_CNTL ) H# FFEFFF00 H# 001E0000 andorset
+H# 18C ( MC_CHP_IO_OE_CNTL ) H# FFFFFFF9 H# 00000006 andorset h# 000A ms
+H# 18C ( MC_CHP_IO_OE_CNTL ) H# FFFFFFFB H# 00000000 andorset H# 000A ms
+H# 18C ( MC_CHP_IO_OE_CNTL ) H# FFFFFFFD H# 00000000 andorset
+;
+
+: CLK-CNTL-INDEX! 8 ( CLK_CNTL_INDEX ) reg-rl! ;
+
+: CLK-CNTL-INDEX@ 8 ( CLK_CNTL_INDEX ) reg-rl@ ;
+
+: PLLWRITEON clk-cntl-index@ H# 80 ( PLL_WR_ENABLE ) or clk-cntl-index! ;
+
+: PLLWRITEOFF clk-cntl-index@ H# 80 ( PLL_WR_ENABLE ) not and clk-cntl-index! ; \ Remove PLL_WR_ENABLE
+
+: CLKDATA! h# 0c ( CLK_CNTL_DATA ) reg-rl! ;
+
+: CLKDATA@ h# 0c ( CLK_CNTL_DATA ) reg-rl@ ;
+
+: PLLINDEXSET clk-cntl-index@ h# FFFFFFC0 and or clk-cntl-index! ;
+
+: PLLSET swap pllindexset clkdata! ;
+
+: pllandorset ( index and or -- )
+ 2 pick pllindexset clkdata@
+ 2 pick AND over OR clkdata! 3drop
+;
+
+: PLLINIT
+pllwriteon
+H# 0D H# FFFF8000 pllset
+H# 12 H# 00350000 pllset
+H# 08 H# 00000000 pllset
+H# 2D H# 00000000 pllset
+H# 1F H# 0000000A pllset 5 ms
+
+H# 03 H# 0000003C pllset
+H# 0A H# 00252504 pllset
+H# 25 H# 00000005 pllset
+H# 0E H# 04756400 pllset
+H# 0C H# 04006401 pllset
+H# 02 H# 0000A703 pllset
+H# 0F H# 0000051C pllset
+H# 10 H# 04000400 pllset 5 ms
+
+H# 0E H# FFFFFFFD 00 pllandorset 5 ms
+H# 0E H# FFFFFFFE 00 pllandorset 5 ms
+H# 12 H# 00350012 pllset 5 ms
+H# 0F H# FFFFFFFE 00 pllandorset 6 ms
+H# 10 H# FFFFFFFE 00 pllandorset 5 ms
+H# 10 H# FFFEFFFF 00 pllandorset 6 ms
+H# 0F H# FFFFFFFD 00 pllandorset 5 ms
+H# 10 H# FFFFFFFD 00 pllandorset 5 ms
+H# 10 H# FFFDFFFF 00 pllandorset d# 10 ms
+H# 0C H# FFFFFFFE 00 pllandorset 6 ms
+H# 0C H# FFFFFFFD 00 pllandorset 5 ms
+h# 0D h# FFFF8007 pllset 5 ms
+H# 08 H# FFFFFF3C 00 pllandorset
+H# 02 h# FFFFFFFF 03 pllandorset
+H# 04 H# 000381C0 pllset
+H# 05 H# 000381F7 pllset
+H# 06 H# 000381C0 pllset
+H# 07 H# 000381F7 pllset
+H# 02 H# FFFFFFFD 00 pllandorset 6 ms
+H# 02 h# FFFFFFFE 00 pllandorset 5 ms
+h# 08 H# FFFFFF3C 03 pllandorset 5 ms
+H# 0B h# 78000800 pllset
+H# 0B H# FFFFFFFF h# 4000 pllandorset
+h# 01 h# FFFFFFFF h# 0010 pllandorset
+
+pllwriteoff
+;
+
+: DYNCKE
+pllwriteon
+H# 14 H# FFFF3FFF H# 30 pllandorset
+H# 14 H# FF1FFFFF H# 00 pllandorset
+H# 01 h# FFFFFFFF h# 80 pllandorset
+H# 0D H# 00000007 pllset 5 ms
+h# 2D H# 0000F8C0 pllset
+h# 08 H# FFFFFFFF h# C0 pllandorset 5 ms
+pllwriteoff
+;
+
+: MEM-MODE@
+ h# 158 ( MEM_SDRAM_MODE_REG ) reg-rl@ ;
+
+: MEM-MODE!
+ h# 158 ( MEM_SDRAM_MODE_REG ) reg-rl! ;
+
+: MEM-STATUS@
+ H# 150 reg-rl@ ;
+
+: WAIT-MEM-CMPLT
+ h# 8000 0 do mem-status@ 3 and 3 = if leave then loop ;
+
+: INITMEM
+
+ mem-mode@ h# 6FFF0000 and h# 4000 or mem-mode!
+ mem-mode@ h# 6FFF0000 and h# 80004000 or mem-mode!
+ wait-mem-cmplt
+ mem-mode@ h# 6FFF0000 and h# 0132 or mem-mode!
+ mem-mode@ h# 6FFF0000 and h# 80000132 or mem-mode!
+ wait-mem-cmplt
+ mem-mode@ h# 6FFF0000 and h# 0032 or mem-mode!
+ mem-mode@ h# 6FFF0000 and h# 80000032 or mem-mode!
+ wait-mem-cmplt
+ mem-mode@ h# 6FFF0000 and h# 10000032 or mem-mode!
+;
+
+
+
+: CLR-REG ( reg -- )
+ 0 swap reg-rl!
+
+;
+: SET-PALETTE ( -- )
+ h# 0 h# b0 pc! \ Reset PALETTE_INDEX
+
+ d# 16 0 do
+ H# 000000 h# B4 reg-rl! \ Write the PALETTE_DATA ( Auto increments)
+ H# aa0000 H# B4 reg-rl!
+ H# 00aa00 H# B4 reg-rl!
+ H# aa5500 H# B4 reg-rl!
+ H# 0000aa H# B4 reg-rl!
+ H# aa00aa H# B4 reg-rl!
+ H# 00aaaa H# B4 reg-rl!
+ H# aaaaaa H# B4 reg-rl!
+ H# 555555 H# B4 reg-rl!
+ H# ff5555 H# B4 reg-rl!
+ H# 55ff55 H# B4 reg-rl!
+ H# ffff55 H# B4 reg-rl!
+ H# 5555ff H# B4 reg-rl!
+ H# ff55ff H# B4 reg-rl!
+ H# 55ffff H# B4 reg-rl!
+ H# ffffff H# B4 reg-rl!
+ loop
+
+ ;
+
+0 VALUE _addr
+0 VALUE _color
+
+: DO-COLOR ( color-addr addr color -- )
+ to _color to _addr 0 to _color
+ 3 0 do _addr i + c@ 2 i - 8 * << _color + to _color loop
+ _color h# B4 reg-rl!
+;
+
+: SET-COLORS ( addr index #indicies -- )
+
+ swap h# B0 pc!
+ ( addr #indicies ) 0 ?do dup ( index ) i 3 * + DO-COLOR loop
+ ( addr ) drop ;
+
+: init-card
+
+ h# FF h# 58 3 + pc! \
+ h# 59 pc@ h# FE and h# 59 pc! \
+ h# 50 reg-rl@ H# FEFFFFFF AND h# 02000200 or \ Clear 24 set 25 and 8-11 to 2
+ h# 50 reg-rl!
+ h# 4F0063 h# 200 reg-rl!
+ H# 8C02A2 h# 204 reg-rl!
+ H# 1Df020C h# 208 reg-rl!
+ h# 8201EA h# 20C reg-rl!
+ h# 50 reg-rl@ H# F8FFFFFF AND h# 03000000 or h# 50 reg-rl!
+ h# 50 h# 22C reg-rl!
+ set-palette
+ mem-addr h# F0000 0 fill
+ ;
+
+: DO-INIT
+ early-map
+ enable-card
+ init1
+ pllinit
+ init2
+ initmem
+ init-card
+ h# 8020 h# 54 reg-rl!
+ early-unmap
+;
+
+d# 640 constant /scanline
+d# 480 constant #scanlines
+/scanline #scanlines * constant /fb
+
+" okay" encode-string " status" property
+
+: display-install ( -- )
+ is_installed not if
+ map-csr-base
+ enable-card
+ mem-addr to frame-buffer-adr
+ h# 8020 h# 54 reg-rl!
+ default-font set-font
+ /scanline #scanlines d# 100 d# 40 fb8-install
+ true to is_installed
+ then
+;
+
+: display-remove ( -- ) ;
+
+do-init \ Set up the card
+\ clear at least 640x480
+10 config-l@ 8 - F0000 0 rfill
+init1_array init1_length encode-array " ibm,init1" property
+init2_array init2_length encode-array " ibm,init2" property
+pllinit_array pllinit_length encode-array " ibm,pllinit" property
+meminit_array meminit_length encode-array " ibm,meminit" property
+0 0 encode-bytes " iso6429-1983-colors" property
+" display" encode-string " device_type" property
+/scanline encode-int " width" property
+ #scanlines encode-int " height" property
+8 encode-int " depth" property
+/scanline encode-int " linebytes" property
+
+' display-install is-install
+' display-remove is-remove
+
+: fill-rectangle ( index x y w h -- )
+ 2swap -rot /scanline * + frame-buffer-adr + ( index w h fbadr )
+ swap 0 ?do ( index w fbadr )
+ 3dup swap rot fill ( index w fbadr )
+ /scanline + ( index w fbadr' )
+ loop
+ 3drop
+;
+: draw-rectangle ( addr x y w h -- )
+ 2swap -rot /scanline * + frame-buffer-adr + ( addr w h fbadr )
+ swap 0 ?do ( addr w fbadr )
+ 3dup swap move ( addr w fbadr )
+ >r tuck + swap r> ( addr' w fbadr )
+ /scanline + ( addr' w fbadr' )
+ loop
+ 3drop
+ ;
+ : read-rectangle ( addr x y w h -- )
+ 2swap -rot /scanline * + frame-buffer-adr + ( addr w h fbadr )
+ swap 0 ?do ( addr w fbadr )
+ 3dup -rot move ( addr w fbadr )
+ >r tuck + swap r> ( addr' w fbadr )
+ /scanline + ( addr' w fbadr' )
+ loop
+ 3drop
+ ;
+
+: dimensions ( -- width height ) /scanline #scanlines ;
+
+." ( rn50 )" cr
diff --git a/board-js2x/slof/pci-device_1014_028c.fs b/board-js2x/slof/pci-device_1014_028c.fs
new file mode 100644
index 0000000..1a3eca5
--- /dev/null
+++ b/board-js2x/slof/pci-device_1014_028c.fs
@@ -0,0 +1,25 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space assign-all-device-bars
+my-space pci-device-props
+my-space pci-set-irq-line
+
+\ set Memory Write and Invalidate Enable, SERR# Enable (see PCI 3.0 Spec Chapter 6.2.2 device control)
+
+7 4 config-w!
+
+
+\ Citrine storage controller.
+s" citrine"
+
+include citrine.fs
diff --git a/board-js2x/slof/pci-device_1014_02bd.fs b/board-js2x/slof/pci-device_1014_02bd.fs
new file mode 100644
index 0000000..a305931
--- /dev/null
+++ b/board-js2x/slof/pci-device_1014_02bd.fs
@@ -0,0 +1,24 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space assign-all-device-bars
+my-space pci-device-props
+my-space pci-set-irq-line
+
+\ set Memory Write and Invalidate Enable, SERR# Enable (see PCI 3.0 Spec Chapter 6.2.2 device control)
+7 4 config-w!
+
+true to bimini?
+\ Citrine storage controller.
+s" obsidian"
+
+include citrine.fs
diff --git a/board-js2x/slof/pci-device_1022_7451.fs b/board-js2x/slof/pci-device_1022_7451.fs
index 3cc1d51..cd9b46a 100644
--- a/board-js2x/slof/pci-device_1022_7451.fs
+++ b/board-js2x/slof/pci-device_1022_7451.fs
@@ -1,111 +1,34 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
-
-\ AMD 8131 dual PCI-X bridge with tunnel.
-
-\ See the documentation at http://www.amd.com ; the datasheet for this chip is
-\ document #24637.
-
-
-\ Device A, function 0: PCI-X bridge.
-
-new-device s" /ht/pci-x@1" full-name
-
-s" pci-x" 2dup device-name device-type
-s" pci" compatible
-
-07 0804 config-b! \ Enable master, memory, I/O.
-00 0818 config-b! \ Set primary bus#.
-10 0819 config-b! \ Set secondary bus#.
-1f 081a config-b! \ Set subordinate bus#.
-f000 081c config-l! 00010001 0830 config-l! \ Set I/O space: 64kB @ 10000.
-9ff09000 0820 config-l! \ Set memory space: 256MB @ 90000000.
-
-: open true ;
-: close ;
-
-\ This is the JS20 extension card slot; we assume there is nothing there.
-
-finish-device
-
-
-\ Device A, function 1: IO-APIC.
-
-new-device s" /ht/io-apic@1,1" full-name
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ IO-APIC init
s" io-apic" 2dup device-name device-type
+my-space pci-class-name type s" ( 8131 IO-APIC )" type
-03 0944 config-b! \ Enable IO-APIC.
-06 0904 config-b! \ Enable IRQ generation and memory space.
-fec01000 0948 config-l! 0 094c config-l! \ Set APIC address.
-10 fec01000 rb! 0000a018 fec01010 rl!-le
-11 fec01000 rb! ff000000 fec01010 rl!-le
-12 fec01000 rb! 0000a019 fec01010 rl!-le
-13 fec01000 rb! ff000000 fec01010 rl!-le
-14 fec01000 rb! 0000a01a fec01010 rl!-le
-15 fec01000 rb! ff000000 fec01010 rl!-le
-16 fec01000 rb! 0000a01b fec01010 rl!-le
-17 fec01000 rb! ff000000 fec01010 rl!-le \ Set IRQs as 18..1b.
+enable-io-access
+enable-mem-access
+pci-master-enable
-: open true ;
-: close ;
+my-space b rshift \ Get slot #.
+dup c lshift fec00000 or \ Calculate base address.
+dup 48 config-l! 0 4c config-l! \ Set base address.
+03 44 config-b! \ Enable IO-APIC.
-finish-device
-
-
-\ Device B, function 0: PCI-X bridge.
-
-new-device s" /ht/pci-x@2" full-name
-
-s" pci-x" 2dup device-name device-type
-s" pci" compatible
-
-07 1004 config-b! \ Enable master, memory, I/O.
-00 1018 config-b! \ Set primary bus#.
-20 1019 config-b! \ Set secondary bus#.
-2f 101a config-b! \ Set subordinate bus#.
-f000 101c config-l! 00020002 1030 config-l! \ Set I/O space: 64kB @ 20000.
-aff0a000 1020 config-l! \ Set memory space: 256MB @ a0000000.
-
-: open true ;
-: close ;
-
-\ This PCI-X bus is where the dual Gb ethernet is connected.
-
-INCLUDE hw/enet.fs
-
-finish-device
-
-
-\ Device B, function 1: IO-APIC.
-
-new-device s" /ht/io-apic@2,1" full-name
-
-s" io-apic" 2dup device-name device-type
+s" ioapic.fs" included
-03 1144 config-b! \ Enable IO-APIC.
-06 1104 config-b! \ Enable IRQ generation and memory space.
-fec02000 1148 config-l! 0 114c config-l! \ Set APIC address.
-10 fec02000 rb! 0000a01c fec02010 rl!-le
-11 fec02000 rb! ff000000 fec02010 rl!-le
-12 fec02000 rb! 0000a01d fec02010 rl!-le
-13 fec02000 rb! ff000000 fec02010 rl!-le
-14 fec02000 rb! 0000a01e fec02010 rl!-le
-15 fec02000 rb! ff000000 fec02010 rl!-le
-16 fec02000 rb! 0000a01f fec02010 rl!-le
-17 fec02000 rb! ff000000 fec02010 rl!-le \ Set IRQs as 1c..1f.
+2 lshift 14 + \ Calculate first IRQ #.
+init-ioapic \ Set IRQs.
-: open true ;
-: close ;
+my-space pci-device-props
-finish-device
+cr
diff --git a/board-js2x/slof/pci-device_1022_7468.fs b/board-js2x/slof/pci-device_1022_7468.fs
new file mode 100644
index 0000000..ac7a719
--- /dev/null
+++ b/board-js2x/slof/pci-device_1022_7468.fs
@@ -0,0 +1,50 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space assign-all-device-bars
+my-space pci-device-props
+my-space pci-set-irq-line
+
+\ See the "ISA/EISA/ISA-PnP" OF binding document.
+
+.( isa)
+
+s" isa" 2dup device-name device-type
+\ We have to say it's ISA i.s.o. LPC, as otherwise Linux can't find
+\ the serial port for its console. Linux uses the name instead of the
+\ device type (and it completely ignores any "compatible" property).
+
+2 encode-int s" #address-cells" property
+1 encode-int s" #size-cells" property
+
+\ We assume all ISA addresses to refer to I/O space.
+: decode-unit 1 hex-decode-unit 1 ;
+: encode-unit drop 1 hex-encode-unit ;
+
+\ 32kB of ISA I/O space.
+1 encode-int my-space 01000000 + encode-64+ 0 encode-int+ 0 encode-int+
+8000 encode-int+ s" ranges" property
+
+: open true ;
+: close ;
+
+\ There's a SIO chip on the LPC bus.
+INCLUDE sio.fs
+
+\ There's also an Atmel TPM chip on JS21
+\ removed on Bimini Pass 2 and therefore disabled on all Biminis
+u4? bimini? not and ?INCLUDE tpm.fs
+
+\ And finally there's the IPMI interface to the BMC.
+u4? ?INCLUDE ipmi-kcs.fs
+
+cr
diff --git a/board-js2x/slof/pci-device_1022_7469.fs b/board-js2x/slof/pci-device_1022_7469.fs
new file mode 100644
index 0000000..999bdfe
--- /dev/null
+++ b/board-js2x/slof/pci-device_1022_7469.fs
@@ -0,0 +1,23 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space assign-all-device-bars
+my-space pci-device-props
+my-space pci-set-irq-line
+
+7 4 config-w!
+
+s" ide" type cr
+
+include ide.fs
+
+cr
diff --git a/board-js2x/slof/pci-interrupts.fs b/board-js2x/slof/pci-interrupts.fs
new file mode 100644
index 0000000..6380332
--- /dev/null
+++ b/board-js2x/slof/pci-interrupts.fs
@@ -0,0 +1,235 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ define function pointer as forward declaration for get-interrupt-line
+\ this is board wireing and southbridge dependent
+\ returns the wired interrupt line for this config addr
+\ ( config-addr -- irq-line )
+DEFER pci-get-irq-line
+
+\ define function pointer as forward declaration for get-interrupt-sense-type
+\ this is board wireing and southbridge dependent
+\ returns the wired interrupt sense type for this config addr
+\ 0 - Edge rising
+\ 1 - Level low
+\ 2 - Level high
+\ 3 - Edge falling
+\ ( config-addr -- irq-sense )
+DEFER pci-get-irq-sense
+
+
+\ *****************************************************************************
+\ Generic IRQ routines
+\ *****************************************************************************
+
+
+
+: unknown-slot ( -- 0 )
+\ cr pci-vec ABORT" Unknown slot "
+ 0
+;
+\ 0c s" /ht/@1/@2" PCI-X INTA & INTC Pnpirq0 -> irq12
+\ 0e s" /ht/@1/@2" PCI-X INTB & INTD Pnpirq1 -> irq14
+\ 10 s" /ht/@8,1" ATA
+\ 0f s" /ht/@1/@1" Obsidian Pnpirq2 -> irq15
+\ 10 s" /ht/@7/@2" Video / Exar Serial PirqA
+\ 11 s" /ht/@2/@4" Ethernet PirqB
+\ 12 s" /ht/@2/@4,1" Ethernet PirqC
+\ 13 s" /ht/@7/@0" USB PirqD
+\ 13 s" /ht/@7/@0,1" USB PirqD
+\ 13 s" /ht/@7/@0,2" USB PirqD
+
+\ 14 s" /ht/@3/@0" PCIe gpio28
+\ 15 s" /ht/@4/@0" PCIe gpio29
+\ 16 s" /ht/@5/@0" PCIe gpio30
+\ 17 s" /ht/@6/@0" PCIe gpio31
+
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt pin for a device on ht u4
+: u4-get-irq-line ( config-addr -- irq-line )
+\ cr s" u4-get-irq-line " type
+ pci-device-vec c@ CASE
+ 1 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 1 OF f ENDOF
+ 2 OF dup pci-interrupt@ CASE
+ 1 OF c ENDOF
+ 3 OF e ENDOF
+ 2 OF c ENDOF
+ 4 OF e ENDOF
+ ENDCASE
+ ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ ELSE
+ unknown-slot
+ THEN
+ ENDOF
+ 2 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 4 OF dup pci-addr2fn 1 >= IF 12 ELSE 11 THEN ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ ELSE
+ unknown-slot
+ THEN
+ ENDOF
+ 3 OF 14 ENDOF
+ 4 OF 15 ENDOF
+ 5 OF 16 ENDOF
+ 6 OF 17 ENDOF
+ 7 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 0 OF 13 ENDOF
+ 2 OF 10 ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ ELSE
+ unknown-slot
+ THEN
+ ENDOF
+ 8 OF 10 ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ swap drop
+;
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt sense type for a device on ht u4
+: u4-get-irq-sense ( config-addr -- irq-sense )
+\ cr s" u4-get-irq-sense " type
+ u4-get-irq-line CASE
+ 0c OF 00 ENDOF
+ 0e OF 00 ENDOF
+ dup OF 01 ENDOF
+ ENDCASE
+;
+
+\ 10 s" /ht/@4,1" set-pci-interrupt \ ATA
+\ 13 s" /ht/@3/@0" set-pci-interrupt \ USB
+\ 13 s" /ht/@3/@0,1" set-pci-interrupt \ USB
+\ 13 s" /ht/@3/@0,2" set-pci-interrupt \ USB
+\ 1c s" /ht/@2/@1" set-pci-interrupt \ Ethernet
+\ 1d s" /ht/@2/@1,1" set-pci-interrupt \ Ethernet
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt pin for a device on ht u3
+: u3-get-irq-line ( config-addr -- irq-line )
+\ cr s" u3-get-irq-line " type
+ pci-device-vec c@ CASE
+ 2 OF pci-device-vec-len 1 >= IF
+ pci-device-vec 1+ c@ CASE
+ 1 OF dup pci-addr2fn 1 >= IF 1d ELSE 1c THEN ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ ELSE
+ unknown-slot
+ THEN
+ ENDOF
+ 3 OF 13 ENDOF
+ 4 OF 10 ENDOF
+ dup OF unknown-slot ENDOF
+ ENDCASE
+ swap drop
+;
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt sense type for a device on ht u3
+: u3-get-irq-sense ( config-addr -- irq-sense )
+\ cr s" u3-get-irq-sense " type
+ u3-get-irq-line CASE
+ dup OF 01 ENDOF
+ ENDCASE
+;
+
+
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt pin for a device on attu
+: pcie-get-irq-line ( config-addr -- irq-line )
+\ cr s" pcie-get-irq-line " type
+ drop
+ 3
+;
+
+
+\ -----------------------------------------------------------------------------
+\ Get the interrupt sense type for a device on attu
+: pcie-get-irq-sense ( config-addr -- irq-sense )
+\ cr s" pcie-get-irq-sense " type
+ drop
+ 01
+;
+
+\ -----------------------------------------------------------------------------
+\ Set up the special routines for HT irq handling
+: ht-irq-init ( -- )
+\ cr s" ht-irq-init " type
+ u4? IF
+ ['] u4-get-irq-line TO pci-get-irq-line
+ ['] u4-get-irq-sense TO pci-get-irq-sense
+ ELSE
+ ['] u3-get-irq-line TO pci-get-irq-line
+ ['] u3-get-irq-sense TO pci-get-irq-sense
+ THEN
+;
+
+\ -----------------------------------------------------------------------------
+\ Set up the special routines for PCI-e irq handling
+: pcie-irq-init ( -- )
+\ cr s" pcie-irq-init " type
+ ['] pcie-get-irq-sense TO pci-get-irq-sense
+ ['] pcie-get-irq-line TO pci-get-irq-line
+;
+
+\ -----------------------------------------------------------------------------
+\ Set up the special routines for irq handling
+0 VALUE mpic
+: pci-irq-init ( mpic puid -- mpic )
+ over TO mpic
+ 18 rshift FF and
+ CASE
+ F1 OF pcie-irq-init ENDOF
+ F2 OF ht-irq-init ENDOF
+ dup OF ABORT" Wrong PUID! in pci-irq-init" ENDOF
+ ENDCASE
+;
+
+\ -----------------------------------------------------------------------------
+\ Set the interrupt pin for a device
+: pci-set-irq-line ( config-addr -- )
+\ cr pci-vec
+ dup pci-get-irq-line
+\ ." ->" dup .
+ swap pci-irq-line!
+;
+
+\ -----------------------------------------------------------------------------
+\ Add an irq entry for the device at config-addr into the irq map
+\ each entry consists of 7 integer values
+\ Structure of an entry:
+\ +----------+---+---+------------+--------------+---------+---------------+
+\ Number# | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
+\ +----------+---+---+------------+--------------+---------+---------------+
+\ meaning | config | | | int# | phandle | intr nr | pos edge (0) |
+\ | addr | | | (1=a, 2=b, | intr contr | | act ll (1) |
+\ +----------+---+---+------------+--------------+---------+---------------+
+\ value | pci slot | 0 | 0 | 1 | mpic | 7 | 0|1 |
+\ +----------+---+---+------------+--------------+---------+---------------+
+: pci-gen-irq-entry ( prop-addr prop-len config-addr -- prop-addr prop-len )
+ dup >r encode-int+ 0 encode-64+ \ config addr
+ r@ pci-interrupt@ encode-int+ \ interrupt type
+ mpic encode-int+ \ phandle to MPIC
+ r@ pci-irq-line@ encode-int+ \ interrupt number
+ r> pci-get-irq-sense encode-int+ \ trigger type
+;
diff --git a/board-js2x/slof/rtas.fs b/board-js2x/slof/rtas.fs
new file mode 100644
index 0000000..6331795
--- /dev/null
+++ b/board-js2x/slof/rtas.fs
@@ -0,0 +1,236 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+#include <rtas/rtas-init.fs>
+#include <rtas/rtas-cpu.fs>
+#include <rtas/rtas-reboot.fs>
+#include <rtas/rtas-flash.fs>
+#include <rtas/rtas-vpd.fs>
+
+\ for update-flash
+: (get-flashside) ( -- flashside ) rtas-get-flashside ;
+
+' (get-flashside) to get-flashside
+
+\ for update-flash
+: (set-flashside) ( flashside -- status )
+ dup rtas-set-flashside = IF -1 ELSE 0 THEN
+;
+
+' (set-flashside) to set-flashside
+
+: rtas-ibm-read-pci-config ( size puid bus devfn off -- x )
+ [ s" ibm,read-pci-config" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 4 rtas-cb rtas>nargs l!
+ 2 rtas-cb rtas>nret l!
+ swap 8 lshift or swap 10 lshift or rtas-cb rtas>args0 l!
+ dup 20 rshift rtas-cb rtas>args1 l!
+ ffffffff and rtas-cb rtas>args2 l!
+ rtas-cb rtas>args3 l!
+ enter-rtas
+ rtas-cb rtas>args5 l@
+;
+
+: rtas-fetch-cpus ( mask -- status )
+ [ s" rtas-fetch-slaves" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ 0 rtas-cb rtas>args1 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+: rtas-stop-bootwatchdog ( -- status )
+ [ s" rtas-stop-bootwatchdog" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 0 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ enter-rtas
+ rtas-cb rtas>args0 l@
+;
+
+: rtas-set-bootwatchdog ( seconds -- )
+ [ s" rtas-set-bootwatchdog" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 0 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+;
+
+' rtas-set-bootwatchdog to set-watchdog
+
+: rtas-dump-flash ( offset cnt -- )
+ [ s" rtas-dump-flash" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 2 rtas-cb rtas>nargs l!
+ 0 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ rtas-cb rtas>args1 l!
+ enter-rtas
+;
+
+\ load-base wird in slof/fs/base.fs gesetzt... nicht überschreiben
+\ 2000000 CONSTANT load-base
+create blist 50 allot
+blist 50 erase
+
+: build-blocklist_old
+ \ set version
+ 1 blist c!
+ \ set length of block list
+ 50 blist 7 + c!
+ \ no more block list
+ 0000000000000000 blist 8 + !
+ \ first block
+ load-base 0 + blist 10 + !
+ 80000 blist 18 + !
+ load-base 80000 + blist 20 + !
+ 80000 blist 28 + !
+ load-base 100000 + blist 30 + !
+ 80000 blist 38 + !
+ load-base 180000 + blist 40 + !
+ 8006C blist 48 + !
+;
+
+80000 constant _block_size
+
+: build-blocklist
+ \ set length of block list
+ \ length of flashfs at load-base is at offset 30... get it...
+ load-base 30 + @
+ \ calculate the number of blocks we need
+ _block_size / 1 +
+ \ total number of blocks is 2 (for header and block_list extension + (number of blocks for flashfs * 2 (1 for address 1 for length))
+ 2 * 2 + 8 * blist !
+ \ set version ( in first byte only )
+ 1 blist c!
+ \ no more block list
+ 0000000000000000 blist 8 + !
+ \ length of flashfs at load-base is at offset 30... get it...
+ load-base 30 + @
+ \ i define one block to be 64K, so calculate the number of blocks we need and loop over them
+ _block_size / 1 + 0 do
+ load-base _block_size i * + \ which position of load-base to store
+ blist 10 + \ at what offset of blist ( 0x8 + for header 0x8 + for extension )
+ i 10 * + \ for each loop we have done 0x10 +
+ ! \ store it
+ load-base 30 + @
+ _block_size i * - \ remaining length
+ dup _block_size >
+ IF \ is the remaining length > block size
+ drop _block_size \ then store the block size as length
+ ELSE
+ \ do nothing (store remaining length)
+ THEN
+ blist 10 + \ store the length at
+ i 10 * + \ correct blist offset
+ 8 + \ + 8 (we have stored address, now the length)
+ ! \ store it
+ loop
+;
+
+
+
+: build-blocklist-v0_old
+ \ set version
+ 0 blist c!
+ 48 blist 7 + c!
+ \ first block
+ load-base 0 + blist 8 + !
+ 80000 blist 10 + !
+ load-base 80000 + blist 18 + !
+ 80000 blist 20 + !
+ load-base 100000 + blist 28 + !
+ 80000 blist 30 + !
+ load-base 180000 + blist 38 + !
+ 8006C blist 40 + !
+;
+
+: build-blocklist-v0
+ \ set length of block list
+ \ length of flashfs at load-base is at offset 30... get it...
+ load-base 30 + @
+ \ calculate the number of blocks we need
+ _block_size / 1 +
+ \ total number of blocks is 1 (for header + (number of blocks for flashfs * 2 (1 for address 1 for length))
+ 2 * 1 + 8 * blist !
+ \ length of flashfs at load-base is at offset 30... get it...
+ load-base 30 + @
+ \ i define one block to be 64K, so calculate the number of blocks we need and loop over them
+ _block_size / 1 + 0 do
+ load-base _block_size i * + \ which position of load-base to store
+ blist 8 + \ at what offset of blist ( 0x8 + for header)
+ i 10 * + \ for each loop we have done 0x10 +
+ ! \ store it
+ load-base 30 + @
+ _block_size i * - \ remaining length
+ dup _block_size >
+ IF \ is the remaining length > block size
+ drop _block_size \ then store the block size as length
+ ELSE
+ \ do nothing (store remaining length)
+ THEN
+ blist 8 + \ store the length at
+ i 10 * + \ correct blist offset
+ 8 + \ + 8 (we have stored address, now the length)
+ ! \ store it
+ loop
+;
+
+
+: yy
+ build-blocklist
+ blist rtas-ibm-update-flash-64-and-reboot
+;
+
+: yy0
+ build-blocklist-v0
+ blist rtas-ibm-update-flash-64-and-reboot
+;
+
+: rtas-ibm-update-flash-64 ( block-list -- status )
+ [ s" ibm,update-flash-64" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+\ for update-flash
+: flash-write ( image-address -- status)
+ load-base >r to load-base build-blocklist-v0
+ blist rtas-ibm-update-flash-64
+ r> to load-base 0= IF true ELSE false THEN
+;
+
+: commit 1 rtas-ibm-manage-flash-image ;
+: reject 0 rtas-ibm-manage-flash-image ;
+
+: rtas-ibm-validate-flash-image ( image-to-commit -- status )
+ [ s" ibm,validate-flash-image" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 2 rtas-cb rtas>nargs l!
+ 2 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+: rtas-get-blade-descr ( address size -- len status )
+ [ s" rtas-get-blade-descr" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 2 rtas-cb rtas>nargs l!
+ 2 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ rtas-cb rtas>args1 l!
+ enter-rtas
+ rtas-cb rtas>args2 l@
+ rtas-cb rtas>args3 l@
+;
diff --git a/board-js2x/slof/rtc.fs b/board-js2x/slof/rtc.fs
new file mode 100644
index 0000000..db497e9
--- /dev/null
+++ b/board-js2x/slof/rtc.fs
@@ -0,0 +1,59 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ National Semiconductor SIO.
+\ See http://www.national.com/pf/PC/PC87417.html for the datasheet.
+\ PC87417.pdf
+\ moved the RTC initialisation from the device tree to a much earlier point
+\ so that the RTC can be accessed before device tree is generated
+
+\ Enable the RTC, set its address at 1070
+\ see PC87417.pdf page 39 (chapter 3.2.3)
+10 7 siocfg!
+1 30 siocfg!
+1070 wbsplit nip dup 60 siocfg! 62 siocfg!
+
+: rtc@ ( offset -- value )
+ 1070 io-c! 1071 io-c@
+;
+
+: rtc! ( value offset -- )
+ 1070 io-c! 1071 io-c!
+;
+
+\ Set sane configuration; BCD mode is required by Linux.
+\ PC87417.pdf page 153 (chapter 8.3.13) - RTC Control Register A
+\ 20 - Divider Chain Control = Normal Operation
+20 0a rtc!
+\ PC87417.pdf page 155 (chapter 8.3.14) - RTC Control Register B
+\ 02 - 24-hour format enabled
+02 0b rtc!
+\ PC87417.pdf page 156 (chapter 8.3.15) - RTC Control Register C
+00 0c rtc!
+
+\ read from the rtc and do the bcd-to-bin conversion
+: rtc-bin@ ( offset -- value )
+ rtc@ bcd-to-bin
+;
+
+\ to be compatible with the cell boards we provide a .date word
+\ .date prints the current date and time on the firmware prompt
+: .date ( -- )
+ 0 rtc-bin@ ( seconds )
+ 2 rtc-bin@
+ 4 rtc-bin@
+ 7 rtc-bin@
+ 8 rtc-bin@ ( seconds minutes hours day month )
+ 9 rtc-bin@ d# 1900 + dup d# 1970 < IF d# 100 + THEN
+ decimal 4 0.r 2d emit 2 0.r 2d emit 2 0.r space
+ 2 0.r 3a emit 2 0.r 3a emit 2 0.r hex
+;
diff --git a/board-js2x/slof/serial.fs b/board-js2x/slof/serial.fs
index b794a1c..eb9506e 100644
--- a/board-js2x/slof/serial.fs
+++ b/board-js2x/slof/serial.fs
@@ -1,28 +1,43 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ Serial console. Enabled very early.
+\ remember last console used
+CREATE lastser 4 allot 0 lastser l!
-: >serial 3f8 + ;
-: serial! >serial io-c! ;
-: serial@ >serial io-c@ ;
+\ On JS21, use serial port 2. Detect Maui by looking at the SIO version.
+20 siocfg@ f2 = IF 2f8 ELSE 3f8 THEN
+
+: >serial LITERAL + ;
+: js21? -2f8 >serial 0= ;
+: serial! js21? IF 2dup 2f8 + io-c! THEN 3f8 + io-c! ;
+: serial1@ 3f8 + io-c@ ;
+: serial2@ 2f8 + io-c@ ;
: serial-init 0 1 serial! 0 2 serial!
80 3 serial! d# 115200 swap / 0 serial! 0 1 serial!
3 3 serial! 3 4 serial! ;
-: serial-emit BEGIN 5 serial@ 20 and UNTIL 0 serial! ;
-: serial-key BEGIN 5 serial@ 1 and UNTIL 0 serial@ ;
-: serial-key? 5 serial@ 1 and 0<> ;
+: serial-emit BEGIN 5 serial1@ 20 and UNTIL
+ js21? IF BEGIN 5 serial2@ 20 and UNTIL THEN 0 serial! ;
+: serial1-key? 5 serial1@ 1 and 0<> ;
+: serial2-key? 5 serial2@ 1 and 0<> ;
+: serial1-key serial1-key? dup IF 0 serial1@ swap 0 lastser l! THEN ;
+: serial2-key serial2-key? dup IF 0 serial2@ swap 1 lastser l! THEN ;
+: serial-key BEGIN serial1-key dup IF ELSE js21? IF drop serial2-key THEN THEN UNTIL ;
+: serial-key? serial1-key? js21? IF serial2-key? or THEN ;
+
+\ : serial-key BEGIN 5 serial2@ 1 and UNTIL 0 serial2@ ;
+\ : serial-key? 5 serial2@ 1 and 0<> ;
d# 19200 serial-init
' serial-emit to emit
@@ -30,4 +45,4 @@ d# 19200 serial-init
' serial-key? to key?
( .( SLOF)
-.( has started execution, serial console enabled.)
+\ .( has started execution, serial console @ ) 0 >serial .
diff --git a/board-js2x/slof/sio.fs b/board-js2x/slof/sio.fs
index c7fa2fe..4c967e0 100644
--- a/board-js2x/slof/sio.fs
+++ b/board-js2x/slof/sio.fs
@@ -1,63 +1,85 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ National Semiconductor SIO.
\ See http://www.national.com/pf/PC/PC87417.html for the datasheet.
-\ We only use the first serial port, and the RTC.
+\ We use both serial ports, and the RTC.
\ See 3.7.5.
-new-device s" /ht/isa@4/serial" full-name
+new-device 3f8 1 set-unit
s" serial" 2dup device-name device-type
+\ Enable this UART.
+3 7 siocfg! 1 30 siocfg!
+
\ 8 bytes of ISA I/O space
-1 encode-int 0 >serial encode-int+ 8 encode-int+ s" reg" property
+my-unit encode-int rot encode-int+ 8 encode-int+ s" reg" property
d# 19200 encode-int s" current-speed" property
+44 encode-int 0 encode-int+ s" interrupts" property
: open true ;
: close ;
: write ( adr len -- actual ) tuck type ;
-: read ( adr len -- actual ) IF key swap c! 1 ELSE 0 THEN ;
+: read ( adr len -- actual ) 0= IF drop 0 EXIT THEN
+ serial-key? 0= IF 0 swap c! -2 EXIT THEN
+ serial-key swap c! 1 ;
+
+finish-device
+
+
+new-device 2f8 1 set-unit
+
+s" serial" 2dup device-name device-type
+
+\ Enable this UART.
+2 7 siocfg! 1 30 siocfg!
+
+\ 8 bytes of ISA I/O space
+my-unit encode-int rot encode-int+ 8 encode-int+ s" reg" property
+d# 19200 encode-int s" current-speed" property
+43 encode-int 0 encode-int+ s" interrupts" property
+
+: open true ;
+: close ;
+: write ( adr len -- actual ) tuck type ;
+: read ( adr len -- actual ) 0= IF drop 0 EXIT THEN
+ serial-key? 0= IF 0 swap c! -2 EXIT THEN
+ serial-key swap c! 1 ;
finish-device
\ See the "Device Support Extensions" OF Recommended Practice document.
-new-device s" /ht/isa@4/rtc" full-name
+new-device 1070 1 set-unit
s" rtc" 2dup device-name device-type
\ Following is for Linux, to recognize this RTC:
s" pnpPNP,b00" compatible
-\ Enable the RTC, set its address at 1070.
-10 7 siocfg! 1 30 siocfg! 10 60 siocfg! 10 62 siocfg!
-
-: rtc! 1070 io-c! 1071 io-c! ;
-: rtc@ 1070 io-c! 1071 io-c@ ;
+: rtc! my-space io-c! my-space 1+ io-c! ;
+: rtc@ my-space io-c! my-space 1+ io-c@ ;
\ 10 bytes of ISA I/O space, at 1070.
-1 encode-int 1070 encode-int+ 10 encode-int+ s" reg" property
-
-\ Set sane configuration; BCD mode is required by Linux.
-20 0a rtc! 02 0b rtc! 00 0c rtc!
+my-unit encode-int rot encode-int+ 10 encode-int+ s" reg" property
: open true ;
: close ;
\ XXX: dummy methods.
-: get-time ( -- sec min hr day mth yr ) 0 0 0 1 1 d# 1973 ;
+: get-time ( -- sec min hr day mth yr ) 38 22 c 1 1 d# 1973 ;
: set-time ( sec min hr day mth yr -- ) 3drop 3drop ;
finish-device
diff --git a/board-js2x/slof/tpm.fs b/board-js2x/slof/tpm.fs
new file mode 100644
index 0000000..5a45c0b
--- /dev/null
+++ b/board-js2x/slof/tpm.fs
@@ -0,0 +1,63 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Atmel TPM.
+
+new-device 500 1 set-unit
+
+s" tpm" 2dup device-name device-type
+
+s" AT97SC3201" compatible
+
+\ 2 bytes of ISA I/O space
+my-unit encode-int rot encode-int+ 2 encode-int+ s" reg" property
+
+: >tpm 4e io-c! ;
+: tpm@ >tpm 4f io-c@ ;
+: tpm! >tpm 4f io-c! ;
+
+: dump-tpm 11 0 DO cr i 2 .r space i tpm@ 2 0.r LOOP ;
+
+my-address wbsplit 9 tpm! 8 tpm! \ set base address
+0 a tpm! \ disable serint
+
+\ Now we need to execute TPM_Startup.
+CREATE startup-cmd
+0 c, c1 c,
+0 c, 0 c, 0 c, c c,
+0 c, 0 c, 0 c, 99 c, \ TPM_ORD_Startup
+0 c, 1 c, \ TCPA_ST_CLEAR
+
+: send ( addr len -- ) bounds ?DO i c@ 500 io-c! LOOP ;
+: wait-for-ready ( -- ) BEGIN 501 io-c@ 3 and 2 = UNTIL ;
+: recv-verbose ( -- )
+ cr ." TPM result: "
+ 500 io-c@ 2 0.r 500 io-c@ 2 0.r space
+ 500 io-c@ 500 io-c@ 500 io-c@ 500 io-c@
+ bljoin lbflip 6 - dup 8 0.r space 0
+ ?DO 500 io-c@ . LOOP
+;
+
+: recv ( -- )
+ 500 io-c@ drop 500 io-c@ drop
+ 500 io-c@ 500 io-c@ 500 io-c@ 500 io-c@
+ bljoin lbflip 6 - 0
+ ?DO 500 io-c@ drop LOOP
+;
+
+startup-cmd c send wait-for-ready recv
+
+: open true ;
+: close ;
+
+finish-device
diff --git a/board-js2x/slof/tree.fs b/board-js2x/slof/tree.fs
index 6063637..6f8c1b1 100644
--- a/board-js2x/slof/tree.fs
+++ b/board-js2x/slof/tree.fs
@@ -1,21 +1,39 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+400 cp
-\ The root of the device tree and some of its kids.
+0 value puid
+
+: >conf-rtas ( config-addr -- config-addr )
+ puid f2000000 >= IF dup ffff > IF 1000000 + THEN THEN puid + ;
+
+: rtas-config-b@ ( config-addr -- value ) >conf-rtas rb@ ;
+: rtas-config-b! ( value config-addr -- ) >conf-rtas rb! ;
+: rtas-config-w@ ( config-addr -- value ) >conf-rtas rw@-le ;
+: rtas-config-w! ( value config-addr -- ) >conf-rtas rw!-le ;
+: rtas-config-l@ ( config-addr -- value ) >conf-rtas rl@-le ;
+: rtas-config-l! ( value config-addr -- ) >conf-rtas rl!-le ;
+
+440 cp
-new-device s" /" full-name
+#include "pci-scan.fs"
+
+480 cp
+
+\ The root of the device tree and some of its kids.
-s" /" device-name
+s" /" find-device
+vpd-read-model encode-string s" model" property
2 encode-int s" #address-cells" property
2 encode-int s" #size-cells" property
@@ -24,63 +42,151 @@ s" /" device-name
0 encode-int+ f8050000 encode-int+ s" platform-open-pic" property
\ Yaboot is stupid. Without this, it can't/won't find /etc/yaboot.conf.
-s" chrp we are not, but smart yaboot is not" device-type
+s" chrp SLOF based 970 blade" device-type
\ To get linux-2.6.10 and later to work out-of-the-box.
s" Momentum,Maple" compatible
+\ See 3.6.5, and the PowerPC OF binding document.
+new-device
+s" mmu" 2dup device-name device-type
+0 0 s" translations" property
+
: open true ;
: close ;
-\ See 3.5.
-new-device s" /openprom" full-name
-s" openprom" device-name
-s" SlimLine Open Firmware (SLOF) version 0.0" encode-string s" model" property
-0 0 s" relative-addressing" property
finish-device
-\ See 3.5.
-new-device s" /chosen" full-name
-s" chosen" device-name
+new-device flash-addr set-unit-64
+ s" flash" 2dup device-name device-type
+ 0 encode-int flash-addr encode-int+
+ 0 encode-int+ get-flash-size encode-int+ s" reg" property
+ get-flash-size encode-int s" #bytes" property
+ 0 0 s" used-by-rtas" property
+ : open true ;
+ : close ;
finish-device
-\ See 3.6.5, and the PowerPC OF binding document.
-new-device s" /mmu" full-name
-s" mmu" 2dup device-name device-type
-0 0 s" translations" property
+4a0 cp
+
+new-device nvram-base set-unit-64
+ s" nvram" 2dup device-name device-type
+ nvram-size encode-int s" #bytes" property
+ 0 encode-int nvram-base encode-int+
+ 0 encode-int+ nvram-size encode-int+ s" reg" property
+ get-node node>path s" nvram" 2swap set-alias
+ : open true ;
+ : close ;
finish-device
-INCLUDE hw/memory.fs
-INCLUDE hw/mpic.fs
-INCLUDE hw/dart.fs
-INCLUDE hw/ht.fs
+4c0 cp
+
+#include "memory.fs"
+
+500 cp
+
+#include "mpic.fs"
+
+580 cp
+
+#include "dart.fs"
+
+5a0 cp
+
+#include "i2c.fs"
+
+600 cp
+get-node device-end
+620 cp
+\ if it is js21/bimini the fbuffer code is included
+u4? ?include fbuffer.fs
+640 cp
+set-node
+
+690 cp
+
+#include "ht.fs"
+
+6a0 cp
+get-node device-end
+6a8 cp
+\ at this point the SAS controller has been detected and we know
+\ if it is bimini or js21
+\ if it is bimini the fcode evaluator is included
+bimini? ?include evaluator.fs
+6b0 cp
+set-node
+6b8 cp
+
+u4? ?include attu.fs
+6c0 cp
\ See the PowerPC OF binding document.
-new-device s" /cpus" full-name
+new-device
s" cpus" device-name
+
1 encode-int s" #address-cells" property
0 encode-int s" #size-cells" property
-INCLUDE hw/cpu.fs
-: create-cpu-nodes
- master-cpu create-cpu-node
- slave? IF master-cpu 1 xor create-cpu-node THEN ;
-create-cpu-nodes
+: decode-unit 1 hex-decode-unit ;
+: encode-unit 1 hex-encode-unit ;
+
+cpu-mask @ 40 0 DO dup 1 and IF
+i s" cpu.fs" INCLUDED THEN u2/ LOOP drop
+
+: open true ;
+: close ;
finish-device
+master-cpu s" /cpus/@" rot (u.) $cat open-dev encode-int s" cpu" set-chosen
+s" /memory" open-dev encode-int s" memory" set-chosen
+
+6e0 cp
+
+new-device
+ s" rtas" device-name
+
+ rtas-size encode-int s" rtas-size" property
+ 00000001 encode-int s" ibm,flash-block-version" property
+ 00000001 encode-int s" rtas-event-scan-rate" property
+ rtas-create-token-properties
+ 00000001 encode-int s" rtas-version" property
+
+: open true ;
+: close ;
+
+: instantiate-rtas instantiate-rtas ;
+
finish-device
+700 cp
+device-end
-: set-chosen ( prop len name len -- )
- s" /chosen" find-package drop set-property ;
+\ Hack for AIX.
+s" /options" find-device
+ \ s" 33554432" encode-string s" load-base" property
+ s" 16384" encode-string s" load-base" property
+device-end
+
+\ See 3.5.
+s" /openprom" find-device
+ s" SLOF," slof-build-id $cat encode-string s" model" property
+ 0 0 s" relative-addressing" property
+device-end
+
+s" /aliases" find-device
+ : open true ;
+ : close ;
+device-end
-master-cpu s" /cpus/cpu@" rot (u.) $cat open-dev encode-int s" cpu" set-chosen
-s" /memory" open-dev encode-int s" memory" set-chosen
s" /mmu" open-dev encode-int s" mmu" set-chosen
-: io open-dev dup encode-int s" stdout" set-chosen
- encode-int s" stdin" set-chosen ;
+#include "available.fs"
+
+#include <term-io.fs>
+
+u3? IF s" /ht/isa/serial@3f8" io
+ ELSE s" /ht/isa/serial@2f8" io THEN
-s" /ht/isa@4/serial" io
diff --git a/board-js2x/slof/u4-mem.fs b/board-js2x/slof/u4-mem.fs
new file mode 100644
index 0000000..a2f1473
--- /dev/null
+++ b/board-js2x/slof/u4-mem.fs
@@ -0,0 +1,313 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ U4 DDR2 memory controller.
+
+cr .( Setting up memory controller...)
+
+
+\ First, I2C access to the SPDs.
+
+: >i2c f8001000 + ;
+: i2c@ >i2c rl@ ;
+: i2c! >i2c rl! ;
+
+: .i2c 80 0 DO i i2c@ . 10 +LOOP ;
+
+: i2c-addr ( addr -- ) 50 i2c! 2 10 i2c! BEGIN 30 i2c@ 2 and UNTIL ;
+: i2c-addr-subaddr ( addr suba -- ) 60 i2c! i2c-addr ;
+: i2c-stop ( -- ) BEGIN 30 i2c@ dup 30 i2c! 4 and UNTIL ;
+: i2c-nak? ( -- failed? ) 20 i2c@ 2 and 0= dup IF i2c-stop THEN ;
+: i2c-short? ( -- failed? ) 30 i2c@ 4 and 0<> dup IF 0 10 i2c! i2c-stop THEN ;
+: i2c-aak-if-more ( n -- ) 1 <> 1 and 10 i2c! ;
+
+: i2c-sub-read ( buf len addr suba -- error? )
+ c 0 i2c! >r 1 or r> i2c-addr-subaddr i2c-nak? IF 2drop true EXIT THEN
+ dup i2c-aak-if-more 2 30 i2c!
+ BEGIN
+ 30 i2c@ 1 and IF
+ 1- >r 70 i2c@ over c! char+ r>
+ dup 0= IF i2c-stop 2drop false EXIT THEN
+ dup i2c-aak-if-more 1 30 i2c! THEN
+ i2c-short? IF 2drop true EXIT THEN
+ AGAIN ;
+
+
+\ What slots are filled with working memory (bitmask).
+
+f VALUE dimms-valid
+: dimm-invalid 1 swap lshift invert dimms-valid and to dimms-valid ;
+: dimm-invalid dup dimm-invalid 2 xor dimm-invalid ; \ DIMMs are paired
+: dimm-valid? 1 swap lshift dimms-valid and ;
+: dimm( +comp postpone 4 postpone 0 postpone DO
+ postpone i postpone dimm-valid? postpone IF ; immediate
+: )dimm postpone THEN postpone LOOP -comp ; immediate
+
+
+\ The data from the SPDs.
+
+CREATE spds 100 allot
+: spd@ ( dimm# off -- value ) swap 40 * + spds + c@ ;
+
+CREATE addresses a0 c, a4 c, a2 c, a6 c,
+dimm( spds i 40 * + 40 addresses i + c@ 0 i2c-sub-read IF i dimm-invalid THEN )dimm
+
+
+\ Accessors.
+
+: spd>rows 3 spd@ ;
+: spd>cols 4 spd@ ;
+: spd>ranks 5 spd@ 7 and 1+ ;
+: spd>width d spd@ ;
+: spd>banks 11 spd@ ;
+: spd>cas 12 spd@ ; \ bit mask of allowable CAS latencies
+: spd>trp 1b spd@ ; \ in units of 0.25 ns
+: spd>trrd 1c spd@ ; \ in units of 0.25 ns
+: spd>trcd 1d spd@ ; \ in units of 0.25 ns
+: spd>tras 1e spd@ ; \ in units of 1 ns
+: spd>twr 24 spd@ ; \ in units of 0.25 ns
+: spd>twtr 25 spd@ ; \ in units of 0.25 ns
+: spd>trtp 26 spd@ ; \ in units of 0.25 ns
+: spd>trc 29 spd@ ; \ in units of 1 ns XXX: should also look at byte 28
+: spd>trfc 2a spd@ ; \ in units of 1 ns XXX: should also look at byte 28
+
+cr .( rows cols ranks width banks trp trrd trcd tras twr twtr trtp trc trfc)
+cr .( =====================================================================)
+decimal
+dimm( cr
+i spd>rows 4 .r i spd>cols 5 .r i spd>ranks 6 .r i spd>width 6 .r
+i spd>banks 6 .r i spd>trp 4 .r i spd>trrd 5 .r i spd>trcd 5 .r
+i spd>tras 5 .r i spd>twr 4 .r i spd>twtr 5 .r i spd>trtp 5 .r
+i spd>trc 4 .r i spd>trfc 5 .r
+)dimm
+hex
+
+ff dimm( i spd>cas and )dimm CONSTANT cl-supported
+: max-cl -1 swap 8 0 DO dup 1 and IF nip i swap THEN u2/ LOOP drop ;
+cl-supported max-cl VALUE cl
+
+: tck>60*ns dup f and swap 4 rshift a * over + 6 * swap CASE
+ a OF 2d - ENDOF b OF 2e - ENDOF c OF 20 - ENDOF d OF 21 - ENDOF
+ ENDCASE ;
+: cl>tck 0 spd>cas max-cl swap -
+ CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF
+ true ABORT" No supported CAS latency for this DIMM" ENDCASE
+ 0 swap spd@ tck>60*ns ;
+
+: spd>min-tck dup spd>cas max-cl cl -
+ CASE 0 OF 9 ENDOF 1 OF 17 ENDOF 2 OF 19 ENDOF
+ true ABORT" No supported CAS latency for this DIMM" ENDCASE
+ spd@ tck>60*ns ;
+: spd>max-tck 2b spd@ tck>60*ns ;
+
+: .tck base @ >r decimal dup d# 60 / 0 .r [char] . emit
+ d# 60 mod d# 1000 * d# 60 / 3 0.r ." ns" r> base ! ;
+
+cr .( CAS latencies supported: )
+8 0 DO cl-supported 1 i lshift and IF i . THEN LOOP
+
+\ Find the lowest CL at the highest tCK.
+8 0 DO cl-supported 1 i lshift and IF cl cl>tck i cl>tck = IF
+ i to cl LEAVE THEN THEN LOOP
+
+.( -- using ) cl .
+
+
+0 dimm( i spd>min-tck max )dimm CONSTANT tck
+dimm( i spd>max-tck tck < IF i dimm-invalid THEN )dimm
+cr .( tCK is ) tck .tck
+
+
+0 CONSTANT al
+cl al + CONSTANT rl
+rl 1- CONSTANT wl
+
+: // dup >r 1- + r> / ; \ round up
+0 spd>tras d# 60 * tck // CONSTANT tras
+0 spd>trtp d# 15 * tck // CONSTANT trtp
+0 spd>twr d# 15 * tck // CONSTANT twr
+0 spd>trp d# 15 * tck // CONSTANT trp
+0 spd>trrd d# 15 * tck // CONSTANT trrd
+0 spd>trrd d# 60 * tck // CONSTANT 4*trrd
+0 spd>trcd d# 15 * tck // CONSTANT trcd
+0 spd>trc d# 60 * tck // CONSTANT trc
+0 spd>twtr d# 15 * tck // CONSTANT twtr
+
+: spd>memmd
+ >r r@ spd>rows r@ spd>cols +
+ r@ spd>banks 2log + 4 * r> spd>width 2log 3 * + 6c - ;
+: dimm-group-size ( dimm# -- size )
+ >r r@ spd>rows r@ spd>cols + 1 swap lshift
+ r@ spd>banks * r> spd>ranks * 10 * ;
+VARIABLE start-address
+VARIABLE was-prev-big
+: assign-dimm-group ( dimm# -- config-value )
+ dup dimm-valid? 0= IF drop 0 EXIT THEN
+ \ MemMd, enable, single-sided or not
+ dup spd>memmd c lshift 1 or over spd>ranks 1 = IF 2 or THEN
+cr ." ---> " dup .
+>r
+ dimm-group-size start-address @ 2dup + rot ( start end size )
+ 80000000 > IF
+ dup 1000000000 < IF dup 4 rshift ELSE 08000000 THEN r> or >r \ Add2G
+ over 0<> IF over c rshift ELSE 00080000 THEN r> or >r \ Sub2G
+ was-prev-big on
+ ELSE
+ was-prev-big @ IF 80000000 + swap 80000000 + swap THEN r> 08080000 or >r
+ was-prev-big off
+ THEN
+ swap 18 rshift r> or >r \ start address
+ dup 80000000 = IF drop 100000000 THEN start-address ! r> ;
+
+
+\ Now set the frequency in the memory controller
+d# 1800 tck / 4 - 12 lshift 33c or f8000800 rl!
+f8000860 rl@ 80000000 or f8000860 rl! 10000 0 DO LOOP
+
+: mc! f8002000 + rl! ;
+: mc@ f8002000 + rl@ ;
+
+
+\ memory timing regs (state machine)
+
+tras 2-
+5 lshift al trtp + 2- or
+5 lshift wl twr + or
+5 lshift trp 2- or
+5 lshift trp 2- 0 spd>banks 8 = IF 1+ THEN or
+7 lshift 030 mc!
+
+al trtp + trp + 2-
+5 lshift cl al + twr + trp + 1- or
+5 lshift trrd 2- or
+5 lshift trc 2- or
+5 lshift trcd 2- or
+5 lshift 4*trrd or
+2 lshift 040 mc!
+
+0
+5 lshift 1 or
+5 lshift 1 or
+5 lshift cl 1- twtr + or
+5 lshift 1 or
+5 lshift 1 or
+2 lshift 050 mc!
+
+0
+5 lshift 1 or
+5 lshift 1 or
+5 lshift 2 or
+5 lshift 2 or
+5 lshift 2 or
+2 lshift 060 mc! \ XXX joerg has different setting
+
+cl 3 = IF 30801800 ( 30800d00 ) 070 mc! \ XXX memory refresh
+ELSE 41002000 070 mc! THEN
+
+\ memory size regs
+
+1 dimm-group-size 0 dimm-group-size > 1 0 rot IF swap THEN \ biggest first
+assign-dimm-group 200 mc!
+assign-dimm-group 210 mc!
+0 220 mc! 0 230 mc!
+
+
+
+
+
+\ arbiter tunables
+\ 40041040 270 mc!
+04041040 270 mc!
+50000000 280 mc!
+\ a0a00000 290 mc! \ a0000000 might be faster
+00000000 290 mc!
+\ 20020820 2a0 mc!
+04020822 2a0 mc!
+00000000 2b0 mc!
+\ 30413cc7 2c0 mc! \ have to calculate the low five bits
+30413dc5 2c0 mc!
+\ cl 3 = IF 76000050 2d0 mc! 70000000 2e0 mc! ELSE
+cl 3 = IF 75000050 2d0 mc! 70000000 2e0 mc! ELSE
+ b8002080 2d0 mc! b0000000 2e0 mc! THEN
+\ Should test for something else really
+
+
+
+cl 3 = IF 00006000 890 mc! 00006000 8a0 mc! ELSE
+ 00006500 890 mc! 00006500 8a0 mc! THEN
+
+cl 3 = IF 1e008a8a ELSE 31000000 THEN
+dup 800 mc! dup 810 mc! dup 820 mc! dup 830 mc!
+dup 900 mc! dup 910 mc! dup 920 mc! dup 930 mc! dup 980 mc!
+dup a00 mc! dup a10 mc! dup a20 mc! dup a30 mc!
+dup b00 mc! dup b10 mc! dup b20 mc! dup b30 mc! b80 mc!
+
+\ 0 8d0 mc! 0 9d0 mc! 0 ad0 mc! 0 bd0 mc!
+61630000 8d0 mc!
+61630000 9d0 mc!
+52510000 ad0 mc!
+434e0000 bd0 mc!
+
+a0200400 100 mc!
+80020000 110 mc!
+80030000 120 mc!
+80010404 130 mc!
+cl 3 = IF
+8000153a 140 mc! ELSE
+8000174a 140 mc! THEN
+a0200400 150 mc!
+\ 92000000 160 mc!
+\ 92000000 170 mc!
+\ 91300000 160 mc!
+\ 91300000 170 mc!
+91800000 160 mc!
+91800000 170 mc!
+cl 3 = IF
+8ff0143a 180 mc! ELSE
+8ff0164a 180 mc! THEN
+80010784 190 mc!
+80010404 1a0 mc!
+0 1b0 mc! 0 1c0 mc! 0 1d0 mc! 0 1e0 mc! 0 1f0 mc!
+
+cl 3 = IF
+143a 0c0 mc! ELSE
+164a 0c0 mc! THEN
+0404 0d0 mc!
+
+\ after this point, setup is common for all speeds and sizes of dimms (sort of)
+
+60000000 3a0 mc!
+
+0 840 mc! 0 850 mc! 0 860 mc! 0 870 mc!
+0 940 mc! 0 950 mc! 0 960 mc! 0 970 mc! 0 990 mc!
+0 a40 mc! 0 a50 mc! 0 a60 mc! 0 a70 mc!
+0 b40 mc! 0 b50 mc! 0 b60 mc! 0 b70 mc! 0 b90 mc!
+
+0 880 mc!
+
+001a4000 9a0 mc!
+
+84800000 500 mc!
+
+10000 0 DO LOOP
+
+80000000 b0 mc! BEGIN b0 mc@ 40000000 and UNTIL
+
+0 300 mc! 0 310 mc!
+
+80000000 440 mc!
+0 410 mc! 27fffffc 420 mc!
+fedcba98 430 mc!
+c0000000 400 mc! BEGIN 400 mc@ c0000000 and 0= UNTIL
+
+cr .( mem done)
diff --git a/board-js2x/slof/vga-display.fs b/board-js2x/slof/vga-display.fs
new file mode 100644
index 0000000..e9decfd
--- /dev/null
+++ b/board-js2x/slof/vga-display.fs
@@ -0,0 +1,215 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ included by pci-class_03.fs
+
+( str len display_num ) \ name prefix
+
+false value is-installed?
+value display_num ( str len )
+
+s" ,Display-" $cat 41 display_num + char-cat \ add ", Display-A" or "-B" to name ( str len )
+encode-string s" name" property \ store as name property
+
+s" display" encode-string s" device_type" property \ add "device_type" propert
+
+\ screen-info is set by pci-class_03.fs contains output of get_vbe_info bios-snk call
+CASE screen-info c@ \ ( display-type )
+ 0 OF s" NONE" ENDOF \ No display
+ 1 OF s" Analog" ENDOF
+ 2 OF s" Digital" ENDOF
+ENDCASE
+encode-string s" display-type" property
+
+screen-info 8 + l@ value mem-adr
+screen-info 1 + w@ value width
+screen-info 3 + w@ value height
+
+screen-info c@ IF
+ \ if screen-info is not 0, we have some screen attached, add needed properties...
+ width encode-int s" width" property
+ height encode-int s" height" property
+ screen-info 5 + w@ encode-int s" linebytes" property
+ screen-info 7 + c@ encode-int s" depth" property
+ mem-adr encode-int s" address" property
+ \ the EDID property breaks the boot... so i leave it out for now,
+ \ maybe encode-bytes does s.th. wrong???
+ \ screen-info c + 80 encode-bytes s" EDID" property
+ s" ISO8859-1" encode-string s" character-set" property \ i hope this is ok...
+THEN
+
+\ words for installation/removal, needed by is-install/is-remove, see display.fs
+: display-remove ( -- )
+;
+: display-install ( -- )
+ is-installed? NOT IF
+ mem-adr to frame-buffer-adr
+ default-font
+ set-font
+ width height width char-width / height char-height / ( width height #lines #cols )
+ fb8-install
+ true to is-installed?
+ THEN
+;
+
+\ as of OF 8bit Graphics Recommendation, these shall be implemented:
+
+: draw-rectangle ( adr x y w h -- )
+ is-installed? IF
+ 0 ?DO
+ 4dup ( adr x y w adr x y w )
+ drop ( adr x y w adr x y )
+ i + screen-width * + \ calculate offset into framebuffer ((y + i) * screen_width + x)
+ ( adr x y w adr offs )
+ frame-buffer-adr + \ add to frame-buffer-adr ( adr x y w adr fb_adr )
+ 1 pick 3 pick i * + swap 3 pick ( adr x y w adr adr_offs fb_adr w )
+ rmove \ copy line ( adr x y w adr )
+ drop ( adr x y w )
+ LOOP
+ 4drop
+ ELSE
+ 4drop drop
+ THEN
+;
+
+: fill-rectangle ( number x y w h -- )
+ is-installed? IF
+ 0 ?DO
+ 4dup ( number x y w number x y w )
+ drop ( number x y w number x y )
+ i + screen-width * + \ calculate offset into framebuffer ((y + i) * screen_width + x)
+ ( number x y w number offs )
+ frame-buffer-adr + \ add to frame-buffer-adr ( number x y w number adr )
+ 2 pick 2 pick ( number x y w number adr w number )
+ rfill \ draw line ( number x y w number )
+ drop ( number x y w )
+ LOOP
+ 4drop
+ ELSE
+ 4drop drop
+ THEN
+;
+
+: read-rectangle ( adr x y w h -- )
+ is-installed? IF
+ 0 ?DO
+ 4dup ( adr x y w adr x y w )
+ drop ( adr x y w adr x y )
+ i + screen-width * + \ calculate offset into framebuffer ((y + i) * screen_width + x)
+ ( adr x y w adr offs )
+ frame-buffer-adr + \ add to frame-buffer-adr ( adr x y w adr fb_adr )
+ 1 pick 3 pick i * + 3 pick ( adr x y w adr fb_adr adr_offs w )
+ rmove \ copy line ( adr x y w adr )
+ drop ( adr x y w )
+ LOOP
+ 4drop
+ ELSE
+ 4drop drop
+ THEN
+;
+
+: color! ( r g b number -- )
+ \ 3c8 is RAMDAC write mode select palette entry register
+ \ 3c9 is RAMDAC write mode write palette entry register ( 3 consecutive writes set new entry )
+ vga-device-node? 3c8 translate-address ( r g b number address )
+ swap 1 pick ( r g b address number address )
+ rb! \ write palette entry number ( r g b address )
+ 1 + \ select next register (3c9)
+ dup 4 pick swap rb! \ write red ( r g b address )
+ dup 3 pick swap rb! \ write green ( r g b address )
+ dup 2 pick swap rb! \ write blue ( r g b address )
+ 4drop
+;
+
+: color@ ( number -- r g b )
+ \ 3c7 is RAMDAC read mode select palette entry register
+ \ 3c9 is RAMDAC read mode read palette entry register ( 3 consecutive reads read entry )
+ vga-device-node? 3c7 translate-address ( number address )
+ swap 1 pick ( address number address )
+ rb! \ write palette entry number ( address )
+ 2 + >r \ select next register (3c9) ( R: address )
+ r@ rb@ \ read red ( r R: address )
+ r@ rb@ \ read green ( r g R: address )
+ r@ rb@ \ write blue ( r g b R: address )
+ r> drop ( r g b )
+;
+
+: set-colors ( adr number #numbers -- )
+ \ 3c8 is RAMDAC write mode select palette entry register
+ \ 3c9 is RAMDAC write mode write palette entry register ( 3 consecutive writes set new entry )
+ \ since after writing 3 entries, the palette entry is automagically incremented,
+ \ we can just continue writing...
+ vga-device-node? 3c8 translate-address ( adr number #numbers )
+ dup 3 pick swap ( adr number #numbers address number address )
+ rb! \ write palette entry number ( adr number #numbers address )
+ 1 + \ select next register (3c9)
+ -rot swap drop ( adr address #numbers )
+ -rot swap rot ( address adr #numbers )
+ 0 ?DO
+ ( address adr )
+ dup rb@ \ read red value from adr ( address adr r )
+ 2 pick rb! \ write to register ( address adr )
+ 1 + \ next adr
+ dup rb@ \ read green value from adr ( address adr g )
+ 2 pick rb! \ write to register ( address adr )
+ 1 + \ next adr
+ dup rb@ \ read blue value from adr ( address adr r )
+ 2 pick rb! \ write to register ( address adr )
+ 1 + \ next adr
+ LOOP
+ 2drop
+;
+
+: get-colors ( adr number #numbers -- )
+ \ 3c7 is RAMDAC read mode select palette entry register
+ \ 3c9 is RAMDAC read mode read palette entry register ( 3 consecutive reads get entry )
+ \ since after reading 3 entries, the palette entry is automagically incremented,
+ \ we can just continue reading...
+ vga-device-node? 3c7 translate-address ( adr number #numbers )
+ dup 3 pick swap ( adr number #numbers address number address )
+ rb! \ write palette entry number ( adr number #numbers address )
+ 2 + \ select next register (3c9)
+ -rot swap drop ( adr address #numbers )
+ -rot swap rot ( address adr #numbers )
+ 0 ?DO
+ ( address adr )
+ 1 pick rb@ \ read red value from register ( address adr r )
+ 1 pick rb! \ write to adr ( address adr )
+ 1 + \ next adr
+ 1 pick rb@ \ read green value from register ( address adr g )
+ 1 pick rb! \ write to adr ( address adr )
+ 1 + \ next adr
+ 1 pick rb@ \ read blue value from register ( address adr b )
+ 1 pick rb! \ write to adr ( address adr )
+ 1 + \ next adr
+ LOOP
+ 2drop
+;
+
+: dimensions ( -- width height )
+width height
+;
+
+\ clear screen
+mem-adr width height * 0 rfill
+
+\ call is-install and is-remove
+' display-install is-install
+
+' display-remove is-remove
+
+s" screen" find-alias 0= IF
+ \ no previous screen alias defined, define it...
+ s" screen" get-node node>path set-alias
+ELSE
+ drop
+THEN
diff --git a/clients/Makefile b/clients/Makefile
new file mode 100644
index 0000000..3198176
--- /dev/null
+++ b/clients/Makefile
@@ -0,0 +1,29 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include clients.mk
+
+all:
+ for dir in $(CLIENTS); do \
+ if [ -r $$dir/Makefile ]; then \
+ $(MAKE) -C $$dir "FLAG=$(FLAG)" || exit 1; \
+ cp $$dir/client $$dir.client; \
+ fi; \
+ done
+
+clean distclean:
+ @for dir in $(CLIENTS); do \
+ if [ -r $$dir/Makefile ]; then \
+ $(MAKE) -C $$dir $@ || exit 1; \
+ rm -f $$dir.client; \
+ fi; \
+ done
diff --git a/clients/clients.mk b/clients/clients.mk
new file mode 100644
index 0000000..45a8534
--- /dev/null
+++ b/clients/clients.mk
@@ -0,0 +1,13 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+CLIENTS = net-snk
diff --git a/clients/net-snk/Makefile b/clients/net-snk/Makefile
new file mode 100644
index 0000000..4636cec
--- /dev/null
+++ b/clients/net-snk/Makefile
@@ -0,0 +1,57 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOP=$(shell pwd)
+export TOP
+include $(TOP)/make.rules
+
+OBJS = kernel/kernel.o oflib/oflib.o libc/libc-glue.o app/app.o
+.PHONY : subdirs clean depend mrproper
+
+client : subdirs $(OBJS) $(LIBCMNDIR)/libc.a
+ $(LD) $(LDFLAGS) -o $@ -Tclient.lds $(OBJS) $(LIBCMNDIR)/libc.a
+ $(OBJDUMP) -DSsx $@ > $@.dis
+ cp $@ $@.unstripped
+ $(STRIP) $@
+
+sec-client : subdirs $(OBJS) $(LIBCMNDIR)/libc.a
+ $(LD) $(LDFLAGS) -o $@ -Tsec-client.lds $(OBJS) $(LIBCMNDIR)/libc.a
+
+subdirs :
+ @for dir in $(dir $(OBJS)); do \
+ $(MAKE) -C $$dir || exit 1; \
+ done
+
+$(LIBCMNDIR)/libc.a:
+ $(MAKE) -C $(LIBCMNDIR) libc
+
+clean:
+ @for dir in $(dir $(OBJS)); do \
+ $(MAKE) -C $$dir clean; \
+ done
+ rm -f $(OBJS) client diag netboot sec-client net-diag \
+ *.dis client.unstripped
+
+mrproper : clean
+ $(MAKE) -C app mrproper
+ $(MAKE) -C libc mrproper
+ $(MAKE) -C kernel mrproper
+ $(MAKE) -C oflib mrproper
+ find -name .*.bak | xargs rm -rf
+
+distclean: mrproper
+
+depend :
+ $(MAKE) -C app depend
+ $(MAKE) -C libc depend
+ $(MAKE) -C kernel depend
+ $(MAKE) -C oflib depend
diff --git a/clients/net-snk/app/Makefile b/clients/net-snk/app/Makefile
new file mode 100644
index 0000000..aa768fc
--- /dev/null
+++ b/clients/net-snk/app/Makefile
@@ -0,0 +1,44 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS +=$(ADDCFLAGS)
+
+OBJS = main.o
+OBJDIRS = netlib/netlib.o netapps/netboot.o
+OBJDIRS += netapps/netflash.o
+OBJDIRS += netapps/ping.o
+OBJDIRS += netapps/args.o
+
+all: app.o
+
+subdirs:
+ for dir in $(dir $(OBJDIRS)); do \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir || exit 1; \
+ done
+
+app.o: subdirs $(OBJS)
+ $(LD) $(LDFLAGS) $(OBJDIRS) $(OBJS) -o $@ -r
+
+clean :
+ $(RM) -f *.o *.a *.i
+ for dir in $(dir $(OBJDIRS)); do \
+ $(CLEAN) ; \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir clean; \
+ done
+
+include $(TOP)/make.depend
diff --git a/clients/net-snk/app/main.c b/clients/net-snk/app/main.c
new file mode 100644
index 0000000..a9dc0f9
--- /dev/null
+++ b/clients/net-snk/app/main.c
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <of.h>
+#include <netapps/netapps.h>
+#include <libbootmsg.h>
+
+extern void _callback_entry(void);
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ of_set_callback((void *) &_callback_entry);
+
+ if (strcmp(argv[0], "netboot") == 0 && argc >= 3)
+ return netboot(argc, argv);
+ if (strcmp(argv[0], "netflash") == 0)
+ return netflash(argc, argv);
+ if (strcmp(argv[0], "ping") == 0)
+ return ping(argc, argv);
+
+ printf("Unknown client application called\n");
+ for (i = 0; i < argc; i++)
+ printf("argv[%d] %s\n", i, argv[i]);
+
+ return -1;
+}
+
+int
+callback(int argc, char *argv[])
+{
+ int i;
+
+ printf("\n");
+
+ /*
+ * Register your application's callback handler here, similar to
+ * the way you would register an application.
+ * Please note that callback functions can be called safely only after
+ * your application has called of_yield(). If you return or exit() from
+ * your client application, the callback can no longer be used.
+ */
+#if 0
+ if (strcmp(argv[0], "example") == 0)
+ return example(argc, argv);
+#endif
+
+ printf("No such callback function\n");
+ for (i = 0; i < argc; i++)
+ printf("argv[%d] %s\n", i, argv[i]);
+
+ return (-1);
+}
diff --git a/clients/net-snk/app/netapps/Makefile b/clients/net-snk/app/netapps/Makefile
new file mode 100644
index 0000000..9882a18
--- /dev/null
+++ b/clients/net-snk/app/netapps/Makefile
@@ -0,0 +1,29 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS += -I../ -I../../../../lib/ -Wall -W
+OBJS = netboot.o netflash.o
+OBJS += ping.o
+OBJS += args.o
+
+all: $(OBJS)
+
+clean:
+ $(RM) -f *.o *.a *.i
+
+include $(TOP)/make.depend
diff --git a/clients/net-snk/app/netapps/args.c b/clients/net-snk/app/netapps/args.c
new file mode 100644
index 0000000..ac71342
--- /dev/null
+++ b/clients/net-snk/app/netapps/args.c
@@ -0,0 +1,142 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Returns pointer of the n'th argument within a string.
+ *
+ * @param arg_str string with arguments, seperated with ','
+ * @param index index of the requested arguments whithin arg_str
+ * @return pointer of argument[index] on success
+ * NULL if index is out of range
+ */
+const char *
+get_arg_ptr(const char *arg_str, unsigned int index)
+{
+ unsigned int i;
+
+ for (i = 0; i < index; ++i) {
+ for (; *arg_str != ',' && *arg_str != 0; ++arg_str);
+ if (*arg_str == 0)
+ return 0;
+ ++arg_str;
+ }
+ return arg_str;
+}
+
+/**
+ * Returns number of arguments within a string.
+ *
+ * @param arg_str string with arguments, seperated with ','
+ * @return number of arguments
+ */
+unsigned int
+get_args_count(const char *arg_str)
+{
+ unsigned int count = 1;
+
+ while ((arg_str = get_arg_ptr(arg_str, 1)) != 0)
+ ++count;
+ return count;
+}
+
+/**
+ * Returns the length of the first argument.
+ *
+ * @param arg_str string with arguments, seperated with ','
+ * @return length of first argument
+ */
+unsigned int
+get_arg_length(const char *arg_str)
+{
+ unsigned int i;
+
+ for (i = 0; *arg_str != ',' && *arg_str != 0; ++i)
+ ++arg_str;
+ return i;
+}
+
+/**
+ * Copy the n'th argument within a string into a buffer in respect
+ * to a limited buffer size
+ *
+ * @param arg_str string with arguments, seperated with ','
+ * @param index index of the requested arguments whithin arg_str
+ * @param buffer pointer to the buffer
+ * @param length size of the buffer
+ * @return pointer of buffer on success
+ * NULL if index is out of range.
+ */
+char *
+argncpy(const char *arg_str, unsigned int index, char *buffer,
+ unsigned int length)
+{
+ const char *ptr = get_arg_ptr(arg_str, index);
+ unsigned int len;
+
+ if (!ptr)
+ return 0;
+ len = get_arg_length(ptr);
+ if (!strncpy(buffer, ptr, length))
+ return 0;
+ buffer[len] = 0;
+ return buffer;
+}
+
+/**
+ * Converts "255.255.255.255" -> char[4] = { 0xff, 0xff, 0xff, 0xff }
+ *
+ * @param str string to be converted
+ * @param ip in case of SUCCESS - 32-bit long IP
+ in case of FAULT - zero
+ * @return TRUE - IP converted successfully;
+ * FALSE - error condition occurs (e.g. bad format)
+ */
+int
+strtoip(const char *str, char ip[4])
+{
+ char octet[10];
+ int res;
+ unsigned int i = 0, len;
+
+ while (*str != 0) {
+ if (i > 3 || !isdigit(*str))
+ return 0;
+ if (strstr(str, ".") != NULL) {
+ len = (int16_t) (strstr(str, ".") - str);
+ if (len >= 10)
+ return 0;
+ strncpy(octet, str, len);
+ octet[len] = 0;
+ str += len;
+ } else {
+ strncpy(octet, str, 9);
+ octet[9] = 0;
+ str += strlen(octet);
+ }
+ res = strtol(octet, NULL, 10);
+ if ((res > 255) || (res < 0))
+ return 0;
+ ip[i] = (char) res;
+ i++;
+ if (*str == '.')
+ str++;
+ }
+
+ if (i != 4)
+ return 0;
+ return -1;
+}
diff --git a/clients/net-snk/app/netapps/args.h b/clients/net-snk/app/netapps/args.h
new file mode 100644
index 0000000..99c1c78
--- /dev/null
+++ b/clients/net-snk/app/netapps/args.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _ARGS_H
+#define _ARGS_H
+
+const char *get_arg_ptr(const char *, unsigned int);
+unsigned int get_args_count(const char *);
+unsigned int get_arg_length(const char *);
+char *argncpy(const char *, unsigned int, char *, unsigned int);
+int strtoip(const char *, char[4]);
+
+#endif /* _ARGS_H */
diff --git a/clients/net-snk/app/netapps/netapps.h b/clients/net-snk/app/netapps/netapps.h
new file mode 100644
index 0000000..836edd4
--- /dev/null
+++ b/clients/net-snk/app/netapps/netapps.h
@@ -0,0 +1,19 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+int netboot(int argc, char *argv[]);
+int netsave(int argc, char *argv[]);
+int netflash(int argc, char *argv[]);
+int bcmflash(int argc, char *argv[]);
+int mac_sync(int argc, char *argv[]);
+int net_eeprom_version( void );
+int ping(int argc, char *argv[]);
diff --git a/clients/net-snk/app/netapps/netboot.c b/clients/net-snk/app/netapps/netboot.c
new file mode 100644
index 0000000..07a1392
--- /dev/null
+++ b/clients/net-snk/app/netapps/netboot.c
@@ -0,0 +1,502 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/icmp.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netapps/args.h>
+#include <libbootmsg/libbootmsg.h>
+#include <sys/socket.h>
+#include <of.h>
+
+#define IP_INIT_DEFAULT 2
+#define IP_INIT_NONE 0
+#define IP_INIT_BOOTP 1
+#define IP_INIT_DHCP 2
+
+#define DEFAULT_BOOT_RETRIES 600
+#define DEFAULT_TFTP_RETRIES 20
+
+typedef struct {
+ int ip_init;
+ char siaddr[4];
+ char filename[100];
+ char ciaddr[4];
+ char giaddr[4];
+ int bootp_retries;
+ int tftp_retries;
+} obp_tftp_args_t;
+
+/**
+ * Parses a argument string which is given by netload, extracts all
+ * parameters and fills a structure according to this
+ *
+ * Netload-Parameters:
+ * [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries
+ *
+ * @param arg_str string with arguments, seperated with ','
+ * @param obp_tftp_args structure which contains the result
+ * @return none
+ */
+static void parse_args(const char *arg_str, obp_tftp_args_t *obp_tftp_args) {
+ unsigned int argc;
+ char arg_buf[100];
+ char *ptr;
+
+ argc = get_args_count(arg_str);
+
+ // find out if we should use BOOTP or DHCP
+ if(argc==0)
+ obp_tftp_args->ip_init = IP_INIT_DEFAULT;
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(strcasecmp(arg_buf, "bootp") == 0) {
+ obp_tftp_args->ip_init = IP_INIT_BOOTP;
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else if(strcasecmp(arg_buf, "dhcp") == 0) {
+ obp_tftp_args->ip_init = IP_INIT_DHCP;
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else
+ obp_tftp_args->ip_init = IP_INIT_DEFAULT;
+ }
+
+ // find out siaddr
+ if(argc==0)
+ memset(obp_tftp_args->siaddr, 0, 4);
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(strtoip(arg_buf, obp_tftp_args->siaddr)) {
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else if(arg_buf[0] == 0) {
+ memset(obp_tftp_args->siaddr, 0, 4);
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else
+ memset(obp_tftp_args->siaddr, 0, 4);
+ }
+
+ // find out filename
+ if(argc==0)
+ obp_tftp_args->filename[0] = 0;
+ else {
+ argncpy(arg_str, 0, obp_tftp_args->filename, 100);
+ for(ptr = obp_tftp_args->filename; *ptr != 0; ++ptr)
+ if(*ptr == '\\')
+ *ptr = '/';
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+
+ // find out ciaddr
+ if(argc==0)
+ memset(obp_tftp_args->ciaddr, 0, 4);
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(strtoip(arg_buf, obp_tftp_args->ciaddr)) {
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else if(arg_buf[0] == 0) {
+ memset(obp_tftp_args->ciaddr, 0, 4);
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else
+ memset(obp_tftp_args->ciaddr, 0, 4);
+ }
+
+ // find out giaddr
+ if(argc==0)
+ memset(obp_tftp_args->giaddr, 0, 4);
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(strtoip(arg_buf, obp_tftp_args->giaddr)) {
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else if(arg_buf[0] == 0) {
+ memset(obp_tftp_args->giaddr, 0, 4);
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+ else
+ memset(obp_tftp_args->giaddr, 0, 4);
+ }
+
+ // find out bootp-retries
+ if(argc==0)
+ obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(arg_buf[0] == 0)
+ obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
+ else {
+ obp_tftp_args->bootp_retries = strtol(arg_buf, 0, 10);
+ if(obp_tftp_args->bootp_retries < 0)
+ obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
+ }
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+
+ // find out tftp-retries
+ if(argc==0)
+ obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
+ else {
+ argncpy(arg_str, 0, arg_buf, 100);
+ if(arg_buf[0] == 0)
+ obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
+ else {
+ obp_tftp_args->tftp_retries = strtol(arg_buf, 0, 10);
+ if(obp_tftp_args->tftp_retries < 0)
+ obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
+ }
+ arg_str = get_arg_ptr(arg_str, 1);
+ --argc;
+ }
+}
+
+int
+netboot(int argc, char *argv[])
+{
+ char buf[256];
+ int rc;
+ int len = strtol(argv[2], 0, 16);
+ char *buffer = (char *) strtol(argv[1], 0, 16);
+ filename_ip_t fn_ip;
+ int fd_device;
+ tftp_err_t tftp_err;
+ obp_tftp_args_t obp_tftp_args;
+ char null_ip[4] = { 0x00, 0x00, 0x00, 0x00 };
+
+ printf("\n");
+ printf(" Bootloader 1.5 \n");
+ memset(&fn_ip, 0, sizeof(filename_ip_t));
+
+ /***********************************************************
+ *
+ * Initialize network stuff and retrieve boot informations
+ *
+ ***********************************************************/
+
+ /* Wait for link up and get mac_addr from device */
+ for(rc=0; rc<DEFAULT_BOOT_RETRIES; ++rc) {
+ if(rc > 0) {
+ set_timer(TICKS_SEC);
+ while (get_timer() > 0);
+ }
+ fd_device = socket(0, 0, 0, (char *) fn_ip.own_mac);
+ if(fd_device != -2)
+ break;
+ if(getchar() == 27) {
+ fd_device = -2;
+ break;
+ }
+ }
+
+ if (fd_device == -1) {
+ strcpy(buf,"E3000: (net) Could not read MAC address");
+ bootmsg_error(0x3000, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -100;
+ }
+ else if (fd_device == -2) {
+ strcpy(buf,"E3006: (net) Could not initialize network device");
+ bootmsg_error(0x3006, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -101;
+ }
+
+ printf(" Reading MAC address from device: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ fn_ip.own_mac[0], fn_ip.own_mac[1], fn_ip.own_mac[2],
+ fn_ip.own_mac[3], fn_ip.own_mac[4], fn_ip.own_mac[5]);
+
+ if (argc >= 4) {
+ parse_args(argv[3], &obp_tftp_args);
+ if(obp_tftp_args.bootp_retries - rc < DEFAULT_BOOT_RETRIES)
+ obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES;
+ else
+ obp_tftp_args.bootp_retries -= rc;
+ }
+ else {
+ memset(&obp_tftp_args, 0, sizeof(obp_tftp_args_t));
+ obp_tftp_args.ip_init = IP_INIT_DEFAULT;
+ obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES;
+ obp_tftp_args.tftp_retries = DEFAULT_TFTP_RETRIES;
+ }
+ memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4);
+
+ // init network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+
+ // reset of error code
+ rc = 0;
+
+ /* if we still have got all necessary parameters, then we don't
+ need to perform an BOOTP/DHCP-Request */
+ if(memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0
+ && memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0
+ && obp_tftp_args.filename[0] != 0) {
+ memcpy(&fn_ip.server_ip, obp_tftp_args.siaddr, 4);
+
+ // try to get the MAC address of the TFTP server
+ if (net_iptomac(fn_ip.server_ip, fn_ip.server_mac)) {
+ // we got it
+ obp_tftp_args.ip_init = IP_INIT_NONE;
+ }
+ else {
+ // figure out if there is a change to get it somehow else
+ switch(obp_tftp_args.ip_init) {
+ case IP_INIT_NONE:
+ case IP_INIT_BOOTP: // BOOTP doesn't help
+ obp_tftp_args.ip_init = IP_INIT_NONE;
+ rc = -2;
+ break;
+ case IP_INIT_DHCP: // the DHCP server might tell us an
+ // appropriate router and netmask
+ default:
+ break;
+ }
+ }
+ }
+
+ // construction of fn_ip from parameter
+ switch(obp_tftp_args.ip_init) {
+ case IP_INIT_BOOTP:
+ printf(" Requesting IP address via BOOTP: ");
+ // if giaddr in not specified, then we have to identify
+ // the BOOTP server via broadcasts
+ if(memcmp(obp_tftp_args.giaddr, null_ip, 4) == 0) {
+ // don't do this, when using DHCP !!!
+ fn_ip.server_ip = 0xFFFFFFFF;
+ memset(fn_ip.server_mac, 0xff, 6);
+ }
+ // if giaddr is specified, then we have to use this
+ // IP address as proxy to identify the BOOTP server
+ else {
+ memcpy(&fn_ip.server_ip, obp_tftp_args.giaddr, 4);
+ memset(fn_ip.server_mac, 0xff, 6);
+ }
+ rc = bootp(fd_device, &fn_ip, obp_tftp_args.bootp_retries);
+ break;
+ case IP_INIT_DHCP:
+ printf(" Requesting IP address via DHCP: ");
+ rc = dhcp(fd_device, &fn_ip, obp_tftp_args.bootp_retries);
+ break;
+ case IP_INIT_NONE:
+ default:
+ break;
+ }
+
+ if(rc >= 0) {
+ if(memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0
+ && memcmp(obp_tftp_args.ciaddr, &fn_ip.own_ip, 4) != 0)
+ memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4);
+
+ if(memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0
+ && memcmp(obp_tftp_args.siaddr, &fn_ip.server_ip, 4) != 0)
+ memcpy(&fn_ip.server_ip, obp_tftp_args.siaddr, 4);
+
+ // reinit network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+
+ if (!net_iptomac(fn_ip.server_ip, fn_ip.server_mac)) {
+ // printf("\nERROR:\t\t\tCan't obtain TFTP server MAC!\n");
+ rc = -2;
+ }
+ }
+
+ if (rc == -1) {
+ strcpy(buf,"E3001: (net) Could not get IP address");
+ bootmsg_error(0x3001, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -101;
+ }
+
+ printf("%d.%d.%d.%d\n",
+ ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
+ ((fn_ip.own_ip >> 8) & 0xFF), ( fn_ip.own_ip & 0xFF));
+
+ if (rc == -2) {
+ sprintf(buf,
+ "E3002: (net) ARP request to TFTP server "
+ "(%d.%d.%d.%d) failed",
+ ((fn_ip.server_ip >> 24) & 0xFF),
+ ((fn_ip.server_ip >> 16) & 0xFF),
+ ((fn_ip.server_ip >> 8) & 0xFF),
+ ( fn_ip.server_ip & 0xFF));
+ bootmsg_error(0x3002, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -102;
+ }
+ if (rc == -4 || rc == -3) {
+ strcpy(buf,"E3008: (net) Can't obtain TFTP server IP address");
+ bootmsg_error(0x3008, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -107;
+ }
+
+
+ /***********************************************************
+ *
+ * Load file via TFTP into buffer provided by OpenFirmware
+ *
+ ***********************************************************/
+
+ if (obp_tftp_args.filename[0] != 0) {
+ strncpy((char *) fn_ip.filename, obp_tftp_args.filename, sizeof(fn_ip.filename)-1);
+ fn_ip.filename[sizeof(fn_ip.filename)-1] = 0;
+ }
+
+ printf(" Requesting file \"%s\" via TFTP\n", fn_ip.filename);
+
+ // accept at most 20 bad packets
+ // wait at most for 40 packets
+ rc = tftp(fd_device, &fn_ip, (unsigned char *) buffer, len, obp_tftp_args.tftp_retries, &tftp_err);
+
+ if(obp_tftp_args.ip_init == IP_INIT_DHCP)
+ dhcp_send_release();
+
+ if (rc > 0) {
+ printf(" TFTP: Received %s (%d KBytes)\n", fn_ip.filename,
+ rc / 1024);
+ } else if (rc == -1) {
+ bootmsg_error(0x3003, "(net) unknown TFTP error");
+ return -103;
+ } else if (rc == -2) {
+ sprintf(buf,
+ "E3004: (net) TFTP buffer of %d bytes "
+ "is too small for %s",
+ len, fn_ip.filename);
+ bootmsg_error(0x3004, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -104;
+ } else if (rc == -3) {
+ sprintf(buf,"E3009: (net) file not found: %s",
+ fn_ip.filename);
+ bootmsg_error(0x3009, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -108;
+ } else if (rc == -4) {
+ strcpy(buf,"E3010: (net) TFTP access violation");
+ bootmsg_error(0x3010, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -109;
+ } else if (rc == -5) {
+ strcpy(buf,"E3011: (net) illegal TFTP operation");
+ bootmsg_error(0x3011, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -110;
+ } else if (rc == -6) {
+ strcpy(buf, "E3012: (net) unknown TFTP transfer ID");
+ bootmsg_error(0x3012, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -111;
+ } else if (rc == -7) {
+ strcpy(buf, "E3013: (net) no such TFTP user");
+ bootmsg_error(0x3013, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -112;
+ } else if (rc == -8) {
+ strcpy(buf, "E3017: (net) TFTP blocksize negotiation failed");
+ bootmsg_error(0x3017, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -116;
+ } else if (rc == -9) {
+ strcpy(buf,"E3018: (net) file exceeds maximum TFTP transfer size");
+ bootmsg_error(0x3018, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -117;
+ } else if (rc <= -10 && rc >= -15) {
+ sprintf(buf,"E3005: (net) ICMP ERROR \"");
+ switch (rc) {
+ case -ICMP_NET_UNREACHABLE - 10:
+ sprintf(buf+strlen(buf),"net unreachable");
+ break;
+ case -ICMP_HOST_UNREACHABLE - 10:
+ sprintf(buf+strlen(buf),"host unreachable");
+ break;
+ case -ICMP_PROTOCOL_UNREACHABLE - 10:
+ sprintf(buf+strlen(buf),"protocol unreachable");
+ break;
+ case -ICMP_PORT_UNREACHABLE - 10:
+ sprintf(buf+strlen(buf),"port unreachable");
+ break;
+ case -ICMP_FRAGMENTATION_NEEDED - 10:
+ sprintf(buf+strlen(buf),"fragmentation needed and DF set");
+ break;
+ case -ICMP_SOURCE_ROUTE_FAILED - 10:
+ sprintf(buf+strlen(buf),"source route failed");
+ break;
+ default:
+ sprintf(buf+strlen(buf)," UNKNOWN");
+ break;
+ }
+ sprintf(buf+strlen(buf),"\"");
+ bootmsg_error(0x3005, &buf[7]);
+
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -105;
+ } else if (rc == -40) {
+ sprintf(buf,
+ "E3014: (net) TFTP error occurred after "
+ "%d bad packets received",
+ tftp_err.bad_tftp_packets);
+ bootmsg_error(0x3014, &buf[7]);
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -113;
+ } else if (rc == -41) {
+ sprintf(buf,
+ "E3015: (net) TFTP error occurred after "
+ "missing %d responses",
+ tftp_err.no_packets);
+ bootmsg_error(0x3015, &buf[7]);
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -114;
+ } else if (rc == -42) {
+ sprintf(buf,
+ "E3016: (net) TFTP error missing block %d, "
+ "expected block was %d",
+ tftp_err.blocks_missed,
+ tftp_err.blocks_received);
+ bootmsg_error(0x3016, &buf[7]);
+ write_mm_log(buf, strlen(buf), 0x91);
+ return -115;
+ }
+ return rc;
+}
diff --git a/clients/net-snk/app/netapps/netflash.c b/clients/net-snk/app/netapps/netflash.c
new file mode 100644
index 0000000..351fdda
--- /dev/null
+++ b/clients/net-snk/app/netapps/netflash.c
@@ -0,0 +1,190 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/icmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <string.h>
+
+#include <rtas.h>
+
+int netflash(int argc, char * argv[])
+{
+ char buf[256];
+ int rc;
+ int manage_mode = 0;
+ static int len = 0x800000; //max flash size
+ char * buffer = NULL;
+ short arp_failed = 0;
+ filename_ip_t fn_ip;
+ int fd_device;
+ tftp_err_t tftp_err;
+ char * ptr;
+
+ printf("\n Flasher 1.4 \n");
+ memset(&fn_ip, 0, sizeof(filename_ip_t));
+
+ if (argc == 3 && argv[2][0] == '-' && argv[2][1] == 'c' && argv[2][2] == 0)
+ manage_mode = 1;
+ else if (argc == 3 &&
+ argv[2][0] == '-' && argv[2][1] == 'r' && argv[2][2] == 0)
+ manage_mode = 1;
+ else if (argc == 4 &&
+ argv[2][0] == '-' && argv[2][1] == 'f' && argv[2][2] == 0)
+ {
+ manage_mode = 0;
+ buffer = (char *)strtol(argv[1],0,16);
+ if ((long)buffer == -1) {
+ printf(" Bad buffer address. Exiting...\n");
+ return -1;
+ }
+ }
+ else
+ {
+ printf(" Usage: netflash [options] [<filename>]\n");
+ printf(" Options:\n");
+ printf(" -f <filename> flash temporary image\n");
+ printf(" -c commit temporary image\n");
+ printf(" -r reject temporary image\n");
+ printf(" Bad arguments. Exiting...\n\n");
+ return -1;
+ }
+
+ if (manage_mode == 1) {
+ if (argv[2][1] == 99)
+ return rtas_ibm_manage_flash(1);
+ else
+ return rtas_ibm_manage_flash(0);
+ }
+
+ /* Get mac_addr from device */
+ printf(" Reading MAC address from device: ");
+ fd_device = socket(0, 0, 0, (char *) fn_ip.own_mac);
+ if (fd_device == -1) {
+ printf("\nE3000: Could not read MAC address\n");
+ return -100;
+ }
+ else if (fd_device == -2) {
+ printf("\nE3006: Could not initialize network device\n");
+ return -101;
+ }
+
+ printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+ fn_ip.own_mac[0], fn_ip.own_mac[1], fn_ip.own_mac[2],
+ fn_ip.own_mac[3], fn_ip.own_mac[4], fn_ip.own_mac[5]);
+
+ // init network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+ // identify the BOOTP/DHCP server via broadcasts
+ // don't do this, when using DHCP !!!
+ // fn_ip.server_ip = 0xFFFFFFFF;
+ // memset(fn_ip.server_mac, 0xff, 6);
+
+ /* Get ip address for our mac address */
+ printf(" Requesting IP address via DHCP: ");
+ arp_failed = dhcp(fd_device, &fn_ip, 30);
+
+ if(arp_failed >= 0) {
+ // reinit network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+
+ if (!net_iptomac(fn_ip.server_ip, fn_ip.server_mac)) {
+ // printf("\nERROR:\t\t\tCan't obtain TFTP server MAC!\n");
+ arp_failed = -2;
+ }
+ }
+
+ if (arp_failed == -1) {
+ printf("\n DHCP: Could not get ip address\n");
+ return 1;
+ }
+
+ if (arp_failed == -2) {
+ sprintf
+ (buf,"\n ARP request to TFTP server (%d.%d.%d.%d) failed",
+ ((fn_ip.server_ip >> 24) & 0xFF), ((fn_ip.server_ip >> 16) & 0xFF),
+ ((fn_ip.server_ip >> 8) & 0xFF), ( fn_ip.server_ip & 0xFF));
+ return 1;
+ }
+
+ printf("%d.%d.%d.%d\n",
+ ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
+ ((fn_ip.own_ip >> 8) & 0xFF), (fn_ip.own_ip & 0xFF));
+
+ /* Load file via TFTP into buffer provided by OpenFirmware */
+
+ for(ptr = argv[3]; *ptr != 0; ++ptr)
+ if(*ptr == '\\')
+ *ptr = '/';
+
+ printf(" Requesting file \"%s\" via TFTP\n",argv[3]);
+
+ strcpy((char *) fn_ip.filename,argv[3]);
+
+ rc = tftp (fd_device, &fn_ip, (unsigned char *) buffer, len, 20, &tftp_err);
+
+ dhcp_send_release();
+
+ if (rc > 0)
+ {
+ printf (" TFTP: Received %s (%d KBytes)\n", fn_ip.filename, rc/1024);
+ printf (" Now flashing:\n");
+ rc = rtas_ibm_update_flash_64((long long)buffer, rc);
+ return rc;
+ }
+ else if (rc == -1)
+ {
+ printf (" Tftp: Could not load file %s\n", fn_ip.filename);
+ return 1;
+ }
+ else if (rc == -2)
+ {
+ printf (" Tftp: Buffer to small for %s\n", fn_ip.filename);
+ return 1;
+ }
+ else if (rc <= -10 && rc >= -15)
+ {
+ printf("\n ICMP ERROR: Destination unreachable: ");
+ switch(rc) {
+ case -ICMP_NET_UNREACHABLE-10:
+ printf("net unreachable");
+ break;
+ case -ICMP_HOST_UNREACHABLE-10:
+ printf("host unreachable");
+ break;
+ case -ICMP_PROTOCOL_UNREACHABLE-10:
+ printf("protocol unreachable");
+ break;
+ case -ICMP_PORT_UNREACHABLE-10:
+ printf("port unreachable");
+ break;
+ case -ICMP_FRAGMENTATION_NEEDED-10:
+ printf("fragmentation needed and DF set");
+ break;
+ case -ICMP_SOURCE_ROUTE_FAILED-10:
+ printf("source route failed");
+ break;
+ default:
+ printf(" UNKNOWN: this should not happen!");
+ break;
+ }
+ printf("\n");
+ return 1;
+ }
+ else if(rc < 0)
+ printf(" UNKNOWN: rc = %d!", rc);
+
+ return 0;
+}
diff --git a/clients/net-snk/app/netapps/ping.c b/clients/net-snk/app/netapps/ping.c
new file mode 100644
index 0000000..2194768
--- /dev/null
+++ b/clients/net-snk/app/netapps/ping.c
@@ -0,0 +1,198 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <netlib/icmp.h>
+#include <netlib/arp.h>
+#include <netlib/netlib.h>
+#include <sys/socket.h>
+#include <netlib/netbase.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netapps/args.h>
+
+struct ping_args {
+ union {
+ char string[4];
+ unsigned int integer;
+ } server_ip;
+ union {
+ char string[4];
+ unsigned int integer;
+ } client_ip;
+ union {
+ char string[4];
+ unsigned int integer;
+ } gateway_ip;
+ unsigned int timeout;
+};
+
+static void
+usage()
+{
+ printf
+ ("\nping device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout]\n");
+
+}
+
+static int
+parse_args(const char *args, struct ping_args *ping_args)
+{
+ unsigned int argc = get_args_count(args);
+ char buf[64];
+ ping_args->timeout = 10;
+ if (argc == 0)
+ /* at least server-ip has to be specified */
+ return -1;
+ if (argc == 1) {
+ /* probably only server ip is specified */
+ argncpy(args, 0, buf, 64);
+ if (!strtoip(buf, ping_args->server_ip.string))
+ return -1;
+ return 0;
+ }
+ /* get first option from list */
+ argncpy(args, 0, buf, 64);
+ if (!strtoip(buf, ping_args->server_ip.string)) {
+ /* it is not an IP address
+ * therefore it has to be device-args
+ * device-args are not supported and just ignored */
+ args = get_arg_ptr(args, 1);
+ argc--;
+ }
+
+ argncpy(args, 0, buf, 64);
+ if (!strtoip(buf, ping_args->server_ip.string)) {
+ /* this should have been the server IP address */
+ return -1;
+ } else {
+ args = get_arg_ptr(args, 1);
+ if (!--argc)
+ return 0;
+ }
+
+ argncpy(args, 0, buf, 64);
+ if (!strtoip(buf, ping_args->client_ip.string)) {
+ /* this should have been the client (our) IP address */
+ return -1;
+ } else {
+ args = get_arg_ptr(args, 1);
+ if (!--argc)
+ return 0;
+ }
+ argncpy(args, 0, buf, 64);
+ if (!strtoip(buf, ping_args->gateway_ip.string)) {
+ /* this should have been the gateway IP address */
+ return -1;
+ } else {
+ args = get_arg_ptr(args, 1);
+ if (!--argc)
+ return 0;
+ }
+ argncpy(args, 0, buf, 64);
+ ping_args->timeout = strtol(args, 0, 10);
+ return 0;
+}
+
+int
+ping(int argc, char *argv[])
+{
+ short arp_failed = 0;
+ filename_ip_t fn_ip;
+ int fd_device;
+ struct ping_args ping_args;
+
+ memset(&ping_args, 0, sizeof(struct ping_args));
+
+ if (argc == 2) {
+ if (parse_args(argv[1], &ping_args)) {
+ usage();
+ return -1;
+ }
+ } else {
+ usage();
+ return -1;
+ }
+
+ memset(&fn_ip, 0, sizeof(filename_ip_t));
+
+ /* Get mac_addr from device */
+ printf("\n Reading MAC address from device: ");
+ fd_device = socket(0, 0, 0, (char *) fn_ip.own_mac);
+ if (fd_device == -1) {
+ printf("\nE3000: Could not read MAC address\n");
+ return -100;
+ } else if (fd_device == -2) {
+ printf("\nE3006: Could not initialize network device\n");
+ return -101;
+ }
+
+ printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+ fn_ip.own_mac[0], fn_ip.own_mac[1], fn_ip.own_mac[2],
+ fn_ip.own_mac[3], fn_ip.own_mac[4], fn_ip.own_mac[5]);
+
+ // init network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+ // identify the BOOTP/DHCP server via broadcasts
+ // don't do this, when using DHCP !!!
+ // fn_ip.server_ip = 0xFFFFFFFF;
+ // memset(fn_ip.server_mac, 0xff, 6);
+
+ if (!ping_args.client_ip.integer) {
+ /* Get ip address for our mac address */
+ printf(" Requesting IP address via DHCP: ");
+ arp_failed = dhcp(fd_device, &fn_ip, 30);
+
+ if (arp_failed == -1) {
+ printf("\n DHCP: Could not get ip address\n");
+ return -1;
+ }
+
+ } else {
+ memcpy(&fn_ip.own_ip, &ping_args.client_ip.integer, 4);
+ arp_failed = 1;
+ printf(" Own IP address: ");
+ }
+
+ // reinit network stack
+ netbase_init(fd_device, fn_ip.own_mac, fn_ip.own_ip);
+
+ printf("%d.%d.%d.%d\n",
+ ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
+ ((fn_ip.own_ip >> 8) & 0xFF), (fn_ip.own_ip & 0xFF));
+
+ memcpy(&fn_ip.server_ip, &ping_args.server_ip.integer, 4);
+ printf(" Ping to %d.%d.%d.%d ", ((fn_ip.server_ip >> 24) & 0xFF),
+ ((fn_ip.server_ip >> 16) & 0xFF),
+ ((fn_ip.server_ip >> 8) & 0xFF), (fn_ip.server_ip & 0xFF));
+
+
+ if (ping_args.gateway_ip.integer) {
+ if (!arp_getmac(ping_args.gateway_ip.integer, fn_ip.server_mac)) {
+ printf("failed\n");
+ return -1;
+ }
+ } else {
+ if (!arp_getmac(fn_ip.server_ip, fn_ip.server_mac)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+
+ if (!echo_request(fd_device, &fn_ip, ping_args.timeout)) {
+ printf("success\n");
+ return 0;
+ } else {
+ printf("failed\n");
+ return -1;
+ }
+}
diff --git a/clients/net-snk/app/netlib/Makefile b/clients/net-snk/app/netlib/Makefile
new file mode 100644
index 0000000..b88d06c
--- /dev/null
+++ b/clients/net-snk/app/netlib/Makefile
@@ -0,0 +1,31 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS += -I../
+
+OBJS = tftp.o netbase.o arp.o dns.o bootp.o dhcp.o icmp.o
+
+all: netlib.o
+
+netlib.o: $(OBJS)
+ $(LD) $(LDFLAGS) $^ -o $@ -r
+
+clean:
+ $(RM) -f *.o *.a *.i
+
+include $(TOP)/make.depend
diff --git a/clients/net-snk/app/netlib/arp.c b/clients/net-snk/app/netlib/arp.c
new file mode 100644
index 0000000..0792d99
--- /dev/null
+++ b/clients/net-snk/app/netlib/arp.c
@@ -0,0 +1,231 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<<<*/
+
+#include <types.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/arp.h>
+#include <time.h>
+
+/* ARP Message types */
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static void
+arp_send_request(uint32_t dest_ip);
+
+static void
+arp_send_reply(uint32_t src_ip, uint8_t * src_mac);
+
+static void
+fill_arphdr(uint8_t * packet, uint8_t opcode,
+ uint8_t * src_mac, uint32_t src_ip,
+ uint8_t * dest_mac, uint32_t dest_ip);
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static uint8_t ether_packet[ETH_MTU_SIZE];
+static int32_t arp_device_socket = 0;
+static uint8_t arp_own_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint32_t arp_own_ip = 0;
+static uint8_t arp_result_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/**
+ * ARP: Initialize the environment for ARP client.
+ * To perform ARP-requests use the function arp_getmac.
+ *
+ * @param device_socket a socket number used to send and recieve packets
+ * @param own_mac client hardware-address (MAC)
+ * @param own_ip client IPv4 address (e.g. 127.0.0.1)
+ * @see arp_getmac
+ */
+void
+arp_init(int32_t device_socket, uint8_t own_mac[], uint32_t own_ip) {
+ arp_device_socket = device_socket;
+ memcpy(arp_own_mac, own_mac, 6);
+ arp_own_ip = own_ip;
+}
+
+/**
+ * ARP: For given IPv4 retrieves MAC via ARP (makes several attempts)
+ *
+ * @param dest_ip IP for the ARP-request
+ * @param dest_mac In case of SUCCESS stores MAC
+ * In case of FAULT stores zeros (0.0.0.0.0.0).
+ * @return TRUE - MAC successfuly retrieved;
+ * FALSE - error condition occurs.
+ */
+int8_t
+arp_getmac(uint32_t dest_ip, uint8_t dest_mac[]) {
+ // this counter is used so that we abort after 30 ARP request
+ // int32_t i;
+
+ // clearing the result buffer to detect an ARP answer
+ memset(arp_result_mac, 0, 6);
+
+// for(i = 0; i<30; ++i) {
+ arp_send_request(dest_ip);
+
+ // setting up a timer with a timeout of one second
+ set_timer(TICKS_SEC);
+
+ do {
+ receive_ether();
+ if (arp_result_mac[0] != 0 || arp_result_mac[1] != 0 ||
+ arp_result_mac[2] != 0 || arp_result_mac[3] != 0 ||
+ arp_result_mac[4] != 0 || arp_result_mac[5] != 0) {
+ memcpy(dest_mac, arp_result_mac, 6);
+ return 1; // no error
+ }
+ } while (get_timer() > 0);
+
+ // time is up
+// }
+
+// printf("\nGiving up after %d ARP requests\n", i);
+ return 0; // error
+}
+
+/**
+ * ARP: Sends an ARP-request package.
+ * For given IPv4 retrieves MAC via ARP (makes several attempts)
+ *
+ * @param dest_ip IP of the host which MAC should be obtained
+ */
+static void
+arp_send_request(uint32_t dest_ip) {
+ uint8_t dest_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+ memset(ether_packet, 0, sizeof(struct ethhdr) + sizeof(struct arphdr));
+
+ fill_arphdr(&ether_packet[sizeof(struct ethhdr)], ARP_REQUEST,
+ arp_own_mac, arp_own_ip, dest_mac, dest_ip);
+ fill_ethhdr(&ether_packet[0], ETHERTYPE_ARP, arp_own_mac, dest_mac);
+
+ PRINT_SENDING(ether_packet,
+ sizeof(struct ethhdr) + sizeof(struct arphdr));
+
+ send(arp_device_socket, ether_packet,
+ sizeof(struct ethhdr) + sizeof(struct arphdr), 0);
+}
+
+/**
+ * ARP: Sends an ARP-reply package.
+ * This package is used to serve foreign requests (in case IP in
+ * foreign request matches our host IP).
+ *
+ * @param src_ip requester IP address (foreign IP)
+ * @param src_mac requester MAC address (foreign MAC)
+ */
+static void
+arp_send_reply(uint32_t src_ip, uint8_t * src_mac) {
+ memset(ether_packet, 0, sizeof(struct ethhdr) + sizeof(struct arphdr));
+
+ fill_ethhdr(&ether_packet[0], ETHERTYPE_ARP, arp_own_mac, src_mac);
+ fill_arphdr(&ether_packet[sizeof(struct ethhdr)], ARP_REPLY,
+ arp_own_mac, arp_own_ip, src_mac, src_ip);
+
+ PRINT_SENDING(ether_packet,
+ sizeof(struct ethhdr) + sizeof(struct arphdr));
+
+ send(arp_device_socket, ether_packet,
+ sizeof(struct ethhdr) + sizeof(struct arphdr), 0);
+};
+
+/**
+ * ARP: Creates ARP package. Places ARP-header in a packet and fills it
+ * with corresponding information.
+ * <p>
+ * Use this function with similar functions for other network layers
+ * (fill_ethhdr).
+ *
+ * @param packet Points to the place where ARP-header must be placed.
+ * @param opcode Identifies is it request (ARP_REQUEST)
+ * or reply (ARP_REPLY) package.
+ * @param src_mac sender MAC address
+ * @param src_ip sender IP address
+ * @param dest_mac receiver MAC address
+ * @param dest_ip receiver IP address
+ * @see arphdr
+ * @see fill_ethhdr
+ */
+static void
+fill_arphdr(uint8_t * packet, uint8_t opcode,
+ uint8_t * src_mac, uint32_t src_ip,
+ uint8_t * dest_mac, uint32_t dest_ip) {
+ struct arphdr * arph = (struct arphdr *) packet;
+
+ arph -> hw_type = htons(1);
+ arph -> proto_type = htons(ETHERTYPE_IP);
+ arph -> hw_len = 6;
+ arph -> proto_len = 4;
+ arph -> opcode = htons(opcode);
+
+ memcpy(arph->src_mac, src_mac, 6);
+ arph->src_ip = htonl(src_ip);
+ memcpy(arph->dest_mac, dest_mac, 6);
+ arph->dest_ip = htonl(dest_ip);
+}
+
+/**
+ * ARP: Handles ARP-messages according to Receive-handle diagram.
+ * Sets arp_result_mac for given dest_ip (see arp_getmac).
+ *
+ * @param packet ARP-packet to be handled
+ * @param packetsize length of the packet
+ * @return ZERO - packet handled successfully;
+ * NON ZERO - packet was not handled (e.g. bad format)
+ * @see arp_getmac
+ * @see receive_ether
+ * @see arphdr
+ */
+int8_t
+handle_arp(uint8_t * packet, int32_t packetsize) {
+ struct arphdr * arph = (struct arphdr *) packet;
+
+ if (packetsize < sizeof(struct arphdr))
+ return -1; // Packet is too small
+
+ if (arph -> hw_type != htons(1) || arph -> proto_type != htons(ETHERTYPE_IP))
+ return -1; // Unknown hardware or unsupported protocol
+
+ if (arph -> dest_ip != htonl(arp_own_ip))
+ return -1; // receiver IP doesn't match our IP
+
+ switch(htons(arph -> opcode)) {
+ case ARP_REQUEST:
+ // foreign request
+ if(arp_own_ip != 0)
+ arp_send_reply(htonl(arph->src_ip), arph -> src_mac);
+ return 0; // no error
+ case ARP_REPLY:
+ // if it is for us -> fill server MAC
+ if (!memcmp(arp_own_mac, arph -> dest_mac, 6))
+ memcpy(arp_result_mac, arph -> src_mac, 6);
+ return 0; // no error
+ default:
+ break;
+ }
+ return -1; // Invalid message type
+}
diff --git a/clients/net-snk/app/netlib/arp.h b/clients/net-snk/app/netlib/arp.h
new file mode 100644
index 0000000..c26c62a
--- /dev/null
+++ b/clients/net-snk/app/netlib/arp.h
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/* Initialize the environment for ARP client. */
+extern void arp_init(int32_t device_socket, uint8_t own_mac[], uint32_t own_ip);
+
+/* For given IPv4 retrieves MAC via ARP */
+extern int8_t arp_getmac(uint32_t dest_ip, uint8_t dest_mac[]);
+
+/* Handles ARP-packets, which are detected by receive_ether. */
+extern int8_t handle_arp(uint8_t * packet, int32_t packetsize);
diff --git a/clients/net-snk/app/netlib/bootp.c b/clients/net-snk/app/netlib/bootp.c
new file mode 100644
index 0000000..ce2ae5f
--- /dev/null
+++ b/clients/net-snk/app/netlib/bootp.c
@@ -0,0 +1,254 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netlib/netlib.h>
+#include <time.h>
+
+#define DEBUG 0
+
+void
+print_ip(char *ip)
+{
+ printf("%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+}
+
+
+/* IP header checksum calculation */
+unsigned short
+checksum(unsigned short *packet, int words)
+{
+ unsigned long checksum;
+ for (checksum = 0; words > 0; words--)
+ checksum += *packet++;
+ checksum = (checksum >> 16) + (checksum & 0xffff);
+ checksum += (checksum >> 16);
+ return ~checksum;
+}
+
+
+static int
+send_bootp(int boot_device, filename_ip_t * fn_ip)
+{
+ int i;
+ unsigned int packetsize =
+ sizeof(struct iphdr) + sizeof(struct ethhdr) +
+ sizeof(struct udphdr) + sizeof(struct btphdr);
+ unsigned char packet[packetsize];
+ struct ethhdr *ethh;
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct btphdr *btph;
+
+ ethh = (struct ethhdr *) packet;
+ iph = (struct iphdr *) ((void *) ethh + sizeof(struct ethhdr));
+ udph = (struct udphdr *) ((void *) iph + sizeof(struct iphdr));
+ btph = (struct btphdr *) ((void *) udph + sizeof(struct udphdr));
+
+ memset(packet, 0, packetsize);
+
+ memcpy(ethh->src_mac, fn_ip->own_mac, 6);
+ memcpy(ethh->dest_mac, fn_ip->server_mac, 6);
+
+ ethh->type = htons(ETHERTYPE_IP);
+ iph->ip_hlv = 0x45;
+ iph->ip_tos = 0;
+ iph->ip_len = htons(packetsize - sizeof(struct ethhdr));
+ iph->ip_id = htons(54321);
+ iph->ip_off = 0;
+ iph->ip_ttl = 255;
+ iph->ip_p = IPTYPE_UDP;
+ iph->ip_src = fn_ip->own_ip;
+ iph->ip_dst = fn_ip->server_ip;
+ iph->ip_sum =
+ checksum((unsigned short *) iph, sizeof(struct iphdr) >> 1);
+
+ udph->uh_sport = htons(UDPPORT_BOOTPC);
+ udph->uh_dport = htons(UDPPORT_BOOTPS);
+ udph->uh_ulen = htons(sizeof(struct udphdr) + sizeof(struct btphdr));
+ udph->uh_sum = 0;
+ btph->op = 1;
+ btph->htype = 1;
+ btph->hlen = 6;
+ strcpy((char *) btph->file, "bla");
+ memcpy(btph->chaddr, ethh->src_mac, 6);
+
+#if DEBUG
+ printf("Sending packet\n");
+ printf("Packet is ");
+ for (i = 0; i < packetsize; i++)
+ printf(" %02x", packet[i]);
+ printf(".\n");
+#endif
+
+ i = send(boot_device, packet, packetsize, 0);
+#if DEBUG
+ printf("%d bytes transmitted over socket.\n", i);
+#endif
+
+ return 0;
+}
+
+
+static int
+receive_bootp(int boot_device, filename_ip_t * fn_ip)
+{
+ int len, old_sum;
+ unsigned int packetsize = 2000;
+ unsigned char packet[packetsize];
+ struct ethhdr *ethh;
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct btphdr *btph;
+
+ ethh = (struct ethhdr *) packet;
+ iph = (struct iphdr *) (packet + sizeof(struct ethhdr));
+ udph = (struct udphdr *) ((void *) iph + sizeof(struct iphdr));
+ btph = (struct btphdr *) ((void *) udph + sizeof(struct udphdr));
+
+ memset(packet, 0, packetsize);
+
+ /* setting up a timer with a timeout of one second */
+ set_timer(TICKS_SEC);
+
+ do {
+
+ /* let's receive a packet */
+ len = recv(boot_device, packet, packetsize, 0);
+
+#if DEBUG
+ int j;
+ printf("%d bytes received, %d expected \n", len, packetsize);
+ if (len == 346) {
+ printf("Rec packet\n");
+ printf("Packet is ");
+ for (j = 0; j < len; j++) {
+ if (j % 16 == 0)
+ printf("\n");
+ printf(" %02x", packet[j]);
+ }
+ printf(".\n");
+ }
+#endif
+ /* check if the ip checksum is correct */
+ old_sum = iph->ip_sum;
+ iph->ip_sum = 0x00;
+ if (old_sum !=
+ checksum((unsigned short *) iph, sizeof(struct iphdr) >> 1))
+ /* checksum failed */
+ continue;
+ /* is it a udp packet */
+ if (iph->ip_p != IPTYPE_UDP)
+ continue;
+ /* check if the source port and destination port and the packet
+ * say that it is a bootp answer */
+ if (udph->uh_dport != htons(UDPPORT_BOOTPC) || udph->uh_sport != htons(UDPPORT_BOOTPS))
+ continue;
+ /* check if it is a Boot Reply */
+ if (btph->op != 2)
+ continue;
+ /* Comparing our mac address with the one in the bootp reply */
+ if (memcmp(fn_ip->own_mac, btph->chaddr, ETH_ALEN))
+ continue;
+
+ fn_ip->own_ip = btph->yiaddr;
+ fn_ip->server_ip = btph->siaddr;
+ memcpy(fn_ip->server_mac, &ethh->src_mac, 6);
+ strcpy((char *) fn_ip->filename, (char *) btph->file);
+
+#if DEBUG
+ printf("\nThese are the details of the bootp reply:\n");
+ printf("Our IP address: ");
+ print_ip(&fn_ip->own_ip);
+ printf("Next server IP address: ");
+ print_ip(&fn_ip->server_ip);
+ printf("Boot file name: %s\n", btph->file);
+ printf("Packet is: %s\n", btph->file);
+ for (j = 0; j < len; j++) {
+ if (j % 16 == 0)
+ printf("\n");
+ printf(" %02x", packet[j]);
+ }
+ printf(".\n");
+ printf("fn_ip->own_mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ fn_ip->own_mac[0], fn_ip->own_mac[1], fn_ip->own_mac[2],
+ fn_ip->own_mac[3], fn_ip->own_mac[4], fn_ip->own_mac[5]);
+ printf("Header ethh->dest_mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ethh->dest_mac[0], ethh->dest_mac[1], ethh->dest_mac[2],
+ ethh->dest_mac[3], ethh->dest_mac[4], ethh->dest_mac[5]);
+ printf("Header ethh->src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ethh->src_mac[0], ethh->src_mac[1], ethh->src_mac[2],
+ ethh->src_mac[3], ethh->src_mac[4], ethh->src_mac[5]);
+ printf("Header ethh->typ: %x\n",ethh->type);
+ printf("Header iph->ip_hlv: %x\n",iph->ip_hlv);
+ printf("Header iph->ip_len: %x\n",iph->ip_len);
+ printf("Header iph->ip_id: %x\n",iph->ip_id);
+ printf("Header iph->ip_off: %x\n",iph->ip_off);
+ printf("Header iph->ip_ttl: %x\n",iph->ip_ttl);
+ printf("Header iph->ip_p: %x\n",iph->ip_p);
+ printf("Header iph->ip_sum: %x\n",iph->ip_sum);
+ printf("Header iph->ip_src: %x\n",iph->ip_src);
+ printf("Header iph->ip_dst: %x\n",iph->ip_dst);
+
+ printf("Header btph->op: %x\n",btph->op);
+ printf("Header btph->htype: %x\n",btph->htype);
+ printf("Header btph->hlen: %x\n",btph->hlen);
+ printf("Header btph->hops: %x\n",btph->hops);
+ printf("Header btph->xid: %x\n",btph->xid);
+ printf("Header btph->secs: %x\n",btph->secs);
+ printf("Header btph->ciaddr: %x\n",btph->ciaddr);
+ printf("Header btph->yiaddr: %x\n",btph->yiaddr);
+ printf("Header btph->siaddr: %x\n",btph->siaddr);
+ printf("Header btph->giaddr: %x\n",btph->giaddr);
+
+ printf("Header btph->chaddr: %02x:%02x:%02x:%02x:%02x:%02x:\n",
+ btph->chaddr[0], btph->chaddr[1], btph->chaddr[2],
+ btph->chaddr[3], btph->chaddr[4], btph->chaddr[5]);
+
+
+#endif
+ return 0;
+
+ /* only do this for the time specified during set_timer() */
+ } while (get_timer() > 0);
+ return -1;
+}
+
+
+int
+bootp(int boot_device, filename_ip_t * fn_ip, unsigned int retries)
+{
+ int i = (int) retries+1;
+ fn_ip->own_ip = 0;
+
+ printf(" ");
+
+ do {
+ printf("\b\b%02d", i);
+ if (!i--) {
+ printf("\nGiving up after %d bootp requests\n",
+ retries+1);
+ return -1;
+ }
+ send_bootp(boot_device, fn_ip);
+ /* if the timer in receive_bootp expired it will return
+ * -1 and we will just send another bootp request just
+ * in case the previous one was lost. And because we don't
+ * trust the network cable we keep on doing this 30 times */
+ } while (receive_bootp(boot_device, fn_ip) != 0);
+ printf("\b\b\b");
+ return 0;
+}
diff --git a/clients/net-snk/app/netlib/dhcp.c b/clients/net-snk/app/netlib/dhcp.c
new file mode 100644
index 0000000..8aa995e
--- /dev/null
+++ b/clients/net-snk/app/netlib/dhcp.c
@@ -0,0 +1,1049 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/** \file dhcp.c <pre>
+ * **************** State-transition diagram for DHCP client *************
+ *
+ * +---------+ Note: DHCP-server msg / DHCP-client msg
+ * | INIT |
+ * +---------+
+ * |
+ * | - / Discover
+ * V
+ * +---------+
+ * | SELECT | Timeout
+ * +---------+ |
+ * | |
+ * | Offer / Request |
+ * | |
+ * V V
+ * +---------+ NACK / - ***********
+ * | REQUEST | ----------------> * FAULT *
+ * +---------+ ***********
+ * |
+ * | ACK / - ***********
+ * +----------------------> * SUCCESS *
+ * ***********
+ *
+ * ************************************************************************
+ * </pre> */
+
+
+/*>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<<<*/
+
+#include <types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/arp.h>
+#include <netlib/dns.h>
+#include <time.h>
+
+/* DHCP Message Types */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNACK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/* DHCP Option Codes */
+#define DHCP_MASK 1
+#define DHCP_ROUTER 3
+#define DHCP_DNS 6
+#define DHCP_REQUESTED_IP 50
+#define DHCP_OVERLOAD 52
+#define DHCP_MSG_TYPE 53
+#define DHCP_SERVER_ID 54
+#define DHCP_REQUEST_LIST 55
+#define DHCP_TFTP_SERVER 66
+#define DHCP_BOOTFILE 67
+#define DHCP_ENDOPT 0xFF
+#define DHCP_PADOPT 0x00
+
+/* "file/sname" overload option values */
+#define DHCP_OVERLOAD_FILE 1
+#define DHCP_OVERLOAD_SNAME 2
+#define DHCP_OVERLOAD_BOTH 3
+
+/* DHCP states codes */
+#define DHCP_STATE_SELECT 1
+#define DHCP_STATE_REQUEST 2
+#define DHCP_STATE_SUCCESS 3
+#define DHCP_STATE_FAULT 4
+
+static uint8_t dhcp_magic[] = {0x63, 0x82, 0x53, 0x63};
+/**< DHCP_magic is a cookie, that identifies DHCP options (see RFC 2132) */
+
+/** \struct dhcp_options_t
+ * This structure is used to fill options in DHCP-msg during transmitting
+ * or to retrieve options from DHCP-msg during receiving.
+ * <p>
+ * If flag[i] == TRUE then field for i-th option retains valid value and
+ * information from this field may retrived (in case of receiving) or will
+ * be transmitted (in case of transmitting).
+ *
+ */
+typedef struct {
+ uint8_t flag[256]; /**< Show if corresponding opt. is valid */
+ uint8_t request_list[256]; /**< o.55 If i-th member is TRUE, then i-th
+ option will be requested from server */
+ uint32_t server_ID; /**< o.54 Identifies DHCP-server */
+ uint32_t requested_IP; /**< o.50 Must be filled in DHCP-Request */
+ uint32_t dns_IP; /**< o. 6 DNS IP */
+ uint32_t router_IP; /**< o. 3 Router IP */
+ uint32_t subnet_mask; /**< o. 1 Subnet mask */
+ uint8_t msg_type; /**< o.53 DHCP-message type */
+ uint8_t overload; /**< o.52 Overload sname/file fields */
+ int8_t tftp_server[256]; /**< o.66 TFTP server name */
+ int8_t bootfile[256]; /**< o.67 Boot file name */
+} dhcp_options_t;
+
+/** Stores state of DHCP-client (refer to State-transition diagram) */
+static uint8_t dhcp_state;
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static int32_t
+dhcp_attempt(void);
+
+static int32_t
+dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct);
+
+static int32_t
+dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
+ dhcp_options_t * opt_struct);
+
+static int8_t
+dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
+ uint8_t src_options[], uint32_t src_len);
+
+static int8_t
+dhcp_find_option(uint8_t options[], uint32_t len,
+ uint8_t op_code, uint32_t * op_offset);
+
+static void
+dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
+ uint8_t * new_option);
+
+static void
+dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
+ uint32_t dst_offset, uint8_t * new_option);
+
+static void
+dhcp_send_discover(void);
+
+static void
+dhcp_send_request(void);
+
+static uint8_t
+strtoip(int8_t * str, uint32_t * ip);
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static uint8_t ether_packet[ETH_MTU_SIZE];
+static int32_t dhcp_device_socket = 0;
+static uint8_t dhcp_own_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint32_t dhcp_own_ip = 0;
+static uint8_t dhcp_server_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint32_t dhcp_server_ip = 0;
+static uint32_t dhcp_siaddr_ip = 0;
+static int8_t dhcp_filename[256];
+static int8_t dhcp_tftp_name[256];
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/**
+ * DHCP: Obtains IP and configuration info from DHCP server
+ * (makes several attempts).
+ *
+ * @param boot_device a socket number used to send and recieve packets
+ * @param fn_ip contains the following configuration information:
+ * client MAC, client IP, TFTP-server MAC,
+ * TFTP-server IP, Boot file name
+ * @return ZERO - IP and configuration info obtained;
+ * NON ZERO - error condition occurs.
+ */
+int32_t
+dhcp(int32_t boot_device, filename_ip_t * fn_ip, unsigned int retries) {
+ int i = (int) retries+1;
+
+ uint8_t dhcp_tftp_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint32_t dhcp_tftp_ip = 0;
+ strcpy((char *) dhcp_filename, "");
+ strcpy((char *) dhcp_tftp_name, "");
+
+ dhcp_device_socket = boot_device;
+ memcpy(dhcp_own_mac, fn_ip -> own_mac, 6);
+
+ printf(" ");
+
+ do {
+ printf("\b\b\b%03d", i-1);
+ if (getchar() == 27) {
+ printf("\nAborted\n");
+ return -1;
+ }
+ if (!--i) {
+ printf("\nGiving up after %d DHCP requests\n", retries);
+ return -1;
+ }
+ } while (!dhcp_attempt());
+ printf("\b\b\b\b");
+
+ if (fn_ip->own_ip) {
+ dhcp_own_ip = fn_ip->own_ip;
+ }
+ if (fn_ip->server_ip) {
+ dhcp_siaddr_ip = fn_ip->server_ip;
+ }
+ if(fn_ip->filename[0] != 0) {
+ strcpy((char *) dhcp_filename, (char *) fn_ip->filename);
+ }
+
+ // Information from DHCP server were obtained
+ PRINT_MSGIP("\n\nClient IP:\t\t", dhcp_own_ip);
+ PRINT_MSGMAC("Client MAC:\t\t", dhcp_own_mac);
+ PRINT_MSGIP("\nDHCP Server IP:\t\t", dhcp_server_ip);
+
+ // Obtain DHCP-server MAC to be able to send dhcp_release
+ net_iptomac(dhcp_server_ip, dhcp_server_mac);
+ PRINT_MSGMAC("DHCP Server MAC:\t", dhcp_server_mac);
+
+ // TFTP SERVER
+ if (!strlen((char *) dhcp_tftp_name)) {
+ if (!dhcp_siaddr_ip) {
+ // ERROR: TFTP name is not presented
+ return -3;
+ }
+
+ // take TFTP-ip from siaddr field
+ dhcp_tftp_ip = dhcp_siaddr_ip;
+ }
+ else {
+ // TFTP server defined by its name
+ NET_DEBUG_PRINTF("\nTFTP server name:\t%s\n", dhcp_tftp_name);
+ if (!strtoip(dhcp_tftp_name, &(dhcp_tftp_ip))) {
+ if (!dns_get_ip(dhcp_tftp_name, &(dhcp_tftp_ip))) {
+ // DNS error - can't obtain TFTP-server name
+ // Use TFTP-ip from siaddr field, if presented
+ if (dhcp_siaddr_ip) {
+ dhcp_tftp_ip = dhcp_siaddr_ip;
+ }
+ else {
+ // ERROR: Can't obtain TFTP server IP
+ return -4;
+ }
+ }
+ }
+ }
+
+ PRINT_MSGIP("\nTFTP server IP:\t\t", dhcp_tftp_ip);
+ if (!net_iptomac(dhcp_tftp_ip, dhcp_tftp_mac)) {
+ // printf("\nERROR:\t\t\tCan't obtain TFTP server MAC!\n");
+ return -2;
+ }
+
+ PRINT_MSGMAC("TFTP server MAC:\t", dhcp_tftp_mac);
+
+// // Bootfile name
+// if (!strlen(dhcp_filename)) {
+// // ERROR: Bootfile name is not presented
+// return -5;
+// }
+
+ NET_DEBUG_PRINTF("\nBootfile name:\t\t%s\n\n", dhcp_filename);
+
+ // Store configuration info into filename_ip strucutre
+ fn_ip -> own_ip = dhcp_own_ip;
+ fn_ip -> server_ip = dhcp_tftp_ip;
+ memcpy(fn_ip -> server_mac, dhcp_tftp_mac, 6);
+ strcpy((char *) fn_ip -> filename, (char *) dhcp_filename);
+
+ return 0;
+}
+
+/**
+ * DHCP: Tries o obtain DHCP parameters, refer to state-transition diagram
+ */
+static int32_t
+dhcp_attempt(void) {
+ int sec;
+
+ // Send DISCOVER message and switch DHCP-client to SELECT state
+ dhcp_send_discover();
+
+ dhcp_state = DHCP_STATE_SELECT;
+
+ // setting up a timer with a timeout of two seconds
+ for (sec = 0; sec < 2; sec++) {
+ set_timer(TICKS_SEC);
+ do {
+ receive_ether();
+
+ // Wait until client will switch to Final state or Timeout occurs
+ switch (dhcp_state) {
+ case DHCP_STATE_SUCCESS :
+ return 1;
+ case DHCP_STATE_FAULT :
+ return 0;
+ }
+ } while (get_timer() > 0);
+ }
+
+ // timeout
+ return 0;
+}
+
+/**
+ * DHCP: Supplements DHCP-message with options stored in structure.
+ * For more information about option coding see dhcp_options_t.
+ *
+ * @param opt_field Points to the "vend" field of DHCP-message
+ * (destination)
+ * @param opt_struct this structure stores info about the options wich
+ * will be added to DHCP-message (source)
+ * @return TRUE - options packed;
+ * FALSE - error condition occurs.
+ * @see dhcp_options_t
+ */
+static int32_t
+dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct) {
+ uint8_t * options = opt_field;
+ uint16_t i, sum; // used to define is any options set
+
+ // magic
+ memcpy(options, dhcp_magic, 4);
+ options += 4;
+
+ // fill message type
+ switch (opt_struct -> msg_type) {
+ case DHCPDISCOVER :
+ case DHCPREQUEST :
+ case DHCPDECLINE :
+ case DHCPINFORM :
+ case DHCPRELEASE :
+ options[0] = DHCP_MSG_TYPE;
+ options[1] = 1;
+ options[2] = opt_struct -> msg_type;
+ options += 3;
+ break;
+ default :
+ return 0; // Unsupported DHCP-message
+ }
+
+ if (opt_struct -> overload) {
+ options[0] = DHCP_OVERLOAD;
+ options[1] = 0x01;
+ options[2] = opt_struct -> overload;
+ options +=3;
+ }
+
+ if (opt_struct -> flag[DHCP_REQUESTED_IP]) {
+ options[0] = DHCP_REQUESTED_IP;
+ options[1] = 0x04;
+ * (uint32_t *) (options + 2) = htonl (opt_struct -> requested_IP);
+ options +=6;
+ }
+
+ if (opt_struct -> flag[DHCP_SERVER_ID]) {
+ options[0] = DHCP_SERVER_ID;
+ options[1] = 0x04;
+ * (uint32_t *) (options + 2) = htonl (opt_struct -> server_ID);
+ options +=6;
+ }
+
+ sum = 0;
+ for (i = 0; i < 256; i++)
+ sum += opt_struct -> request_list[i];
+
+ if (sum) {
+ options[0] = DHCP_REQUEST_LIST;
+ options[1] = sum;
+ options += 2;
+ for (i = 0; i < 256; i++) {
+ if (opt_struct -> request_list[i]) {
+ options[0] = i; options++;
+ }
+ }
+ }
+
+ if (opt_struct -> flag[DHCP_TFTP_SERVER]) {
+ options[0] = DHCP_TFTP_SERVER;
+ options[1] = strlen((char *) opt_struct -> tftp_server) + 1;
+ memcpy(options + 2, opt_struct -> tftp_server, options[1]);
+ options += options[1] + 2;
+ }
+
+ if (opt_struct -> flag[DHCP_BOOTFILE]) {
+ options[0] = DHCP_BOOTFILE;
+ options[1] = strlen((char *) opt_struct -> bootfile) + 1;
+ memcpy(options + 2, opt_struct -> bootfile, options[1]);
+ options += options[1] + 2;
+ }
+
+ // end options
+ options[0] = 0xFF;
+ options++;
+
+ return 1;
+}
+
+/**
+ * DHCP: Extracts encoded options from DHCP-message into the structure.
+ * For more information about option coding see dhcp_options_t.
+ *
+ * @param opt_field Points to the "options" field of DHCP-message
+ * (source).
+ * @param opt_len Length of "options" field.
+ * @param opt_struct this structure stores info about the options wich
+ * was extracted from DHCP-message (destination).
+ * @return TRUE - options extracted;
+ * FALSE - error condition occurs.
+ * @see dhcp_options_t
+ */
+static int32_t
+dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len,
+ dhcp_options_t * opt_struct) {
+ int32_t offset = 0;
+
+ memset(opt_struct, 0, sizeof(dhcp_options_t));
+
+ // magic
+ if (memcmp(opt_field, dhcp_magic, 4)) {
+ return 0;
+ }
+
+ offset += 4;
+ while (offset < opt_len) {
+ opt_struct -> flag[opt_field[offset]] = 1;
+ switch(opt_field[offset]) {
+ case DHCP_OVERLOAD :
+ opt_struct -> overload = opt_field[offset + 2];
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_REQUESTED_IP :
+ opt_struct -> requested_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_MASK :
+ opt_struct -> flag[DHCP_MASK] = 1;
+ opt_struct -> subnet_mask = htonl(* (uint32_t *) (opt_field + offset + 2));
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_DNS :
+ opt_struct -> flag[DHCP_DNS] = 1;
+ opt_struct -> dns_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_ROUTER :
+ opt_struct -> flag[DHCP_ROUTER] = 1;
+ opt_struct -> router_IP = htonl(* (uint32_t *) (opt_field + offset + 2));
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_MSG_TYPE :
+ if ((opt_field[offset + 2] > 0) && (opt_field[offset + 2] < 9))
+ opt_struct -> msg_type = opt_field[offset + 2];
+ else
+ return 0;
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_SERVER_ID :
+ opt_struct -> server_ID = htonl(* (uint32_t *) (opt_field + offset + 2));
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_TFTP_SERVER :
+ memcpy(opt_struct -> tftp_server, opt_field + offset + 2, opt_field[offset + 1]);
+ (opt_struct -> tftp_server)[opt_field[offset + 1]] = 0;
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_BOOTFILE :
+ memcpy(opt_struct -> bootfile, opt_field + offset + 2, opt_field[offset + 1]);
+ (opt_struct -> bootfile)[opt_field[offset + 1]] = 0;
+ offset += 2 + opt_field[offset + 1];
+ break;
+
+ case DHCP_PADOPT :
+ offset++;
+ break;
+
+ case DHCP_ENDOPT : // End of options
+ return 1;
+
+ default :
+ offset += 2 + opt_field[offset + 1]; // Unsupported opt. - do nothing
+ }
+ }
+ if (offset == opt_len)
+ return 1; // options finished without 0xFF
+
+ return 0;
+}
+
+/**
+ * DHCP: Appends information from source "options" into dest "options".
+ * This function is used to support "file/sname" overloading.
+ *
+ * @param dst_options destanation "options" field
+ * @param dst_len size of dst_options (modified by this function)
+ * @param src_options source "options" field
+ * @param src_len size of src_options
+ * @return TRUE - options merged;
+ * FALSE - error condition occurs.
+ */
+static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len,
+ uint8_t src_options[], uint32_t src_len) {
+ int32_t dst_offset, src_offset = 0;
+
+ // remove ENDOPT if presented
+ if (dhcp_find_option(dst_options, * dst_len, DHCP_ENDOPT, (uint32_t *) &dst_offset))
+ * dst_len = dst_offset;
+
+ while (src_offset < src_len) {
+ switch(src_options[src_offset]) {
+ case DHCP_PADOPT:
+ src_offset++;
+ break;
+ case DHCP_ENDOPT:
+ return 1;
+ default:
+ if (dhcp_find_option(dst_options, * dst_len,
+ src_options[src_offset],
+ (uint32_t *) &dst_offset)) {
+ dhcp_combine_option(dst_options, dst_len,
+ dst_offset,
+ (uint8_t *) src_options +
+ src_offset);
+ }
+ else {
+ dhcp_append_option(dst_options, dst_len, src_options + src_offset);
+ }
+ src_offset += 2 + src_options[src_offset + 1];
+ }
+ }
+
+ if (src_offset == src_len)
+ return 1;
+ return 0;
+}
+
+/**
+ * DHCP: Finds given occurence of the option with the given code (op_code)
+ * in "options" field of DHCP-message.
+ *
+ * @param options "options" field of DHCP-message
+ * @param len length of the "options" field
+ * @param op_code code of the option to find
+ * @param op_offset SUCCESS - offset to an option occurence;
+ * FAULT - offset is set to zero.
+ * @return TRUE - option was find;
+ * FALSE - option wasn't find.
+ */
+static int8_t dhcp_find_option(uint8_t options[], uint32_t len,
+ uint8_t op_code, uint32_t * op_offset) {
+ uint32_t srch_offset = 0;
+ * op_offset = 0;
+
+ while (srch_offset < len) {
+ if (options[srch_offset] == op_code) {
+ * op_offset = srch_offset;
+ return 1;
+ }
+ if (options[srch_offset] == DHCP_ENDOPT)
+ return 0;
+
+ if (options[srch_offset] == DHCP_PADOPT)
+ srch_offset++;
+ else
+ srch_offset += 2 + options[srch_offset + 1];
+ }
+ return 0;
+}
+
+/**
+ * DHCP: Appends new option from one list (src) into the tail
+ * of another option list (dst)
+ *
+ * @param dst_options "options" field of DHCP-message
+ * @param dst_len length of the "options" field (modified)
+ * @param new_option points to an option in another list (src)
+ */
+static void
+dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len,
+ uint8_t * new_option) {
+ memcpy(dst_options + ( * dst_len), new_option, 2 + (* (new_option + 1)));
+ * dst_len += 2 + *(new_option + 1);
+}
+
+/**
+ * DHCP: This function is used when options with the same code are
+ * presented in both merged lists. In this case information
+ * about the option from one list (src) is combined (complemented)
+ * with information about the option in another list (dst).
+ *
+ * @param dst_options "options" field of DHCP-message
+ * @param dst_len length of the "options" field (modified)
+ * @param dst_offset offset of the option from beggining of the list
+ * @param new_option points to an option in another list (src)
+ */
+static void
+dhcp_combine_option(uint8_t dst_options[], uint32_t * dst_len,
+ uint32_t dst_offset, uint8_t * new_option) {
+
+ uint8_t tmp_buffer[1024]; // use to provide safe memcpy
+ uint32_t tail_len;
+
+ // move all subsequent options (allocate size for additional info)
+ tail_len = (* dst_len) - dst_offset - 2 - dst_options[dst_offset + 1];
+
+ memcpy(tmp_buffer, dst_options + (* dst_len) - tail_len, tail_len);
+ memcpy(dst_options + (* dst_len) - tail_len + (* (new_option + 1)),
+ tmp_buffer, tail_len);
+
+ // add new_content to option
+ memcpy(dst_options + (* dst_len) - tail_len, new_option + 2,
+ * (new_option + 1));
+ dst_options[dst_offset + 1] += * (new_option + 1);
+
+ // correct dst_len
+ * dst_len += * (new_option + 1);
+}
+
+/**
+ * DHCP: Sends DHCP-Discover message. Looks for DHCP servers.
+ */
+static void
+dhcp_send_discover(void) {
+ uint32_t packetsize = sizeof(struct ethhdr) + sizeof(struct iphdr) +
+ sizeof(struct udphdr) + sizeof(struct btphdr);
+ struct btphdr *btph;
+ uint8_t dest_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ dhcp_options_t opt;
+
+ memset(ether_packet, 0, packetsize);
+
+ btph = (struct btphdr *) (&ether_packet[sizeof(struct ethhdr) +
+ sizeof(struct iphdr) + sizeof(struct udphdr)]);
+
+ btph -> op = 1;
+ btph -> htype = 1;
+ btph -> hlen = 6;
+ memcpy(btph -> chaddr, dhcp_own_mac, 6);
+
+ memset(&opt, 0, sizeof(dhcp_options_t));
+
+ opt.msg_type = DHCPDISCOVER;
+
+ opt.request_list[DHCP_MASK] = 1;
+ opt.request_list[DHCP_DNS] = 1;
+ opt.request_list[DHCP_ROUTER] = 1;
+ opt.request_list[DHCP_TFTP_SERVER] = 1;
+ opt.request_list[DHCP_BOOTFILE] = 1;
+
+ dhcp_encode_options(btph -> vend, &opt);
+
+ fill_udphdr(&ether_packet[sizeof(struct ethhdr) + sizeof(struct iphdr)],
+ sizeof(struct btphdr) + sizeof(struct udphdr),
+ UDPPORT_BOOTPC, UDPPORT_BOOTPS);
+ fill_iphdr(&ether_packet[sizeof(struct ethhdr)], sizeof(struct btphdr) +
+ sizeof(struct udphdr) + sizeof(struct iphdr),
+ IPTYPE_UDP, dhcp_own_ip, 0xFFFFFFFF);
+ fill_ethhdr(&ether_packet[0], ETHERTYPE_IP, dhcp_own_mac, dest_mac);
+
+ PRINT_SENDING(ether_packet, packetsize);
+
+ send(dhcp_device_socket, ether_packet, packetsize, 0);
+}
+
+/**
+ * DHCP: Sends DHCP-Request message. Asks for acknowledgment to occupy IP.
+ */
+static void
+dhcp_send_request(void) {
+ uint32_t packetsize = sizeof(struct ethhdr) + sizeof(struct iphdr) +
+ sizeof(struct udphdr) + sizeof(struct btphdr);
+ struct btphdr *btph;
+ uint8_t dest_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ dhcp_options_t opt;
+
+ memset(ether_packet, 0, packetsize);
+
+ btph = (struct btphdr *) (&ether_packet[sizeof(struct ethhdr) +
+ sizeof(struct iphdr) + sizeof(struct udphdr)]);
+
+ btph -> op = 1;
+ btph -> htype = 1;
+ btph -> hlen = 6;
+ memcpy(btph -> chaddr, dhcp_own_mac, 6);
+
+ memset(&opt, 0, sizeof(dhcp_options_t));
+
+ opt.msg_type = DHCPREQUEST;
+ memcpy(&(opt.requested_IP), &dhcp_own_ip, 4);
+ opt.flag[DHCP_REQUESTED_IP] = 1;
+ memcpy(&(opt.server_ID), &dhcp_server_ip, 4);
+ opt.flag[DHCP_SERVER_ID] = 1;
+
+ opt.request_list[DHCP_MASK] = 1;
+ opt.request_list[DHCP_DNS] = 1;
+ opt.request_list[DHCP_ROUTER] = 1;
+ opt.request_list[DHCP_TFTP_SERVER] = 1;
+ opt.request_list[DHCP_BOOTFILE] = 1;
+
+ dhcp_encode_options(btph -> vend, &opt);
+
+ fill_udphdr(&ether_packet[sizeof(struct ethhdr) + sizeof(struct iphdr)],
+ sizeof(struct btphdr) + sizeof(struct udphdr),
+ UDPPORT_BOOTPC, UDPPORT_BOOTPS);
+ fill_iphdr(&ether_packet[sizeof(struct ethhdr)], sizeof(struct btphdr) +
+ sizeof(struct udphdr) + sizeof(struct iphdr),
+ IPTYPE_UDP, 0, 0xFFFFFFFF);
+ fill_ethhdr(&ether_packet[0], ETHERTYPE_IP, dhcp_own_mac, dest_mac);
+
+ PRINT_SENDING(ether_packet, packetsize);
+
+ send(dhcp_device_socket, ether_packet, packetsize, 0);
+}
+
+
+/**
+ * DHCP: Sends DHCP-Release message. Releases occupied IP.
+ */
+void dhcp_send_release(void) {
+ uint32_t packetsize = sizeof(struct ethhdr) + sizeof(struct iphdr) +
+ sizeof(struct udphdr) + sizeof(struct btphdr);
+ struct btphdr *btph;
+ dhcp_options_t opt;
+
+ btph = (struct btphdr *) (&ether_packet[sizeof(struct ethhdr) +
+ sizeof(struct iphdr) + sizeof(struct udphdr)]);
+
+ memset(ether_packet, 0, packetsize);
+
+ btph -> op = 1;
+ btph -> htype = 1;
+ btph -> hlen = 6;
+ strcpy((char *) btph -> file, "");
+ memcpy(btph -> chaddr, dhcp_own_mac, 6);
+ btph -> ciaddr = htonl(dhcp_own_ip);
+
+ memset(&opt, 0, sizeof(dhcp_options_t));
+
+ opt.msg_type = DHCPRELEASE;
+ opt.server_ID = dhcp_server_ip;
+ opt.flag[DHCP_SERVER_ID] = 1;
+
+ dhcp_encode_options(btph -> vend, &opt);
+
+ fill_udphdr(&ether_packet[sizeof(struct ethhdr) + sizeof(struct iphdr)],
+ sizeof(struct btphdr) + sizeof(struct udphdr),
+ UDPPORT_BOOTPC, UDPPORT_BOOTPS);
+ fill_iphdr(&ether_packet[sizeof(struct ethhdr)], sizeof(struct btphdr) +
+ sizeof(struct udphdr) + sizeof(struct iphdr), IPTYPE_UDP,
+ dhcp_own_ip, dhcp_server_ip);
+ fill_ethhdr(&ether_packet[0], ETHERTYPE_IP, dhcp_own_mac, dhcp_server_mac);
+
+ PRINT_SENDING(ether_packet, packetsize);
+
+ send(dhcp_device_socket, ether_packet, packetsize, 0);
+}
+
+/**
+ * DHCP: Handles DHCP-messages according to Receive-handle diagram.
+ * Changes the state of DHCP-client.
+ *
+ * @param packet BootP/DHCP-packet to be handled
+ * @param packetsize length of the packet
+ * @return ZERO - packet handled successfully;
+ * NON ZERO - packet was not handled (e.g. bad format)
+ * @see receive_ether
+ * @see btphdr
+ */
+
+int8_t
+handle_dhcp(uint8_t * packet, int32_t packetsize) {
+ struct btphdr * btph;
+ struct iphdr * iph;
+ dhcp_options_t opt;
+
+ memset(&opt, 0, sizeof(dhcp_options_t));
+ btph = (struct btphdr *) packet;
+ iph = (struct iphdr *) packet - sizeof(struct udphdr) -
+ sizeof(struct iphdr);
+ if (btph -> op != 2)
+ return -1; // it is not Boot Reply
+
+ if (memcmp(btph -> vend, dhcp_magic, 4)) {
+ // It is BootP - RFC 951
+ NET_DEBUG_PRINTF("WARNING:\t\tBooting via BootP 951\n");
+
+ dhcp_own_ip = htonl(btph -> yiaddr);
+ dhcp_siaddr_ip = htonl(btph -> siaddr);
+ dhcp_server_ip = htonl(iph -> ip_src);
+
+ if (strlen((char *) btph -> sname) && !dhcp_siaddr_ip) {
+ strncpy((char *) dhcp_tftp_name, (char *) btph -> sname,
+ sizeof(btph -> sname));
+ dhcp_tftp_name[sizeof(btph -> sname)] = 0;
+ }
+
+ if (strlen((char *) btph -> file)) {
+ strncpy((char *) dhcp_filename, (char *) btph -> file, sizeof(btph -> file));
+ dhcp_filename[sizeof(btph -> file)] = 0;
+ }
+
+ dhcp_state = DHCP_STATE_SUCCESS;
+ return 0;
+ }
+
+
+ // decode options
+ if (!dhcp_decode_options(btph -> vend, packetsize -
+ sizeof(struct btphdr) + sizeof(btph -> vend),
+ &opt)) {
+ return -1; // can't decode options
+ }
+
+ if (opt.overload) {
+ int16_t decode_res = 0;
+ uint8_t options[1024]; // buffer for merged options
+ uint32_t opt_len;
+
+ // move 1-st part of options from vend field into buffer
+ opt_len = packetsize - sizeof(struct btphdr) +
+ sizeof(btph -> vend) - 4;
+ memcpy(options, btph -> vend, opt_len + 4);
+
+ // add other parts
+ switch (opt.overload) {
+ case DHCP_OVERLOAD_FILE:
+ decode_res = dhcp_merge_options(options + 4, &opt_len,
+ btph -> file,
+ sizeof(btph -> file));
+ break;
+ case DHCP_OVERLOAD_SNAME:
+ decode_res = dhcp_merge_options(options + 4, &opt_len,
+ btph -> sname,
+ sizeof(btph -> sname));
+ break;
+ case DHCP_OVERLOAD_BOTH:
+ decode_res = dhcp_merge_options(options + 4, &opt_len,
+ btph -> file,
+ sizeof(btph -> file));
+ if (!decode_res)
+ break;
+ decode_res = dhcp_merge_options(options + 4, &opt_len,
+ btph -> sname,
+ sizeof(btph -> sname));
+ break;
+ }
+
+ if (!decode_res)
+ return -1; // bad options in sname/file fields
+
+ // decode merged options
+ if (!dhcp_decode_options(options, opt_len + 4, &opt)) {
+ return -1; // can't decode options
+ }
+ }
+
+ if (!opt.msg_type) {
+ // It is BootP with Extensions - RFC 1497
+ NET_DEBUG_PRINTF("WARNING:\t\tBooting via BootP 1497\n");
+
+ // retrieve conf. settings from BootP - reply
+ dhcp_own_ip = htonl(btph -> yiaddr);
+ dhcp_siaddr_ip = htonl(btph -> siaddr);
+ if (strlen((char *) btph -> sname) && !dhcp_siaddr_ip) {
+ strncpy((char *) dhcp_tftp_name, (char *) btph -> sname, sizeof(btph -> sname));
+ dhcp_tftp_name[sizeof(btph -> sname)] = 0;
+ }
+
+ if (strlen((char *) btph -> file)) {
+ strncpy((char *) dhcp_filename, (char *) btph -> file, sizeof(btph -> file));
+ dhcp_filename[sizeof(btph -> file)] = 0;
+ }
+
+ // retrieve DHCP-server IP from IP-header
+ dhcp_server_ip = iph -> htonl(ip_src);
+
+ dhcp_state = DHCP_STATE_SUCCESS;
+ }
+ else {
+ // It is DHCP - RFC 2131 & RFC 2132
+ // opt contains parameters from server
+ switch (dhcp_state) {
+ case DHCP_STATE_SELECT :
+ if (opt.msg_type == DHCPOFFER) {
+ dhcp_own_ip = htonl(btph -> yiaddr);
+ dhcp_server_ip = opt.server_ID;
+ dhcp_send_request();
+ dhcp_state = DHCP_STATE_REQUEST;
+ }
+ return 0;
+ case DHCP_STATE_REQUEST :
+ switch (opt.msg_type) {
+ case DHCPNACK :
+ dhcp_own_ip = 0;
+ dhcp_server_ip = 0;
+ dhcp_state = DHCP_STATE_FAULT;
+ break;
+ case DHCPACK :
+ dhcp_own_ip = htonl(btph -> yiaddr);
+ dhcp_server_ip = opt.server_ID;
+ dhcp_siaddr_ip = htonl(btph -> siaddr);
+ if (opt.flag[DHCP_TFTP_SERVER]) {
+ strcpy((char *) dhcp_tftp_name, (char *) opt.tftp_server);
+ }
+ else {
+ strcpy((char *) dhcp_tftp_name, "");
+ if ((opt.overload != DHCP_OVERLOAD_SNAME &&
+ opt.overload != DHCP_OVERLOAD_BOTH) &&
+ !dhcp_siaddr_ip) {
+ strncpy((char *) dhcp_tftp_name,
+ (char *) btph->sname,
+ sizeof(btph -> sname));
+ dhcp_tftp_name[sizeof(btph->sname)] = 0;
+ }
+ }
+
+ if (opt.flag[DHCP_BOOTFILE]) {
+ strcpy((char *) dhcp_filename, (char *) opt.bootfile);
+ }
+ else {
+ strcpy((char *) dhcp_filename, "");
+ if (opt.overload != DHCP_OVERLOAD_FILE &&
+ opt.overload != DHCP_OVERLOAD_BOTH &&
+ strlen((char *) btph -> file)) {
+ strncpy((char *) dhcp_filename,
+ (char *) btph->file,
+ sizeof(btph->file));
+ dhcp_filename[sizeof(btph -> file)] = 0;
+ }
+ }
+
+ dhcp_state = DHCP_STATE_SUCCESS;
+ break;
+ default:
+ break; // Unused DHCP-message - do nothing
+ }
+ break;
+ default :
+ return -1; // Illegal DHCP-client state
+ }
+ }
+
+ if (dhcp_state == DHCP_STATE_SUCCESS) {
+
+ // initialize network entity with real own_ip
+ // to be able to answer for foreign requests
+ netbase_init(dhcp_device_socket, dhcp_own_mac, dhcp_own_ip);
+
+ /* Subnet mask */
+ if (opt.flag[DHCP_MASK]) {
+ /* Router */
+ if (opt.flag[DHCP_ROUTER]) {
+ if(net_setrouter(opt.router_IP, opt.subnet_mask)
+ == 0) {
+ // don't abort if ARP faild
+ // dhcp_state = DHCP_STATE_FAULT;
+ // return -1;
+
+ // pretend like no router was specified
+ opt.flag[DHCP_ROUTER] = 0;
+ net_setrouter(0, opt.subnet_mask);
+ }
+ }
+
+ if (! opt.flag[DHCP_ROUTER]) {
+ NET_DEBUG_PRINTF("WARNING:\t\tRouter IP is not presented!\n");
+ }
+ }
+ else {
+ NET_DEBUG_PRINTF("\nWARNING:\t\tSubnet mask is not presented!\n");
+ }
+
+ /* DNS-server */
+ if (opt.flag[DHCP_DNS]) {
+ dns_init(dhcp_device_socket, dhcp_own_mac, dhcp_own_ip, opt.dns_IP);
+ }
+ else {
+ NET_DEBUG_PRINTF("WARNING:\t\tDomain Name Server IP is not presented!\n");
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * DHCP: Converts "255.255.255.255" -> 32-bit long IP
+ *
+ * @param str string to be converted
+ * @param ip in case of SUCCESS - 32-bit long IP
+ in case of FAULT - zero
+ * @return TRUE - IP converted successfully;
+ * FALSE - error condition occurs (e.g. bad format)
+ */
+static uint8_t
+strtoip(int8_t * str, uint32_t * ip) {
+ int8_t ** ptr = &str;
+ int16_t i = 0, res, len;
+ char octet[256];
+
+ * ip = 0;
+
+ while (**ptr != 0) {
+ if (i > 3 || !isdigit(**ptr))
+ return 0;
+ if (strstr((char *) * ptr, ".") != NULL) {
+ len = (int16_t) ((int8_t *) strstr((char *) * ptr, ".") -
+ (int8_t *) (* ptr));
+ strncpy(octet, (char *) * ptr, len); octet[len] = 0;
+ * ptr += len;
+ }
+ else {
+ strcpy(octet, (char *) * ptr);
+ * ptr += strlen(octet);
+ }
+ res = strtol(octet, NULL, 10);
+ if ((res > 255) || (res < 0))
+ return 0;
+ * ip = ((* ip) << 8) + res;
+ i++;
+ if (** ptr == '.')
+ (*ptr)++;
+ }
+
+ if (i != 4)
+ return 0;
+ return 1;
+}
diff --git a/clients/net-snk/app/netlib/dhcp.h b/clients/net-snk/app/netlib/dhcp.h
new file mode 100644
index 0000000..5d0d636
--- /dev/null
+++ b/clients/net-snk/app/netlib/dhcp.h
@@ -0,0 +1,14 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/* Handles DHCP-packets, which are detected by receive_ether. */
+extern int8_t handle_dhcp(uint8_t * packet, int32_t packetsize);
diff --git a/clients/net-snk/app/netlib/dns.c b/clients/net-snk/app/netlib/dns.c
new file mode 100644
index 0000000..d0eb7b0
--- /dev/null
+++ b/clients/net-snk/app/netlib/dns.c
@@ -0,0 +1,522 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<<<*/
+
+#include <types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/arp.h>
+#include <netlib/dns.h>
+#include <time.h>
+
+#define DNS_FLAG_MSGTYPE 0xF800 /**< Message type mask (opcode) */
+#define DNS_FLAG_SQUERY 0x0000 /**< Standard query type */
+#define DNS_FLAG_SRESPONSE 0x8000 /**< Standard response type */
+#define DNS_FLAG_RD 0x0100 /**< Recursion desired flag */
+#define DNS_FLAG_RCODE 0x000F /**< Response code mask
+ (stores err.cond.) code */
+#define DNS_RCODE_NERROR 0 /**< "No errors" code */
+
+#define DNS_QTYPE_A 1 /**< A 32-bit IP record type */
+#define DNS_QTYPE_CNAME 5 /**< Canonical name record type */
+
+#define DNS_QCLASS_IN 1 /**< Query class for internet msgs */
+
+/** \struct dnshdr
+ * A header for DNS-messages (see RFC 1035, paragraph 4.1.1).
+ * <p>
+ * DNS-message consist of DNS-header and 4 optional sections,
+ * arranged in the following order:<ul>
+ * <li> DNS-header
+ * <li> question section
+ * <li> answer section
+ * <li> authority section
+ * <li> additional section
+ * </ul>
+ */
+struct dnshdr {
+ uint16_t id; /**< an identifier used to match up replies */
+ uint16_t flags; /**< contains op_code, err_code, etc. */
+ uint16_t qdcount; /**< specifies the number of entries in the
+ question section */
+ uint16_t ancount; /**< specifies the number of entries in the
+ answer section */
+ uint16_t nscount; /**< specifies the number of entries in the
+ authority section */
+ uint16_t arcount; /**< specifies the number of entries in the
+ additional section */
+};
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static void
+dns_send_query(int8_t * domain_name);
+
+static void
+fill_dnshdr(uint8_t * packet, int8_t * domain_name);
+
+static uint8_t *
+dns_extract_name(uint8_t * dnsh, int8_t * head, int8_t * domain_name);
+
+static int8_t
+urltohost(char * url, char * host_name);
+
+static int8_t
+hosttodomain(char * host_name, char * domain_name);
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static uint8_t ether_packet[ETH_MTU_SIZE];
+static int32_t dns_device_socket = 0;
+static uint8_t dns_own_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static int32_t dns_own_ip = 0;
+static uint8_t dns_server_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static int32_t dns_server_ip = 0;
+static int32_t dns_result_ip = 0;
+static int8_t dns_error = 0; /**< Stores error code or 0 */
+static int8_t dns_domain_name[0x100]; /**< Raw domain name */
+static int8_t dns_domain_cname[0x100]; /**< Canonical domain name */
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/**
+ * DNS: Initialize the environment for DNS client.
+ * To perfrom DNS-queries use the function dns_get_ip.
+ *
+ * @param device_socket a socket number used to send and recieve packets
+ * @param own_mac client hardware-address (MAC)
+ * @param own_ip client IPv4 address (e.g. 127.0.0.1)
+ * @param server_ip DNS-server IPv4 address (e.g. 127.0.0.1)
+ * @return TRUE in case of successful initialization;
+ * FALSE in case of fault (e.g. can't obtain MAC).
+ * @see dns_get_ip
+ */
+int8_t
+dns_init(int32_t device_socket, uint8_t own_mac[], uint32_t own_ip,
+ uint32_t server_ip) {
+ dns_device_socket = device_socket;
+ memcpy(dns_own_mac, own_mac, 6);
+ dns_own_ip = own_ip;
+ dns_server_ip = server_ip;
+
+ PRINT_MSGIP("\nDomain Name Server IP:\t", dns_server_ip);
+ if (net_iptomac(dns_server_ip, dns_server_mac)) {
+ PRINT_MSGMAC("DNS Server MAC:\t\t", dns_server_mac);
+ return 1;
+ }
+
+ dns_server_ip = 0;
+ dns_own_ip = 0;
+ memset(dns_server_mac, 0, 6);
+
+ NET_DEBUG_PRINTF("\nWARNING:\t\tCan't obtain DNS server MAC!\n");
+ return 0;
+}
+
+/**
+ * DNS: For given URL retrieves IPv4 from DNS-server.
+ * <p>
+ * URL can be given in one of the following form: <ul>
+ * <li> scheme with full path with (without) user and password
+ * <br>(e.g. "http://user:pass@www.host.org/url-path");
+ * <li> host name with url-path
+ * <br>(e.g. "www.host.org/url-path");
+ * <li> nothing but host name
+ * <br>(e.g. "www.host.org");
+ * </ul>
+ *
+ * @param url the URL to be resolved
+ * @param domain_ip In case of SUCCESS stores extracted IP.
+ * In case of FAULT stores zeros (0.0.0.0).
+ * @return TRUE - IP successfuly retrieved;
+ * FALSE - error condition occurs.
+ */
+int8_t
+dns_get_ip(int8_t * url, uint32_t * domain_ip) {
+ /* this counter is used so that we abort after 30 DNS request */
+ int32_t i;
+ /* this buffer stores host name retrieved from url */
+ static int8_t host_name[0x100];
+
+ (* domain_ip) = 0;
+
+ // Retrieve host name from URL
+ if (!urltohost((char *) url, (char *) host_name)) {
+ printf("\nERROR:\t\t\tBad URL!\n");
+ return 0;
+ }
+
+ // Reformat host name into a series of labels
+ if (!hosttodomain((char *) host_name, (char *) dns_domain_name)) {
+ printf("\nERROR:\t\t\tBad host name!\n");
+ return 0;
+ }
+
+ // Check if DNS server is presented and accessable
+ if (dns_server_ip == 0) {
+ printf("\nERROR:\t\t\tCan't resolve domain name "
+ "(DNS server is not presented)!\n");
+ return 0;
+ }
+ if (dns_server_mac[0] == 0 && dns_server_mac[1] == 0 &&
+ dns_server_mac[2] == 0 && dns_server_mac[3] == 0 &&
+ dns_server_mac[4] == 0 && dns_server_mac[5] == 0) {
+ if(!net_iptomac(dns_server_ip, dns_server_mac)) {
+ printf("\nERROR:\t\t\tCan't resolve domain name "
+ "(DNS server is not presented)!\n");
+ return 0;
+ }
+ }
+
+ // Use DNS-server to obtain IP
+ dns_result_ip = 0;
+ dns_error = 0;
+ strcpy((char *) dns_domain_cname, "");
+
+ for(i = 0; i < 30; ++i) {
+ // Use canonical name in case we obtained it
+ if (strlen((char *) dns_domain_cname))
+ dns_send_query(dns_domain_cname);
+ else
+ dns_send_query(dns_domain_name);
+
+ // setting up a timer with a timeout of one seconds
+ set_timer(TICKS_SEC);
+ do {
+ receive_ether();
+ if (dns_error)
+ return 0; // FALSE - error
+ if (dns_result_ip != 0) {
+ (* domain_ip) = dns_result_ip;
+ return 1; // TRUE - success (domain IP retrieved)
+ }
+ } while (get_timer() > 0);
+ }
+
+ printf("\nGiving up after %d DNS requests\n", i);
+ return 0; // FALSE - domain name wasn't retrieved
+}
+
+/**
+ * DNS: Handles DNS-messages according to Receive-handle diagram.
+ * Sets dns_result_ip for given dns_domain_name (see dns_get_ip)
+ * or signals error condition occurs during DNS-resolving proccess
+ * by setting dns_error flag.
+ *
+ * @param packet DNS-packet to be handled
+ * @param packetsize length of the packet
+ * @return ZERO - packet handled successfully;
+ * NON ZERO - packet was not handled (e.g. bad format)
+ * @see dns_get_ip
+ * @see receive_ether
+ * @see dnshdr
+ */
+int32_t
+handle_dns(uint8_t * packet, int32_t packetsize) {
+ struct dnshdr * dnsh = (struct dnshdr *) packet;
+ uint8_t * resp_section = packet + sizeof(struct dnshdr);
+ /* This string stores domain name from DNS-packets */
+ static int8_t handle_domain_name[0x100];
+ int i;
+
+ // verify ID - is it response for our query?
+ if (dnsh -> id != htons(0x1234))
+ return 0;
+
+ // Is it DNS response?
+ if ((dnsh -> flags & htons(DNS_FLAG_MSGTYPE)) != htons(DNS_FLAG_SRESPONSE))
+ return 0;
+
+ // Is error condition occurs? (check error field in incoming packet)
+ if ((dnsh -> flags & htons(DNS_FLAG_RCODE)) != DNS_RCODE_NERROR) {
+ NET_DEBUG_PRINTF("\nERROR:\t\t\tDNS error - can't obtain IP!\n");
+ dns_error = 1;
+ return 0;
+ }
+
+ /* Pass all (qdcount) records in question section */
+
+ for (i = 0; i < htons(dnsh -> qdcount); i++) {
+ // pass QNAME
+ resp_section = dns_extract_name((uint8_t *) dnsh, (int8_t *) resp_section,
+ handle_domain_name);
+ if (resp_section == NULL) {
+ return -1; // incorrect domain name (bad packet)
+ }
+ // pass QTYPE & QCLASS
+ resp_section += 4;
+ }
+
+ /* Handle all (ancount) records in answer section */
+
+ for (i = 0; i < htons(dnsh -> ancount); i++) {
+ // retrieve domain name from the packet
+ resp_section = dns_extract_name((uint8_t *) dnsh, (int8_t *) resp_section,
+ handle_domain_name);
+
+ if (resp_section == NULL) {
+ return -1; // incorrect domain name (bad packet)
+ }
+
+ // Check the class of the query (should be IN for Internet)
+ if (* (uint16_t *) (resp_section + 2) == htons(DNS_QCLASS_IN)) {
+ // check if retrieved name fit raw or canonical domain name
+ if (!strcmp((char *) handle_domain_name, (char *) dns_domain_name) ||
+ !strcmp((char *) handle_domain_name, (char *) dns_domain_cname)) {
+ switch (htons(* (uint16_t *) resp_section)) {
+
+ case DNS_QTYPE_A :
+ // rdata contains IP
+ dns_result_ip = htonl(* (uint32_t *) (resp_section + 10));
+ return 0; // IP successfully obtained
+
+ case DNS_QTYPE_CNAME :
+ // rdata contains canonical name, store it for further requests
+ if (dns_extract_name((uint8_t *) dnsh, (int8_t *) resp_section + 10,
+ dns_domain_cname) == NULL) {
+ // incorrect domain name (bad packet)
+ return -1;
+ }
+ break;
+ }
+ }
+ // continue with next record in answer section
+ resp_section += htons(* (uint16_t *) (resp_section + 8)) + 10;
+ }
+ }
+ return 0; // Packet succesfuly handled but IP wasn't obtained
+}
+
+/**
+ * DNS: Sends a standard DNS-query (read request package) to a DNS-server.
+ * DNS-server respones with host IP or signals some error condition.
+ * Responses from the server are handled by handle_dns function.
+ *
+ * @param domain_name the domain name given as series of labels preceded
+ * with length(label) and terminated with 0
+ * <br>(e.g. "\3,w,w,w,\4,h,o,s,t,\3,o,r,g,\0")
+ * @see handle_dns
+ */
+static void
+dns_send_query(int8_t * domain_name) {
+ int qry_len = strlen((char *) domain_name) + 5;
+
+ uint32_t packetsize = sizeof(struct iphdr) + sizeof(struct ethhdr) +
+ sizeof(struct udphdr) + sizeof(struct dnshdr) +
+ qry_len;
+
+ memset(ether_packet, 0, packetsize);
+ fill_dnshdr(&ether_packet[sizeof(struct ethhdr) +
+ sizeof(struct iphdr) + sizeof(struct udphdr)],
+ domain_name);
+ fill_udphdr(&ether_packet[sizeof(struct ethhdr) +
+ sizeof(struct iphdr)], sizeof(struct dnshdr) +
+ sizeof(struct udphdr) + qry_len,
+ UDPPORT_DNSC, UDPPORT_DNSS);
+ fill_iphdr(ether_packet + sizeof(struct ethhdr),
+ sizeof(struct dnshdr) + sizeof(struct udphdr) +
+ sizeof(struct iphdr) + qry_len,
+ IPTYPE_UDP, dns_own_ip, dns_server_ip);
+ fill_ethhdr(ether_packet, ETHERTYPE_IP, dns_own_mac, dns_server_mac);
+
+ PRINT_SENDING(ether_packet, packetsize);
+
+ send(dns_device_socket, ether_packet, packetsize, 0);
+}
+
+/**
+ * DNS: Creates standard DNS-query package. Places DNS-header
+ * and question section in a packet and fills it with
+ * corresponding information.
+ * <p>
+ * Use this function with similar functions for other network layers
+ * (fill_udphdr, fill_iphdr, fill_ethhdr).
+ *
+ * @param packet Points to the place where ARP-header must be placed.
+ * @param domain_name the domain name given as series of labels preceded
+ * with length(label) and terminated with 0
+ * <br>(e.g. "\3,w,w,w,\4,h,o,s,t,\3,o,r,g,\0")
+ * @see fill_udphdr
+ * @see fill_iphdr
+ * @see fill_ethhdr
+ */
+static void
+fill_dnshdr(uint8_t * packet, int8_t * domain_name) {
+ struct dnshdr * dnsh = (struct dnshdr *) packet;
+ uint8_t * qry_section = packet + sizeof(struct dnshdr);
+
+ dnsh -> id = htons(0x1234);
+ dnsh -> flags = htons(DNS_FLAG_SQUERY) | htons(DNS_FLAG_RD);
+ dnsh -> qdcount = htons(1);
+
+ strcpy((char *) qry_section, (char *) domain_name);
+ qry_section += strlen((char *) domain_name) + 1;
+
+ // fill QTYPE (ask for IP)
+ * (uint16_t *) qry_section = htons(DNS_QTYPE_A);
+ qry_section += 2;
+ // fill QCLASS (IN is a standard class for Internet)
+ * (uint16_t *) qry_section = htons(DNS_QCLASS_IN);
+}
+
+/**
+ * DNS: Extracts domain name from the question or answer section of
+ * the DNS-message. This function is need to support message
+ * compression requirement (see RFC 1035, paragraph 4.1.4).
+ *
+ * @param dnsh Points at the DNS-header.
+ * @param head Points at the beginning of the domain_name
+ * which has to be extracted.
+ * @param domain_name In case of SUCCESS this string stores extracted name.
+ * In case of FAULT this string is empty.
+ * @return NULL in case of FAULT (domain name > 255 octets);
+ * otherwise pointer to the data following the name.
+ * @see dnshdr
+ */
+static uint8_t *
+dns_extract_name(uint8_t * dnsh, int8_t * head, int8_t * domain_name) {
+ int8_t * tail = domain_name;
+ int8_t * ptr = head;
+ int8_t * next_section = NULL;
+
+ while (1) {
+ if ((ptr[0] & 0xC0) == 0xC0) {
+ // message compressed (reference is used)
+ next_section = ptr + 2;
+ ptr = (int8_t *) dnsh + (htons(* (uint16_t *) ptr) & 0x3FFF);
+ continue;
+ }
+ if (ptr[0] == 0) {
+ // message termination
+ tail[0] = 0;
+ ptr += 1;
+ break;
+ }
+ // maximum length for domain name is 255 octets w/o termination sym
+ if (tail - domain_name + ptr[0] + 1 > 255) {
+ strcpy((char *) domain_name, "");
+ return NULL;
+ }
+ memcpy(tail, ptr, ptr[0] + 1);
+ tail += ptr[0] + 1;
+ ptr += ptr[0] + 1;
+ }
+
+ if (next_section == NULL)
+ next_section = ptr;
+
+ return (uint8_t *) next_section;
+}
+
+/**
+ * DNS: Parses URL and returns host name.
+ * Input string can be given as: <ul>
+ * <li> scheme with full path with (without) user and password
+ * <br>(e.g. "http://user:pass@www.host.org/url-path");
+ * <li> host name with url-path
+ * <br>(e.g. "www.host.org/url-path");
+ * <li> nothing but host name
+ * <br>(e.g. "www.host.org");
+ * </ul>
+ *
+ * @param url string that stores incoming URL
+ * @param host_name In case of SUCCESS this string stores the host name,
+ * In case of FAULT this string is empty.
+ * @return TRUE - host name retrieved,
+ * FALSE - host name > 255 octets or empty.
+ */
+static int8_t
+urltohost(char * url, char * host_name) {
+ uint16_t length1;
+ uint16_t length2;
+
+ strcpy(host_name, "");
+
+ if (strstr(url, "://") != NULL)
+ url = strstr(url, "//") + 2; // URL
+
+ if (strstr(url, "@") != NULL) // truncate user & password
+ url = strstr(url, "@") + 1;
+
+ if (strstr(url, "/") != NULL) // truncate url path
+ length1 = strstr(url, "/") - url;
+ else
+ length1 = strlen(url);
+
+ if (strstr(url, ":") != NULL) // truncate port path
+ length2 = strstr(url, ":") - url;
+ else
+ length2 = strlen(url);
+
+ if(length1 > length2)
+ length1 = length2;
+
+ if (length1 == 0)
+ return 0; // string is empty
+ if(length1 >= 256)
+ return 0; // host name is too big
+
+ strncpy(host_name, url, length1);
+ host_name[length1] = 0;
+
+ return 1; // Host name is retrieved
+}
+
+/**
+ * DNS: Transforms host name string into a series of labels
+ * each of them preceded with length(label). 0 is a terminator.
+ * "www.domain.dom" -> "\3,w,w,w,\6,d,o,m,a,i,n,\3,c,o,m,\0"
+ * <p>
+ * This format is used in DNS-messages.
+ *
+ * @param host_name incoming string with the host name
+ * @param domain_name resulting string with series of labels
+ * or empty string in case of FAULT
+ * @return TRUE - host name transformed,
+ * FALSE - host name > 255 octets or label > 63 octets.
+ */
+static int8_t
+hosttodomain(char * host_name, char * domain_name) {
+ char * domain_iter = domain_name;
+ char * host_iter = host_name;
+
+ strcpy(domain_name, "");
+
+ if(strlen(host_name) > 255)
+ return 0; // invalid host name (refer to RFC 1035)
+
+ for(; 1; ++host_iter) {
+ if(*host_iter != '.' && *host_iter != 0)
+ continue;
+ *domain_iter = host_iter - host_name;
+ if (*domain_iter > 63) {
+ strcpy(domain_name, "");
+ return 0; // invalid host name (refer to RFC 1035)
+ }
+ ++domain_iter;
+ strncpy(domain_iter, host_name, host_iter - host_name);
+ domain_iter += (host_iter - host_name);
+ if(*host_iter == 0) {
+ *domain_iter = 0;
+ break;
+ }
+ host_name = host_iter + 1;
+ }
+ return 1; // ok
+}
diff --git a/clients/net-snk/app/netlib/dns.h b/clients/net-snk/app/netlib/dns.h
new file mode 100644
index 0000000..5bf0f84
--- /dev/null
+++ b/clients/net-snk/app/netlib/dns.h
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+/* Initialize the environment for DNS client. */
+extern int8_t dns_init(int32_t device_socket, uint8_t own_mac[], uint32_t own_ip, uint32_t server_ip);
+
+/* For given URL retrieves IPv4 from DNS-server. */
+extern int8_t dns_get_ip(int8_t * domain_name, uint32_t * domain_ip);
+
+/* Handles DNS-packets, which are detected by receive_ether. */
+extern int32_t handle_dns(uint8_t * packet, int32_t packetsize);
diff --git a/clients/net-snk/app/netlib/icmp.c b/clients/net-snk/app/netlib/icmp.c
new file mode 100644
index 0000000..a767de4
--- /dev/null
+++ b/clients/net-snk/app/netlib/icmp.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <netlib/icmp.h>
+#include <netlib/arp.h>
+#include <netlib/netbase.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <time.h>
+
+/* from bootp.c */
+unsigned short checksum(unsigned short *, int);
+
+int
+handle_icmp(struct icmphdr *icmp)
+{
+ /* we currently only handle type 3 (detination unreachable)
+ * ICMP messages */
+ if (icmp->type != 3)
+ return 0;
+ return -icmp->code - 10;
+}
+
+static void
+fill_icmp_echo_data(unsigned char *data, int length)
+{
+ char *filler = "SLOF";
+ if (length <= 0)
+ return;
+ do {
+ memcpy(data, filler,
+ (length >= strlen(filler)) ? strlen(filler) : length);
+ data += strlen(filler);
+ } while ((length -= strlen(filler)) > 0);
+}
+
+int
+echo_request(int device, filename_ip_t * fn_ip, unsigned int timeout)
+{
+ unsigned int packetsize =
+ sizeof(struct ethhdr) + sizeof(struct iphdr) +
+ sizeof(struct icmphdr);
+ unsigned char packet[packetsize * 2];
+ struct icmphdr *icmp;
+ int i;
+ struct iphdr *ip;
+ struct ethhdr *ethh;
+ memset(packet, 0, packetsize);
+ fill_ethhdr(packet, htons(ETHERTYPE_IP), fn_ip->own_mac,
+ fn_ip->server_mac);
+ ethh = (struct ethhdr *) packet;
+ fill_iphdr(packet + sizeof(struct ethhdr),
+ sizeof(struct iphdr) + sizeof(struct icmphdr), IPTYPE_ICMP,
+ fn_ip->own_ip, fn_ip->server_ip);
+ icmp =
+ (struct icmphdr *) ((void *) (packet + sizeof(struct ethhdr)) +
+ sizeof(struct iphdr));
+ ip = (struct iphdr *) (packet + sizeof(struct ethhdr));
+ icmp->type = 8;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->options.echo.id = 0xd476;
+ icmp->options.echo.seq = 1;
+ fill_icmp_echo_data(icmp->payload.data, sizeof(icmp->payload.data));
+ icmp->checksum =
+ checksum((unsigned short *) icmp, sizeof(struct icmphdr) >> 1);
+ send(device, packet, packetsize, 0);
+ set_timer(TICKS_SEC / 10 * timeout);
+ do {
+ memset(packet, 0, packetsize);
+ i = recv(device, packet, packetsize * 2, 0);
+ if (i == 0)
+ continue;
+ if (ethh->type == htons(ETHERTYPE_ARP)) {
+ handle_arp(packet + sizeof(struct ethhdr), i);
+ continue;
+ }
+ if (ip->ip_p != PROTO_ICMP)
+ continue;
+ if (icmp->type != 0)
+ continue;
+ if (icmp->options.echo.id != 0xd476)
+ continue;
+ if (icmp->options.echo.seq != 1)
+ continue;
+ return 0;
+ } while (get_timer() > 0);
+ return -1;
+}
diff --git a/clients/net-snk/app/netlib/icmp.h b/clients/net-snk/app/netlib/icmp.h
new file mode 100644
index 0000000..ad98eba
--- /dev/null
+++ b/clients/net-snk/app/netlib/icmp.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _ICMP_H_
+#define _ICMP_H_
+
+#include <netlib/netlib.h>
+
+/* RFC 792 - Internet Control Message Protocol
+
+ http://www.faqs.org/rfcs/rfc792.html
+
+Summary of Message Types
+ 0 Echo Reply
+ 3 Destination Unreachable
+ 4 Source Quench
+ 5 Redirect
+ 8 Echo
+ 11 Time Exceeded
+ 12 Parameter Problem
+ 13 Timestamp
+ 14 Timestamp Reply
+ 15 Information Request
+ 16 Information Reply
+*/
+
+#define PROTO_ICMP 1
+
+#define ICMP_TYPE_DEST_UNREACHABLE 3
+
+#define ICMP_NET_UNREACHABLE 0
+#define ICMP_HOST_UNREACHABLE 1
+#define ICMP_PROTOCOL_UNREACHABLE 2
+#define ICMP_PORT_UNREACHABLE 3
+#define ICMP_FRAGMENTATION_NEEDED 4
+#define ICMP_SOURCE_ROUTE_FAILED 5
+
+struct icmphdr {
+ unsigned char type;
+ unsigned char code;
+ unsigned short int checksum;
+ union {
+ /* for type 3 "Destination Unreachable" */
+ unsigned int unused;
+ /* for type 0 and 8 */
+ struct echo {
+ unsigned short int id;
+ unsigned short int seq;
+ } echo;
+ } options;
+ union {
+ /* payload for destination unreachable */
+ struct dun {
+ unsigned char iphdr[20];
+ unsigned char data[64];
+ } dun;
+ /* payload for echo or echo reply */
+ /* maximum size supported is 84 */
+ unsigned char data[84];
+ } payload;
+};
+
+int handle_icmp(struct icmphdr *);
+int echo_request(int, filename_ip_t *, unsigned int);
+
+#endif /* _ICMP_H_ */
diff --git a/clients/net-snk/app/netlib/netbase.c b/clients/net-snk/app/netlib/netbase.c
new file mode 100644
index 0000000..a82522d
--- /dev/null
+++ b/clients/net-snk/app/netlib/netbase.c
@@ -0,0 +1,451 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/** \file netbase.c <pre>
+ * *********************** Receive-handle diagram *************************
+ *
+ * Note: Every layer calls out required upper layer
+ * lower
+ * Receive packet (receive_ether)
+ * | |
+ * | |
+ * | Ethernet (handle_ether)
+ * | |
+ * | +-----------+---------+
+ * | | |
+ * | ARP (handle_arp) IP (handle_ip)
+ * | |
+ * | |
+ * | UDP (handle_udp)
+ * | |
+ * V +----------------+-----------+
+ * | |
+ * upper DNS (handle_dns) BootP / DHCP (handle_bootp_client)
+ *
+ * ************************************************************************
+ * </pre> */
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<*/
+
+#include <types.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netlib/netlib.h>
+#include <netlib/netbase.h>
+#include <netlib/arp.h>
+#include <netlib/dhcp.h>
+#include <netlib/dns.h>
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static int8_t
+handle_ip(uint8_t * packet, int32_t packetsize);
+
+static int8_t
+handle_udp(uint8_t * packet, int32_t packetsize);
+
+static unsigned short
+checksum(unsigned short *packet, int words);
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+static uint8_t ether_packet[ETH_MTU_SIZE];
+static int32_t net_device_socket = 0;
+static uint8_t net_own_mac[6];
+static uint32_t net_own_ip = 0;
+
+/* Routing parameters */
+static uint32_t net_router_ip = 0;
+static uint8_t net_router_mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint32_t net_subnet_mask = 0;
+
+
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+/**
+ * NET: Initializes basic network enviroment and ARP-client.
+ *
+ * @param device_socket a socket number used to send and recieve packets
+ * @param own_mac own hardware-address (MAC)
+ * @param own_ip own IPv4 address (e.g. 127.0.0.1)
+ */
+void
+netbase_init(int32_t device_socket, uint8_t * own_mac, uint32_t own_ip) {
+ net_device_socket = device_socket;
+ if (own_mac)
+ memcpy(net_own_mac, own_mac, 6);
+ else
+ memset(net_own_mac, 0, 6);
+ net_own_ip = own_ip;
+ arp_init(device_socket, own_mac, own_ip);
+}
+
+/**
+ * NET: Sets routing parameters.
+ * For more information see net_iptomac function.
+ *
+ * @param router_ip IP address of the router
+ * @param subnet_mask Subnet mask
+ * @see net_iptomac
+ * @return TRUE - router was installed;
+ * FALSE - error condition occurs.
+ */
+int8_t
+net_setrouter(uint32_t router_ip, uint32_t subnet_mask) {
+ net_subnet_mask = subnet_mask;
+ net_router_ip = router_ip;
+
+ if(router_ip != 0) {
+ PRINT_MSGIP("\nRouter IP:\t\t", net_router_ip);
+ if (arp_getmac(net_router_ip, net_router_mac)) {
+ PRINT_MSGMAC("Router MAC:\t\t", net_router_mac);
+ return 1;
+ }
+ }
+
+ memset(net_router_mac, 0, 6);
+ NET_DEBUG_PRINTF("WARNING:\t\tCan't obtain router MAC!\n");
+ return 0;
+}
+
+/**
+ * NET: For given IP retrieves MAC address (or sets router MAC).
+ * To set routing parameters use net_setrouter function.
+ *
+ * @param dest_ip IP address of the host
+ * @param dest_mac in case of SUCCESS stores MAC address of the host;
+ * in case of FAULT filled with zeros.
+ * @see net_setrouter
+ * @return TRUE - destination MAC address was obtained;
+ * FALSE - can't obtain destination MAC address
+ */
+int8_t
+net_iptomac(uint32_t dest_ip, uint8_t dest_mac[]) {
+ /* check if dest_ip and own_ip are in the same subnet */
+ if ((net_subnet_mask & net_own_ip) ==
+ (net_subnet_mask & dest_ip)) {
+ /* In the same subnet - use ARP to obtain DNS-server MAC */
+ if (!arp_getmac(dest_ip, dest_mac)) {
+ NET_DEBUG_PRINTF("\nWARNING:\t\tCan't retrieve MAC!\n");
+ memset(dest_mac, 0, 6);
+ return 0;
+ }
+ return 1;
+ }
+
+ /* In different subnets - check if router is presented */
+ if (net_router_mac[0] != 0 || net_router_mac[1] != 0
+ || net_router_mac[2] != 0 || net_router_mac[3] != 0
+ || net_router_mac[4] != 0 || net_router_mac[5] != 0) {
+ /* Use router MAC-address for DNS-connections */
+ memcpy(dest_mac, net_router_mac, 6);
+ return 1;
+ }
+
+ NET_DEBUG_PRINTF("\nWARNING:\t\tCan't obtain MAC (router is not presented)!\n");
+ return 0;
+}
+
+/**
+ * NET: Receives an ethernet-packet and handles it according to
+ * Receive-handle diagram.
+ *
+ * @return ZERO - packet was handled or no packets received;
+ * NON ZERO - error condition occurs.
+ */
+int32_t
+receive_ether(void) {
+ int32_t bytes_received;
+ struct ethhdr * ethh;
+
+ memset(ether_packet, 0, ETH_MTU_SIZE);
+ bytes_received = recv(net_device_socket, ether_packet, ETH_MTU_SIZE, 0);
+
+ if (!bytes_received) // No messages
+ return 0;
+
+ PRINT_RECEIVED(ether_packet, bytes_received);
+
+ if (bytes_received < sizeof(struct ethhdr))
+ return -1; // packet is too small
+
+ ethh = (struct ethhdr *) ether_packet;
+
+ switch (htons(ethh -> type)) {
+ case ETHERTYPE_IP:
+ return handle_ip(ether_packet + sizeof(struct ethhdr),
+ bytes_received - sizeof(struct ethhdr));
+ case ETHERTYPE_ARP:
+ return handle_arp(ether_packet + sizeof(struct ethhdr),
+ bytes_received - sizeof(struct ethhdr));
+ default:
+ break;
+ }
+ return -1; // unknown protocol
+}
+
+/**
+ * NET: Handles IP-packets according to Receive-handle diagram.
+ *
+ * @param ip_packet IP-packet to be handled
+ * @param packetsize Length of the packet
+ * @return ZERO - packet handled successfully;
+ * NON ZERO - packet was not handled (e.g. bad format)
+ * @see receive_ether
+ * @see iphdr
+ */
+static int8_t
+handle_ip(uint8_t * ip_packet, int32_t packetsize) {
+ struct iphdr * iph;
+ int32_t old_sum;
+
+ if (packetsize < sizeof(struct iphdr))
+ return -1; // packet is too small
+
+ iph = (struct iphdr * ) ip_packet;
+
+ old_sum = iph -> ip_sum;
+ iph -> ip_sum = 0;
+ if (old_sum != checksum((uint16_t *) iph, sizeof (struct iphdr) >> 1))
+ return -1; // Wrong IP checksum
+
+ switch (iph -> ip_p) {
+ case IPTYPE_UDP:
+ return handle_udp(ip_packet + sizeof(struct iphdr),
+ iph -> ip_len - sizeof(struct iphdr));
+ default:
+ break;
+ }
+ return -1; // Unknown protocol
+}
+
+/**
+ * NET: Handles UDP-packets according to Receive-handle diagram.
+ *
+ * @param udp_packet UDP-packet to be handled
+ * @param packetsize Length of the packet
+ * @return ZERO - packet handled successfully;
+ * NON ZERO - packet was not handled (e.g. bad format)
+ * @see receive_ether
+ * @see udphdr
+ */
+static int8_t
+handle_udp(uint8_t * udp_packet, int32_t packetsize) {
+ struct udphdr * udph = (struct udphdr *) udp_packet;
+
+ if (packetsize < sizeof(struct udphdr))
+ return -1; // packet is too small
+
+ switch (htons(udph -> uh_dport)) {
+ case UDPPORT_BOOTPC:
+ if (udph -> uh_sport == htons(UDPPORT_BOOTPS))
+ return handle_dhcp(udp_packet + sizeof(struct udphdr),
+ packetsize - sizeof(struct udphdr));
+ else
+ return -1;
+ case UDPPORT_DNSC:
+ if (udph -> uh_sport == htons(UDPPORT_DNSS))
+ return handle_dns(udp_packet + sizeof(struct udphdr),
+ packetsize - sizeof(struct udphdr));
+ else
+ return -1;
+ default:
+ return -1;
+ }
+}
+
+/**
+ * NET: Creates Ethernet-packet. Places Ethernet-header in a packet and
+ * fills it with corresponding information.
+ * <p>
+ * Use this function with similar functions for other network layers
+ * (fill_arphdr, fill_iphdr, fill_udphdr, fill_dnshdr, fill_btphdr).
+ *
+ * @param packet Points to the place where eth-header must be placed.
+ * @param eth_type Type of the next level protocol (e.g. IP or ARP).
+ * @param src_mac Sender MAC address
+ * @param dest_mac Receiver MAC address
+ * @see ethhdr
+ * @see fill_arphdr
+ * @see fill_iphdr
+ * @see fill_udphdr
+ * @see fill_dnshdr
+ * @see fill_btphdr
+ */
+void
+fill_ethhdr(uint8_t * packet, uint16_t eth_type,
+ uint8_t * src_mac, uint8_t * dest_mac) {
+ struct ethhdr * ethh = (struct ethhdr *) packet;
+
+ ethh -> type = htons(eth_type);
+ memcpy(ethh -> src_mac, src_mac, 6);
+ memcpy(ethh -> dest_mac, dest_mac, 6);
+}
+
+/**
+ * NET: Creates IP-packet. Places IP-header in a packet and fills it
+ * with corresponding information.
+ * <p>
+ * Use this function with similar functions for other network layers
+ * (fill_ethhdr, fill_udphdr, fill_dnshdr, fill_btphdr).
+ *
+ * @param packet Points to the place where IP-header must be placed.
+ * @param packetsize Size of the packet in bytes incl. this hdr and data.
+ * @param ip_proto Type of the next level protocol (e.g. UDP).
+ * @param ip_src Sender IP address
+ * @param ip_dst Receiver IP address
+ * @see iphdr
+ * @see fill_ethhdr
+ * @see fill_udphdr
+ * @see fill_dnshdr
+ * @see fill_btphdr
+ */
+void
+fill_iphdr(uint8_t * packet, uint16_t packetsize,
+ uint8_t ip_proto, uint32_t ip_src, uint32_t ip_dst) {
+ struct iphdr * iph = (struct iphdr *) packet;
+
+ iph -> ip_hlv = 0x45;
+ iph -> ip_tos = 0x10;
+ iph -> ip_len = htons(packetsize);
+ iph -> ip_id = htons(0);
+ iph -> ip_off = 0;
+ iph -> ip_ttl = 0xFF;
+ iph -> ip_p = ip_proto;
+ iph -> ip_src = htonl(ip_src);
+ iph -> ip_dst = htonl(ip_dst);
+ iph -> ip_sum = 0;
+ iph -> ip_sum = checksum((unsigned short *) iph, sizeof(struct iphdr) >> 1);
+}
+
+/**
+ * NET: Creates UDP-packet. Places UDP-header in a packet and fills it
+ * with corresponding information.
+ * <p>
+ * Use this function with similar functions for other network layers
+ * (fill_ethhdr, fill_iphdr, fill_dnshdr, fill_btphdr).
+ *
+ * @param packet Points to the place where UDP-header must be placed.
+ * @param packetsize Size of the packet in bytes incl. this hdr and data.
+ * @param src_port UDP source port
+ * @param dest_port UDP destination port
+ * @see udphdr
+ * @see fill_ethhdr
+ * @see fill_iphdr
+ * @see fill_dnshdr
+ * @see fill_btphdr
+ */
+void
+fill_udphdr(uint8_t * packet, uint16_t packetsize,
+ uint16_t src_port, uint16_t dest_port) {
+ struct udphdr * udph = (struct udphdr *) packet;
+
+ udph -> uh_sport = htons(src_port);
+ udph -> uh_dport = htons(dest_port);
+ udph -> uh_ulen = htons(packetsize);
+ udph -> uh_sum = htons(0);
+}
+
+/**
+ * NET: Calculates checksum for IP header.
+ *
+ * @param packet Points to the IP-header
+ * @param words Size of the packet in words incl. IP-header and data.
+ * @return Checksum
+ * @see iphdr
+ */
+static unsigned short
+checksum(unsigned short * packet, int words) {
+ unsigned long checksum;
+
+ for (checksum = 0; words > 0; words--)
+ checksum += *packet++;
+ checksum = (checksum >> 16) + (checksum & 0xffff);
+ checksum += (checksum >> 16);
+
+ return ~checksum;
+}
+
+
+#ifdef NET_DEBUG // Printing for debugging purposes
+
+/**
+ * DEBUG: Dumps ethernet-packet with appropriate header names.
+ *
+ * @param packet Points to the ethernet-packet.
+ * @param packetsize Size of the packet in bytes.
+ */
+void
+net_print_packet(uint8_t * packet, uint16_t packetsize) {
+ struct ethhdr * ethh = (struct ethhdr *) packet;
+ struct iphdr * iph;
+ struct udphdr * udph;
+ struct btphdr * btph;
+ struct dnshdr * dnsh;
+ struct arphdr * arph;
+
+ PRINT_HDR("ETH:\t\t", (uint8_t *) ethh, sizeof(struct ethhdr));
+
+ switch (htons(ethh -> type)) {
+ case ETHERTYPE_IP :
+ iph = (struct iphdr *) (packet + sizeof(struct ethhdr));
+ PRINT_HDR("IP:\t\t", (uint8_t *) iph, sizeof(struct iphdr));
+ switch (iph -> ip_p) {
+ case IPTYPE_UDP:
+ udph = (struct udphdr *) (packet +
+ sizeof(struct ethhdr) +
+ sizeof(struct iphdr));
+ PRINT_HDR("UDP:\t\t", (uint8_t *) udph, sizeof(struct udphdr));
+ switch (htons(udph -> uh_dport)) {
+ case UDPPORT_BOOTPC: case UDPPORT_BOOTPS:
+ btph = (struct btphdr *) (packet +
+ sizeof(struct ethhdr) +
+ sizeof(struct iphdr) +
+ sizeof(struct udphdr));
+ PRINT_HDR("DHCP/BootP:\t", (uint8_t *) btph,
+ packetsize - sizeof(struct ethhdr) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr));
+ break;
+ case UDPPORT_DNSC: case UDPPORT_DNSS:
+ dnsh = (struct dnshdr *) (packet +
+ sizeof(struct ethhdr) +
+ sizeof(struct iphdr) +
+ sizeof(struct udphdr));
+ PRINT_HDR("DNS:\t\t", (uint8_t *) dnsh,
+ packetsize - sizeof(struct ethhdr) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr));
+ break;
+ }
+ break;
+ }
+ break;
+ case ETHERTYPE_ARP:
+ arph = (struct arphdr *) (packet + sizeof(struct ethhdr));
+ PRINT_HDR("ARP:\t\t", (uint8_t *) arph, sizeof(struct arphdr));
+ break;
+ }
+}
+
+#endif
diff --git a/clients/net-snk/app/netlib/netbase.h b/clients/net-snk/app/netlib/netbase.h
new file mode 100644
index 0000000..c0f5afb
--- /dev/null
+++ b/clients/net-snk/app/netlib/netbase.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/* Network debug switches */
+
+/* main debug switch, without this switch the others don't work */
+// #define NET_DEBUG
+
+/* show received data */
+// #define NET_SHOW_RECV
+
+/* show transmitted data */
+// #define NET_SHOW_XMIT
+
+#include <types.h>
+
+/* Initializes basic network enviroment and ARP-client */
+extern void netbase_init(int32_t device_socket, uint8_t * own_mac, uint32_t own_ip);
+
+/* Sets routing parameters */
+extern int8_t net_setrouter(uint32_t router_ip, uint32_t subnet_mask);
+
+/* For given IP retrieves MAC address (or sets router MAC) */
+extern int8_t net_iptomac(uint32_t dest_ip, uint8_t dest_mac[]);
+
+/* Receives and handles packets, according to Receive-handle diagram */
+extern int32_t receive_ether(void);
+
+/* fills ethernet header */
+extern void fill_ethhdr(uint8_t * packet, uint16_t eth_type,
+ uint8_t * src_mac, uint8_t * dest_mac);
+
+/* fills ip header */
+extern void fill_iphdr(uint8_t * packet, uint16_t packetsize,
+ uint8_t ip_proto, uint32_t ip_src, uint32_t ip_dst);
+
+/* fills udp header */
+extern void fill_udphdr(uint8_t *packet, uint16_t packetsize,
+ uint16_t src_port, uint16_t dest_port);
+
+#ifdef NET_DEBUG
+
+
+/* DEBUG: Dumps ethernet-packet with appropriate header names */
+extern void net_print_packet(uint8_t * packet, uint16_t packetsize);
+
+
+#define NET_DEBUG_PRINTF(format, ...) printf(format, ## __VA_ARGS__)
+
+
+/* Prints message and IP in the following format: "DDD.DDD.DDD.DDD" */
+#define PRINT_MSGIP(msg, ip) \
+ do { \
+ printf("%s%03d.%03d.%03d.%03d\n", msg, \
+ (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, \
+ (ip >> 8) & 0xFF, (ip >> 0) & 0xFF); \
+ } while (0)
+
+
+/* Prints message and MAC in the following format "XX.XX.XX.XX.XX.XX" */
+#define PRINT_MSGMAC(msg, mac) \
+ do { \
+ printf("%s%02X:%02X:%02X:%02X:%02X:%02X\n", msg, \
+ mac[0], mac[1], mac[2], \
+ mac[3], mac[4], mac[5]); \
+ } while (0)
+
+
+/* Prints packet header in the following form: "msg: XX XX XX ... XX" */
+#define PRINT_HDR(msg, hdr, hdrsize) \
+ do { \
+ uint16_t i, j; \
+ printf("%s", msg); \
+ for (i = 0; i < hdrsize; ) { \
+ for (j = 0; j < 20; j++, i++) \
+ printf("%2x ", * (hdr + i)); \
+ printf("\n\t\t"); \
+ } \
+ printf("\n"); \
+ } while (0)
+
+
+#ifdef NET_SHOW_XMIT
+
+/* Prints "sending" packet with approp. header names */
+#define PRINT_SENDING(packet, packetsize) \
+ do { \
+ printf("\nSending packet, size:\t%d\n", packetsize); \
+ net_print_packet(packet, packetsize); \
+ } while (0)
+
+#else
+
+#define PRINT_SENDING(packet, packetsize)
+
+#endif
+
+#ifdef NET_SHOW_RECV
+
+/* Prints "received" packet with approp. header names */
+#define PRINT_RECEIVED(packet, packetsize) \
+ do { \
+ printf("\nReceived packet, size:\t%d\n", packetsize); \
+ net_print_packet(packet, packetsize); \
+ } while (0)
+
+#else
+
+#define PRINT_RECEIVED(packet, packetsize)
+
+#endif
+
+#else // NET_DEBUG not defined
+
+#define NET_DEBUG_PRINTF(format, ...)
+
+#define PRINT_MSGIP(msg, ip)
+
+#define PRINT_MSGMAC(msg, mac)
+
+#define PRINT_HDR(msg, hdr, hdrsize)
+
+#define NET_PRINT_PACKET(packet, packetsize)
+
+#define PRINT_SENDING(packet, packetsize)
+
+#define PRINT_RECEIVED(packet, packetsize)
+
+#endif
diff --git a/clients/net-snk/app/netlib/netlib.h b/clients/net-snk/app/netlib/netlib.h
new file mode 100644
index 0000000..752df1f
--- /dev/null
+++ b/clients/net-snk/app/netlib/netlib.h
@@ -0,0 +1,146 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _NETLIB_H_
+#define _NETLIB_H_
+
+#include <types.h>
+
+#define ETH_MTU_SIZE 1518 /**< Maximum Transfer Unit */
+#define ETH_ALEN 6 /**< HW address length */
+#define ETHERTYPE_IP 0x0800
+#define ETHERTYPE_ARP 0x0806
+
+#define IPTYPE_ICMP 1
+#define IPTYPE_UDP 17
+
+#define UDPPORT_BOOTPS 67 /**< UDP port of BootP/DHCP-server */
+#define UDPPORT_BOOTPC 68 /**< UDP port of BootP/DHCP-client */
+#define UDPPORT_DNSS 53 /**< UDP port of DNS-server */
+#define UDPPORT_DNSC 32769 /**< UDP port of DNS-client */
+
+typedef int32_t socklen_t;
+
+/** \struct ethhdr
+ * A header for Ethernet-packets.
+ */
+struct ethhdr {
+ uint8_t dest_mac[ETH_ALEN]; /**< Destination HW address */
+ uint8_t src_mac[ETH_ALEN]; /**< Source HW address */
+ uint16_t type; /**< Next level protocol type */
+};
+
+/** \struct iphdr
+ * A header for IP-packets.
+ * For more information see RFC 791.
+ */
+struct iphdr {
+ uint8_t ip_hlv; /**< Header length and version of the header */
+ uint8_t ip_tos; /**< Type of Service */
+ uint16_t ip_len; /**< Length in octets, inlc. this header and data */
+ uint16_t ip_id; /**< ID is used to aid in assembling framents */
+ uint16_t ip_off; /**< Info about fragmentation (control, offset) */
+ uint8_t ip_ttl; /**< Time to Live */
+ uint8_t ip_p; /**< Next level protocol type */
+ uint16_t ip_sum; /**< Header checksum */
+ uint32_t ip_src; /**< Source IP address */
+ uint32_t ip_dst; /**< Destination IP address */
+};
+
+struct pseudo_iphdr {
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ int8_t ip_unused;
+ uint8_t ip_p;
+ uint16_t ip_ulen;
+};
+
+/** \struct udphdr
+ * A header for UDP-packets.
+ * For more information see RFC 768.
+ */
+struct udphdr {
+ uint16_t uh_sport; /**< Source port */
+ uint16_t uh_dport; /**< Destinantion port */
+ uint16_t uh_ulen; /**< Length in octets, incl. this header and data */
+ uint16_t uh_sum; /**< Checksum */
+};
+
+/** \struct btphdr
+ * A header for BootP/DHCP-messages.
+ * For more information see RFC 951 / RFC 2131.
+ */
+struct btphdr {
+ uint8_t op; /**< Identifies is it request (1) or reply (2) */
+ uint8_t htype; /**< HW address type (ethernet usually) */
+ uint8_t hlen; /**< HW address length */
+ uint8_t hops; /**< This info used by relay agents (not used) */
+ uint32_t xid; /**< This ID is used to match queries and replies */
+ uint16_t secs; /**< Unused */
+ uint16_t unused; /**< Unused */
+ uint32_t ciaddr; /**< Client IP address (if client knows it) */
+ uint32_t yiaddr; /**< "Your" (client) IP address */
+ uint32_t siaddr; /**< Next server IP address (TFTP server IP) */
+ uint32_t giaddr; /**< Gateway IP address (used by relay agents) */
+ uint8_t chaddr[16]; /**< Client HW address */
+ uint8_t sname[64]; /**< Server host name (TFTP server name) */
+ uint8_t file[128]; /**< Boot file name */
+ uint8_t vend[64]; /**< Optional parameters field (DHCP-options) */
+};
+
+struct tftphdr {
+ int16_t th_opcode;
+ uint16_t th_data;
+};
+
+
+/** \struct arphdr
+ * A header for ARP-messages, retains info about HW and proto addresses.
+ * For more information see RFC 826.
+ */
+struct arphdr {
+ uint16_t hw_type; /**< HW address space (1 for Ethernet) */
+ uint16_t proto_type; /**< Protocol address space */
+ uint8_t hw_len; /**< Byte length of each HW address */
+ uint8_t proto_len; /**< Byte length of each proto address */
+ uint16_t opcode; /**< Identifies is it request (1) or reply (2) */
+ uint8_t src_mac[6]; /**< HW address of sender of this packet */
+ uint32_t src_ip; /**< Proto address of sender of this packet */
+ uint8_t dest_mac[6]; /**< HW address of target of this packet */
+ uint32_t dest_ip; /**< Proto address of target of this packet */
+} __attribute((packed));
+
+typedef struct {
+ uint32_t own_ip;
+ uint32_t server_ip;
+ uint8_t own_mac[6]; // unsigned
+ uint8_t server_mac[6]; // unsigned
+ int8_t filename[256];
+} filename_ip_t;
+
+int dhcp(int32_t, filename_ip_t *, unsigned int);
+void dhcp_send_release(void);
+
+int bootp(int32_t, filename_ip_t *, unsigned int);
+
+typedef struct {
+ uint32_t bad_tftp_packets;
+ uint32_t no_packets;
+ uint32_t blocks_missed;
+ uint32_t blocks_received;
+} tftp_err_t;
+
+int tftp(int, filename_ip_t *, unsigned char *, int, unsigned int, tftp_err_t *);
+int tftp_netsave(int32_t, filename_ip_t *, uint8_t * buffer, int32_t len,
+ int use_ci, unsigned int retries, tftp_err_t * tftp_err);
+
+#endif /* _NETLIB_H_ */
diff --git a/clients/net-snk/app/netlib/tftp.c b/clients/net-snk/app/netlib/tftp.c
new file mode 100644
index 0000000..7536770
--- /dev/null
+++ b/clients/net-snk/app/netlib/tftp.c
@@ -0,0 +1,658 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/socket.h>
+
+#include <netlib/netlib.h>
+#include <netlib/icmp.h>
+
+//#define __DEBUG__
+
+#define BUFFER_LEN 2048
+#define ACK_BUFFER_LEN 256
+#define READ_BUFFER_LEN 256
+
+#define ENOTFOUND 1
+#define EACCESS 2
+#define EBADOP 4
+#define EBADID 5
+#define ENOUSER 7
+//#define EUNDEF 0
+//#define ENOSPACE 3
+//#define EEXISTS 6
+
+#define RRQ 1
+#define WRQ 2
+#define DATA 3
+#define ACK 4
+#define ERROR 5
+#define OACK 6
+
+/**
+ * dump_package - Prints a package.
+ *
+ * @package: package which is to print
+ * @len: length of the package
+ */
+#ifdef __DEBUG__
+
+static void
+dump_package(unsigned char *buffer, unsigned int len)
+{
+ int i;
+
+ for (i = 1; i <= len; i++) {
+ printf("%02x%02x ", buffer[i - 1], buffer[i]);
+ i++;
+ if ((i % 16) == 0)
+ printf("\n");
+ }
+ printf("\n");
+}
+#endif
+
+/* UDP header checksum calculation */
+
+static unsigned short
+checksum(unsigned short *packet, int words, unsigned short *pseudo_ip)
+{
+ int i;
+ unsigned long checksum;
+ for (checksum = 0; words > 0; words--)
+ checksum += *packet++;
+ if (pseudo_ip) {
+ for (i = 0; i < 6; i++)
+ checksum += *pseudo_ip++;
+ }
+ checksum = (checksum >> 16) + (checksum & 0xffff);
+ checksum += (checksum >> 16);
+ return ~checksum;
+}
+
+
+/**
+ * send_rrq - Sends a read request package.
+ *
+ * @client: client IPv4 address (e.g. 127.0.0.1)
+ * @server: server IPv4 address (e.g. 127.0.0.1)
+ * @filename: name of the file which should be downloaded
+ */
+static void
+send_rrq(int boot_device, filename_ip_t * fn_ip)
+{
+ int i;
+ unsigned char mode[] = "octet";
+ unsigned char packet[READ_BUFFER_LEN];
+ char *ptr;
+ struct ethhdr *ethh;
+ struct iphdr *ip;
+ struct udphdr *udph;
+ struct tftphdr *tftp;
+ struct pseudo_iphdr piph = { 0 };
+
+ memset(packet, 0, READ_BUFFER_LEN);
+
+ ethh = (struct ethhdr *) packet;
+
+ memcpy(ethh->src_mac, fn_ip->own_mac, 6);
+ memcpy(ethh->dest_mac, fn_ip->server_mac, 6);
+ ethh->type = htons(ETHERTYPE_IP);
+
+ ip = (struct iphdr *) ((unsigned char *) ethh + sizeof(struct ethhdr));
+ ip->ip_hlv = 0x45;
+ ip->ip_tos = 0x00;
+ ip->ip_len = sizeof(struct iphdr) + sizeof(struct udphdr)
+ + strlen((char *) fn_ip->filename) + strlen((char *) mode) + 4
+ + strlen("blksize") + strlen("1432") + 2;
+ ip->ip_id = 0x0;
+ ip->ip_off = 0x0000;
+ ip->ip_ttl = 60;
+ ip->ip_p = 17;
+ ip->ip_src = fn_ip->own_ip;
+ ip->ip_dst = fn_ip->server_ip;
+ ip->ip_sum = 0;
+
+ udph = (struct udphdr *) (ip + 1);
+ udph->uh_sport = htons(2001);
+ udph->uh_dport = htons(69);
+ udph->uh_ulen = htons(sizeof(struct udphdr)
+ + strlen((char *) fn_ip->filename) + strlen((char *) mode) + 4
+ + strlen("blksize") + strlen("1432") + 2);
+
+ tftp = (struct tftphdr *) (udph + 1);
+ tftp->th_opcode = htons(RRQ);
+
+ ptr = (char *) &tftp->th_data;
+ memcpy(ptr, fn_ip->filename, strlen((char *) fn_ip->filename) + 1);
+
+ ptr += strlen((char *) fn_ip->filename) + 1;
+ memcpy(ptr, mode, strlen((char *) mode) + 1);
+
+ ptr += strlen((char *) mode) + 1;
+ memcpy(ptr, "blksize", strlen("blksize") + 1);
+
+ ptr += strlen("blksize") + 1;
+ memcpy(ptr, "1432", strlen("1432") + 1);
+
+ piph.ip_src = ip->ip_src;
+ piph.ip_dst = ip->ip_dst;
+ piph.ip_p = ip->ip_p;
+ piph.ip_ulen = udph->uh_ulen;
+
+ udph->uh_sum = 0;
+ udph->uh_sum =
+ checksum((unsigned short *) udph, udph->uh_ulen >> 1,
+ (unsigned short *) &piph);
+
+ ip->ip_sum =
+ checksum((unsigned short *) ip, sizeof(struct iphdr) >> 1, 0);
+ i = send(boot_device, packet, ip->ip_len + sizeof(struct ethhdr), 0);
+#ifdef __DEBUG__
+ printf("tftp RRQ %d bytes transmitted over socket.\n", i);
+#endif
+ return;
+}
+
+/**
+ * send_ack - Sends a acknowlege package.
+ *
+ * @boot_device:
+ * @fn_ip:
+ * @blckno: block number
+ */
+static void
+send_ack(int boot_device, filename_ip_t * fn_ip,
+ int blckno, unsigned short dport)
+{
+ int i;
+ unsigned char packet[ACK_BUFFER_LEN];
+ struct ethhdr *ethh;
+ struct iphdr *ip;
+ struct udphdr *udph;
+ struct tftphdr *tftp;
+ struct pseudo_iphdr piph = { 0 };
+
+ memset(packet, 0, ACK_BUFFER_LEN);
+
+ ethh = (struct ethhdr *) packet;
+ memcpy(ethh->src_mac, fn_ip->own_mac, 6);
+ memcpy(ethh->dest_mac, fn_ip->server_mac, 6);
+ ethh->type = htons(ETHERTYPE_IP);
+
+ ip = (struct iphdr *) ((unsigned char *) ethh + sizeof(struct ethhdr));
+ ip->ip_hlv = 0x45;
+ ip->ip_tos = 0x00;
+ ip->ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + 4;
+ ip->ip_id = 0;
+ ip->ip_off = 0x0000;
+ ip->ip_ttl = 60;
+ ip->ip_p = 17;
+ ip->ip_src = fn_ip->own_ip;
+ ip->ip_dst = fn_ip->server_ip;
+
+ ip->ip_sum = 0;
+
+ udph = (struct udphdr *) (ip + 1);
+ udph->uh_sport = htons(2001);
+ udph->uh_dport = htons(dport);
+ udph->uh_ulen = htons(sizeof(struct udphdr) + 4);
+
+ tftp = (struct tftphdr *) (udph + 1);
+ tftp->th_opcode = htons(ACK);
+ tftp->th_data = htons(blckno);
+
+ piph.ip_src = ip->ip_src;
+ piph.ip_dst = ip->ip_dst;
+ piph.ip_p = ip->ip_p;
+ piph.ip_ulen = udph->uh_ulen;
+
+ udph->uh_sum = 0;
+ udph->uh_sum =
+ checksum((unsigned short *) udph, udph->uh_ulen >> 1,
+ (unsigned short *) &piph);
+
+ ip->ip_sum =
+ checksum((unsigned short *) ip, sizeof(struct iphdr) >> 1, 0);
+
+ i = send(boot_device, packet, ip->ip_len + sizeof(struct ethhdr), 0);
+
+#ifdef __DEBUG__
+ printf("tftp ACK %d bytes transmitted over socket.\n", i);
+#endif
+
+ return;
+}
+
+/**
+ * send_error - Sends an error package.
+ *
+ * @boot_device: socket handle
+ * @fn_ip: some OSI CEP-IDs
+ * @error_code: Used sub code for error packet
+ * @dport: UDP destination port
+ */
+static void
+send_error(int boot_device, filename_ip_t * fn_ip,
+ int error_code, unsigned short dport)
+{
+ int i;
+ unsigned char packet[256];
+ struct ethhdr *ethh;
+ struct iphdr *ip;
+ struct udphdr *udph;
+ struct tftphdr *tftp;
+ struct pseudo_iphdr piph = { 0 };
+
+ memset(packet, 0, 256);
+
+ ethh = (struct ethhdr *) packet;
+ memcpy(ethh->src_mac, fn_ip->own_mac, 6);
+ memcpy(ethh->dest_mac, fn_ip->server_mac, 6);
+ ethh->type = htons(ETHERTYPE_IP);
+
+ ip = (struct iphdr *) ((unsigned char *) ethh + sizeof(struct ethhdr));
+ ip->ip_hlv = 0x45;
+ ip->ip_tos = 0x00;
+ ip->ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + 5;
+ ip->ip_id = 0;
+ ip->ip_off = 0x0000;
+ ip->ip_ttl = 60;
+ ip->ip_p = 17;
+ ip->ip_src = fn_ip->own_ip;
+ ip->ip_dst = fn_ip->server_ip;
+
+ ip->ip_sum = 0;
+
+ udph = (struct udphdr *) (ip + 1);
+ udph->uh_sport = htons(2001);
+ udph->uh_dport = htons(dport);
+ udph->uh_ulen = htons(sizeof(struct udphdr) + 5);
+
+ tftp = (struct tftphdr *) (udph + 1);
+ tftp->th_opcode = htons(ERROR);
+ tftp->th_data = htons(error_code);
+ ((char *) &tftp->th_data)[2] = 0;
+
+ piph.ip_src = ip->ip_src;
+ piph.ip_dst = ip->ip_dst;
+ piph.ip_p = ip->ip_p;
+ piph.ip_ulen = udph->uh_ulen;
+
+ udph->uh_sum = 0;
+ udph->uh_sum =
+ checksum((unsigned short *) udph, udph->uh_ulen >> 1,
+ (unsigned short *) &piph);
+
+ ip->ip_sum =
+ checksum((unsigned short *) ip, sizeof(struct iphdr) >> 1, 0);
+
+ i = send(boot_device, packet, ip->ip_len + sizeof(struct ethhdr), 0);
+
+#ifdef __DEBUG__
+ printf("tftp ERROR %d bytes transmitted over socket.\n", i);
+#endif
+
+ return;
+}
+
+
+static int
+send_arp_reply(int boot_device, filename_ip_t * fn_ip)
+{
+ int i;
+ unsigned int packetsize = sizeof(struct ethhdr) + sizeof(struct arphdr);
+ unsigned char packet[packetsize];
+ struct ethhdr *ethh;
+ struct arphdr *arph;
+
+ ethh = (struct ethhdr *) packet;
+ arph = (struct arphdr *) ((void *) ethh + sizeof(struct ethhdr));
+
+ memset(packet, 0, packetsize);
+
+ memcpy(ethh->src_mac, fn_ip->own_mac, 6);
+ memcpy(ethh->dest_mac, fn_ip->server_mac, 6);
+ ethh->type = htons(ETHERTYPE_ARP);
+
+ arph->hw_type = 1;
+ arph->proto_type = 0x800;
+ arph->hw_len = 6;
+ arph->proto_len = 4;
+
+ memcpy(arph->src_mac, fn_ip->own_mac, 6);
+ arph->src_ip = fn_ip->own_ip;
+
+ arph->dest_ip = fn_ip->server_ip;
+
+ arph->opcode = 2;
+#ifdef __DEBUG__
+ printf("send arp reply\n");
+#endif
+#if 0
+ printf("Sending packet\n");
+ printf("Packet is ");
+ for (i = 0; i < packetsize; i++)
+ printf(" %2.2x", packet[i]);
+ printf(".\n");
+#endif
+
+ i = send(boot_device, packet, packetsize, 0);
+ return i;
+}
+
+static void
+print_progress(int urgent, int received_bytes)
+{
+ static unsigned int i = 1;
+ static int first = -1;
+ static int last_bytes = 0;
+ char buffer[100];
+ char *ptr;
+
+ // 1MB steps or 0x400 times or urgent
+ if(((received_bytes - last_bytes) >> 20) > 0
+ || (i & 0x3FF) == 0 || urgent) {
+ if(!first) {
+ sprintf(buffer, "%d KBytes", (last_bytes >> 10));
+ for(ptr = buffer; *ptr != 0; ++ptr)
+ *ptr = '\b';
+ printf(buffer);
+ }
+ printf("%d KBytes", (received_bytes >> 10));
+ i = 1;
+ first = 0;
+ last_bytes = received_bytes;
+ }
+ ++i;
+}
+
+/**
+ * get_blksize tries to extract the blksize from the OACK package
+ * the TFTP returned. From RFC 1782
+ * The OACK packet has the following format:
+ *
+ * +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ * | opc | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
+ * +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ *
+ * @param buffer the network packet
+ * @param len the length of the network packet
+ * @return the blocksize the server supports or 0 for error
+ */
+static int
+get_blksize(unsigned char *buffer, unsigned int len)
+{
+ unsigned char *orig = buffer;
+ /* skip all headers until tftp has been reached */
+ buffer += sizeof(struct ethhdr);
+ buffer += sizeof(struct iphdr);
+ buffer += sizeof(struct udphdr);
+ /* skip opc */
+ buffer += 2;
+ while (buffer < orig + len) {
+ if (!memcmp(buffer, "blksize", strlen("blksize") + 1))
+ return (unsigned short) strtoul((char *) (buffer +
+ strlen("blksize") + 1),
+ (char **) NULL, 10);
+ else {
+ /* skip the option name */
+ buffer = (unsigned char *) strchr((char *) buffer, 0);
+ if (!buffer)
+ return 0;
+ buffer++;
+ /* skip the option value */
+ buffer = (unsigned char *) strchr((char *) buffer, 0);
+ if (!buffer)
+ return 0;
+ buffer++;
+ }
+ }
+ return 0;
+}
+
+/**
+ * this prints out some status characters
+ * \|-/ for each packet received
+ * A for an arp packet
+ * I for an ICMP packet
+ * #+* for different unexpected TFTP packets (not very good)
+ */
+static int
+the_real_tftp(int boot_device, filename_ip_t * fn_ip, unsigned char *buffer,
+ int len, unsigned int retries, tftp_err_t * tftp_err)
+{
+ int i, j = 0;
+ int received_len = 0;
+ struct ethhdr *ethh;
+ struct arphdr *arph;
+
+ struct iphdr *ip;
+ struct udphdr *udph;
+ struct tftphdr *tftp;
+ struct icmphdr *icmp;
+
+ unsigned char packet[BUFFER_LEN];
+ short port_number = -1;
+ unsigned short block = 0;
+ unsigned short blocksize = 512;
+ int lost_packets = 0;
+
+ tftp_err->bad_tftp_packets = 0;
+ tftp_err->no_packets = 0;
+
+ send_rrq(boot_device, fn_ip);
+
+ printf(" Receiving data: ");
+ print_progress(-1, 0);
+
+ set_timer(TICKS_SEC);
+ while (j++ < 0x100000) {
+ /* bad_tftp_packets are counted whenever we receive a TFTP packet
+ * which was not expected; if this gets larger than 'retries'
+ * we just exit */
+ if (tftp_err->bad_tftp_packets > retries) {
+ return -40;
+ }
+ /* no_packets counts the times we have returned from recv() without
+ * any packet received; if this gets larger than 'retries'
+ * we also just exit */
+ if (tftp_err->no_packets > retries) {
+ return -41;
+ }
+ /* don't wait longer than 0.5 seconds for packet to be recevied */
+ do {
+ i = recv(boot_device, packet, BUFFER_LEN, 0);
+ if (i != 0)
+ break;
+ } while (get_timer() > 0);
+
+ /* no packet received; no processing */
+ if (i == 0) {
+ /* the server doesn't seem to retry let's help out a bit */
+ if (tftp_err->no_packets > 4 && port_number != -1
+ && block > 1)
+ send_ack(boot_device, fn_ip, block,
+ port_number);
+ tftp_err->no_packets++;
+ set_timer(TICKS_SEC);
+ continue;
+ }
+#ifndef __DEBUG__
+ print_progress(0, received_len);
+#endif
+ ethh = (struct ethhdr *) packet;
+ arph =
+ (struct arphdr *) ((void *) ethh + sizeof(struct ethhdr));
+ ip = (struct iphdr *) (packet + sizeof(struct ethhdr));
+ udph = (struct udphdr *) ((void *) ip + sizeof(struct iphdr));
+ tftp =
+ (struct tftphdr *) ((void *) udph + sizeof(struct udphdr));
+ icmp = (struct icmphdr *) ((void *) ip + sizeof(struct iphdr));
+
+ if (memcmp(ethh->dest_mac, fn_ip->own_mac, 6) == 0) {
+ set_timer(TICKS_SEC);
+ tftp_err->no_packets = 0;
+ }
+
+ if (ethh->type == htons(ETHERTYPE_ARP) &&
+ arph->hw_type == 1 &&
+ arph->proto_type == 0x800 && arph->opcode == 1) {
+ /* let's see if the arp request asks for our IP address
+ * else we will not answer */
+ if (fn_ip->own_ip == arph->dest_ip) {
+#ifdef __DEBUG__
+ printf("\bA ");
+#endif
+ send_arp_reply(boot_device, fn_ip);
+ }
+ continue;
+ }
+
+ /* check if packet is an ICMP packet */
+ if (ip->ip_p == PROTO_ICMP) {
+#ifdef __DEBUG__
+ printf("\bI ");
+#endif
+ i = handle_icmp(icmp);
+ if (i)
+ return i;
+ }
+
+ /* only IPv4 UDP packets we want */
+ if (ip->ip_hlv != 0x45 || ip->ip_p != 0x11) {
+#ifdef __DEBUG__
+ printf("Unknown packet %x %x %x %x %x \n", ethh->type,
+ ip->ip_hlv, ip->ip_p, ip->ip_dst, fn_ip->own_ip);
+#endif
+ continue;
+ }
+
+ /* we only want packets for our own IP and broadcast UDP packets
+ * there will be probably never be a broadcast UDP TFTP packet
+ * but the RFC talks about it (crazy RFC) */
+ if (!(ip->ip_dst == fn_ip->own_ip || ip->ip_dst == 0xFFFFFFFF))
+ continue;
+#ifdef __DEBUG__
+ dump_package(packet, i);
+#endif
+
+ port_number = udph->uh_sport;
+ if (tftp->th_opcode == htons(OACK)) {
+ /* an OACK means that the server answers our blocksize request */
+ blocksize = get_blksize(packet, i);
+ if (!blocksize || blocksize > 1432) {
+ send_error(boot_device, fn_ip, 8, port_number);
+ return -8;
+ }
+ send_ack(boot_device, fn_ip, 0, port_number);
+ } else if (tftp->th_opcode == htons(ACK)) {
+ /* an ACK means that the server did not answers
+ * our blocksize request, therefore we will set the blocksize
+ * to the default value of 512 */
+ blocksize = 512;
+ send_ack(boot_device, fn_ip, 0, port_number);
+ } else if ((unsigned char) tftp->th_opcode == ERROR) {
+#ifdef __DEBUG__
+ printf("tftp->th_opcode : %x\n", tftp->th_opcode);
+ printf("tftp->th_data : %x\n", tftp->th_data);
+#endif
+ if ((unsigned char) tftp->th_data == ENOTFOUND) /* 1 */
+ return -3; // ERROR: file not found
+ else if ((unsigned char) tftp->th_data == EACCESS) /* 2 */
+ return -4; // ERROR: access violation
+ else if ((unsigned char) tftp->th_data == EBADOP) /* 4 */
+ return -5; // ERROR: illegal TFTP operation
+ else if ((unsigned char) tftp->th_data == EBADID) /* 5 */
+ return -6; // ERROR: unknown transfer ID
+ else if ((unsigned char) tftp->th_data == ENOUSER) /* 7 */
+ return -7; // ERROR: no such user
+ return -1; // ERROR: unknown error
+ } else if (tftp->th_opcode == DATA) {
+ /* DATA PACKAGE */
+ if (tftp->th_data == block + 1)
+ block++;
+ else if (tftp->th_data == block) {
+#ifdef __DEBUG__
+ printf
+ ("\nTFTP: Received block %x, expected block was %x\n",
+ tftp->th_data, block + 1);
+ printf("\b+ ");
+#endif
+ send_ack(boot_device, fn_ip, tftp->th_data,
+ port_number);
+ lost_packets++;
+ tftp_err->bad_tftp_packets++;
+ continue;
+ } else if (tftp->th_data < block) {
+#ifdef __DEBUG__
+ printf
+ ("\nTFTP: Received block %x, expected block was %x\n",
+ tftp->th_data, block + 1);
+ printf("\b* ");
+#endif
+ /* This means that an old data packet appears (again);
+ * this happens sometimes if we don't answer fast enough
+ * and a timeout is generated on the server side;
+ * as we already have this packet we just ignore it */
+ tftp_err->bad_tftp_packets++;
+ continue;
+ } else {
+ tftp_err->blocks_missed = block + 1;
+ tftp_err->blocks_received = tftp->th_data;
+ return -42;
+ }
+
+ tftp_err->bad_tftp_packets = 0;
+ /* check if our buffer is large enough */
+ if (received_len + udph->uh_ulen - 12 > len)
+ return -2;
+ memcpy(buffer + received_len, &tftp->th_data + 1,
+ udph->uh_ulen - 12);
+ send_ack(boot_device, fn_ip, tftp->th_data,
+ port_number);
+ received_len += udph->uh_ulen - 12;
+ /* Last packet reached if the payload of the UDP packet
+ * is smaller than blocksize + 12
+ * 12 = UDP header (8) + 4 bytes TFTP payload */
+ if (udph->uh_ulen < blocksize + 12)
+ break;
+ /* 0xffff is the highest block number possible
+ * see the TFTP RFCs */
+ if (block >= 0xffff)
+ return -9;
+ } else {
+#ifdef __DEBUG__
+ printf("Unknown packet %x\n", tftp->th_opcode);
+ printf("\b# ");
+#endif
+ tftp_err->bad_tftp_packets++;
+ continue;
+ }
+ }
+ print_progress(-1, received_len);
+ printf("\n");
+ if (lost_packets)
+ printf("Lost ACK packets: %d\n", lost_packets);
+ return received_len;
+}
+
+int
+tftp(int boot_device, filename_ip_t * fn_ip, unsigned char *buffer, int len,
+ unsigned int retries, tftp_err_t * tftp_err)
+{
+ return the_real_tftp(boot_device, fn_ip, buffer, len, retries,
+ tftp_err);
+}
diff --git a/clients/net-snk/client.lds b/clients/net-snk/client.lds
new file mode 100644
index 0000000..5943897
--- /dev/null
+++ b/clients/net-snk/client.lds
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_entry)
+
+SECTIONS {
+ .client 0xF000000:
+ {
+ __client_start = .;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ KEEP (*(.opd))
+ . = ALIGN(256);
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(256);
+ } =0x60000000
+
+ .lowmem :
+ {
+ _lowmem_start = .;
+ *(.lowmem)
+ _lowmem_end = .;
+ }
+
+ .got :
+ {
+ . = ALIGN(8);
+ _got = .;
+ *(.got .toc)
+ _got_end = .;
+ }
+ .comment : { *(.comment) }
+ .branch_lt : { *(.branch_lt) }
+ .bss :
+ {
+ *(*COM* .bss .gnu.linkonce.b.*)
+ __client_end = .;
+ }
+}
diff --git a/clients/net-snk/include/crt0.h b/clients/net-snk/include/crt0.h
new file mode 100644
index 0000000..4b8ee89
--- /dev/null
+++ b/clients/net-snk/include/crt0.h
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _CRT0_H
+#define _CRT0_H
+
+int gen_argv(const char *, int, char **);
+
+
+#endif
diff --git a/clients/net-snk/include/endian.h b/clients/net-snk/include/endian.h
new file mode 100644
index 0000000..e57317d
--- /dev/null
+++ b/clients/net-snk/include/endian.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef MY_ENDIAN_H
+#define MY_ENDIAN_H
+
+#include "types.h"
+
+extern inline uint16_t bswap_16 (uint16_t x);
+extern inline uint32_t bswap_32 (uint32_t x);
+extern inline uint64_t bswap_64 (uint64_t x);
+#define CPU_BIG_ENDIAN
+
+#ifndef CPU_BIG_ENDIAN
+#define cpu_to_le64(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_be16(x) bswap_16(x)
+#define cpu_to_be32(x) bswap_32(x)
+#define le64_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
+#define be32_to_cpu(x) bswap_32(x)
+#else
+#define cpu_to_le64(x) bswap_64(x)
+#define cpu_to_le32(x) bswap_32(x)
+#define cpu_to_le16(x) bswap_16(x)
+#define cpu_to_be16(x) (x)
+#define cpu_to_be32(x) (x)
+#define le64_to_cpu(x) bswap_64(x)
+#define le32_to_cpu(x) bswap_32(x)
+#define le16_to_cpu(x) bswap_16(x)
+#define be32_to_cpu(x) (x)
+#endif
+
+#endif
diff --git a/clients/net-snk/include/fcntl.h b/clients/net-snk/include/fcntl.h
new file mode 100644
index 0000000..80b7846
--- /dev/null
+++ b/clients/net-snk/include/fcntl.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _FCNTL_H
+#define _FCNTL_H
+
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDRW 02
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#endif /* fcntl.h */
diff --git a/clients/net-snk/include/ioctl.h b/clients/net-snk/include/ioctl.h
new file mode 100644
index 0000000..1991bfc
--- /dev/null
+++ b/clients/net-snk/include/ioctl.h
@@ -0,0 +1,19 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _IOCTL_H
+#define _IOCTL_H
+
+extern int ioctl(int fd, int request, void *data);
+
+#endif
diff --git a/clients/net-snk/include/kernel.h b/clients/net-snk/include/kernel.h
new file mode 100644
index 0000000..531d82c
--- /dev/null
+++ b/clients/net-snk/include/kernel.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef KERNEL_H
+#define KERNEL_H
+#include <stddef.h>
+
+int printk(const char *, ...);
+void *memcpy(void *, const void *, size_t);
+void *memset(void *, int, size_t);
+void udelay(unsigned int);
+void mdelay(unsigned int);
+int getchar(void);
+
+int strcmp(const char *, const char *);
+char *strcpy(char *, const char *);
+int printf(const char *, ...);
+void *malloc_aligned(size_t size, int align);
+
+void exception_forward(void);
+void undo_exception(void);
+
+#endif
diff --git a/clients/net-snk/include/macros.h b/clients/net-snk/include/macros.h
new file mode 100644
index 0000000..9c86ea5
--- /dev/null
+++ b/clients/net-snk/include/macros.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#define LOAD64(rn,name) \
+ lis rn,name##@highest; \
+ ori rn,rn,name##@higher; \
+ rldicr rn,rn,32,31; \
+ oris rn,rn,name##@h; \
+ ori rn,rn,name##@l
+
+#define LOAD32(rn, name) \
+ lis rn,name##@h; \
+ ori rn,rn,name##@l
+
+// load 32 bit constant in little endian order
+#define LOAD32le(rn,name) \
+ lis rn,(((name>>8)&0x00FF)|((name<<8)&0xFF00)); \
+ ori rn,rn,(((name>>24)&0x00FF)|((name>>8)&0xFF00))
+
+// load 16 bit constant in little endian order
+#define LOAD16le(rn,name) \
+ li rn,(((name>>8)&0x00FF)|(name<<8))
+
+#define SET_CI(rn) \
+ sync; \
+ mfspr rn,LPCR; \
+ ori rn,rn,2; \
+ mtspr LPCR,rn; \
+ sync
+
+#define CLR_CI(rn) \
+ sync; \
+ mfspr rn,LPCR; \
+ ori rn,rn,2; \
+ xori rn,rn,2; \
+ mtspr LPCR,rn; \
+ sync
+
+#define SAVE_AND_SET_CI(rn,rx) \
+ sync; \
+ mfspr rx,LPCR; \
+ ori rn,rx,2; \
+ mtspr LPCR,rn; \
+ sync
+
+#define RESTORE_CI(rx) \
+ sync; \
+ mtspr LPCR,rx; \
+ sync
+
+#define ENTRY(func_name) \
+ .text; \
+ .align 2; \
+ .globl .func_name; \
+ .func_name: \
+ .globl func_name; \
+ func_name:
+
+#define ASM_ENTRY(fn) \
+ .globl fn; \
+fn:
+
diff --git a/clients/net-snk/include/net.h b/clients/net-snk/include/net.h
new file mode 100644
index 0000000..d54501f
--- /dev/null
+++ b/clients/net-snk/include/net.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _NET_H
+#define _NET_H
+#include <pci.h>
+
+typedef struct {
+ int device_id;
+ int vendor_id;
+
+ int (*net_init) (pci_config_t *pciconf, char *mac_addr);
+ int (*net_term) (pci_config_t *pciconf);
+ int (*net_transmit) (pci_config_t *pciconf, char *buffer, int len);
+ int (*net_receive) (pci_config_t *pciconf, char *buffer, int len);
+ int (*net_ioctl) (pci_config_t *pciconf, int request, void* data);
+
+} net_driver_t;
+
+#endif
diff --git a/clients/net-snk/include/netdriver_int.h b/clients/net-snk/include/netdriver_int.h
new file mode 100644
index 0000000..68c1cc9
--- /dev/null
+++ b/clients/net-snk/include/netdriver_int.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _NETDRIVER_INT_H
+#define _NETDRIVER_INT_H
+#include <stddef.h>
+
+/* Constants for different kinds of IOCTL requests
+ */
+
+#define SIOCETHTOOL 0x1000
+
+typedef struct {
+ unsigned int addr;
+ unsigned int size;
+ int type;
+} bar_t;
+
+typedef struct {
+ unsigned long long puid;
+ unsigned int bus;
+ unsigned int devfn;
+ unsigned int vendor_id;
+ unsigned int device_id;
+ unsigned int revision_id;
+ unsigned int class_code;
+ bar_t bars[6];
+ unsigned int interrupt_line;
+} pci_config_t;
+
+typedef int (*net_init_t) (pci_config_t * conf, char *mac_addr);
+typedef int (*net_term_t) (pci_config_t * conf);
+typedef int (*net_receive_t) (pci_config_t * conf, char *buffer, int len);
+typedef int (*net_xmit_t) (pci_config_t * conf, char *buffer, int len);
+typedef int (*net_ioctl_t) (pci_config_t * conf, int request, void *data);
+
+typedef struct {
+ int version;
+ net_init_t net_init;
+ net_term_t net_term;
+ net_receive_t net_receive;
+ net_xmit_t net_xmit;
+ net_ioctl_t net_ioctl;
+} snk_module_t;
+
+
+typedef int (*print_t) (const char *, ...);
+typedef void (*us_delay_t) (unsigned int);
+typedef void (*ms_delay_t) (unsigned int);
+typedef int (*pci_config_read_t) (long long puid, int size,
+ int bus, int devfn, int offset);
+typedef int (*pci_config_write_t) (long long puid, int size,
+ int bus, int devfn, int offset, int value);
+typedef void *(*malloc_aligned_t) (size_t, int);
+typedef unsigned int (*io_read_t) (void *, size_t);
+typedef int (*io_write_t) (void *, unsigned int, size_t);
+typedef unsigned int (*romfs_lookup_t) (const char *name, void **addr);
+typedef void (*translate_addr_t) (unsigned long *);
+
+typedef struct {
+ int version;
+ print_t print;
+ us_delay_t us_delay;
+ ms_delay_t ms_delay;
+ pci_config_read_t pci_config_read;
+ pci_config_write_t pci_config_write;
+ malloc_aligned_t k_malloc_aligned;
+ io_read_t io_read;
+ io_write_t io_write;
+ romfs_lookup_t k_romfs_lookup;
+ translate_addr_t translate_addr;
+} snk_kernel_t;
+
+
+/* special structure and constants for IOCTL requests of type ETHTOOL
+ */
+
+#define ETHTOOL_GMAC 0x03
+#define ETHTOOL_SMAC 0x04
+#define ETHTOOL_VERSION 0x05
+
+typedef struct {
+ int idx;
+ char address[6];
+} ioctl_ethtool_mac_t;
+
+typedef struct {
+ unsigned int length;
+ char *text;
+} ioctl_ethtool_version_t;
+
+
+/* default structure and constants for IOCTL requests
+ */
+
+#define IF_NAME_SIZE 0xFF
+
+typedef struct {
+ char if_name[IF_NAME_SIZE];
+ int subcmd;
+ union {
+ ioctl_ethtool_mac_t mac;
+ ioctl_ethtool_version_t version;
+ } data;
+} ioctl_net_data_t;
+
+/* Entry of module */
+snk_module_t *module_init(snk_kernel_t * snk_kernel_int,
+ pci_config_t * pciconf);
+#endif /* _NETDRIVER_INT_H */
diff --git a/clients/net-snk/include/of.h b/clients/net-snk/include/of.h
new file mode 100644
index 0000000..c638dd3
--- /dev/null
+++ b/clients/net-snk/include/of.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef OF_H
+#define OF_H
+#define p32 int
+#define p32cast (int) (unsigned long) (void*)
+
+#define phandle_t p32
+#define ihandle_t p32
+
+typedef struct
+{
+ unsigned int serv;
+ int nargs;
+ int nrets;
+ unsigned int args[16];
+} of_arg_t;
+
+
+phandle_t of_finddevice (const char *);
+phandle_t of_peer (phandle_t);
+phandle_t of_child (phandle_t);
+phandle_t of_parent (phandle_t);
+int of_getprop (phandle_t, const char *, void *, int);
+void * of_call_method_3 (const char *, ihandle_t, int);
+
+
+ihandle_t of_open (const char *);
+void of_close(ihandle_t);
+int of_read (ihandle_t , void*, int);
+int of_write (ihandle_t, void*, int);
+int of_seek (ihandle_t, int, int);
+
+void * of_claim(void *, unsigned int , unsigned int );
+void of_release(void *, unsigned int );
+
+int of_yield(void);
+void * of_set_callback(void *);
+
+unsigned int romfs_lookup(const char *, void **);
+int vpd_read(unsigned int , unsigned int , char *);
+int vpd_write(unsigned int , unsigned int , char *);
+int write_mm_log(char *, unsigned int , unsigned short );
+
+#endif
diff --git a/clients/net-snk/include/pci.h b/clients/net-snk/include/pci.h
new file mode 100644
index 0000000..4c2c18b
--- /dev/null
+++ b/clients/net-snk/include/pci.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _PCI_H
+#define _PCI_H
+#include <netdriver_int.h>
+#include <of.h>
+
+int pci_calc_bar_size (long long puid, int bus, int devfn, int bar);
+int pci_get_bar_start (long long puid, int bus, int devfn, int bar);
+void pci_set_bar_start (long long puid, int bus, int devfn, int bar, int value);
+int pci_bus_scan_puid(long long puid, int class_to_check,
+ pci_config_t *pci_devices, int max_devs);
+long long get_next_phb (phandle_t *phb);
+
+#endif
diff --git a/clients/net-snk/include/rtas.h b/clients/net-snk/include/rtas.h
new file mode 100644
index 0000000..5591050
--- /dev/null
+++ b/clients/net-snk/include/rtas.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef RTAS_H
+#define RTAS_H
+
+#include "of.h"
+
+typedef struct dtime {
+ unsigned int year;
+ unsigned int month;
+ unsigned int day;
+ unsigned int hour;
+ unsigned int minute;
+ unsigned int second;
+ unsigned int nano;
+} dtime;
+
+typedef void (*thread_t) (int);
+
+int rtas_token(const char *);
+int rtas_call(int, int, int, int *, ...);
+void rtas_init();
+int rtas_pci_config_read (long long, int, int, int, int);
+int rtas_pci_config_write (long long, int, int, int, int, int);
+int rtas_set_time_of_day(dtime *);
+int rtas_get_time_of_day(dtime *);
+int rtas_ibm_update_flash_64(long long, long long);
+int rtas_ibm_update_flash_64_and_reboot(long long, long long);
+int rtas_system_reboot();
+int rtas_start_cpu (int, thread_t, int);
+int rtas_stop_self (void);
+int rtas_ibm_manage_flash(int);
+
+#endif
diff --git a/clients/net-snk/include/socket.h b/clients/net-snk/include/socket.h
new file mode 100644
index 0000000..b39f113
--- /dev/null
+++ b/clients/net-snk/include/socket.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _SOCKET_H
+#define _SOCKET_H
+extern int socket(int dom, int type, int proto, char *mac_addr);
+extern int sendto(int fd, const void* buffer, int len,
+ int flags, const void* sock_addr, int sock_addr_len);
+extern int send(int fd, void* buffer, int len, int flags);
+extern int recv(int fd, void* buffer, int len, int flags);
+
+#define htonl(x) x
+#define htons(x) x
+
+#endif
diff --git a/clients/net-snk/include/sys/socket.h b/clients/net-snk/include/sys/socket.h
new file mode 100644
index 0000000..5c38e0a
--- /dev/null
+++ b/clients/net-snk/include/sys/socket.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _SOCKET_H
+#define _SOCKET_H
+
+#include "systemcall.h"
+
+int socket(int, int, int, char *);
+int sendto(int, const void *, int, int, const void *, int);
+int send(int, void *, int, int);
+int recv(int, void *, int, int);
+
+#define htonl(x) x
+#define htons(x) x
+
+#endif
+
diff --git a/clients/net-snk/include/systemcall.h b/clients/net-snk/include/systemcall.h
new file mode 100644
index 0000000..265d7d2
--- /dev/null
+++ b/clients/net-snk/include/systemcall.h
@@ -0,0 +1,148 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef SYSTEMCALL_H
+#define SYSTEMCALL_H
+
+extern inline int
+syscall (int nr)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3");
+ asm volatile ("sc" : "=r" (r3)
+ : "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_1 (int nr, long arg0)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_2 (int nr, long arg0, long arg1)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_3 (int nr, long arg0, long arg1, long arg2)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ register unsigned long r5 asm("r5") = arg2;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r5), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_4 (int nr, long arg0, long arg1, long arg2, long arg3)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ register unsigned long r5 asm("r5") = arg2;
+ register unsigned long r6 asm("r6") = arg3;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r5), "r" (r6), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_5 (int nr, long arg0, long arg1, long arg2, long arg3,
+ long arg4)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ register unsigned long r5 asm("r5") = arg2;
+ register unsigned long r6 asm("r6") = arg3;
+ register unsigned long r7 asm("r7") = arg4;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r5),
+ "r" (r6), "r" (r7), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_6 (int nr, long arg0, long arg1, long arg2, long arg3,
+ long arg4, long arg5)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ register unsigned long r5 asm("r5") = arg2;
+ register unsigned long r6 asm("r6") = arg3;
+ register unsigned long r7 asm("r7") = arg4;
+ register unsigned long r8 asm("r8") = arg5;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r5),
+ "r" (r6), "r" (r7), "r" (r8), "r" (r0));
+ return r3;
+}
+
+extern inline long
+syscall_7 (int nr, long arg0, long arg1, long arg2, long arg3,
+ long arg4, long arg5, long arg6)
+{
+ register unsigned long r0 asm("r0") = nr;
+ register unsigned long r3 asm("r3") = arg0;
+ register unsigned long r4 asm("r4") = arg1;
+ register unsigned long r5 asm("r5") = arg2;
+ register unsigned long r6 asm("r6") = arg3;
+ register unsigned long r7 asm("r7") = arg4;
+ register unsigned long r8 asm("r8") = arg5;
+ register unsigned long r9 asm("r9") = arg6;
+ asm volatile ("sc" : "=r" (r3)
+ : "0" (r3), "r" (r4), "r" (r5),
+ "r" (r6), "r" (r7), "r" (r8),
+ "r" (r9), "r" (r0));
+ return r3;
+}
+
+
+#define _exit_sc_nr 1
+#define _read_sc_nr 2
+#define _write_sc_nr 3
+#define _open_sc_nr 4
+#define _close_sc_nr 5
+#define _getpid_sc_nr 6
+#define _brk_sc_nr 7
+#define _ioctl_sc_nr 8
+#define _socket_sc_nr 9
+#define _wait4_sc_nr 10
+#define _sigreturn_sc_nr 11
+#define _rt_sigaction_sc_nr 12
+#define _lseek_sc_nr 13
+
+#define _sock_sc_nr 1
+#define _sendto_sc_nr 2
+#define _send_sc_nr 3
+#define _recv_sc_nr 4
+
+
+//typedef unsigned long size_t;
+
+#endif
diff --git a/clients/net-snk/include/time.h b/clients/net-snk/include/time.h
new file mode 100644
index 0000000..d57c2f9
--- /dev/null
+++ b/clients/net-snk/include/time.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _TIME_H_
+#define _TIME_H_
+
+typedef unsigned long clock_t;
+typedef unsigned long time_t;
+
+time_t time(time_t *);
+
+extern unsigned long tb_freq;
+
+/* setup the timer to start counting from the given parameter */
+void set_timer(int);
+/* read the current value from the decrementer */
+int get_timer();
+/* get the number of ticks for which the decrementer needs 1 second */
+int get_sec_ticks();
+/* get the number of ticks for which the decrementer needs 1 millisecond */
+int get_msec_ticks();
+
+#define TICKS_MSEC get_msec_ticks()
+#define TICKS_SEC get_sec_ticks()
+
+#endif
diff --git a/clients/net-snk/include/types.h b/clients/net-snk/include/types.h
new file mode 100644
index 0000000..0036387
--- /dev/null
+++ b/clients/net-snk/include/types.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#ifndef _TYPES_H
+#define _TYPES_H
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#ifndef u32
+typedef unsigned int u32;
+#endif
+#ifndef u64
+typedef unsigned long long u64;
+#endif
+
+#endif
diff --git a/clients/net-snk/kernel/Makefile b/clients/net-snk/kernel/Makefile
new file mode 100644
index 0000000..73e8127
--- /dev/null
+++ b/clients/net-snk/kernel/Makefile
@@ -0,0 +1,43 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+OBJS = entry.o init.o systemcall.o lowmem.o crt0.o endian.o timer.o
+OBJDIRS = driver/net.o
+
+all: kernel.o
+
+driver/net.o:
+ make -C driver
+
+kernel.o: subdirs $(OBJS)
+ $(LD) $(LDFLAGS) $(OBJDIRS) $(OBJS) -o $@ -r
+
+subdirs:
+ for dir in $(dir $(OBJDIRS)); do \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir || exit 1; \
+ done
+
+clean:
+ $(RM) -f *.o *.a *.i
+ @for dir in $(dir $(OBJDIRS)); do \
+ $(CLEAN); \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir clean; \
+ done
+
+include $(TOP)/make.depend
diff --git a/clients/net-snk/kernel/crt0.c b/clients/net-snk/kernel/crt0.c
new file mode 100644
index 0000000..e3c443b
--- /dev/null
+++ b/clients/net-snk/kernel/crt0.c
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <stdlib.h>
+#include <string.h>
+extern int main (int, char**);
+extern int callback (int, char **);
+
+#define MAX_ARGV 10
+int
+gen_argv(const char *arg_string, int len, char* argv[])
+{
+ const char *str, *str_end, *arg_string_end = arg_string + len;
+ int i;
+
+ str = arg_string;
+ for (i = 0; i < MAX_ARGV; i++)
+ {
+ str_end = str;
+
+ while((*str_end++ != ' ') && (str_end <= arg_string_end));
+
+ argv[i] = malloc(str_end-str);
+
+ memcpy (argv[i], str, str_end-str-1);
+ argv[i][str_end-str-1] = '\0';
+ str = str_end-1;
+ while(*(++str) == ' ');
+ if (str >= arg_string_end)
+ break;
+ }
+ return i+1;
+}
+
+
+
+int
+_start(char * arg_string, long len)
+{
+ int rc;
+ int argc;
+ char* argv[MAX_ARGV];
+
+ argc = gen_argv(arg_string, len, argv);
+
+ rc = main(argc, argv);
+
+ return rc;
+}
+
+/*
+ * Takes a Forth representation of a string and generates an argument array,
+ * then calls callback().
+ */
+unsigned long
+callback_entry(void *base, unsigned long len) {
+ char *argv[MAX_ARGV];
+ int argc;
+
+ argc = gen_argv(base, len, argv);
+
+ return (callback(argc, argv));
+}
+
diff --git a/clients/net-snk/kernel/driver/Makefile b/clients/net-snk/kernel/driver/Makefile
new file mode 100644
index 0000000..6c2c8d4
--- /dev/null
+++ b/clients/net-snk/kernel/driver/Makefile
@@ -0,0 +1,40 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+OBJS = net_support.o
+OBJDIRS = net/net_driver.o
+
+all: net.o
+
+net.o: subdirs $(OBJS)
+ $(LD) $(LDFLAGS) $(OBJDIRS) $(OBJS) -o $@ -r
+
+subdirs:
+ for dir in $(dir $(OBJDIRS)); do \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir || exit 1; \
+ done
+
+clean:
+ $(RM) -f *.o *.a *.i
+ @for dir in $(dir $(OBJDIRS)); do \
+ $(CLEAN); \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir clean; \
+ done
+
+-include $(TOP)/make.depend
diff --git a/clients/net-snk/kernel/driver/net/Makefile b/clients/net-snk/kernel/driver/net/Makefile
new file mode 100644
index 0000000..95efa2b
--- /dev/null
+++ b/clients/net-snk/kernel/driver/net/Makefile
@@ -0,0 +1,38 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+OBJS = netmodule.o
+
+all: net_driver.o
+
+net_driver.o: $(OBJS)
+ $(LD) $(LDFLAGS) $^ -o $@ -r
+
+clean:
+ $(RM) -f *.o *.a *.i
+
+include $(TOP)/make.depend
+
+#depend :
+# @echo "create .depend file"
+# @touch .depend ; \
+# makedepend -v -f.depend -- $(CFLAGS) -- $(OBJS:.o=.c) 2> /dev/null
+
+#mrproper : clean
+# rm -rf .depend
diff --git a/clients/net-snk/kernel/driver/net/netmodule.c b/clients/net-snk/kernel/driver/net/netmodule.c
new file mode 100644
index 0000000..e81628e
--- /dev/null
+++ b/clients/net-snk/kernel/driver/net/netmodule.c
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <netdriver_int.h>
+#include <kernel.h>
+#include <of.h>
+#include <rtas.h>
+#include <cpu.h>
+
+# define MODULE_ADDR 0xF800000
+
+unsigned int read_io(void *, size_t);
+int write_io(void *, unsigned int, size_t);
+void translate_address(unsigned long *);
+
+static snk_kernel_t snk_kernel_interface = {
+ .version = 1,
+ .print = printk,
+ .us_delay = udelay,
+ .ms_delay = mdelay,
+ .pci_config_read = rtas_pci_config_read,
+ .pci_config_write = rtas_pci_config_write,
+ .k_malloc_aligned = malloc_aligned,
+ .k_romfs_lookup = romfs_lookup,
+ .translate_addr = translate_address
+};
+
+static snk_module_t *snk_module_interface;
+
+typedef snk_module_t *(*module_init_t) (snk_kernel_t *, pci_config_t *);
+
+/* Load module and call init code.
+ Init code will check, if module is responsible for device.
+ Returns -1, if not responsible for device, 0 otherwise.
+*/
+
+int
+load_module(const char *name, pci_config_t * pciconf)
+{
+ int len;
+ void *addr;
+ module_init_t module_init;
+
+ /* Read module from FLASH */
+ len = romfs_lookup(name, &addr);
+
+ if (len <= 0) {
+ return -1;
+ }
+ /* Copy image from flash to RAM
+ * FIXME fix address 8MB
+ */
+
+ memcpy((void *) MODULE_ADDR, addr, len);
+
+ flush_cache((void *) MODULE_ADDR, len);
+
+ /* Module starts with opd structure of the module_init
+ * function.
+ */
+ module_init = (module_init_t) MODULE_ADDR;
+ snk_module_interface = module_init(&snk_kernel_interface, pciconf);
+ if (snk_module_interface == 0)
+ return -1;
+ return 0;
+}
+
+int
+net_init(pci_config_t * pciconf, char *mac_addr)
+{
+ snk_kernel_interface.io_read = read_io;
+ snk_kernel_interface.io_write = write_io;
+
+ if (snk_module_interface->net_init){
+ return snk_module_interface->net_init(pciconf, mac_addr);
+ }
+ else {
+ printk("No net_init function available");
+ return -1;
+ }
+}
+
+int
+net_term(pci_config_t * pciconf)
+{
+ if (snk_module_interface->net_term)
+ return snk_module_interface->net_term(pciconf);
+ else {
+ printk("No net_term function available");
+ return -1;
+ }
+}
+
+
+int
+net_xmit(pci_config_t * pciconf, char *buffer, int len)
+{
+ if (snk_module_interface->net_xmit)
+ return snk_module_interface->net_xmit(pciconf, buffer, len);
+ else {
+ printk("No net_xmit function available");
+ return -1;
+ }
+}
+
+int
+net_receive(pci_config_t * pciconf, char *buffer, int len)
+{
+ if (snk_module_interface->net_receive)
+ return snk_module_interface->net_receive(pciconf, buffer, len);
+ else {
+ printk("No net_receive function available");
+ return -1;
+ }
+}
+
+int
+net_ioctl(pci_config_t * pciconf, int request, void* data)
+{
+ snk_kernel_interface.io_read = read_io;
+ snk_kernel_interface.io_write = write_io;
+
+ if (snk_module_interface->net_ioctl)
+ return snk_module_interface->net_ioctl(pciconf, request, data);
+ else {
+ printk("No net_ioctl function available");
+ return -1;
+ }
+}
diff --git a/clients/net-snk/kernel/driver/net_support.c b/clients/net-snk/kernel/driver/net_support.c
new file mode 100644
index 0000000..983374a
--- /dev/null
+++ b/clients/net-snk/kernel/driver/net_support.c
@@ -0,0 +1,534 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <pci.h>
+#include <net.h>
+#include <netdriver_int.h>
+#include <kernel.h>
+#include <rtas.h>
+#include <stdlib.h>
+#include <of.h>
+#include <types.h>
+
+extern int net_init(pci_config_t * pciconf, char *mac_addr);
+extern int net_term(pci_config_t * pciconf);
+extern int net_xmit(pci_config_t * pciconf, char *buffer, int len);
+extern int net_receive(pci_config_t * pciconf, char *buffer, int len);
+extern int net_ioctl(pci_config_t * conf, int request, void *data);
+extern int load_module(const char *, pci_config_t *);
+
+
+static char *mod_names[] = {
+ "net_e1000",
+ "net_bcm",
+ "net_nx203x",
+ "net_mcmal",
+ "net_spider",
+ 0
+};
+
+net_driver_t *
+find_net_driver(pci_config_t pci_conf)
+{
+ int rc;
+ int i = 0;
+ static net_driver_t module_net_driver;
+
+ /* Loop over module name */
+ while (mod_names[i]) {
+ rc = load_module(mod_names[i], &pci_conf);
+ if (rc == 0) {
+ module_net_driver.net_init = net_init;
+ module_net_driver.net_term = net_term;
+ module_net_driver.net_transmit = net_xmit;
+ module_net_driver.net_receive = net_receive;
+ module_net_driver.net_ioctl = net_ioctl;
+ return &module_net_driver;
+ }
+ i++;
+ }
+ return 0;
+}
+
+static phandle_t
+get_boot_device(void)
+{
+ static int nameprinted = 1;
+ char buf[1024];
+ phandle_t dev = of_finddevice("/chosen");
+
+ if (dev == -1) {
+ printk("/chosen not found\n");
+ dev = of_finddevice("/aliases");
+ if (dev == -1)
+ return dev;
+ printk("/aliases found, net=%s\n", buf);
+ of_getprop(dev, "net", buf, 1024);
+ } else
+ of_getprop(dev, "bootpath", buf, 1024);
+
+// FIXME: This printk is nice add to "Reading MAC from device" from netboot
+// However it is too hackish having "kernel" code finish the application
+// output line
+ if (!nameprinted++)
+ printk("%s: ", buf);
+
+ return of_finddevice(buf);
+}
+
+static void
+get_mac(char *mac)
+{
+ phandle_t net = get_boot_device();
+
+ if (net == -1)
+ return;
+
+ of_getprop(net, "local-mac-address", mac, 6);
+}
+
+void translate_address_dev(uint64_t *, phandle_t);
+
+/**
+ * get_puid walks up in the device tree until it finds a parent
+ * node without a reg property. get_puid is assuming that if the
+ * parent node has no reg property it has found the pci host bridge
+ *
+ * this is not the correct way to find PHBs but it seems to work
+ * for all our systems
+ *
+ * @param node the device for which to find the puid
+ *
+ * @return the puid or 0
+ */
+uint64_t
+get_puid(phandle_t node)
+{
+ uint64_t puid = 0;
+ uint64_t tmp = 0;
+ phandle_t curr_node = of_parent(node);
+ if (!curr_node)
+ /* no parent found */
+ return 0;
+ for (;;) {
+ puid = tmp;
+ if (of_getprop(curr_node, "reg", &tmp, 8) < 8) {
+ /* if the found PHB is not directly under
+ * root we need to translate the found address */
+ translate_address_dev(&puid, node);
+ return puid;
+ }
+ curr_node = of_parent(curr_node);
+ if (!curr_node)
+ return 0;
+ }
+ return 0;
+}
+
+/* Fill in the pci config structure from the device tree */
+int
+set_pci_config(pci_config_t * pci_config)
+{
+ unsigned char buf[1024];
+ int len, bar_nr;
+ unsigned int *assigned_ptr;
+ phandle_t net = get_boot_device();
+
+ if (net == -1)
+ return -1;
+ of_getprop(net, "vendor-id", &pci_config->vendor_id, 4);
+ of_getprop(net, "device-id", &pci_config->device_id, 4);
+ of_getprop(net, "revision-id", &pci_config->revision_id, 4);
+ of_getprop(net, "class-code", &pci_config->class_code, 4);
+ of_getprop(net, "interrupts", &pci_config->interrupt_line, 4);
+
+ len = of_getprop(net, "assigned-addresses", buf, 400);
+ if (len <= 0)
+ return -1;
+ assigned_ptr = (unsigned int *) &buf[0];
+ pci_config->bus = (assigned_ptr[0] & 0x00ff0000) >> 16;
+ pci_config->devfn = (assigned_ptr[0] & 0x0000ff00) >> 8;
+
+ while (len > 0) {
+ /* Fixme 64 bit bars */
+ bar_nr = ((assigned_ptr[0] & 0xff) - 0x10) / 4;
+ pci_config->bars[bar_nr].type =
+ (assigned_ptr[0] & 0x0f000000) >> 24;
+ pci_config->bars[bar_nr].addr = assigned_ptr[2];
+ pci_config->bars[bar_nr].size = assigned_ptr[4];
+ assigned_ptr += 5;
+ len -= 5 * sizeof(int);
+ }
+
+ pci_config->puid = get_puid(net);
+
+ return 0;
+}
+
+
+typedef struct {
+ pci_config_t pci_conf;
+ net_driver_t net_driv;
+
+ char mac_addr[6];
+ int running;
+} net_status_t;
+
+static net_status_t net_status;
+
+int
+init_net_driver()
+{
+ int result = 0;
+ net_driver_t *net_driver;
+
+ /* Find net device and initialize pci config */
+ if (set_pci_config(&net_status.pci_conf) == -1) {
+ printk(" No net device found \n");
+ return -1;
+ }
+
+ /* Get mac address from device tree */
+ get_mac(net_status.mac_addr);
+
+ /* Find net device driver */
+
+ net_driver = find_net_driver(net_status.pci_conf);
+ if (net_driver == 0) {
+ printk(" No net device driver found \n");
+ return -1;
+ }
+ net_status.net_driv = *net_driver;
+ /* Init net device driver */
+ result = net_status.net_driv.net_init(&net_status.pci_conf,
+ &net_status.mac_addr[0]);
+ if (result == -1) {
+ net_status.running = 0;
+ return -2;
+ } else {
+ net_status.running = 1;
+ }
+ return 0;
+}
+
+
+void
+term_net_driver()
+{
+ if (net_status.running == 1)
+ net_status.net_driv.net_term(&net_status.pci_conf);
+}
+
+
+int
+_socket(int domain, int type, int proto, char *mac_addr)
+{
+ static int first_time = 1;
+ if (first_time) {
+ switch (init_net_driver()) {
+ case -1:
+ return -1;
+ case -2:
+ return -2;
+ default:
+ break;
+ }
+ first_time = 0;
+ }
+
+ memcpy(mac_addr, &net_status.mac_addr[0], 6);
+ return 0;
+}
+
+
+long
+_recv(int fd, void *packet, int packet_len, int flags)
+{
+ return net_status.net_driv.net_receive(&net_status.pci_conf,
+ packet, packet_len);
+}
+
+
+long
+_sendto(int fd, void *packet, int packet_len, int flags,
+ void *sock_addr, int sock_addr_len)
+{
+ return net_status.net_driv.net_transmit(&net_status.pci_conf,
+ packet, packet_len);
+}
+
+long
+_send(int fd, void *packet, int packet_len, int flags)
+{
+ return net_status.net_driv.net_transmit(&net_status.pci_conf,
+ packet, packet_len);
+}
+
+long
+_ioctl(int fd, int request, void *data)
+{
+ net_driver_t *net_driver;
+
+ /* Find net device and initialize pci config */
+ if (set_pci_config(&net_status.pci_conf) == -1) {
+ printk(" No net device found \n");
+ return -1;
+ }
+
+ /* Find net device driver */
+
+ net_driver = find_net_driver(net_status.pci_conf);
+ if (net_driver == 0) {
+ printk(" No net device driver found \n");
+ return -1;
+ }
+ net_status.net_driv = *net_driver;
+
+ return net_status.net_driv.net_ioctl(&net_status.pci_conf,
+ request, data);
+}
+
+
+void *
+malloc_aligned(size_t size, int align)
+{
+ unsigned long p = (unsigned long) malloc(size + align - 1);
+ p = p + align - 1;
+ p = p & ~(align - 1);
+
+ return (void *) p;
+}
+
+#define CONFIG_SPACE 0
+#define IO_SPACE 1
+#define MEM_SPACE 2
+
+#define ASSIGNED_ADDRESS_PROPERTY 0
+#define REG_PROPERTY 1
+
+#define DEBUG_TRANSLATE_ADDRESS 0
+#if DEBUG_TRANSLATE_ADDRESS != 0
+#define DEBUG_TR(str...) printk(str)
+#else
+#define DEBUG_TR(str...)
+#endif
+
+/**
+ * pci_address_type tries to find the type for which a
+ * mapping should be done. This is PCI specific and is done by
+ * looking at the first 32bit of the phys-addr in
+ * assigned-addresses
+ *
+ * @param node the node of the device which requests
+ * translatation
+ * @param address the address which needs to be translated
+ * @param prop_type the type of the property to search in (either REG_PROPERTY or ASSIGNED_ADDRESS_PROPERTY)
+ * @return the corresponding type (config, i/o, mem)
+ */
+static int
+pci_address_type(phandle_t node, uint64_t address, uint8_t prop_type)
+{
+ char *prop_name = "assigned-addresses";
+ if (prop_type == REG_PROPERTY)
+ prop_name = "reg";
+ /* #address-cells */
+ const unsigned int nac = 3; //PCI
+ /* #size-cells */
+ const unsigned int nsc = 2; //PCI
+ /* up to 11 pairs of (phys-addr(3) size(2)) */
+ unsigned char buf[11 * (nac + nsc) * sizeof(int)];
+ unsigned int *assigned_ptr;
+ int result = -1;
+ int len;
+ len = of_getprop(node, prop_name, buf, 11 * (nac + nsc) * sizeof(int));
+ assigned_ptr = (unsigned int *) &buf[0];
+ while (len > 0) {
+ if ((prop_type == REG_PROPERTY)
+ && ((assigned_ptr[0] & 0xFF) != 0)) {
+ //BARs and Expansion ROM must be in assigned-addresses... so in reg
+ // we only look for those without config space offset set...
+ assigned_ptr += (nac + nsc);
+ len -= (nac + nsc) * sizeof(int);
+ continue;
+ }
+ DEBUG_TR("%s %x size %x\n", prop_name, assigned_ptr[2],
+ assigned_ptr[4]);
+ if (address >= assigned_ptr[2]
+ && address <= assigned_ptr[2] + assigned_ptr[4]) {
+ DEBUG_TR("found a match\n");
+ result = (assigned_ptr[0] & 0x03000000) >> 24;
+ break;
+ }
+ assigned_ptr += (nac + nsc);
+ len -= (nac + nsc) * sizeof(int);
+ }
+ /* this can only handle 32bit memory space and should be
+ * removed as soon as translations for 64bit are available */
+ return (result == 3) ? MEM_SPACE : result;
+}
+
+/**
+ * this is a hack which returns the lower 64 bit of any number of cells
+ * all the higher bits will silently discarded
+ * right now this works pretty good as long 64 bit addresses is all we want
+ *
+ * @param addr a pointer to the first address cell
+ * @param nc number of cells addr points to
+ * @return the lower 64 bit to which addr points
+ */
+static uint64_t
+get_dt_address(uint32_t *addr, uint32_t nc)
+{
+ uint64_t result = 0;
+ while (nc--)
+ result = (result << 32) | *(addr++);
+ return result;
+}
+
+/**
+ * this functions tries to find a mapping for the given address
+ * it assumes that if we have #address-cells == 3 that we are trying
+ * to do a PCI translation
+ *
+ * @param addr a pointer to the address that should be translated
+ * if a translation has been found the address will
+ * be modified
+ * @param type this is required for PCI devices to find the
+ * correct translation
+ * @param ranges this is one "range" containing the translation
+ * information (one range = nac + pnac + nsc)
+ * @param nac the OF property #address-cells
+ * @param nsc the OF property #size-cells
+ * @param pnac the OF property #address-cells from the parent node
+ * @return -1 if no translation was possible; else 0
+ */
+static int
+map_one_range(uint64_t *addr, int type, uint32_t *ranges, uint32_t nac,
+ uint32_t nsc, uint32_t pnac)
+{
+ long offset;
+ /* cm - child mapping */
+ /* pm - parent mapping */
+ uint64_t cm, size, pm;
+ /* only check for the type if nac == 3 (PCI) */
+ DEBUG_TR("type %x, nac %x\n", ranges[0], nac);
+ if (((ranges[0] & 0x03000000) >> 24) != type && nac == 3)
+ return -1;
+ /* okay, it is the same type let's see if we find a mapping */
+ size = get_dt_address(ranges + nac + pnac, nsc);
+ if (nac == 3) /* skip type if PCI */
+ cm = get_dt_address(ranges + 1, nac - 1);
+ else
+ cm = get_dt_address(ranges, nac);
+
+ DEBUG_TR("\t\tchild_mapping %lx\n", cm);
+ DEBUG_TR("\t\tsize %lx\n", size);
+ DEBUG_TR("\t\t*address %lx\n", (uint64_t) * addr);
+ if (cm + size <= (uint64_t) * addr || cm > (uint64_t) * addr)
+ /* it is not inside the mapping range */
+ return -1;
+ /* get the offset */
+ offset = *addr - cm;
+ /* and add the offset on the parent mapping */
+ if (pnac == 3) /* skip type if PCI */
+ pm = get_dt_address(ranges + nac + 1, pnac - 1);
+ else
+ pm = get_dt_address(ranges + nac, pnac);
+ DEBUG_TR("\t\tparent_mapping %lx\n", pm);
+ *addr = pm + offset;
+ DEBUG_TR("\t\t*address %lx\n", *addr);
+ return 0;
+}
+
+/**
+ * translate_address_dev tries to translate the device specific address
+ * to a host specific address by walking up in the device tree
+ *
+ * @param address a pointer to a 64 bit value which will be
+ * translated
+ * @param current_node phandle of the device from which the
+ * translation will be started
+ */
+void
+translate_address_dev(uint64_t *addr, phandle_t current_node)
+{
+ unsigned char buf[1024];
+ phandle_t parent;
+ unsigned int pnac;
+ unsigned int nac;
+ unsigned int nsc;
+ int addr_type;
+ int len;
+ unsigned int *ranges;
+ unsigned int one_range;
+ DEBUG_TR("translate address %lx, node: %lx\n", *addr, current_node);
+ of_getprop(current_node, "name", buf, 400);
+ DEBUG_TR("current node: %s\n", buf);
+ addr_type =
+ pci_address_type(current_node, *addr, ASSIGNED_ADDRESS_PROPERTY);
+ if (addr_type == -1) {
+ // check in "reg" property if not found in "assigned-addresses"
+ addr_type = pci_address_type(current_node, *addr, REG_PROPERTY);
+ }
+ DEBUG_TR("address_type %x\n", addr_type);
+ current_node = of_parent(current_node);
+ while (1) {
+ parent = of_parent(current_node);
+ if (!parent) {
+ DEBUG_TR("reached root node...\n");
+ break;
+ }
+ of_getprop(current_node, "#address-cells", &nac, 4);
+ of_getprop(current_node, "#size-cells", &nsc, 4);
+ of_getprop(parent, "#address-cells", &pnac, 4);
+ one_range = nac + pnac + nsc;
+ len = of_getprop(current_node, "ranges", buf, 400);
+ if (len < 0) {
+ DEBUG_TR("no 'ranges' property; not translatable\n");
+ return;
+ }
+ ranges = (unsigned int *) &buf[0];
+ while (len > 0) {
+ if (!map_one_range
+ ((uint64_t *) addr, addr_type, ranges, nac, nsc,
+ pnac))
+ /* after a successful mapping we stop
+ * going through the ranges */
+ break;
+ ranges += one_range;
+ len -= one_range * sizeof(int);
+ }
+ DEBUG_TR("address %lx\n", *addr);
+ of_getprop(current_node, "name", buf, 400);
+ DEBUG_TR("current node: %s\n", buf);
+ DEBUG_TR("\t#address-cells: %x\n", nac);
+ DEBUG_TR("\t#size-cells: %x\n", nsc);
+ of_getprop(parent, "name", buf, 400);
+ DEBUG_TR("parent node: %s\n", buf);
+ DEBUG_TR("\t#address-cells: %x\n", pnac);
+ current_node = parent;
+ }
+}
+
+/**
+ * translate_address tries to translate the device specific address
+ * of the boot device to a host specific address
+ *
+ * @param address a pointer to a 64 bit value which will be
+ * translated
+ */
+void
+translate_address(uint64_t *addr)
+{
+ translate_address_dev(addr, get_boot_device());
+}
diff --git a/clients/net-snk/kernel/endian.c b/clients/net-snk/kernel/endian.c
new file mode 100644
index 0000000..9748778
--- /dev/null
+++ b/clients/net-snk/kernel/endian.c
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "endian.h"
+
+inline uint16_t bswap_16 (uint16_t x)
+{
+ return ((x&0xff00) >> 8) | ((x&0xff) << 8);
+}
+
+inline uint32_t bswap_32 (uint32_t x)
+{
+ return bswap_16((x&0xffff0000) >> 16) | (bswap_16(x&0xffff) << 16);
+}
+
+inline uint64_t bswap_64 (uint64_t x)
+{
+ return (unsigned long long) bswap_32((x&0xffffffff00000000ULL) >> 32) |
+ (unsigned long long) bswap_32(x&0xffffffffULL) << 32;
+}
diff --git a/clients/net-snk/kernel/entry.S b/clients/net-snk/kernel/entry.S
new file mode 100644
index 0000000..8db10af
--- /dev/null
+++ b/clients/net-snk/kernel/entry.S
@@ -0,0 +1,167 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#define STACKSIZE 0x100000
+#include <macros.h>
+
+/*
+Function:
+ Input:
+ r3:
+ r4:
+ r5: prom entry
+ Output:
+
+Decription: Main entry point, called from OF
+
+*/
+ .globl _entry
+ .section ".opd","aw"
+ .align 3
+_entry:
+ .quad ._entry,.TOC.@tocbase,0
+ .previous
+ .size main,24
+ .globl ._entry
+._entry:
+ mr r3, r6 # parm 0 passed in r6
+ mr r4, r7 # parm 1 passed in r7
+ mr r6, r1 # save stack pointer
+ mflr r7 # save link register
+ bcl 20,31,over # branch after pointer table
+base:
+ .align 3
+.LCgot: .quad _got-base+0x8000
+.LCstack: .quad _stack+STACKSIZE-0x80-base
+over:
+ mflr r8 # gpr 8 is the base
+ ld r1,.LCstack-base(r8) # load new stack pointer
+ add r1, r1, r8 # add base
+ std r2, 64(r1) # save got
+ std r7, 56(r1) # save link register
+# ld r2, .LCgot-base(r8) # load got pointer
+# add r2, r2, r8 # add base
+ std r6, 0(r1) # save stack pointer
+
+ ld r6, _prom_entry@got(r2)
+ std r5, 0(r6) # Save prom handle
+
+ ld r10, _exit_sp@got(r2) # save stack pointer for exit call
+ std r1, 0(r10)
+
+ bl ._start_kernel # call kernel init code
+
+the_end:
+ ld r4, 56(r1) # Restore link register
+ mtlr r4
+ ld r2, 64(r1) # restore got
+ ld r1, 0(r1)
+
+ blr
+
+/*
+ * Function: _callback_entry
+ * Input: r6 start address of parameter string
+ * r7 length of parameter string.
+ *
+ * Description: If a client application wants to register a callback function,
+ * this function is registered w/ SLOF, not the application's function. SLOF
+ * passes the parameter string in Forth representation in R6 and R7. This
+ * function moves R6 to R3 and R7 to R4 and then calls callback_entry().
+ *
+ */
+ .globl _callback_entry
+ .section ".opd", "aw"
+ .align 3
+_callback_entry:
+ .quad ._callback_entry,.TOC.@tocbase,0
+ .previous
+ .size callback,24
+ .type ._callback_entry, @function
+ .globl ._callback_entry
+._callback_entry:
+ # Save the LR
+ mflr r0
+ std r0, 16(r1)
+
+ # Reserve stack space
+ stdu r1, -32(r1)
+
+ # SLOF passes the parameters in Registers R6 and R7 but the target
+ # wants them in registers R3 and R4
+ mr r3, r6
+ mr r4, r7
+
+ # Branch to the callback_entry function
+ bl .callback_entry
+
+ # Destroy stack frame
+ ld r1, 0(r1)
+
+ # Restore LR
+ ld r0, 16(r1)
+ mtlr r0
+
+ # Return to caller
+ blr
+
+
+ .globl _exit_sp
+_exit_sp: .quad 0
+ .globl _prom_entry
+_prom_entry: .quad 0
+
+ENTRY(_exit)
+ ld r1, _exit_sp@got(r2)
+ ld r1, 0(r1)
+ b the_end
+
+ .globl .undo_exception
+.undo_exception:
+ .globl undo_exception
+undo_exception:
+
+/*
+ unwind stack
+*/
+ ld r3,exception_stack_frame@got(r2)
+ ld r1,0(r3)
+
+ ld r14,0x130(r1)
+ mtctr r14
+
+// restore regs same as in _exception_handler:
+
+ .irp i, 2,3,4,5,6,7,8,9,10,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ ld r\i, 0x30+\i*8 (r1)
+ .endr
+ addi r1, r1, 0x130
+
+// restore regs as in default handler
+
+ ld r0, 0x48(r1)
+ mtsrr0 r0
+ ld r0, 0x50(r1)
+ mtsrr1 r0
+// 20
+ ld r0, 0x38(r1)
+ mtlr r0
+ ld r0, 0x30(r1)
+ ld r11, 0x40(r1)
+// 30
+ addi r1, r1, 0x58
+
+ rfid
+
+ .lcomm _stack,STACKSIZE,16
diff --git a/clients/net-snk/kernel/init.c b/clients/net-snk/kernel/init.c
new file mode 100644
index 0000000..76b35ed
--- /dev/null
+++ b/clients/net-snk/kernel/init.c
@@ -0,0 +1,175 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <of.h>
+#include <rtas.h>
+#include <pci.h>
+#include <kernel.h>
+#include <types.h>
+#include <string.h>
+#include <cpu.h>
+
+/* Application entry point .*/
+extern int _start(unsigned char *arg_string, long len);
+
+unsigned long exception_stack_frame;
+
+ihandle_t fd_array[32];
+pci_config_t pci_device_array[32];
+
+extern uint64_t tb_freq;
+
+void term_net_driver(void);
+
+static int
+init_io()
+{
+ phandle_t chosen = of_finddevice("/chosen");
+
+ if (chosen == -1)
+ return -1;
+
+ of_getprop(chosen, "stdin", &fd_array[0], sizeof(ihandle_t));
+ of_getprop(chosen, "stdout", &fd_array[1], sizeof(ihandle_t));
+
+ if (of_write(fd_array[1], " ", 1) < 0)
+ return -2;
+
+ return 0;
+}
+
+static char save_vector[0x4000];
+extern char _lowmem_start;
+extern char _lowmem_end;
+extern char __client_start;
+extern char __client_end;
+
+static void
+copy_exception_vectors()
+{
+ char *dest;
+ char *src;
+ int len;
+
+ dest = save_vector;
+ src = (char *) 0x200;
+ len = &_lowmem_end - &_lowmem_start;
+ memcpy(dest, src, len);
+
+ dest = (char *) 0x200;
+ src = &_lowmem_start;
+ memcpy(dest, src, len);
+ flush_cache(dest, len);
+}
+
+static void
+restore_exception_vectors()
+{
+ char *dest;
+ char *src;
+ int len;
+
+ dest = (char *) 0x200;
+ src = save_vector;
+ len = &_lowmem_end - &_lowmem_start;
+ memcpy(dest, src, len);
+ flush_cache(dest, len);
+}
+
+static long memory_size;
+
+static void
+checkmemorysize()
+{
+ char buf[255];
+ phandle_t ph;
+ memory_size = 0;
+
+ struct reg {
+ long adr;
+ long size;
+ } reg;
+
+ ph = of_peer(0); // begin from root-node
+ ph = of_child(ph); // get a child
+
+ while (ph != 0) {
+ if (of_getprop(ph, "device_type", buf, 255) != -1) {
+ /* if device_type == memory */
+ if (strcmp(buf, "memory") == 0)
+ if (of_getprop(ph, "reg", &reg, 16) != -1) {
+ memory_size += reg.size;
+ }
+ }
+ ph = of_peer(ph); // get next siblings
+ }
+}
+
+long
+getmemsize()
+{
+ return memory_size;
+}
+
+static void
+get_timebase()
+{
+ unsigned int timebase;
+ phandle_t cpu;
+ phandle_t cpus = of_finddevice("/cpus");
+
+ if (cpus == -1)
+ return;
+
+ cpu = of_child(cpus);
+
+ if (cpu == -1)
+ return;
+
+ of_getprop(cpu, "timebase-frequency", &timebase, 4);
+ tb_freq = (uint64_t) timebase;
+}
+
+int
+_start_kernel(unsigned long p0, unsigned long p1)
+{
+ int rc,claim_rc;
+ size_t _client_start = (size_t)&__client_start;
+ size_t _client_size = (size_t)&__client_end - (size_t)&__client_start;
+
+ claim_rc=(int)(long)of_claim((void *)(long)_client_start, _client_size, 0);
+
+ if (init_io() <= -1)
+ return -1;
+ copy_exception_vectors();
+
+ checkmemorysize();
+ get_timebase();
+ rtas_init();
+ rc = _start((unsigned char *) p0, p1);
+
+ term_net_driver();
+
+ restore_exception_vectors();
+ if (claim_rc >= 0) {
+ of_release((void *)(long)_client_start, _client_size);
+ }
+ return rc;
+}
+
+
+void
+exception_forward(void)
+{
+ restore_exception_vectors();
+ undo_exception();
+}
diff --git a/clients/net-snk/kernel/lowmem.S b/clients/net-snk/kernel/lowmem.S
new file mode 100644
index 0000000..ad5127f
--- /dev/null
+++ b/clients/net-snk/kernel/lowmem.S
@@ -0,0 +1,186 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <macros.h>
+.section .lowmem,"aw",@progbits
+
+ .irp i, 0x0200,0x0300,0x0380,0x0400,0x0480,0x0500,0x0600,0x0700, \
+ 0x0800,0x0900,0x0a00,0x0b00
+ . = \i - 0x200
+// 0
+ stdu r1, -0x58(r1)
+ std r0, 0x30(r1)
+ mflr r0
+ std r0, 0x38(r1)
+// 10
+ mfsrr0 r0
+ std r0, 0x48(r1)
+ mfsrr1 r0
+ std r0, 0x50(r1)
+// 20
+ std r11, 0x40(r1)
+ li r0, \i
+ ld r11, 0x60 + \i(0)
+ bl _exception_handler
+
+// 30
+ ld r0, 0x48(r1)
+ mtsrr0 r0
+ ld r0, 0x50(r1)
+ mtsrr1 r0
+
+// 40
+ ld r0, 0x38(r1)
+ mtlr r0
+ ld r0, 0x30(r1)
+ ld r11, 0x40(r1)
+// 50
+ addi r1, r1, 0x58
+ rfid
+ nop
+ nop
+// 60
+// .quad \i+0x68
+ .quad .exception_forward
+// 68
+ blr
+ .endr
+
+ # System call entry
+ . = 0xc00 - 0x200
+
+ stdu r1, -0x50(r1)
+ mflr r11
+ std r11, 0x30(r1)
+ mfsrr0 r11
+ std r11, 0x40(r1)
+ mfsrr1 r11
+ std r11, 0x48(r1)
+ ld r11, _system_call@got(r2)
+ ld r11, 0(r11)
+ mtctr r11
+ mr r10, r0
+ bctrl
+ ld r11, 0x30(r1)
+ mtlr r11
+ ld r11, 0x40(r1)
+ mtsrr0 r11
+ ld r11, 0x48(r1)
+ mtsrr1 r11
+ addi r1, r1, 0x50
+ rfid
+
+ .irp i, 0x0d00,0x0e00,0x0f00, \
+ 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
+ 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
+ 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
+ 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00
+ . = \i - 0x200
+// 0
+ stdu r1, -0x58(r1)
+ std r0, 0x30(r1)
+ mflr r0
+ std r0, 0x38(r1)
+// 10
+ mfsrr0 r0
+ std r0, 0x48(r1)
+ mfsrr1 r0
+ std r0, 0x50(r1)
+// 20
+ std r11, 0x40(r1)
+ li r0, \i
+ ld r11, 0x60 + \i(0)
+ bl _exception_handler
+
+// 30
+ ld r0, 0x48(r1)
+ mtsrr0 r0
+ ld r0, 0x50(r1)
+ mtsrr1 r0
+
+// 40
+ ld r0, 0x38(r1)
+ mtlr r0
+ ld r0, 0x30(r1)
+ ld r11, 0x40(r1)
+// 50
+ addi r1, r1, 0x58
+ rfid
+ nop
+ nop
+// 60
+// .quad \i+0x68
+ .quad .exception_forward
+// 68
+ blr
+ .endr
+
+/* Saves all register potential clobbered in exception handler.
+ In r0 the pointer to the function is passed.
+ */
+
+_exception_handler:
+ stdu r1, -0x130(r1)
+ .irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ std r\i, 0x30+\i*8 (r1)
+ .endr
+ mfctr r14
+ std r14,0x130(r1)
+ mtctr r11
+
+ LOAD64(r3,_entry)
+ ld r2,8(r3)
+
+ ld r3,exception_stack_frame@got(r2)
+ std r1,0(r3)
+
+
+ mflr r14
+ bctrl
+ mtlr r14
+
+ ld r14,0x130(r1)
+ mtctr r14
+/*
+ mfsrr0 r2
+ addi r2, r2, 4
+ mtsrr0 r2
+*/
+ .irp i, 2,3,4,5,6,7,8,9,10,12,13,14,15,16, \
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 27, 28, 29, 30, 31
+ ld r\i, 0x30+\i*8 (r1)
+ .endr
+ addi r1, r1, 0x130
+ blr
+
+ .text
+
+/* Set exception handler for given exception vector.
+ r3: exception vector offset
+ r4: exception handler
+*/
+ .globl .set_exception
+.set_exception:
+ .globl set_exception
+set_exception:
+ ld r4,0x0(r4)
+ .globl .set_exception_asm
+.set_exception_asm:
+ .globl set_exception_asm
+set_exception_asm:
+ std r4, 0x60(r3) # fixme diff 1f - 0b
+ blr
+
diff --git a/clients/net-snk/kernel/systemcall.c b/clients/net-snk/kernel/systemcall.c
new file mode 100644
index 0000000..f15cae1
--- /dev/null
+++ b/clients/net-snk/kernel/systemcall.c
@@ -0,0 +1,171 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <of.h>
+#include <systemcall.h>
+#include <stdarg.h>
+
+extern ihandle_t fd_array[32];
+
+int _socket (int, int, int, char*);
+long _recv (int, void*, int, int);
+long _sendto (int, void*, int, int, void*, int);
+long _send (int, void*, int, int);
+long _ioctl (int, int, void*);
+int vsprintf(char *, const char *, va_list);
+
+long
+_syscall_write (int fd, char *buf, long len)
+{
+ char dest_buf[512];
+ char *dest_buf_ptr;
+ int i;
+ if (fd == 1 || fd == 2)
+ {
+ dest_buf_ptr = &dest_buf[0];
+ for (i = 0; i < len && i < 256; i++)
+ {
+ *dest_buf_ptr++ = *buf++;
+ if (buf[-1] == '\n')
+ *dest_buf_ptr++ = '\r';
+ }
+ len = dest_buf_ptr - &dest_buf[0];
+ buf = &dest_buf[0];
+ }
+ return of_write (fd_array[fd], buf, len);
+}
+
+int
+printk(const char* fmt, ...)
+{
+ int count;
+ va_list ap;
+ char buffer[256];
+ va_start (ap, fmt);
+ count=vsprintf(buffer, fmt, ap);
+ _syscall_write (1, buffer, count);
+ va_end (ap);
+ return count;
+}
+
+long
+_syscall_read (int fd, char *buf, long len)
+{
+ return of_read (fd_array[fd], buf, len);
+}
+
+long
+_syscall_lseek (int fd, long offset, int whence)
+{
+ if (whence != 0)
+ return -1;
+
+ of_seek (fd_array[fd], (unsigned int) (offset>>32), (unsigned int) (offset & 0xffffffffULL));
+
+ return offset;
+}
+
+void
+_syscall_close(int fd)
+{
+ of_close(fd_array[fd]);
+}
+
+int
+_syscall_ioctl (int fd, int request, void* data)
+{
+ return _ioctl (fd, request, data);
+}
+
+long
+_syscall_socket (long which, long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5)
+{
+ long rc = -1;
+ switch (which)
+ {
+ case _sock_sc_nr:
+ rc = _socket (arg0, arg1, arg2, (char*) arg3);
+ break;
+ case _recv_sc_nr:
+ rc = _recv (arg0, (void *) arg1, arg2, arg3);
+ break;
+ case _send_sc_nr:
+ rc = _send (arg0, (void *) arg1, arg2, arg3);
+ break;
+ case _sendto_sc_nr:
+ rc = _sendto (arg0, (void *) arg1, arg2, arg3, (void *) arg4, arg5);
+ break;
+ }
+ return rc;
+}
+
+int
+_syscall_open(const char* name, int flags)
+{
+ static int fd = 2;
+ ihandle_t ihandle;
+
+ if ((ihandle = of_open (name)) == 0)
+ {
+ printk ("Cannot open %s\n", name);
+ return -1;
+ }
+
+ fd++;
+ fd_array[fd] = ihandle;
+
+ return fd;
+}
+
+long
+_system_call(long arg0, long arg1, long arg2, long arg3,
+ long arg4, long arg5, long arg6, int nr)
+{
+ long rc = -1;
+ switch (nr)
+ {
+
+ case _open_sc_nr:
+ rc = _syscall_open ((void *) arg0, arg1);
+ break;
+ case _read_sc_nr:
+ rc = _syscall_read (arg0, (void *) arg1, arg2);
+ break;
+ case _close_sc_nr:
+ _syscall_close (arg0);
+ break;
+ case _lseek_sc_nr:
+ rc = _syscall_lseek (arg0, arg1, arg2);
+ break;
+ case _write_sc_nr:
+ rc = _syscall_write (arg0, (void *) arg1, arg2);
+ break;
+ case _ioctl_sc_nr:
+ rc = _syscall_ioctl (arg0, arg1, (void *) arg2);
+ break;
+ case _socket_sc_nr:
+ rc = _syscall_socket (arg0, arg1, arg2, arg3,
+ arg4, arg5, arg6);
+ break;
+ }
+ return rc;
+}
+
+void _exit(int status);
+
+void
+exit(int status)
+{
+ _exit(status);
+}
diff --git a/clients/net-snk/kernel/timer.c b/clients/net-snk/kernel/timer.c
new file mode 100644
index 0000000..a57a463
--- /dev/null
+++ b/clients/net-snk/kernel/timer.c
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <types.h>
+
+//*******************************************************************
+// variable "tb_freq" contains the frequency in Hz
+// and is read from the device tree (setup by LLFW) in "init.c"
+uint64_t tb_freq;
+
+//-------------------------------------------------------------------
+// Read the current timebase
+uint64_t get_time(void)
+{
+ uint64_t act;
+
+ __asm__ __volatile__(
+ "0: mftbu %0 ;\
+ mftbl %%r0 ; \
+ mftbu %%r4 ; \
+ cmpw %0,%%r4 ; \
+ bne 0b; \
+ sldi %0,%0,32; \
+ or %0,%0,%%r0"
+ : "=r"(act)
+ : /* no inputs */
+ : "r0", "r4");
+ return act;
+}
+
+//-------------------------------------------------------------------
+// wait for ticks/scale timebase ticks
+void wait_ticks(uint64_t ticks)
+{
+ uint64_t timeout = get_time() + ticks;
+ while (get_time() < timeout) {
+ unsigned int i;
+ for (i = 1000; i > 0; i--)
+ __asm__ __volatile__ ("" : : : "memory");
+ }
+}
+
+//-------------------------------------------------------------------
+// wait for (at least) usecs microseconds
+void udelay(unsigned int usecs)
+{
+ // first multiply the usec with timebase and then devide
+ // because 1.000.000 is relatively huge compared to usecs
+ wait_ticks((usecs*tb_freq)/1000000);
+}
+
+//-------------------------------------------------------------------
+// wait for (at least) msecs milliseconds
+void mdelay(unsigned int msecs)
+{
+ // first multiply the msec and timebase and then devide
+ // because 1.000 is relatively huge compared to msecs
+ wait_ticks((msecs*tb_freq)/1000);
+}
diff --git a/clients/net-snk/libc/Makefile b/clients/net-snk/libc/Makefile
new file mode 100644
index 0000000..82e2b4c
--- /dev/null
+++ b/clients/net-snk/libc/Makefile
@@ -0,0 +1,48 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+
+CFLAGS = -g -I$(TOP)/include -I$(LIBCMNDIR)/libc/include -O2 \
+ -fno-builtin -ffreestanding -nostdinc -msoft-float -Wall
+LDFLAGS= -nostdlib
+
+OBJS = socket/socket.o time/time.o sbrk.o io.o ioctl.o
+SUBDIRS = $(filter-out ./,$(dir $(OBJS)))
+
+
+all: libc-glue.o
+
+libc-glue.o: subdirs sbrk.o io.o ioctl.o
+ $(LD) $(LDFLAGS) $(OBJS) -o $@ -r
+
+
+subdirs :
+ for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir || exit 1; \
+ done
+
+clean:
+ $(RM) -f *.a *.o
+ @for dir in $(SUBDIRS); do \
+ $(CLEAN) ; \
+ $(MAKE) -C $$dir DIRECTORY=$(DIRECTORY)$$dir clean; \
+ done
+
+include $(TOP)/make.depend
+
diff --git a/clients/net-snk/libc/io.c b/clients/net-snk/libc/io.c
new file mode 100644
index 0000000..937e51a
--- /dev/null
+++ b/clients/net-snk/libc/io.c
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stddef.h"
+#include "systemcall.h"
+#include "unistd.h"
+
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+ return syscall_3 (_write_sc_nr, fd, (long) buf, count);
+}
+
+ssize_t read(int fd, void *buf, size_t count)
+{
+ return syscall_3 (_read_sc_nr, fd, (long) buf, count);
+}
+
+ssize_t lseek(int fd, long off, int whence)
+{
+ return syscall_3 (_lseek_sc_nr, fd, off, whence);
+}
+
+int open(const char *name, int flags)
+{
+ return syscall_2 (_open_sc_nr, (long int) name, flags);
+}
+
+int close(int fd)
+{
+ return syscall_1(_close_sc_nr,fd);
+}
+
+int
+getchar(void)
+{
+ char buf;
+ int i;
+
+ if((i = read (1, &buf, 1)) == 1)
+ return (int) buf;
+ return -1;
+}
diff --git a/clients/net-snk/libc/ioctl.c b/clients/net-snk/libc/ioctl.c
new file mode 100644
index 0000000..64d666c
--- /dev/null
+++ b/clients/net-snk/libc/ioctl.c
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "systemcall.h"
+
+
+int ioctl(int fd, int request, void *data)
+{
+ return syscall_3 (_ioctl_sc_nr, fd, request, (long) data);
+}
diff --git a/clients/net-snk/libc/sbrk.c b/clients/net-snk/libc/sbrk.c
new file mode 100644
index 0000000..2969018
--- /dev/null
+++ b/clients/net-snk/libc/sbrk.c
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#define HEAP_SIZE 0x200000
+
+
+static char heap[HEAP_SIZE];
+static char *actptr;
+
+void *sbrk(int increment)
+{
+ char *oldptr;
+
+ /* Called for the first time? Then init the actual pointer */
+ if (!actptr) {
+ actptr = heap;
+ }
+
+ if (actptr + increment > heap + HEAP_SIZE) {
+ /* Out of memory */
+ return (void *)-1;
+ }
+
+ oldptr = actptr;
+ actptr += increment;
+
+ return oldptr;
+}
diff --git a/clients/net-snk/libc/socket/Makefile b/clients/net-snk/libc/socket/Makefile
new file mode 100644
index 0000000..c18fe15
--- /dev/null
+++ b/clients/net-snk/libc/socket/Makefile
@@ -0,0 +1,41 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+
+CFLAGS = -g -I$(TOP)/include -O2 -fno-builtin -ffreestanding -msoft-float -Wall
+LDFLAGS= -nostdlib
+
+
+OBJS=send.c
+
+
+all: socket.o
+
+
+socket.o: $(OBJS:.c=.o)
+ $(LD) $(LDFLAGS) -r $^ -o $@
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $^ -o $@
+
+
+clean:
+ $(RM) -f *.o *.i *.s
+
+distclean mrproper: clean
diff --git a/clients/net-snk/libc/socket/send.c b/clients/net-snk/libc/socket/send.c
new file mode 100644
index 0000000..0095822
--- /dev/null
+++ b/clients/net-snk/libc/socket/send.c
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "sys/socket.h"
+
+int socket(int dom, int type, int proto, char *mac_addr)
+{
+ return syscall_5 (_socket_sc_nr, _sock_sc_nr, dom, type, proto, (long)mac_addr);
+}
+
+int sendto(int fd, const void* buffer, int len, int flags, const void* sock_addr, int sock_addr_len)
+{
+ return syscall_7 (_socket_sc_nr, _sendto_sc_nr, fd, (long) buffer, len, flags, (long) sock_addr, sock_addr_len);
+}
+
+int send(int fd, void* buffer, int len, int flags)
+{
+ return syscall_5 (_socket_sc_nr, _send_sc_nr, fd, (long) buffer, len, flags);
+}
+
+int recv(int fd, void* buffer, int len, int flags)
+{
+ return syscall_5 (_socket_sc_nr, _recv_sc_nr, fd, (long) buffer, len, flags);
+}
+
+
diff --git a/clients/net-snk/libc/time/Makefile b/clients/net-snk/libc/time/Makefile
new file mode 100644
index 0000000..1db98e7
--- /dev/null
+++ b/clients/net-snk/libc/time/Makefile
@@ -0,0 +1,43 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+
+endif
+include $(TOP)/make.rules
+
+
+CFLAGS = -g -I$(TOP)/include -I$(LIBCMNDIR)/libc/include -O2 -msoft-float \
+ -Wall -fno-builtin -ffreestanding -nostdinc
+LDFLAGS= -nostdlib
+
+
+OBJS=timer.c ftime.c
+
+
+all: time.o
+
+
+time.o: $(OBJS:.c=.o)
+ $(LD) $(LDFLAGS) -r $^ -o $@
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $^ -o $@
+
+
+clean:
+ $(RM) -f *.o *.i *.s
+
+distclean mrproper: clean
diff --git a/clients/net-snk/libc/time/ftime.c b/clients/net-snk/libc/time/ftime.c
new file mode 100644
index 0000000..139988e
--- /dev/null
+++ b/clients/net-snk/libc/time/ftime.c
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <time.h>
+#include <rtas.h>
+#include <stdio.h>
+
+time_t
+time(time_t *tod)
+{
+ dtime ts;
+
+ rtas_get_time_of_day(&ts);
+ printf("debug!!\n");
+
+ printf("year : %d\n", ts.year);
+ printf("month : %d\n", ts.month);
+ printf("day : %d\n", ts.day);
+ printf("hour : %d\n", ts.hour);
+ printf("minute: %d\n", ts.minute);
+ printf("second: %d\n", ts.second);
+ printf("nano : %d\n", ts.nano);
+ printf("debug ende\n");
+
+// if(tod)
+// *tod = t;
+ return 0;
+}
diff --git a/clients/net-snk/libc/time/timer.c b/clients/net-snk/libc/time/timer.c
new file mode 100644
index 0000000..b0effaa
--- /dev/null
+++ b/clients/net-snk/libc/time/timer.c
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "time.h"
+
+int get_msec_ticks()
+{
+ return tb_freq/1000;
+}
+
+int get_sec_ticks()
+{
+ return tb_freq;
+}
+
+void set_timer(int val)
+{
+ asm volatile ("mtdec %0"::"r" (val));
+}
+
+int get_timer()
+{
+ int val;
+ asm volatile ("mfdec %0":"=r" (val));
+ return val;
+}
+
+
+
diff --git a/clients/net-snk/make.depend b/clients/net-snk/make.depend
new file mode 100644
index 0000000..31997fc
--- /dev/null
+++ b/clients/net-snk/make.depend
@@ -0,0 +1,36 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+-include .depend
+
+depend :
+ @rm -rf .depend
+ifdef OBJS
+ @touch .depend && \
+ $(CC) -M $(CFLAGS) $(OBJS:.o=.c) >> .depend
+#else
+# @echo "OBJ is NOT defined"
+endif
+ifdef OBJS2
+ @$(CC) -M $(CFLAGS) $(OBJS2:.o=.S) >> .depend
+#else
+# @echo "OBJ2 is NOT definde"
+endif
+ @for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir depend ; \
+ done
+
+mrproper :
+ @rm -rf .depend ; \
+ for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir mrproper ; \
+ done
diff --git a/clients/net-snk/make.rules b/clients/net-snk/make.rules
new file mode 100644
index 0000000..1343d82
--- /dev/null
+++ b/clients/net-snk/make.rules
@@ -0,0 +1,43 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+CROSS ?= powerpc64-linux-
+
+HOSTCC ?= gcc
+HOSTCFLAGS = -g -Wall -W -O2 -I. -I../include
+
+INCLCMNDIR ?= $(TOP)/../../include
+LIBCMNDIR ?= $(TOP)/../../lib
+CFLAGS = -g -I. -I$(TOP)/include -I$(LIBCMNDIR)/libc/include \
+ -I$(LIBCMNDIR)/libbootmsg -I$(INCLCMNDIR)/$(CPUARCH) \
+ -O2 -fno-builtin -ffreestanding -msoft-float -mno-altivec \
+ -Wall $(FLAG)
+LDFLAGS = -nostdlib
+ASFLAGS = -I. -I$(TOP)/include -Wa,-mregnames -I$(INCLCMNDIR)/$(CPUARCH)
+DD = dd
+
+ifdef NEW_BUILD
+MAKEFLAGS = --silent
+CC = echo -e "\t[CC]\t$(DIRECTORY)$@"; $(CROSS)gcc -m64
+AS = echo -e "\t[AS]\t$(DIRECTORY)$@"; $(CROSS)as -m64
+LD = echo -e "\t[LD]\t$(DIRECTORY)$@"; $(CROSS)ld -melf64ppc
+CLEAN = echo -e "\t[CLEAN]\t$(DIRECTORY)$$dir"
+else
+CC = $(CROSS)gcc -m64
+AS = $(CROSS)as -m64
+LD = $(CROSS)ld -melf64ppc
+CLEAN = echo -n
+endif
+
+OBJCOPY = $(CROSS)objcopy
+OBJDUMP = $(CROSS)objdump
+STRIP = $(CROSS)strip
diff --git a/clients/net-snk/oflib/Makefile b/clients/net-snk/oflib/Makefile
new file mode 100644
index 0000000..c4a8219
--- /dev/null
+++ b/clients/net-snk/oflib/Makefile
@@ -0,0 +1,41 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+OBJS = rtas.o of.o pci.o
+OBJS2 = entry.o
+
+all: oflib.o
+
+
+oflib.o: $(OBJS) $(OBJS2)
+ $(LD) $(LDFLAGS) $^ -o oflib.o -r
+
+clean:
+ $(RM) -f $(OBJS) $(OBJS2) oflib.o
+
+include $(TOP)/make.depend
+
+
+#mrproper : clean
+# rm -rf .depend
+#
+#depend :
+# @rm -rf .depend ; touch .depend ; \
+# makedepend -v -f.depend -- $(CFLAGS) -- $(OBJS:.o=.c) 2> /dev/null ; \
+# $(CC) -M $(CFLAGS) $(OBJS2:.o=.S) >> .depend
diff --git a/clients/net-snk/oflib/entry.S b/clients/net-snk/oflib/entry.S
new file mode 100644
index 0000000..e88c617
--- /dev/null
+++ b/clients/net-snk/oflib/entry.S
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+ .globl call_client_interface
+call_client_interface:
+ .globl .call_client_interface
+.call_client_interface:
+ ld r4, _prom_entry@got(r2) # Load prom entry point
+ mflr r0
+ ld r4, 0(r4)
+ stdu r1, -16(r1)
+ mtctr r4
+ std r0, 8(r1)
+ bctrl
+ ld r0, 8(r1)
+ mtlr r0
+ addi r1, r1, 16
+ blr
+
+ .globl rtas_call_entry
+rtas_call_entry:
+ .globl .rtas_call_entry
+.rtas_call_entry:
+ mtctr r5
+ bctr
+
+
diff --git a/clients/net-snk/oflib/of.c b/clients/net-snk/oflib/of.c
new file mode 100644
index 0000000..7c65c2e
--- /dev/null
+++ b/clients/net-snk/oflib/of.c
@@ -0,0 +1,357 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include <of.h>
+#include <string.h>
+
+extern void call_client_interface(of_arg_t *);
+
+extern inline int
+of_0_1(const char *serv)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 0, 1,
+ { 0 }
+ };
+
+ call_client_interface(&arg);
+
+ return arg.args[0];
+}
+
+extern inline void
+of_1_0(const char *serv, int arg0)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 1, 0,
+ {arg0, 0}
+ };
+
+ call_client_interface(&arg);
+}
+
+extern inline unsigned int
+of_1_1(const char *serv, int arg0)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 1, 1,
+ {arg0, 0}
+ };
+
+ call_client_interface(&arg);
+ return arg.args[1];
+}
+
+extern inline unsigned int
+of_1_2(const char *serv, int arg0, int *ret0)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 1, 2,
+ {arg0, 0, 0}
+ };
+
+ call_client_interface(&arg);
+ *ret0 = arg.args[2];
+ return arg.args[1];
+}
+
+extern inline void
+of_2_0(const char *serv, int arg0, int arg1)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 2, 0,
+ {arg0, arg1, 0}
+ };
+
+ call_client_interface(&arg);
+}
+
+extern inline unsigned int
+of_2_1(const char *serv, int arg0, int arg1)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 2, 1,
+ {arg0, arg1, 0}
+ };
+
+ call_client_interface(&arg);
+ return arg.args[2];
+}
+
+extern inline unsigned int
+of_2_2(const char *serv, int arg0, int arg1, int *ret0)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 2, 2,
+ {arg0, arg1, 0, 0}
+ };
+
+ call_client_interface(&arg);
+ *ret0 = arg.args[3];
+ return arg.args[2];
+}
+
+extern inline unsigned int
+of_2_3(const char *serv, int arg0, int arg1, int *ret0, int *ret1)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 2, 3,
+ {arg0, arg1, 0, 0, 0}
+ };
+
+ call_client_interface(&arg);
+ *ret0 = arg.args[3];
+ *ret1 = arg.args[4];
+ return arg.args[2];
+}
+
+extern inline void
+of_3_0(const char *serv, int arg0, int arg1, int arg2)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 3, 0,
+ {arg0, arg1, arg2, 0}
+ };
+
+ call_client_interface(&arg);
+ return;
+}
+
+extern inline unsigned int
+of_3_1(const char *serv, int arg0, int arg1, int arg2)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 3, 1,
+ {arg0, arg1, arg2, 0}
+ };
+
+ call_client_interface(&arg);
+ return arg.args[3];
+}
+
+extern inline unsigned int
+of_3_2(const char *serv, int arg0, int arg1, int arg2, int *ret0)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 3, 2,
+ {arg0, arg1, arg2, 0, 0}
+ };
+
+ call_client_interface(&arg);
+ *ret0 = arg.args[4];
+ return arg.args[3];
+}
+
+extern inline unsigned int
+of_3_3(const char *serv, int arg0, int arg1, int arg2, int *ret0, int *ret1)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 3, 3,
+ {arg0, arg1, arg2, 0, 0, 0}
+ };
+
+ call_client_interface(&arg);
+ *ret0 = arg.args[4];
+ *ret1 = arg.args[5];
+ return arg.args[3];
+}
+
+extern inline unsigned int
+of_4_1(const char *serv, int arg0, int arg1, int arg2, int arg3)
+{
+ of_arg_t arg = {
+ p32cast serv,
+ 4, 1,
+ {arg0, arg1, arg2, arg3, 0}
+ };
+
+ call_client_interface(&arg);
+ return arg.args[4];
+}
+
+int
+of_interpret_1(void *s, void *ret)
+{
+ return of_1_2("interpret", p32cast s, ret);
+}
+
+void
+of_close(ihandle_t ihandle)
+{
+ of_1_0("close", ihandle);
+}
+
+int
+of_write(ihandle_t ihandle, void *s, int len)
+{
+ return of_3_1("write", ihandle, p32cast s, len);
+}
+
+int
+of_read(ihandle_t ihandle, void *s, int len)
+{
+ return of_3_1("read", ihandle, p32cast s, len);
+}
+
+int
+of_seek(ihandle_t ihandle, int poshi, int poslo)
+{
+ return of_3_1("seek", ihandle, poshi, poslo);
+}
+
+int
+of_getprop(phandle_t phandle, const char *name, void *buf, int len)
+{
+ return of_4_1("getprop", phandle, p32cast name, p32cast buf, len);
+}
+
+phandle_t
+of_peer(phandle_t phandle)
+{
+ return (phandle_t) of_1_1("peer", phandle);
+}
+
+phandle_t
+of_child(phandle_t phandle)
+{
+ return (phandle_t) of_1_1("child", phandle);
+}
+
+phandle_t
+of_parent(phandle_t phandle)
+{
+ return (phandle_t) of_1_1("parent", phandle);
+}
+
+phandle_t
+of_finddevice(const char *name)
+{
+ return (phandle_t) of_1_1("finddevice", p32cast name);
+}
+
+ihandle_t
+of_open(const char *name)
+{
+ return (ihandle_t) of_1_1("open", p32cast name);
+}
+
+void *
+of_claim(void *start, unsigned int size, unsigned int align)
+{
+ return(void *)(long)(size_t)of_3_1("claim", p32cast start, size, align);
+}
+
+void
+of_release(void *start, unsigned int size)
+{
+ (void) of_2_0("release", p32cast start, size);
+}
+
+unsigned int
+romfs_lookup(const char *name, void **addr)
+{
+ unsigned int high, low;
+ unsigned int i = of_2_3("ibm,romfs-lookup", p32cast name, strlen(name),
+ (int *) &high, (int *) &low);
+ *addr = (void*)(((unsigned long) high << 32) | (unsigned long) low);
+ return i;
+}
+
+void *
+of_call_method_3(const char *name, ihandle_t ihandle, int arg0)
+{
+ int entry, rc;
+ rc = of_3_2("call-method", p32cast name, ihandle, arg0, &entry);
+ return rc != 0 ? 0 : (void *) (long) entry;
+}
+
+int
+vpd_read(unsigned int offset, unsigned int length, char *data)
+{
+ int result;
+ long tmp = (long) data;
+ result = of_3_1("rtas-read-vpd", offset, length, (int) tmp);
+ return result;
+}
+
+int
+vpd_write(unsigned int offset, unsigned int length, char *data)
+{
+ int result;
+ long tmp = (long) data;
+ result = of_3_1("rtas-write-vpd", offset, length, (int) tmp);
+ return result;
+}
+
+static void
+ipmi_oem_led_set(int type, int instance, int state)
+{
+ return of_3_0("set-led", type, instance, state);
+}
+
+int
+write_mm_log(char *data, unsigned int length, unsigned short type)
+{
+ long tmp = (long) data;
+
+ ipmi_oem_led_set(2, 0, 1);
+ return of_3_1("write-mm-log", (int) tmp, length, type);
+}
+
+int
+of_yield(void)
+{
+ return of_0_1("yield");
+}
+
+void *
+of_set_callback(void *addr)
+{
+ return (void *) (long) (size_t) of_1_1("set-callback", p32cast addr);
+}
+
+void
+bootmsg_warning(short id, const char *str, short lvl)
+{
+ (void) of_3_0("bootmsg-warning", id, lvl, p32cast str);
+}
+
+void
+bootmsg_error(short id, const char *str)
+{
+ (void) of_2_0("bootmsg-error", id, p32cast str);
+}
+
+void
+bootmsg_debugcp(short id, const char *str, short lvl)
+{
+ (void) of_3_0("bootmsg-debugcp", id, lvl, p32cast str);
+}
+
+void
+bootmsg_cp(short id)
+{
+ (void) of_1_0("bootmsg-cp", id);
+}
diff --git a/clients/net-snk/oflib/pci.c b/clients/net-snk/oflib/pci.c
new file mode 100644
index 0000000..6b774fa
--- /dev/null
+++ b/clients/net-snk/oflib/pci.c
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <rtas.h>
+#include <of.h>
+#include <pci.h>
+#include <string.h>
+#include <kernel.h>
+#include <cpu.h>
+
+int
+pci_calc_bar_size(long long puid, int bus, int devfn, int bar)
+{
+ int size;
+ int old;
+ bar = bar * 4 + 0x10;
+ old = rtas_pci_config_read(puid, 4, bus, devfn, bar);
+ rtas_pci_config_write(puid, 4, bus, devfn, bar, 0xffffffff);
+ size = (rtas_pci_config_read(puid, 4, bus, devfn, bar) & (-4)) * -1;
+ rtas_pci_config_write(puid, 4, bus, devfn, bar, old);
+ return size;
+}
+
+int
+pci_get_bar_start(long long puid, int bus, int devfn, int bar)
+{
+ return rtas_pci_config_read(puid, 4, bus, devfn, bar * 4 + 0x10);
+}
+
+void
+pci_set_bar_start(long long puid, int bus, int devfn, int bar, int value)
+{
+ rtas_pci_config_write(puid, 4, bus, devfn, bar * 4 + 0x10, value);
+}
+
+unsigned int
+read_io(void *addr, size_t sz)
+{
+ unsigned int ret;
+
+ switch (sz) {
+ case 1:
+ set_ci();
+ ret = (unsigned int) *((unsigned char *) addr);
+ clr_ci();
+ break;
+ case 2:
+ set_ci();
+ ret = (unsigned int) *((unsigned short *) addr);
+ clr_ci();
+ break;
+ case 4:
+ set_ci();
+ ret = *((unsigned int *) addr);
+ clr_ci();
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int
+write_io(void *addr, unsigned int value, size_t sz)
+{
+ switch (sz) {
+ case 1:
+ set_ci();
+ *((unsigned char *) addr) = (unsigned char) value;
+ clr_ci();
+ break;
+ case 2:
+ set_ci();
+ *((unsigned short *) addr) = (unsigned short) value;
+ clr_ci();
+ break;
+ case 4:
+ set_ci();
+ *((unsigned int *) addr) = value;
+ clr_ci();
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/clients/net-snk/oflib/rtas.c b/clients/net-snk/oflib/rtas.c
new file mode 100644
index 0000000..037baf0
--- /dev/null
+++ b/clients/net-snk/oflib/rtas.c
@@ -0,0 +1,334 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <rtas.h>
+#include <of.h>
+#include <types.h>
+#include "kernel.h"
+
+typedef int rtas_arg_t;
+
+typedef struct {
+ int token;
+ int nargs;
+ int nret;
+ rtas_arg_t args[16];
+ rtas_arg_t *rets; /* Pointer to return values in args[]. */
+} rtas_args_t;
+
+rtas_args_t rtas_args;
+
+typedef struct {
+ void *rtas_start;
+ void *rtas_entry;
+ int rtas_size;
+ phandle_t dev;
+} rtas_t;
+
+extern rtas_t _rtas;
+static int instantiate_rtas(void);
+void rtas_call_entry(rtas_args_t *, void *, void *);
+
+int
+rtas_token(const char *service)
+{
+ int token;
+ int retVal;
+ if (_rtas.dev == 0)
+ instantiate_rtas();
+
+ retVal = of_getprop(_rtas.dev, service, &token, sizeof(token));
+ if (retVal == -1) {
+ token = 0;
+ }
+ return token;
+}
+
+int
+rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+ va_list list;
+ int i;
+
+ rtas_args.token = token;
+ rtas_args.nargs = nargs;
+ rtas_args.nret = nret;
+ rtas_args.rets = (rtas_arg_t *) & (rtas_args.args[nargs]);
+ va_start(list, outputs);
+ for (i = 0; i < nargs; ++i) {
+ rtas_args.args[i] = (rtas_arg_t) (va_arg(list, unsigned int));
+ }
+ va_end(list);
+
+ for (i = 0; i < nret; ++i)
+ rtas_args.rets[i] = 0;
+
+ rtas_call_entry(&rtas_args, _rtas.rtas_start, _rtas.rtas_entry);
+ if (nret > 0 && outputs != 0)
+ for (i = 0; i < nret; i++)
+ outputs[i] = rtas_args.rets[i];
+#if 0
+ printf("rtas call %x %x %x args: %x %x %x %x %x %x %x %x\n",
+ token, nargs, nret,
+ rtas_args.args[0],
+ rtas_args.args[1],
+ rtas_args.args[2],
+ rtas_args.args[3],
+ rtas_args.args[4], rtas_args.args[5], outputs[0], outputs[1]);
+#endif
+ return ((nret > 0) ? rtas_args.rets[0] : 0);
+}
+
+rtas_t _rtas;
+
+static int
+instantiate_rtas(void)
+{
+ long long *rtas_mem_space;
+ ihandle_t ihandle;
+ _rtas.dev = of_finddevice("/rtas");
+ if ((long) _rtas.dev < 0) {
+ printf("Could not open /rtas\n");
+ return -1;
+ }
+
+ of_getprop(_rtas.dev, "rtas-size", &_rtas.rtas_size,
+ sizeof(_rtas.rtas_size));
+
+ if (_rtas.rtas_size <= 0) {
+ printf("Size of rtas (%x) too small to make sense\n",
+ _rtas.rtas_size);
+ return -1;
+ }
+
+ rtas_mem_space = (long long *) malloc_aligned(_rtas.rtas_size, 0x100);
+
+ if (!rtas_mem_space) {
+ printf("Failed to allocated memory for RTAS\n");
+ return -1;
+ }
+
+ ihandle = of_open("/rtas");
+
+ if ((long) ihandle < 0) {
+ printf("Could not open /rtas\n");
+ return -1;
+ }
+
+ if ((long) (_rtas.rtas_entry = of_call_method_3("instantiate-rtas",
+ ihandle,
+ p32cast rtas_mem_space))
+ > 0) {
+ _rtas.rtas_start = rtas_mem_space;
+ } else {
+ printf("instantiate-rtas failed\n");
+ return -1;
+ }
+#if 0
+ printf("\ninstantiate-rtas at %x size %x entry %x\n",
+ _rtas.rtas_start, _rtas.rtas_size, _rtas.rtas_entry);
+#endif
+ return 0;
+}
+
+static int read_pci_config_token = 0;
+static int write_pci_config_token = 0;
+static int ibm_read_pci_config_token = 0;
+static int ibm_write_pci_config_token = 0;
+static int ibm_update_flash_64_and_reboot_token = 0;
+static int ibm_update_flash_64_token = 0;
+static int manage_flash_token = 0;
+static int system_reboot_token = 0;
+static int get_time_of_day_token = 0;
+static int set_time_of_day_token = 0;
+static int start_cpu_token = 0;
+static int stop_self_token = 0;
+
+void
+rtas_init()
+{
+ int ret;
+ ret = instantiate_rtas();
+ if (ret)
+ return;
+ read_pci_config_token = rtas_token("read-pci-config");
+ ibm_read_pci_config_token = rtas_token("ibm,read-pci-config");
+ write_pci_config_token = rtas_token("write-pci-config");
+ ibm_write_pci_config_token = rtas_token("ibm,write-pci-config");
+ ibm_update_flash_64_and_reboot_token =
+ rtas_token("ibm,update-flash-64-and-reboot");
+ ibm_update_flash_64_token = rtas_token("ibm,update-flash-64");
+ manage_flash_token = rtas_token("ibm,manage-flash-image");
+ system_reboot_token = rtas_token("system-reboot");
+ get_time_of_day_token = rtas_token("get-time-of-day");
+ set_time_of_day_token = rtas_token("set-time-of-day");
+ start_cpu_token = rtas_token("start-cpu");
+ stop_self_token = rtas_token("stop-self");
+}
+
+
+int
+rtas_pci_config_read(long long puid, int size, int bus, int devfn, int offset)
+{
+ int value[2];
+
+ if (ibm_read_pci_config_token && puid) {
+ rtas_call(ibm_read_pci_config_token, 4, 2, value,
+ bus << 16 | devfn << 8 | offset,
+ puid >> 32, puid & 0xffffffffULL, size);
+ } else if (read_pci_config_token) {
+ rtas_call(read_pci_config_token, 2, 2, value,
+ bus << 16 | devfn << 8 | offset, size);
+ }
+
+ return value[1];
+}
+
+int
+rtas_pci_config_write(long long puid, int size, int bus, int devfn,
+ int offset, int value)
+{
+ int rc;
+
+ if (ibm_write_pci_config_token && puid) {
+ rtas_call(ibm_write_pci_config_token, 5, 1, &rc,
+ bus << 16 | devfn << 8 | offset,
+ puid >> 32, puid & 0xffffffffULL, size, value);
+ } else
+ rtas_call(write_pci_config_token, 3, 1, &rc,
+ bus << 16 | devfn << 8 | offset, size, value);
+
+ return rc;
+}
+
+/* a simple blocklist like this will us give no animation during flashing */
+
+struct block_list {
+ long long size; //size of blocklist in bytes
+ long long address; //address of memory area
+ long long length; //lenght of memory area
+};
+
+int
+rtas_ibm_update_flash_64_and_reboot(long long address, long long length)
+{
+ int rc;
+ struct block_list block_list;
+ block_list.size = sizeof(block_list);
+ block_list.address = address;
+ block_list.length = length;
+ if (ibm_update_flash_64_and_reboot_token)
+ rtas_call(ibm_update_flash_64_and_reboot_token, 1, 1, &rc,
+ &block_list);
+
+ return rc;
+}
+
+int
+rtas_ibm_manage_flash(int mode)
+{
+ int rc;
+ if (manage_flash_token)
+ rtas_call(manage_flash_token, 1, 1, &rc, mode);
+ return rc;
+}
+
+int
+rtas_ibm_update_flash_64(long long address, long long length)
+{
+ int rc;
+ struct block_list block_list;
+ block_list.size = sizeof(block_list);
+ block_list.address = address;
+ block_list.length = length;
+ if (ibm_update_flash_64_token)
+ rtas_call(ibm_update_flash_64_token, 1, 1, &rc, &block_list);
+
+ return rc;
+}
+
+int
+rtas_system_reboot()
+{
+ int rc;
+ if (system_reboot_token)
+ rtas_call(system_reboot_token, 0, 1, &rc);
+ return rc;
+}
+
+
+int
+rtas_get_time_of_day(dtime * get)
+{
+ int rc = -1;
+ unsigned int year;
+ unsigned int month;
+ unsigned int day;
+ unsigned int hour;
+ unsigned int minute;
+ unsigned int second;
+ unsigned int nano;
+
+ if (get_time_of_day_token)
+ rtas_call(get_time_of_day_token, 0, 8, &rc, &year, &month, &day,
+ &hour, &minute, &second, &nano);
+
+ get->year = year;
+ get->month = month;
+ get->day = day;
+ get->hour = hour;
+ get->minute = minute;
+ get->second = second;
+ get->nano = nano;
+
+ return rc;
+}
+
+int
+rtas_set_time_of_day(dtime * set)
+{
+ int rc = -1;
+ if (set_time_of_day_token)
+ rtas_call(set_time_of_day_token, 7, 1, &rc, set->year,
+ set->month, set->day, set->hour, set->minute,
+ set->second, set->nano);
+ return rc;
+}
+
+
+int
+rtas_start_cpu(int pid, thread_t func_ptr, int r3)
+{
+ int rc;
+ if (start_cpu_token)
+ rtas_call(start_cpu_token, 3, 1, &rc, pid,
+ (int) (long) func_ptr, (int) r3);
+ printk("start-cpu called %d %x %x %x\n", rc, start_cpu_token, pid,
+ (long) func_ptr);
+ return rc;
+}
+
+int
+rtas_stop_self()
+{
+ int rc;
+ // fixme
+ stop_self_token = 0x20;
+
+ if (stop_self_token) {
+ rtas_call(stop_self_token, 0, 1, &rc);
+ printk("TOK\n");
+ }
+ return rc;
+}
diff --git a/clients/net-snk/sec-client.lds b/clients/net-snk/sec-client.lds
new file mode 100644
index 0000000..a1b13a4
--- /dev/null
+++ b/clients/net-snk/sec-client.lds
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_entry)
+
+SECTIONS {
+ .client 0x200000:
+ {
+ __client_start = .;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ KEEP (*(.opd))
+ . = ALIGN(256);
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(256);
+/* *(*COM* .bss .gnu.linkonce.b.*) */
+ } =0x60000000
+
+ .lowmem :
+ {
+ _lowmem_start = .;
+ *(.lowmem)
+ _lowmem_end = .;
+ }
+
+ .got :
+ {
+ . = ALIGN(8);
+ _got = .;
+ *(.got .toc)
+ _got_end = .;
+ }
+ .bss :
+ {
+ *(*COM* .bss .gnu.linkonce.b.*)
+ __client_end = .;
+ }
+}
diff --git a/clients/takeover/Makefile b/clients/takeover/Makefile
new file mode 100644
index 0000000..acd6c48
--- /dev/null
+++ b/clients/takeover/Makefile
@@ -0,0 +1,60 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include $(TOPCMNDIR)/make.rules
+
+SNKDIR = $(TOPCMNDIR)/clients/net-snk
+
+CFLAGS += -fno-builtin -I$(LIBCMNDIR)/libc/include
+CFLAGS += -I$(SNKDIR)/include -I. $(CPUARCHDEF)
+CFLAGS += -I$(INCLBRDDIR) -I.. -O2 -msoft-float
+CFLAGS += $(PLATFORM) -I$(INCLCMNDIR)/$(CPUARCH)
+CFLAGS += $(BOOT) -Wa,-mregnames $(RELEASE)
+
+OBJS = $(SNKDIR)/kernel/kernel.o
+OBJS += $(SNKDIR)/oflib/oflib.o
+OBJS += $(SNKDIR)/libc/time/timer.o
+OBJS += $(LIBCMNDIR)/libc.a entry.o main.o of.elf takeover.o
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $^
+
+all: takeover.elf
+
+takeover.elf: ppc32wrap.o takeover.elf32
+ @echo " ====== Building $@ ======"
+ $(CROSS)gcc -m32 -N -Wl,-melf32ppclinux -static -nostdlib \
+ -Wl,-Ttext,0x400000 -Wl,-Tdata,0x400100 \
+ $(CFLAGS) $^ -o $@
+
+takeover.elf64: entry.o main.o takeover.o $(SNKDIR)/libc/time/timer.o of.elf
+ make -C $(LIBCMNDIR) libc
+ make -C $(CLIENTSDIR)
+ $(LD) $(LDFLAGS) -o $@ -Tclient.lds $(OBJS)
+
+of.elf: ../../boot_rom.bin
+ $(OBJCOPY) --input-target=binary --binary-architecture=powerpc -O elf64-powerpc $< $@
+
+takeover.elf32: takeover.elf64
+ $(OBJCOPY) -O binary $^ takeover.tmp
+ $(OBJCOPY) --input-target=binary --binary-architecture=powerpc -O elf32-powerpc takeover.tmp $@
+
+ppc32wrap.o: ppc32wrap.S
+ $(CROSS)gcc -m32 -a32 $(CFLAGS) -c $< -o $@
+
+clean distclean:
+ make -C $(LIBCMNDIR) clean
+ make -C $(CLIENTSDIR) clean
+ $(RM) *.o *.bin *.elf
+ $(RM) takeover.elf32 takeover.elf64 takeover.tmp
+%.o: %.oco
+ cp -f $< $@
diff --git a/clients/takeover/client.lds b/clients/takeover/client.lds
new file mode 100644
index 0000000..2352db5
--- /dev/null
+++ b/clients/takeover/client.lds
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_entry)
+
+SECTIONS {
+ .client 0x400100:
+ {
+ __client_start = .;
+ *(.start)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ KEEP (*(.opd))
+ . = ALIGN(256);
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(256);
+ } =0x60000000
+
+ .diag_table :
+ {
+ _diag_init_start = .;
+ *(.diag_init)
+ _diag_init_end = .;
+ }
+ .lowmem :
+ {
+ _lowmem_start = .;
+ *(.lowmem)
+ _lowmem_end = .;
+ }
+
+ .got :
+ {
+ . = ALIGN(8);
+ _got = .;
+ *(.got .toc)
+ _got_end = .;
+ }
+ .comment : { *(.comment) }
+ .branch_lt : { *(.branch_lt) }
+ .bss :
+ {
+ __bssStart = .;
+ *(*COM* .bss .gnu.linkonce.b.*)
+ __client_end = .;
+ __bssSize = . - __bssStart;
+ }
+}
diff --git a/clients/takeover/entry.S b/clients/takeover/entry.S
new file mode 100644
index 0000000..32f2300
--- /dev/null
+++ b/clients/takeover/entry.S
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <macros.h>
+#include "takeover.h"
+
+ .globl _wrapclient
+ .section ".start"
+ .align 3
+
+_wrapclient:
+ bcl 20,31,over # branch after pointer table
+base:
+ .align 3
+.LCgot: .quad _got-base+0x8000
+over:
+ mflr r8 # gpr 8 is the base
+ ld r2, .LCgot-base(r8) # load got pointer
+ add r2, r2, r8 # add base
+ li 14, 0
+ oris 14, 14, __bssSize@h
+ ori 14, 14, __bssSize@l
+ addi 14,14,7
+ srwi 14,14,3
+ mtctr 14
+ li 14, 0
+ oris 14, 14, __bssStart@h
+ ori 14, 14, __bssStart@l
+ subi 14, 14, 8
+ li 15, 0
+1:
+ stdu 15,8(14)
+ bdnz 1b
+
+ bl ._entry
+
+
+
+ .globl slaveLoopNoTakeover
+slaveLoopNoTakeover:
+ mr 28,3
+
+ li 14,0
+ oris 14, 14, slaveQuitt@h
+ ori 14, 14, slaveQuitt@l
+
+ li 3,0
+ std 3,0(14)
+1:
+ ld 3,0(14)
+ cmpld 3,28
+ bne 1b
+
+ li 3,0
+ std 3,0(14)
+
+ LOAD64(r3, (TAKEOVERBASEADDRESS+0x150))
+ mtctr r3
+ bctr
+
+
+ .globl slaveLoop
+slaveLoop:
+ mr 28,3
+ li r3, 0x5124
+ li r0, -1; .long 0x44000022
+
+ li 14,0
+ oris 14, 14, slaveQuitt@h
+ ori 14, 14, slaveQuitt@l
+ li 3,0
+ std 3,0(14)
+1:
+ ld 3,0(14)
+ cmpld 3,28
+ bne 1b
+
+ li 3,0
+ std 3,0(14)
+
+ LOAD64(r3, (TAKEOVERBASEADDRESS+0x150))
+ mtctr r3
+ bctr
+
diff --git a/clients/takeover/main.c b/clients/takeover/main.c
new file mode 100644
index 0000000..3568a1f
--- /dev/null
+++ b/clients/takeover/main.c
@@ -0,0 +1,157 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <of.h>
+#include <pci.h>
+#include <cpu.h>
+#include <takeover.h>
+
+#define boot_rom_bin_start _binary_______boot_rom_bin_start
+#define boot_rom_bin_end _binary_______boot_rom_bin_end
+
+extern char boot_rom_bin_start;
+extern char boot_rom_bin_end;
+extern ihandle_t fd_array[32];
+
+size_t
+write(int fd, void *buf, size_t cnt)
+{
+ of_write((ihandle_t) fd_array[1], buf, cnt);
+ return 0;
+}
+
+void *
+sbrk(int incr)
+{
+ return (void *) -1;
+}
+
+void
+doWait(void)
+{
+ static const char *wheel = "|/-\\";
+ static int i = 0;
+ volatile int dly = 0xf0000;
+ while (dly--);
+ printf("\b%c", wheel[i++]);
+ i &= 0x3;
+}
+
+void
+quiesce(void)
+{
+ of_arg_t arg = {
+ p32cast "quiesce",
+ 0, 0,
+ };
+ call_client_interface(&arg);
+}
+
+int
+startCpu(int num, int addr, int reg)
+{
+ of_arg_t arg = {
+ p32cast "start-cpu",
+ 3, 0,
+ {num, addr, reg}
+ };
+ call_client_interface(&arg);
+ return arg.args[3];
+}
+
+volatile unsigned long slaveQuitt;
+int takeoverFlag;
+
+int
+main(int argc, char *argv[])
+{
+ phandle_t cpus;
+ phandle_t cpu;
+ unsigned long slaveMask;
+ extern int slaveLoop[];
+ extern int slaveLoopNoTakeover[];
+ char devtype[100];
+ int rcode;
+ int index = 0;
+ int delay = 100;
+ unsigned long reg;
+ unsigned long msr;
+ asm volatile ("mfmsr %0":"=r" (msr));
+ if (msr & 0x1000000000000000)
+ takeoverFlag = 0;
+ else
+ takeoverFlag = 1;
+
+ cpus = of_finddevice("/cpus");
+ cpu = of_child(cpus);
+ slaveMask = 0;
+ while (cpu) {
+ char devType[100];
+ *devType = '\0';
+ of_getprop(cpu, "device_type", devType, sizeof(devType));
+ if (strcmp(devType, "cpu") == 0) {
+ of_getprop(cpu, "reg", &reg, sizeof(reg));
+ if (index) {
+ printf("\r\n takeover on cpu%d (%x, %x) ", index,
+ cpu, reg);
+ slaveQuitt = -1;
+ if (takeoverFlag)
+ startCpu(cpu, (int) slaveLoop, index);
+ else
+ startCpu(cpu, (int) slaveLoopNoTakeover,
+ index);
+ slaveMask |= 0x1 << index;
+ delay = 100;
+ while (delay-- && slaveQuitt)
+ doWait();
+ }
+ index++;
+ }
+ cpu = of_peer(cpu);
+ }
+
+
+ printf("\r\n takeover on master cpu ");
+ quiesce();
+
+ delay = 5;
+ while (delay--)
+ doWait();
+ if (takeoverFlag)
+ rcode = takeover();
+
+ memcpy((void*)TAKEOVERBASEADDRESS, &boot_rom_bin_start, &boot_rom_bin_end - &boot_rom_bin_start);
+ flush_cache((void *)TAKEOVERBASEADDRESS, &boot_rom_bin_end - &boot_rom_bin_start);
+ index = 0;
+
+ while (slaveMask) {
+ unsigned long shifter = 0x1 << index;
+ if (shifter & slaveMask) {
+ slaveQuitt = index;
+ while (slaveQuitt);
+ slaveMask &= ~shifter;
+ }
+ index++;
+ }
+
+ asm volatile(" mtctr %0 ; bctr " : : "r" (TAKEOVERBASEADDRESS+0x180) );
+}
+
+int
+callback(int argc, char *argv[])
+{
+ /* Dummy, only for takeover */
+ return (0);
+}
diff --git a/clients/takeover/ppc32wrap.S b/clients/takeover/ppc32wrap.S
new file mode 100644
index 0000000..ff96095
--- /dev/null
+++ b/clients/takeover/ppc32wrap.S
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+ .globl _start
+ .section ".text"
+ .align 3
+
+_start:
+ nop
+ bl over
+ .llong 0x9000000000003000
+over:
+ li 14, 0
+ oris 14, 14, _binary_takeover_tmp_start@h
+ ori 14, 14, _binary_takeover_tmp_start@l
+ mtsrr0 14
+ mflr 15
+ ld 14,0(15)
+ mtsrr1 14
+ rfid
+
diff --git a/clients/takeover/takeover.h b/clients/takeover/takeover.h
new file mode 100644
index 0000000..f5201ef
--- /dev/null
+++ b/clients/takeover/takeover.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#if defined(CPU_CBEA)
+#define TAKEOVERBASEADDRESS 0x0e000000
+#elif defined(CPU_PPC970)
+#define TAKEOVERBASEADDRESS 0x00000000
+#else
+#error no processor specified
+#endif
+
+#ifndef __ASSEMBLER__
+int takeover();
+#endif
diff --git a/include/calculatecrc.h b/include/calculatecrc.h
new file mode 100644
index 0000000..9f646e5
--- /dev/null
+++ b/include/calculatecrc.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef CALCULATECRC_H
+#define CALCULATECRC_H
+
+ #define FLASHFS_DATADDR 0x18 // uint64_t position of pointer to data
+ #define FLASHFS_FILE_SIZE_ADDR 0x08 // uint64_t pos of total flashimage size value relative to data
+ #define FLASHFS_HEADER_SIZE_ADDR 0x08 // uint64_t position of total flash header size value
+
+ #ifdef __ASSEMBLER__
+ // "CRC_GENERATOR" must contain equal inforamtion as "CRC_METHODE"
+ #define CRC_GENERATOR 0x0000000004C11DB7
+ #define CRC_REGISTERMASK 0x00000000FFFFFFFF
+ #define CRC_REGISTERLENGTH 32
+ #endif /* __ASSEMBLER__ */
+
+ #ifndef __ASSEMBLER__
+ #define FLASHFS_ROMADDR 0x00 // uint64_t position of pointer to next file
+ #define FLASHFS_HEADER_DATA_SIZE 0x68 // 104 bytes of total header data size
+ #define CRC_METHODE Ethernet_32 // define the CRc genarator (CRC 16 bit to 64 is supported)
+
+ //--- header format ---------------------------------
+ struct stH {
+ char magic[8]; // (generic!) headerfile
+ uint64_t flashlen; // dyn
+ char version[16]; // $DRIVER_INFO alignment!
+ char platform_name[32]; // (hardware) headerfile
+ char date[6]; // dyn (format -> JB)
+ char padding1[2]; // padding byte
+ char mdate[6]; // modify date
+ char padding2[2]; // padding byte
+ char platform_revision[4];// (hardware) headerfile
+ uint32_t padding;
+ uint64_t ui64CRC; // insert calculated CRC here
+ uint64_t ui64FileEnd; // = 0xFFFF FFFF FFFF FFFF
+ };
+ #endif /* __ASSEMBLER__ */
+
+#endif /* CALCULATECRC_H */
+
+/*--- supported CRC Generators -------------------------
++ Name length usage Generator
++ Tap_16 16 bit Tape 0x00008005
++ Floppy_16 16 bit Floppy 0x00001021
++ Ethernet_32 32 bit Ethernet 0x04C11DB7
++ SPTrEMBL_64 64 bit white noise like date 0x0000001B
++ SPTrEMBL_improved_64 64 bit DNA code like date 0xAD93D23594C9362D
++ DLT1_64 64 bit Tape 0x42F0E1EBA9EA3693
++
++ CRC_REGISTERLENGTH = bit length
++ CRC_REGISTERMASK = -1 for a n-bit numer where n = bit length
++ example TAP_16: CRC_REGSISTERLENGTH = 16
++ CRC_REGISTERMASK = 0xFFFFFFFF = (-1 if 16 bit number is used)
++
++ TrEMBL see also http://www.cs.ud.ac.uk/staff/D.Jones/crcbote.pdf
++ DLT1 se also http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf
++--------------------------------------------------------*/
diff --git a/include/macros.h b/include/macros.h
new file mode 100644
index 0000000..79c67c4
--- /dev/null
+++ b/include/macros.h
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#define LOAD64(rn,name) \
+ lis rn,name##@highest; \
+ ori rn,rn,name##@higher; \
+ rldicr rn,rn,32,31; \
+ oris rn,rn,name##@h; \
+ ori rn,rn,name##@l
+
+#define LOAD32(rn, name) \
+ lis rn,name##@h; \
+ ori rn,rn,name##@l
+
+// load 32 bit constant in little endian order
+#define LOAD32le(rn,name) \
+ lis rn,(((name>>8)&0x00FF)|((name<<8)&0xFF00)); \
+ ori rn,rn,(((name>>24)&0x00FF)|((name>>8)&0xFF00))
+
+// load 16 bit constant in little endian order
+#define LOAD16le(rn,name) \
+ li rn,(((name>>8)&0x00FF)|((name<<8)&0xFF00))
+
+#define ENTRY(func_name) \
+ .text; \
+ .align 2; \
+ .globl .func_name; \
+ .func_name: \
+ .globl func_name; \
+ func_name:
+
+#define C_ENTRY(func_name) \
+ .section ".text"; \
+ .align 2; \
+ .globl func_name; \
+ .section ".opd","aw"; \
+ .align 3; \
+ func_name: \
+ .quad .func_name,.TOC.@tocbase,0; \
+ .previous; \
+ .size func_name,24; \
+ .type .func_name,@function; \
+ .globl .func_name; \
+ .func_name:
+
+#define ASM_ENTRY(fn) \
+ .globl fn; \
+fn:
+
diff --git a/include/memmap.h b/include/memmap.h
new file mode 100644
index 0000000..5c9687a
--- /dev/null
+++ b/include/memmap.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef MEMMAP_H
+#define MEMMAP_H
+
+#define MEG 0x100000
+
+#define SLAVELOOP_LOADBASE 0x0000000000003f00
+#define STAGE2_LOADBASE (60 * MEG)
+#define OF_LOADBASE 0x000000000000a000
+
+#define MEM_HALF (512 * MEG)
+
+/* BE Engines Offsets */
+#define BE_MIC_BASE 0x50A000
+
+#endif
diff --git a/include/pcd.h b/include/pcd.h
new file mode 100644
index 0000000..078d8fc
--- /dev/null
+++ b/include/pcd.h
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef PCD_H
+#define PCD_H
+
+#define PCD_START_ADDR 0xFF00000 // FIXME: this should not interfere with
+ // other parts of the firmware
+#define PCD_HDR_SIZE (6 * 8) /* only use for ctrl file */
+
+/* PCD File Definition ****************************************/
+/* File = "p:ctrl" 0x703a6374726c0000 */
+/* Data : */
+/* [00:07] - pointer to header of last file which was created */
+/* [08:0f] - pointer to header of next file for creation */
+/**************************************************************/
+#define PCDF_CTRL_LAST 0
+#define PCDF_CTRL_NEXT 8
+
+/* PCD File Definition ****************************************/
+/* File = "p:pXmem" */
+/* Data : */
+/* [00:07] - number of memory segments */
+/* [08:0f] - real base of memory segment #n */
+/* [10:17] - real size of memory segment #n */
+/* [18:1f] - real base of memory segment #n+1 */
+/* [20:27] - real size of memory segment #n+1 */
+/* ... and so on.. */
+/**************************************************************/
+#define PCDF_MEM_NUM 0
+#define PCDF_MEMN_BASE(N) (8 + (N * 8))
+#define PCDF_MEMN_SIZE(M) (PCDF_MEMN_BASE(M) + 8)
+
+/* PCD File Definition ****************************************/
+/* File = "p:pXcfg" */
+/* Data : */
+/* [00:07] - number of memory segments */
+/* [08:0f] - real base of memory segment #n */
+/* [10:17] - real size of memory segment #n */
+/* [18:1f] - real base of memory segment #n+1 */
+/* [20:27] - real size of memory segment #n+1 */
+/* ... and so on.. */
+/**************************************************************/
+#define PCDF_PCFG_IOCBASE (0 * 8)
+#define PCDF_PCFG_BPBASE (1 * 8)
+#define PCDF_PCFG_SPUMAP (2 * 8)
+#define PCDF_PCFG_TIMEBASE (3 * 8)
+#define PCDF_PCFG_CPUFREQ (4 * 8)
+
+#endif
diff --git a/include/ppc970/cpu.h b/include/ppc970/cpu.h
new file mode 100644
index 0000000..001bb84
--- /dev/null
+++ b/include/ppc970/cpu.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __PPC970_H
+#define __PPC970_H
+
+/* SPRs numbers */
+
+#define CTRL_RD 136
+#define CTRL_WR 152
+#define PVR 287
+#define HSPRG0 304
+#define HSPRG1 305
+#define HIOR 311
+#define HID0 1008
+#define HID1 1009
+#define HID4 1012
+#define HID6 1017
+#define PIR 1023
+
+#define SETCI(r) sync; \
+ mfspr r, HID4; \
+ sync; \
+ rldicl r, r, 32,0; \
+ ori r, r, 0x0100; \
+ rldicl r, r, 32,0; \
+ sync; \
+ slbia; \
+ mtspr HID4, r; \
+ isync;
+
+#define CLRCI(r) sync; \
+ mfspr r, HID4; \
+ sync; \
+ rldicl r, r, 32, 0; \
+ ori r, r, 0x0100; \
+ xori r, r, 0x0100; \
+ rldicl r, r, 32, 0; \
+ sync; \
+ slbia; \
+ mtspr HID4, r; \
+ isync;
+
+/* This macro uses r0 */
+#define FLUSH_CACHE(r, n) add n, n, r; \
+ addi n, n, 127; \
+ rlwinm r, r, 0,0,24; \
+ rlwinm n, n, 0,0,24; \
+ sub n, n, r; \
+ srwi n, n, 7; \
+ mtctr n; \
+ 0: dcbst 0, r; \
+ sync; \
+ icbi 0, r; \
+ sync; \
+ isync; \
+ addi r, r, 128; \
+ bdnz 0b;
+
+#ifndef __ASSEMBLER__
+#define STRINGIFY(x...) #x
+#define EXPAND(x) STRINGIFY(x)
+
+static inline void
+set_ci()
+{
+ unsigned long tmp;
+ asm volatile(EXPAND(SETCI(%0)) : "=r"(tmp) :: "memory", "cc");
+}
+
+static inline void
+clr_ci()
+{
+ unsigned long tmp;
+ asm volatile(EXPAND(CLRCI(%0)) : "=r"(tmp) :: "memory", "cc");
+}
+
+static inline void
+eieio()
+{
+ asm volatile ("eieio":::"memory");
+}
+
+static inline void
+flush_cache(void* r, long n)
+{
+ asm volatile(EXPAND(FLUSH_CACHE(%0, %1)) : "+r"(r), "+r"(n) :: "memory", "cc", "r0", "ctr");
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif
diff --git a/include/romfs.h b/include/romfs.h
new file mode 100644
index 0000000..612d805
--- /dev/null
+++ b/include/romfs.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef ROMFS_H
+#define ROMFS_H
+
+#define RFS_T_SIZE 0x00
+#define RFS_T_FLAGS 0x08
+#define RFS_T_FILEADDR 0x10
+#define RFS_T_NEXT 0x18
+#define RFS_T_NAME 0x20
+#define RFS_T_DATA 0x28
+
+#define RFS_H_NEXT 0x00
+#define RFS_H_SIZE 0x08
+#define RFS_H_FLAGS 0x10
+#define RFS_H_DATA 0x18
+#define RFS_H_NAME 0x20
+
+#define ROMFS_HDR_NEXT (0 * 8)
+#define ROMFS_HDR_LEN (1 * 8)
+#define ROMFS_HDR_FLAG (2 * 8)
+#define ROMFS_HDR_DPTR (3 * 8)
+#define ROMFS_HDR_NAME (4 * 8)
+
+#ifndef __ASSEMBLER__
+/* no not change except if you change romfs.S */
+struct romfs_t {
+ unsigned long size;
+ unsigned long flags;
+ unsigned long fileaddr;
+ unsigned long nexfile;
+ unsigned char *namep;
+ unsigned char *datap;
+};
+
+struct romfs_lookup_t {
+ unsigned long addr_header;
+ unsigned long addr_data;
+ unsigned long size_data;
+ unsigned long flags;
+};
+
+int romfs_stat(char *filename, struct romfs_t *hnd);
+
+int romfs_stat_file(char *filename, struct romfs_t *hnd);
+
+int c_romfs_lookup(char *filename, unsigned long rombase,
+ struct romfs_lookup_t *ret);
+
+#endif /* __ASSEMBLER__ */
+#endif /* ROMFS_H */
diff --git a/include/rtas.h b/include/rtas.h
new file mode 100644
index 0000000..c2f1029
--- /dev/null
+++ b/include/rtas.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __RTAS_H
+#define __RTAS_H
+
+#ifndef __ASSEMBLER__
+
+#include <stddef.h>
+
+typedef int rtas_arg_t;
+typedef struct {
+ int token;
+ int nargs;
+ int nret;
+ rtas_arg_t args[16];
+} rtas_args_t;
+
+#else
+
+#define RTAS_STACKSIZE 0x1000
+
+#define RTAS_PARM_0 0x0c
+#define RTAS_PARM_1 0x10
+#define RTAS_PARM_2 0x14
+#define RTAS_PARM_3 0x18
+#define RTAS_PARM_4 0x1C
+#define RTAS_PARM_5 0x20
+#define RTAS_PARM_6 0x24
+#define RTAS_PARM_7 0x28
+
+#endif /* __ASSEMBLER__ */
+#endif /* __RTAS_H */
diff --git a/include/rtas_table.h b/include/rtas_table.h
new file mode 100644
index 0000000..ee161e7
--- /dev/null
+++ b/include/rtas_table.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __RTAS_TABLE_H
+#define __RTAS_TABLE_H
+
+
+typedef struct {
+ char *name;
+ void (*func)(rtas_args_t *args);
+ unsigned long flags;
+} rtas_funcdescr_t;
+
+
+// Flags for the RTAS table:
+#define RTAS_TBLFLG_INTERNAL 1
+
+
+extern const rtas_funcdescr_t rtas_func_tab[];
+extern const int rtas_func_tab_size;
+
+
+#endif // __RTAS_TABLE_H
diff --git a/include/termctrl.h b/include/termctrl.h
new file mode 100644
index 0000000..082d3f1
--- /dev/null
+++ b/include/termctrl.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef TERMCTRL_H
+#define TERMCTRL_H
+
+/* foreground colors */
+#define TERM_FG_BLACK ""
+#define TERM_FG_RED ""
+#define TERM_FG_GREEN ""
+#define TERM_FG_YELLOW ""
+#define TERM_FG_BLUE ""
+#define TERM_FG_MAGENTA ""
+#define TERM_FG_CYAN ""
+#define TERM_FG_WHITE ""
+
+/* background colors */
+#define TERM_BG_BLACK ""
+#define TERM_BG_RED ""
+#define TERM_BG_GREEN ""
+#define TERM_BG_YELLOW ""
+#define TERM_BG_BLUE ""
+#define TERM_BG_MAGENTA ""
+#define TERM_BG_CYAN ""
+#define TERM_BG_WHITE ""
+
+/* control */
+#define TERM_CTRL_RESET ""
+#define TERM_CTRL_BRIGHT ""
+#define TERM_CTRL_DIM ""
+#define TERM_CTRL_UNDERSCORE ""
+#define TERM_CTRL_BLINK ""
+#define TERM_CTRL_REVERSE ""
+#define TERM_CTRL_HIDDEN ""
+#define TERM_CTRL_CLEAR ""
+#define TERM_CTRL_HOME ""
+
+#define TERM_CTRL_1UP ""
+#define TERM_CTRL_1BACK ""
+#define TERM_CTRL_SAVECRS ""
+#define TERM_CTRL_RESTCRS ""
+#define TERM_CTRL_CRSON "[?25h"
+#define TERM_CTRL_CRSOFF "[?25l"
+#define TERM_CTRL_CRSFWDN "[%dC"
+#define TERM_CTRL_CRSX "[%dC"
+#define TERM_CTRL_CRSY "[%dB"
+#define TERM_CTRL_CRSXY "[%d;%dH" /* y,x */
+
+/* keys */
+#define KEY_CTRL 0x1b
+#define KEY_UP 0x41
+#define KEY_DN 0x42
+
+#endif
diff --git a/include/types.h b/include/types.h
new file mode 100644
index 0000000..8e04a94
--- /dev/null
+++ b/include/types.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _TYPES_H
+#define _TYPES_H
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#endif
diff --git a/include/xvect.h b/include/xvect.h
new file mode 100644
index 0000000..bcece53
--- /dev/null
+++ b/include/xvect.h
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __XVECT_H
+#define __XVECT_H
+
+#define XVECT_M_HANDLER 0x2ff0 /* Master Handler */
+#define XVECT_S_HANDLER 0x2ff8 /* Slave Handler */
+#define XVECT_TOPADDR 0x3fff
+#define XVECT_SLP_ENTRY SLAVELOOP_LOADBASE
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..4b3f299
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,34 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+SUBDIRS = libc libipmi libbootmsg libbases
+
+all: subdirs
+
+.PHONY : subdirs $(SUBDIRS) clean distclean
+
+
+subdirs: $(SUBDIRS)
+
+$(SUBDIRS):
+ $(MAKE) -C $@ $(MAKEARG)
+
+# Rules for making clean:
+clean:
+ @for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir clean || exit 1; \
+ done
+
+distclean:
+ @for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir distclean || exit 1; \
+ done
diff --git a/lib/libbases/Makefile b/lib/libbases/Makefile
new file mode 100644
index 0000000..0ffa0c7
--- /dev/null
+++ b/lib/libbases/Makefile
@@ -0,0 +1,42 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+include $(TOPCMNDIR)/make.rules
+
+ASFLAGS = $(PLATFORM) $(BOOT) $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames
+CFLAGS = -g -O2 -fno-builtin -ffreestanding -nostdinc -msoft-float \
+ -mno-altivec -mabi=no-altivec -Wall
+CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) -I. -I../../include
+LDFLAGS = -nostdlib
+
+all:
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
+ $(RM) Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(RM) Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+
+
+# Include dependency file if available:
+-include Makefile.dep
+
diff --git a/lib/libbases/libbases.code b/lib/libbases/libbases.code
new file mode 100644
index 0000000..7f0a752
--- /dev/null
+++ b/lib/libbases/libbases.code
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <southbridge.h>
+
+// : get-nvram-base ( -- base )
+PRIM(get_X2d_nvram_X2d_base)
+ PUSH;
+ TOS.u = SB_NVRAM_adr;
+MIRP
+
+// : get-nvram-size ( -- size )
+PRIM(get_X2d_nvram_X2d_size)
+ PUSH;
+ TOS.u = NVRAM_LENGTH;
+MIRP
+
+// : get-flash-base ( -- base )
+PRIM(get_X2d_flash_X2d_base)
+ PUSH;
+ TOS.u = SB_FLASH_adr;
+MIRP
+
+// : get-flash-size ( -- size )
+PRIM(get_X2d_flash_X2d_size)
+ PUSH;
+ TOS.u = FLASH_LENGTH;
+MIRP
+
+// : get-mbx-base ( -- base )
+PRIM(get_X2d_mbx_X2d_base)
+ PUSH;
+ TOS.u = SB_MAILBOX_adr;
+MIRP
diff --git a/lib/libbases/libbases.in b/lib/libbases/libbases.in
new file mode 100644
index 0000000..ed63de6
--- /dev/null
+++ b/lib/libbases/libbases.in
@@ -0,0 +1,17 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+cod(get-nvram-base)
+cod(get-nvram-size)
+cod(get-flash-base)
+cod(get-flash-size)
+cod(get-mbx-base)
diff --git a/lib/libbootmsg/Makefile b/lib/libbootmsg/Makefile
new file mode 100644
index 0000000..e1b4d30
--- /dev/null
+++ b/lib/libbootmsg/Makefile
@@ -0,0 +1,59 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+include $(TOPCMNDIR)/make.rules
+
+ASFLAGS = $(PLATFORM) $(BOOT) $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames
+CFLAGS = -g -O2 -fno-builtin -ffreestanding -nostdinc -msoft-float \
+ -mno-altivec -mabi=no-altivec -Wall
+CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) -I. -I../../include
+LDFLAGS = -nostdlib
+
+TARGET = ../libbootmsg.a
+
+
+all: $(TARGET)
+
+
+# SRCS = bootmsg.c
+SRCS =
+SRCSS = bootmsg_lvl.S
+
+OBJS = $(SRCS:%.c=%.o) $(SRCSS:%.S=%.o)
+
+$(TARGET): $(OBJS)
+ $(AR) -rc $@ $(OBJS)
+ $(RANLIB) $@
+
+%.o: %.S
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c $< -o $@
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
+ $(RM) Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(RM) Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+ $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(SRCSS) > Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
+
diff --git a/lib/libbootmsg/bootmsg.code b/lib/libbootmsg/bootmsg.code
new file mode 100644
index 0000000..e43afa1
--- /dev/null
+++ b/lib/libbootmsg/bootmsg.code
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <libbootmsg.h>
+
+// : cp ( cp-id -- )
+PRIM(bootmsg_X2d_cp)
+ int cpid = TOS.n; POP;
+ bootmsg_cp(cpid);
+MIRP
+
+// : bootmsg-warning ( cp-id lvl pstr -- )
+PRIM(bootmsg_X2d_warning)
+ char* str = TOS.a; POP;
+ short lvl = TOS.n; POP;
+ short cpid = TOS.n; POP;
+ bootmsg_warning(cpid, (const char*)str, lvl);
+MIRP
+
+// : bootmsg-error ( cp-id pstr -- )
+PRIM(bootmsg_X2d_error)
+ char* str = TOS.a; POP;
+ short cpid = TOS.n; POP;
+ bootmsg_error(cpid, (const char*)str);
+MIRP
+
+// : bootmsg-debugcp ( cp-id lvl pstr -- )
+PRIM(bootmsg_X2d_debugcp)
+ char* str = TOS.a; POP;
+ short lvl = TOS.n; POP;
+ short cpid = TOS.n; POP;
+ bootmsg_debugcp(cpid, (const char*)str, lvl);
+MIRP
+
+// : bootmsg-setlevel ( area lvl -- )
+PRIM(bootmsg_X2d_setlevel)
+ char lvl = TOS.n; POP;
+ short area = TOS.n; POP;
+ bootmsg_setlevel(area, lvl);
+MIRP
+
+// : bootmsg-setlevel ( -- )
+PRIM(bootmsg_X2d_nvupdate)
+ bootmsg_nvupdate();
+MIRP
diff --git a/lib/libbootmsg/bootmsg.in b/lib/libbootmsg/bootmsg.in
new file mode 100644
index 0000000..66492b3
--- /dev/null
+++ b/lib/libbootmsg/bootmsg.in
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+cod(bootmsg-cp)
+cod(bootmsg-warning)
+cod(bootmsg-error)
+cod(bootmsg-debugcp)
+cod(bootmsg-setlevel)
+cod(bootmsg-nvupdate)
diff --git a/lib/libbootmsg/bootmsg_lvl.S b/lib/libbootmsg/bootmsg_lvl.S
new file mode 100644
index 0000000..1f8ec16
--- /dev/null
+++ b/lib/libbootmsg/bootmsg_lvl.S
@@ -0,0 +1,210 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#define _ASM_
+#include "macros.h"
+#include "southbridge.h"
+#include "nvramlog.h"
+
+#define bootmsg_area_size 128
+
+ .text
+ .align 3
+
+// Declare the warning level for all 128 possibilities of AC/pCKG kombinations
+ WRNG_LVL:
+ .rept bootmsg_area_size
+ .byte 0x0
+ .endr
+
+
+//*****************************************************************************
+// Check UserWarningLevel against SystemWarningLevel
+// input : r3=cp-id, r5=level
+// change: r6,r7
+// output: CR0 ( compared user vs system level )
+// example:
+// bl GET_WRNG_LVL
+// ble print_warning
+// bgt do_not_print_warning
+ENTRY(GET_WRNG_LVL)
+ mflr r7 // save linkage register
+ bl 0f // get current
+0: mflr r6 // Instruction Address
+ mtlr r7 // restore linkage register
+ addi r6,r6,WRNG_LVL-0b // calc addr of WRNG_LVL array
+ rldic r7,r3,56,57 // calc index into array
+ lbzux r7,r6,r7 // read the warning level
+ cmpw r5,r7 // and compare it
+ blr
+
+//*****************************************************************************
+// Print CheckPoint
+// input : r3=cp-id
+// change: r3, r4, r5, r6, r7, r11
+// output: none
+ENTRY(bootmsg_cp)
+ mflr r11
+ mr r9, r3 // save checkpoint ID
+ li r3, 'C'
+ bl io_putchar // print character
+ mr r3, r9
+ bl io_printhex16 // print checkpoint ID
+ .rept 5
+ li r3,'\b'
+ bl io_putchar // print backspaces
+ .endr
+ mtlr r11
+ blr
+
+//*****************************************************************************
+// Print a general BootMessage
+// input : r3=cp-id, r4=string, r5=char (type C,W,E)
+// change: r3,r4,r5,r6,r7,r9,r10,r11,r12
+// output: none
+ENTRY(print_msg)
+ mflr r11 // Save linkage register
+ mr r9, r3 // Save ID
+ mr r10, r4 // Save ptr to string
+ mr r12, r5 // Save type (char [CWE])
+ li r3, '\n' // make it a new line
+ bl io_putchar
+ li r3, '\r'
+ bl io_putchar
+ mr r3, r12 // restore type
+ bl io_putchar // print character
+ mr r3, r9 // restore ID
+ bl io_printhex16 // print checkpoint ID
+ li r3, ' ' // print a space
+ bl io_putchar
+ mr r3, r10 // restore ptr to string
+ bl io_print // print message
+ li r3, '\n' // add a new line
+ bl io_putchar
+ li r3, '\r'
+ bl io_putchar
+ mtlr r11 // restore linkage register
+ blr
+
+//*****************************************************************************
+// Print an Error Boot Message
+// input : r3=cp-id, r4=string-ptr
+// change : r3,r4,r5,r6,r7,r9,r10,r11,r12
+// output : none
+ENTRY(bootmsg_error)
+ li r5, 'E' // E is for Error
+ b print_msg // and print this message
+
+//*****************************************************************************
+// Print a Warning Boot Message
+// input : r3=cp-id, r4=string-ptr, r5=level
+// change : r3,r4,r5,r6,r7,r9,r10,r11,r12
+// output : none
+ENTRY(bootmsg_warning)
+ mflr r11 // save linkage register
+ bl GET_WRNG_LVL // check UserLevel against SystemLevel
+ mtlr r11 // restore linkage register
+ li r5, 'W' // 'W' is for Warning
+ ble print_msg // if UserLevel<=SystemLevel print and return
+ blr // else return
+
+//*****************************************************************************
+// Print a Debug Checkpoint
+// input : r3=cp-id, r4=string-ptr, r5=level
+// change : r3,r4,r5,r6,r7,r9,r10,r11,r12
+// output : none
+// r3=cp-id, r4=string, r5=level
+ENTRY(bootmsg_debugcp)
+ mflr r11 // save linkage register
+ addi r5,r5,0x20 // add checkpoint offset
+ bl GET_WRNG_LVL // check UserLevel against SystemLevel
+ mtlr r11 // restore linkage register
+ li r5, 'D' // 'D' is for Debug CheckPoint
+ ble print_msg // if UserLevel<=SystemLevel print and return
+ blr // else return
+
+// r3=area|pkg, r4=level
+ENTRY(bootmsg_setlevel)
+ mflr r5
+ bl WarningMsg // calc current IA
+ WarningMsg:
+ mflr r6 // get current IA
+ addi r6,r6,WRNG_LVL-WarningMsg
+ andi. r3, r3, 0x7F
+ add r6,r3,r6 // address |
+ stb r4,0(r6) // store level |_ stwbrx r4,r3,r6
+ LOAD64(r6, SB_NVRAM_FWONLY_adr + 8 )
+ add r6,r6,r3
+ stb r4,0(r6)
+ mtlr r5
+ blr
+
+ENTRY(bootmsg_nvupdate)
+ mflr r10
+ LOAD64(r3, SB_NVRAM_FWONLY_adr)
+ lbz r4, 0(r3)
+ cmpwi r4, 0x424E // find bootmsg area header
+ bne 0f
+
+ LOAD64(r5, bootmsg_area_size/8)
+ mtctr r5
+ bl WngMsg
+ WngMsg:
+ mflr r5
+ addi r5,r5,WRNG_LVL-WngMsg-8
+
+1:
+ ldu r4, 8(r3)
+ stdu r4, 8(r5)
+ bdnz+ 1b
+ b 2f
+
+0: // find last partition an resize it
+ li r4, 0x10
+ mtctr r4
+ li r4, 0x0
+ li r7, 0x0
+ LOAD64(r5, SB_NVRAM_adr)
+ LOAD64(r8, NVRAM_LENGTH)
+1:
+ bdz+ 2f
+ add r5, r5, r4
+ lhz r6, 2(r5)
+ rldicl r6, r6, 4, 0
+ mr r4, r6
+ add r7, r7, r4
+ cmpw r7, r8
+ ble 1b
+
+ sub r7, r7, r4 // write new size
+ sub r6, r8, r7
+ sradi r6, r6, 4
+ sth r6, 2(r5)
+
+ mr r7, r3
+ mr r8, r5
+ mr r3, r5
+ bl .calPartitionHeaderChecksum
+ stb r3, 1(r8) // write checksum
+
+ mr r3, r7
+ LOAD64(r5, bootmsg_area_size)
+ mtctr r5
+ li r4, 0x424E // clear bootmsg log area
+ stb r4, 0(r3)
+ li r4, 0
+
+1: stdu r4, 8(r3)
+ bdnz+ 1b
+
+2: // the end
+ mtlr r10
+ blr
diff --git a/lib/libbootmsg/libbootmsg.h b/lib/libbootmsg/libbootmsg.h
new file mode 100644
index 0000000..be0ad7e
--- /dev/null
+++ b/lib/libbootmsg/libbootmsg.h
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef _LIBBOOTMSG_H
+#define _LIBBOOTMSG_H
+void bootmsg_cp(short p);
+void bootmsg_error(short p, const char *str);
+void bootmsg_warning(short p, const char *str, short lvl);
+void bootmsg_debugcp(short p, const char *str, short lvl);
+void bootmsg_setlevel(short p, short level);
+void *bootmsg_nvupdate();
+#endif /* _LIBBOOTMSG_H */
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
new file mode 100644
index 0000000..57b9694
--- /dev/null
+++ b/lib/libc/Makefile
@@ -0,0 +1,60 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+LIBCCMNDIR = $(shell pwd)
+STRINGCMNDIR = $(LIBCCMNDIR)/string
+CTYPECMNDIR = $(LIBCCMNDIR)/ctype
+STDLIBCMNDIR = $(LIBCCMNDIR)/stdlib
+STDIOCMNDIR = $(LIBCCMNDIR)/stdio
+
+include $(TOPCMNDIR)/make.rules
+
+
+CFLAGS = -g -O2 -fno-builtin -ffreestanding -nostdinc -msoft-float -mno-altivec -mabi=no-altivec -Wall
+CPPFLAGS = -I$(LIBCCMNDIR)/include
+LDFLAGS= -nostdlib
+
+TARGET = ../libc.a
+
+
+all: $(TARGET)
+
+# Use the following target to build a native version of the lib
+# (for example for debugging purposes):
+native:
+ $(MAKE) CROSS="" CC=$(HOSTCC) NATIVEBUILD=1
+
+
+include $(STRINGCMNDIR)/Makefile.inc
+include $(CTYPECMNDIR)/Makefile.inc
+include $(STDLIBCMNDIR)/Makefile.inc
+include $(STDIOCMNDIR)/Makefile.inc
+
+OBJS = $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS)
+
+ifneq ($(NATIVEBUILD),1)
+# These parts of the libc use assembler, so they can only be compiled when
+# we are _not_ building a native version.
+endif
+
+
+$(TARGET): $(OBJS)
+ $(AR) -rc $@ $(OBJS)
+ $(RANLIB) $@
+
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
diff --git a/lib/libc/README.txt b/lib/libc/README.txt
new file mode 100644
index 0000000..eaafdf4
--- /dev/null
+++ b/lib/libc/README.txt
@@ -0,0 +1,49 @@
+
+ Standard C library for the SLOF firmware project
+ ================================================
+
+To use this library, link your target against the "libc.a" archive.
+
+However, there are some prerequisites before you can use certain parts of the
+library:
+
+1) If you want to use malloc() and the like, you have to supply an implemen-
+ tation of sbrk() in your own code. malloc() uses sbrk() to get new, free
+ memory regions.
+
+ Prototype: void *sbrk(int incr);
+ Description: sbrk() increments the available data space by incr bytes and
+ returns a pointer to the start of the new area.
+
+ See the man-page of sbrk for details about this function.
+
+2) Before you can use the stdio output functions like printf(), puts() and the
+ like, you have to provide a standard write() function in your code.
+ printf() and the like use write() to print out the strings to the standard
+ output.
+
+ Prototype: ssize_t write(int fd, const void *buf, size_t cnt);
+ Description: Write cnt byte from the buffer buf to the stream associated
+ with the file descriptor fd.
+
+ The stdio functions will print their output to the stdout channel which is
+ assigned with the file descriptor 1 by default. Note that the stdio
+ functions will not use open() before calling write(), so if the stdout
+ cannel needs to be opened first, you should do that in your start-up code
+ before using the libc functions for the first time.
+
+3) Before you can use the stdio input functions like scanf() and the
+ like, you have to provide a standard read() function in your code.
+ scanf() and the like use read() to get the characters from the standard
+ input.
+
+ Prototype: ssize_t read(int fd, void *buf, size_t cnt);
+ Description: Read cnt byte from the stream associated with the file
+ descriptor fd and put them into the buffer buf.
+
+ The stdio functions will get their input from the stdin channel which is
+ assigned with the file descriptor 0 by default. Note that the stdio
+ functions will not use open() before calling read(), so if the stdin
+ cannel needs to be opened first, you should do that in your start-up code
+ before using the libc functions for the first time.
+
diff --git a/lib/libc/ctype/Makefile.inc b/lib/libc/ctype/Makefile.inc
new file mode 100644
index 0000000..8486a8a
--- /dev/null
+++ b/lib/libc/ctype/Makefile.inc
@@ -0,0 +1,20 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+CTYPE_SRC_C = isdigit.c isspace.c isxdigit.c tolower.c toupper.c
+CTYPE_SRC_ASM =
+CTYPE_SRCS = $(CTYPE_SRC_C:%=$(CTYPECMNDIR)/%) $(CTYPE_SRC_ASM:%=$(CTYPECMNDIR)/%)
+CTYPE_OBJS = $(CTYPE_SRC_C:%.c=%.o) $(CTYPE_SRC_ASM:%.S=%.o)
+
+%.o : $(CTYPECMNDIR)/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/lib/libc/ctype/isdigit.c b/lib/libc/ctype/isdigit.c
new file mode 100644
index 0000000..b3d1835
--- /dev/null
+++ b/lib/libc/ctype/isdigit.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <ctype.h>
+
+int isdigit(int ch)
+{
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return 1;
+
+ default:
+ return 0;
+ }
+}
diff --git a/lib/libc/ctype/isspace.c b/lib/libc/ctype/isspace.c
new file mode 100644
index 0000000..0e749d7
--- /dev/null
+++ b/lib/libc/ctype/isspace.c
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <ctype.h>
+
+int isspace(int ch)
+{
+ switch (ch) {
+ case ' ':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ return 1;
+
+ default:
+ return 0;
+ }
+}
diff --git a/lib/libc/ctype/isxdigit.c b/lib/libc/ctype/isxdigit.c
new file mode 100644
index 0000000..2b55d1a
--- /dev/null
+++ b/lib/libc/ctype/isxdigit.c
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <ctype.h>
+
+int isxdigit(int ch)
+{
+ return (
+ (ch >= '0' && ch <= '9') |
+ (ch >= 'A' && ch <= 'F') |
+ (ch >= 'a' && ch <= 'f') );
+}
diff --git a/lib/libc/ctype/tolower.c b/lib/libc/ctype/tolower.c
new file mode 100644
index 0000000..f7eb03b
--- /dev/null
+++ b/lib/libc/ctype/tolower.c
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <ctype.h>
+
+int tolower(int c)
+{
+ return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c);
+}
diff --git a/lib/libc/ctype/toupper.c b/lib/libc/ctype/toupper.c
new file mode 100644
index 0000000..0eba9d0
--- /dev/null
+++ b/lib/libc/ctype/toupper.c
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "ctype.h"
+
+int toupper (int cha)
+{
+ if((cha >= 'a') && (cha <= 'z'))
+ return(cha - 'a' + 'A');
+ return(cha);
+}
diff --git a/lib/libc/include/ctype.h b/lib/libc/include/ctype.h
new file mode 100644
index 0000000..3e5e47b
--- /dev/null
+++ b/lib/libc/include/ctype.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+int isdigit(int c);
+int isxdigit(int c);
+int isspace(int c);
+
+int tolower(int c);
+int toupper(int c);
+
+#endif
diff --git a/lib/libc/include/errno.h b/lib/libc/include/errno.h
new file mode 100644
index 0000000..eea7a36
--- /dev/null
+++ b/lib/libc/include/errno.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+extern int errno;
+
+/*
+ * Error number definitions
+ */
+#define EPERM 1 /* not permitted */
+#define ENOENT 2 /* file or directory not found */
+#define EIO 5 /* input/output error */
+#define ENOMEM 12 /* not enough space */
+#define EACCES 13 /* permission denied */
+#define EFAULT 14 /* bad address */
+#define EBUSY 16 /* resource busy */
+#define EEXIST 17 /* file already exists */
+#define ENODEV 19 /* device not found */
+#define EINVAL 22 /* invalid argument */
+#define EDOM 33 /* math argument out of domain of func */
+#define ERANGE 34 /* math result not representable */
+
+#endif
diff --git a/lib/libc/include/limits.h b/lib/libc/include/limits.h
new file mode 100644
index 0000000..ce694ea
--- /dev/null
+++ b/lib/libc/include/limits.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#define UCHAR_MAX 255
+#define SCHAR_MAX 127
+#define SCHAR_MIN (-128)
+
+#define USHRT_MAX 65535
+#define SHRT_MAX 32767
+#define SHRT_MIN (-32768)
+
+#define UINT_MAX (4294967295U)
+#define INT_MAX 2147483647
+#define INT_MIN (-2147483648)
+
+#define ULONG_MAX ((unsigned long)-1L)
+#define LONG_MAX (ULONG_MAX/2)
+#define LONG_MIN ((-LONG_MAX)-1)
+
+#endif
diff --git a/lib/libc/include/stdarg.h b/lib/libc/include/stdarg.h
new file mode 100644
index 0000000..422c598
--- /dev/null
+++ b/lib/libc/include/stdarg.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STDARG_H
+#define _STDARG_H
+
+typedef __builtin_va_list va_list;
+
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define va_end(v) __builtin_va_end(v)
+
+#endif
diff --git a/lib/libc/include/stddef.h b/lib/libc/include/stddef.h
new file mode 100644
index 0000000..318e2bb
--- /dev/null
+++ b/lib/libc/include/stddef.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+
+#define NULL ((void *)0)
+
+
+typedef unsigned int size_t;
+
+
+#endif
+
+
diff --git a/lib/libc/include/stdint.h b/lib/libc/include/stdint.h
new file mode 100644
index 0000000..e455f19
--- /dev/null
+++ b/lib/libc/include/stdint.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+
+typedef unsigned long long uint64_t;
+typedef signed long long int64_t;
+
+#endif
diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h
new file mode 100644
index 0000000..096e035
--- /dev/null
+++ b/lib/libc/include/stdio.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <stdarg.h>
+#include "stddef.h"
+
+#define EOF (-1)
+
+#define _IONBF 0
+#define _IOLBF 1
+#define _IOFBF 2
+#define BUFSIZ 80
+
+typedef struct {
+ int fd;
+ int mode;
+ int pos;
+ char *buf;
+ int bufsiz;
+} FILE;
+
+extern FILE stdin_data;
+extern FILE stdout_data;
+extern FILE stderr_data;
+
+#define stdin (&stdin_data)
+#define stdout (&stdout_data)
+#define stderr (&stderr_data)
+
+int fileno(FILE *stream);
+int printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
+int fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+int sprintf(char *str, const char *format, ...) __attribute__((format (printf, 2, 3)));
+int vfprintf(FILE *stream, const char *format, va_list);
+int vsprintf(char *str, const char *format, va_list);
+int vsnprintf(char *str, size_t size, const char *format, va_list);
+void setbuf(FILE *stream, char *buf);
+int setvbuf(FILE *stream, char *buf, int mode , size_t size);
+
+int putc(int ch, FILE *stream);
+int putchar(int ch);
+int puts(char *str);
+
+int scanf(const char *format, ...) __attribute__((format (scanf, 1, 2)));
+int fscanf(FILE *stream, const char *format, ...) __attribute__((format (scanf, 2, 3)));
+int vfscanf(FILE *stream, const char *format, va_list);
+int vsscanf(const char *str, const char *format, va_list);
+int getc(FILE *stream);
+int getchar(void);
+
+#endif
diff --git a/lib/libc/include/stdlib.h b/lib/libc/include/stdlib.h
new file mode 100644
index 0000000..ad0ef4f
--- /dev/null
+++ b/lib/libc/include/stdlib.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#include "stddef.h"
+
+#define RAND_MAX 32767
+
+
+void *malloc(size_t size);
+void *realloc(void *ptr, size_t size);
+void free(void *ptr);
+void *memalign(size_t boundary, size_t size);
+
+unsigned long int strtoul(const char *nptr, char **endptr, int base);
+long int strtol(const char *nptr, char **endptr, int base);
+
+int rand(void);
+
+#endif
diff --git a/lib/libc/include/string.h b/lib/libc/include/string.h
new file mode 100644
index 0000000..d792b1b
--- /dev/null
+++ b/lib/libc/include/string.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _STRING_H
+#define _STRING_H
+
+#include "stddef.h"
+
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, size_t n);
+char *strcat(char *dest, const char *src);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, size_t n);
+int strcasecmp(const char *s1, const char *s2);
+int strncasecmp(const char *s1, const char *s2, size_t n);
+char *strchr(const char *s, int c);
+char *strrchr(const char *s, int c);
+size_t strlen(const char *s);
+char *strstr(const char *hay, const char *needle);
+
+void *memset(void *s, int c, size_t n);
+void *memchr(const void *s, int c, size_t n);
+void *memcpy(void *dest, const void *src, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
+
+#endif
diff --git a/lib/libc/include/unistd.h b/lib/libc/include/unistd.h
new file mode 100644
index 0000000..c09c45d
--- /dev/null
+++ b/lib/libc/include/unistd.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+typedef long ssize_t;
+
+extern int open(const char *name, int flags);
+extern int close(int fd);
+extern ssize_t read(int fd, void *buf, size_t count);
+extern ssize_t write(int fd, const void *buf, size_t count);
+extern ssize_t lseek(int fd, long offset, int whence);
+
+extern void *sbrk(int increment);
+
+#endif
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
new file mode 100644
index 0000000..8783570
--- /dev/null
+++ b/lib/libc/stdio/Makefile.inc
@@ -0,0 +1,23 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+STDIO_SRC_C = fscanf.c sprintf.c vfprintf.c vsnprintf.c vsprintf.c fprintf.c \
+ printf.c setvbuf.c putc.c puts.c putchar.c scanf.c stdchnls.c \
+ vfscanf.c vsscanf.c fileno.c
+
+STDIO_SRC_ASM =
+STDIO_SRCS = $(STDIO_SRC_C:%=$(STDIOCMNDIR)/%) $(STDIO_SRC_ASM:%=$(STDIOCMNDIR)/%)
+STDIO_OBJS = $(STDIO_SRC_C:%.c=%.o) $(STDIO_SRC_ASM:%.S=%.o)
+
+%.o : $(STDIOCMNDIR)/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c
new file mode 100644
index 0000000..de77906
--- /dev/null
+++ b/lib/libc/stdio/fileno.c
@@ -0,0 +1,19 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+
+int
+fileno(FILE *stream)
+{
+ return stream->fd;
+}
diff --git a/lib/libc/stdio/fprintf.c b/lib/libc/stdio/fprintf.c
new file mode 100644
index 0000000..2337464
--- /dev/null
+++ b/lib/libc/stdio/fprintf.c
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+
+
+int fprintf(FILE *stream, const char* fmt, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = vfprintf(stream, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c
new file mode 100644
index 0000000..e2e28de
--- /dev/null
+++ b/lib/libc/stdio/fscanf.c
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+
+int
+fscanf(FILE *stream, const char *fmt, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = vfscanf(stream, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
diff --git a/lib/libc/stdio/printf.c b/lib/libc/stdio/printf.c
new file mode 100644
index 0000000..e73798b
--- /dev/null
+++ b/lib/libc/stdio/printf.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+
+
+int printf(const char* fmt, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
+
diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c
new file mode 100644
index 0000000..b21e37b
--- /dev/null
+++ b/lib/libc/stdio/putc.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+#include "unistd.h"
+
+int
+putc(int ch, FILE *stream)
+{
+ unsigned char outchar = ch;
+
+ if (write(stream->fd, &outchar, 1) == 1)
+ return outchar;
+ else
+ return EOF;
+}
diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c
new file mode 100644
index 0000000..524423e
--- /dev/null
+++ b/lib/libc/stdio/putchar.c
@@ -0,0 +1,21 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdio.h"
+
+
+int
+putchar(int ch)
+{
+ return putc(ch, stdout);
+}
diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c
new file mode 100644
index 0000000..bf2b8af
--- /dev/null
+++ b/lib/libc/stdio/puts.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdio.h"
+#include "string.h"
+#include "unistd.h"
+
+
+int
+puts(char *str)
+{
+ int ret;
+
+ ret = write(stdout->fd, str, strlen(str));
+ write(stdout->fd, "\r\n", 2);
+
+ return ret;
+}
diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c
new file mode 100644
index 0000000..9ff8f00
--- /dev/null
+++ b/lib/libc/stdio/scanf.c
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+
+int
+scanf(const char *fmt, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, fmt);
+ count = vfscanf(stdin, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c
new file mode 100644
index 0000000..fcc10f5
--- /dev/null
+++ b/lib/libc/stdio/setvbuf.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+
+int setvbuf(FILE *stream, char *buf, int mode , size_t size)
+{
+ if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF)
+ return -1;
+ stream->buf = buf;
+ stream->mode = mode;
+ stream->bufsiz = size;
+ return 0;
+}
+
+void setbuf(FILE *stream, char *buf)
+{
+ setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c
new file mode 100644
index 0000000..c84255b
--- /dev/null
+++ b/lib/libc/stdio/sprintf.c
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+
+
+int sprintf(char *buff, const char *format, ...)
+{
+ va_list ar;
+ int count;
+
+ if ((buff==NULL) || (format==NULL))
+ return(-1);
+
+ va_start(ar, format);
+ count = vsprintf(buff, format, ar);
+ va_end(ar);
+
+ return(count);
+}
+
diff --git a/lib/libc/stdio/stdchnls.c b/lib/libc/stdio/stdchnls.c
new file mode 100644
index 0000000..9b45be0
--- /dev/null
+++ b/lib/libc/stdio/stdchnls.c
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdio.h"
+
+static char stdin_buffer[BUFSIZ], stdout_buffer[BUFSIZ];
+
+FILE stdin_data = { .fd = 0, .mode = _IOLBF, .pos = 0,
+ .buf = stdin_buffer, .bufsiz = BUFSIZ };
+FILE stdout_data = { .fd = 1, .mode = _IOLBF, .pos = 0,
+ .buf = stdout_buffer, .bufsiz = BUFSIZ };
+FILE stderr_data = { .fd = 2, .mode = _IONBF, .pos = 0,
+ .buf = NULL, .bufsiz = 0 };
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
new file mode 100644
index 0000000..9a657ec
--- /dev/null
+++ b/lib/libc/stdio/vfprintf.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+#include "unistd.h"
+
+
+int vfprintf(FILE *stream, const char *fmt, va_list ap)
+{
+ int count;
+ char buffer[320];
+
+ count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ write(stream->fd, buffer, count);
+
+ return count;
+}
+
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
new file mode 100644
index 0000000..7a9f237
--- /dev/null
+++ b/lib/libc/stdio/vfscanf.c
@@ -0,0 +1,256 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+#include "ctype.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "unistd.h"
+
+
+static int
+_getc(FILE *stream)
+{
+ int count;
+ char c;
+
+ if (stream->mode == _IONBF || stream->buf == NULL) {
+ if (read(stream->fd,&c,1) == 1)
+ return (int)c;
+ else
+ return EOF;
+ }
+
+ if (stream->pos == 0 || stream->pos >= BUFSIZ ||
+ stream->buf[stream->pos] == '\0') {
+ count = read(stream->fd, stream->buf, BUFSIZ);
+ if (count < 0)
+ count = 0;
+ if (count < BUFSIZ)
+ stream->buf[count] = '\0';
+ stream->pos = 0;
+ }
+
+ return stream->buf[stream->pos++];
+}
+
+static void
+_ungetc(int ch, FILE *stream)
+{
+ if(stream->mode != _IONBF && stream->pos > 0)
+ stream->pos--;
+}
+
+static int
+_is_voidage(int ch)
+{
+ if(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0')
+ return 1;
+ else
+ return 0;
+}
+
+
+static int
+_scanf(FILE *stream, const char *fmt, va_list *ap)
+{
+ int i=0;
+ int length = 0;
+
+ fmt++;
+
+ while(*fmt != '\0') {
+
+ char tbuf[256];
+ char ch;
+
+ switch(*fmt) {
+ case 'd':
+ case 'i':
+ ch = _getc(stream);
+ if(length == 0) {
+ while(!_is_voidage(ch) && isdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while(!_is_voidage(ch) && i < length && isdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ _ungetc(ch, stream);
+ tbuf[i] = '\0';
+
+ ch = _getc(stream);
+ if(!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if(strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10);
+ break;
+ case 'X':
+ case 'x':
+ ch = _getc(stream);
+ if(length == 0) {
+ while(!_is_voidage(ch) && isxdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while(!_is_voidage(ch) && i < length && isxdigit(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ _ungetc(ch, stream);
+ tbuf[i] = '\0';
+
+ ch = _getc(stream);
+ if(!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if(strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16);
+ break;
+ case 'O':
+ case 'o':
+ ch = _getc(stream);
+ if(length == 0) {
+ while(!_is_voidage(ch) && !(ch < '0' || ch > '7')) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while(!_is_voidage(ch) && i < length && !(ch < '0' || ch > '7')) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ _ungetc(ch, stream);
+ tbuf[i] = '\0';
+
+ ch = _getc(stream);
+ if(!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ if(strlen(tbuf) == 0)
+ return 0;
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8);
+ break;
+ case 'c':
+ ch = _getc(stream);
+ while(_is_voidage(ch))
+ ch = _getc(stream);
+
+ *(va_arg(*ap, char *)) = ch;
+
+ ch = _getc(stream);
+ if(!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ break;
+ case 's':
+ ch = _getc(stream);
+ if(length == 0) {
+ while(!_is_voidage(ch)) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ } else {
+ while(!_is_voidage(ch) && i < length) {
+ tbuf[i] = ch;
+ ch = _getc(stream);
+ i++;
+ }
+ }
+ _ungetc(ch, stream);
+ tbuf[i] = '\0';
+
+ ch = _getc(stream);
+ if(!_is_voidage(ch))
+ _ungetc(ch, stream);
+
+ strcpy(va_arg(*ap, char *), tbuf);
+ break;
+ default:
+ if(*fmt >= '0' && *fmt <= '9')
+ length += *fmt - '0';
+ break;
+ }
+ fmt++;
+ }
+
+ return 1;
+}
+
+
+
+int
+vfscanf(FILE *stream, const char *fmt, va_list ap)
+{
+ int args = 0;
+
+ while(*fmt != '\0') {
+
+ if(*fmt == '%') {
+
+ char formstr[20];
+ int i=0;
+
+ do {
+ formstr[i] = *fmt;
+ fmt++;
+ i++;
+ } while(!(*fmt == 'd' || *fmt == 'i' || *fmt == 'x' || *fmt == 'X'
+ || *fmt == 'p' || *fmt == 'c' || *fmt == 's' || *fmt == '%'
+ || *fmt == 'O' || *fmt == 'o' ));
+ formstr[i++] = *fmt;
+ formstr[i] = '\0';
+ if(*fmt != '%') {
+ if(_scanf(stream, formstr, &ap) <= 0)
+ return args;
+ else
+ args++;
+ }
+
+ }
+
+ fmt++;
+
+ }
+
+ return args;
+}
+
+int getc(FILE *stream)
+{
+ return _getc(stream);
+}
+
+int getchar(void)
+{
+ return _getc(stdin);
+}
+
diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c
new file mode 100644
index 0000000..200512f
--- /dev/null
+++ b/lib/libc/stdio/vsnprintf.c
@@ -0,0 +1,242 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+
+const static unsigned long long convert[] = {
+ 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
+};
+
+
+
+static int
+print_itoa(char **buffer,unsigned long value, unsigned short int base)
+{
+ const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+ static char sign = 0;
+
+ if(base <= 2 || base > 16)
+ return 0;
+
+ if(value < 0) {
+ sign = 1;
+ value *= -1;
+ }
+
+ if(value < base) {
+ if(sign) {
+ **buffer = '-';
+ *buffer += 1;
+ sign = 0;
+ }
+ **buffer = zeichen[value];
+ *buffer += 1;
+ } else {
+ print_itoa(buffer, value / base, base);
+ **buffer = zeichen[(value % base)];
+ *buffer += 1;
+ }
+
+ return 1;
+}
+
+
+static unsigned int
+print_intlen(unsigned long value, unsigned short int base)
+{
+ int i = 0;
+
+ while(value > 0) {
+ value /= base;
+ i++;
+ }
+ if(i == 0) i = 1;
+ return i;
+}
+
+
+static int
+print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen)
+{
+ int i, sizei, len;
+
+ sizei = strtoul(sizec, NULL, 10);
+ len = print_intlen(size, base) + optlen;
+ if(sizei > len) {
+ for(i = 0; i < (sizei - len); i++) {
+ **buffer = c;
+ *buffer += 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+print_format(char **buffer, const char *format, void *var)
+{
+ unsigned long start;
+ unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int);
+ unsigned long value = 0;
+ unsigned long signBit;
+ char *form, sizec[32];
+ char sign = ' ';
+
+ form = (char *) format;
+ start = (unsigned long) *buffer;
+
+ form++;
+ if(*form == '0' || *form == '.') {
+ sign = '0';
+ form++;
+ }
+
+ while(*form != '\0') {
+ switch(*form) {
+ case 'u':
+ case 'd':
+ case 'i':
+ sizec[i] = '\0';
+ value = (unsigned long) var;
+ signBit = 0x1ULL << (length_mod * 8 - 1);
+ if (signBit & value) {
+ **buffer = '-';
+ *buffer += 1;
+ value = (-(unsigned long)value) & convert[length_mod];
+ }
+ print_fill(buffer, sizec, value, 10, sign, 0);
+ print_itoa(buffer, value, 10);
+ break;
+ case 'X':
+ case 'x':
+ sizec[i] = '\0';
+ value = (unsigned long) var & convert[length_mod];
+ print_fill(buffer, sizec, value, 16, sign, 0);
+ print_itoa(buffer, value, 16);
+ break;
+ case 'O':
+ case 'o':
+ sizec[i] = '\0';
+ value = (long int) var & convert[length_mod];
+ print_fill(buffer, sizec, value, 8, sign, 0);
+ print_itoa(buffer, value, 8);
+ break;
+ case 'p':
+ sizec[i] = '\0';
+ print_fill(buffer, sizec, (unsigned long) var, 16, ' ', 2);
+ **buffer = '0';
+ *buffer += 1;
+ **buffer = 'x';
+ *buffer += 1;
+ print_itoa(buffer,(unsigned long) var, 16);
+ break;
+ case 'c':
+ sizec[i] = '\0';
+ print_fill(buffer, sizec, 1, 10, ' ', 0);
+ **buffer = (unsigned long) var;
+ *buffer += 1;
+ break;
+ case 's':
+ sizec[i] = '\0';
+ sizei = strtoul(sizec, NULL, 10);
+ len = strlen((char *) var);
+ if(sizei > len) {
+ for(i = 0; i < (sizei - len); i++) {
+ **buffer = ' ';
+ *buffer += 1;
+ }
+ }
+ for(i = 0; i < strlen((char *) var); i++) {
+ **buffer = ((char *) var)[i];
+ *buffer += 1;
+ }
+ break;
+ case 'l':
+ form++;
+ if(*form == 'l') {
+ length_mod = sizeof(long long int);
+ } else {
+ form--;
+ length_mod = sizeof(long int);
+ }
+ break;
+ case 'h':
+ form++;
+ if(*form == 'h') {
+ length_mod = sizeof(signed char);
+ } else {
+ form--;
+ length_mod = sizeof(short int);
+ }
+ break;
+ default:
+ if(*form >= '0' && *form <= '9')
+ sizec[i++] = *form;
+ }
+ form++;
+ }
+
+
+ return (long int) (*buffer - start);
+}
+
+
+/*
+ * The vsnprintf function prints a formated strings into a buffer.
+ * BUG: buffer size checking does not fully work yet
+ */
+int
+vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
+{
+ char *ptr, *bstart;
+
+ bstart = buffer;
+ ptr = (char *) format;
+
+ while(*ptr != '\0' && (buffer - bstart) < bufsize)
+ {
+ if(*ptr == '%') {
+ char formstr[20];
+ int i=0;
+
+ do {
+ formstr[i] = *ptr;
+ ptr++;
+ i++;
+ } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X'
+ || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%'
+ || *ptr == 'O' || *ptr == 'o' ));
+ formstr[i++] = *ptr;
+ formstr[i] = '\0';
+ if(*ptr == '%') {
+ *buffer++ = '%';
+ } else {
+ print_format(&buffer, formstr, va_arg(arg, void *));
+ }
+ ptr++;
+ } else {
+
+ *buffer = *ptr;
+
+ buffer++;
+ ptr++;
+ }
+ }
+
+ *buffer = '\0';
+
+ return (buffer - bstart);
+}
diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c
new file mode 100644
index 0000000..c565a89
--- /dev/null
+++ b/lib/libc/stdio/vsprintf.c
@@ -0,0 +1,19 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+
+int
+vsprintf(char *buffer, const char *format, va_list arg)
+{
+ return vsnprintf(buffer, 0x7fffffff, format, arg);
+}
diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c
new file mode 100644
index 0000000..68760b5
--- /dev/null
+++ b/lib/libc/stdio/vsscanf.c
@@ -0,0 +1,131 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+
+
+static void
+_scanf(const char **buffer, const char *fmt, va_list *ap)
+{
+ int i;
+ int length = 0;
+
+ fmt++;
+
+ while(*fmt != '\0') {
+
+ char tbuf[256];
+
+ switch(*fmt) {
+ case 'd':
+ case 'i':
+ if(length == 0) length = 256;
+
+ for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) {
+ tbuf[i] = **buffer;
+ *buffer += 1;
+ }
+ tbuf[i] = '\0';
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10);
+ break;
+ case 'X':
+ case 'x':
+ if(length == 0) length = 256;
+
+ for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) {
+ tbuf[i] = **buffer;
+ *buffer += 1;
+ }
+ tbuf[i] = '\0';
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16);
+ break;
+ case 'O':
+ case 'o':
+ if(length == 0) length = 256;
+
+ for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) {
+ tbuf[i] = **buffer;
+ *buffer += 1;
+ }
+ tbuf[i] = '\0';
+
+ *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8);
+ break;
+ case 'c':
+ *(va_arg(*ap, char *)) = **buffer;
+ *buffer += 1;
+ if(length > 1)
+ for(i = 1; i < length; i++)
+ *buffer += 1;
+ break;
+ case 's':
+ if(length == 0) length = 256;
+
+ for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) {
+ tbuf[i] = **buffer;
+ *buffer += 1;
+ }
+
+ tbuf[i] = '\0';
+
+ strcpy(va_arg(*ap, char *), tbuf);
+ break;
+ default:
+ if(*fmt >= '0' && *fmt <= '9')
+ length += *fmt - '0';
+ break;
+ }
+ fmt++;
+ }
+
+}
+
+
+int
+vsscanf(const char *buffer, const char *fmt, va_list ap)
+{
+
+ while(*fmt != '\0') {
+
+ if(*fmt == '%') {
+
+ char formstr[20];
+ int i=0;
+
+ do {
+ formstr[i] = *fmt;
+ fmt++;
+ i++;
+ } while(!(*fmt == 'd' || *fmt == 'i' || *fmt == 'x' || *fmt == 'X'
+ || *fmt == 'p' || *fmt == 'c' || *fmt == 's' || *fmt == '%'
+ || *fmt == 'O' || *fmt == 'o' ));
+ formstr[i++] = *fmt;
+ formstr[i] = '\0';
+ if(*fmt != '%') {
+ while(*buffer == ' ' || *buffer == '\t' || *buffer == '\n')
+ buffer++;
+ _scanf(&buffer, formstr, &ap);
+ }
+
+ }
+
+ fmt++;
+
+ }
+
+ return 0;
+}
+
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
new file mode 100644
index 0000000..5b854fc
--- /dev/null
+++ b/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,22 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+STDLIB_SRC_C = error.c strtoul.c strtol.c rand.c \
+ malloc.c memalign.c realloc.c free.c
+
+STDLIB_SRC_ASM =
+STDLIB_SRCS = $(STDLIB_SRC_C:%=$(STDLIBCMNDIR)/%) $(STDLIB_SRC_ASM:%=$(STDLIBCMNDIR)/%)
+STDLIB_OBJS = $(STDLIB_SRC_C:%.c=%.o) $(STDLIB_SRC_ASM:%.S=%.o)
+
+%.o : $(STDLIBCMNDIR)/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/lib/libc/stdlib/error.c b/lib/libc/stdlib/error.c
new file mode 100644
index 0000000..d440f7c
--- /dev/null
+++ b/lib/libc/stdlib/error.c
@@ -0,0 +1,15 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+int errno;
+
diff --git a/lib/libc/stdlib/free.c b/lib/libc/stdlib/free.c
new file mode 100644
index 0000000..7aff279
--- /dev/null
+++ b/lib/libc/stdlib/free.c
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdlib.h"
+#include "malloc_defs.h"
+
+void
+free(void *ptr)
+{
+ struct chunk *header;
+
+ header = (struct chunk *) ptr;
+ header--;
+ header->inuse = 0;
+
+}
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000..4bc4b79
--- /dev/null
+++ b/lib/libc/stdlib/malloc.c
@@ -0,0 +1,157 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stddef.h"
+#include "stdlib.h"
+#include "unistd.h"
+#include "malloc_defs.h"
+
+
+static int clean(void);
+
+
+/* act points to the end of the initialized heap and the start of uninitialized heap */
+static char *act;
+
+/* Pointers to start and end of heap: */
+static char *heap_start, *heap_end;
+
+
+/*
+ * Standard malloc function
+ */
+void *
+malloc(size_t size)
+{
+ char *header;
+ void *data;
+ size_t blksize; /* size of memory block including the chunk */
+
+ blksize = size + sizeof(struct chunk);
+
+ /* has malloc been called for the first time? */
+ if (act == 0) {
+ size_t initsize;
+ /* add some space so we have a good initial playground */
+ initsize = (blksize + 0x1000) & ~0x0fff;
+ /* get initial memory region with sbrk() */
+ heap_start = sbrk(initsize);
+ if (heap_start == (void*)-1)
+ return NULL;
+ heap_end = heap_start + initsize;
+ act = heap_start;
+ }
+
+ header = act;
+ data = act + sizeof(struct chunk);
+
+ /* Check if there is space left in the uninitialized part of the heap */
+ if (act + blksize > heap_end) {
+ //search at begin of heap
+ header = heap_start;
+
+ while ((((struct chunk *) header)->inuse != 0
+ || ((struct chunk *) header)->length < size)
+ && header < act) {
+ header = header + sizeof(struct chunk)
+ + ((struct chunk *) header)->length;
+ }
+
+ // check if heap is full
+ if (header >= act) {
+ if (clean()) {
+ // merging of free blocks succeeded, so try again
+ return malloc(size);
+ } else if (sbrk(blksize) == heap_end) {
+ // succeeded to get more memory, so try again
+ heap_end += blksize;
+ return malloc(size);
+ } else {
+ // No more memory available
+ return 0;
+ }
+ }
+
+ // Check if we need to split this memory block into two
+ if (((struct chunk *) header)->length > blksize) {
+ //available memory is too big
+ int alt;
+
+ alt = ((struct chunk *) header)->length;
+ ((struct chunk *) header)->inuse = 1;
+ ((struct chunk *) header)->length = size;
+ data = header + sizeof(struct chunk);
+
+ //mark the rest of the heap
+ header = data + size;
+ ((struct chunk *) header)->inuse = 0;
+ ((struct chunk *) header)->length =
+ alt - blksize;
+ } else {
+ //new memory matched exactly in available memory
+ ((struct chunk *) header)->inuse = 1;
+ data = header + sizeof(struct chunk);
+ }
+
+ } else {
+
+ ((struct chunk *) header)->inuse = 1;
+ ((struct chunk *) header)->length = size;
+
+ act += blksize;
+ }
+
+ return data;
+}
+
+
+/*
+ * Merge free memory blocks in initialized heap if possible
+ */
+static int
+clean(void)
+{
+ char *header;
+ char *firstfree = 0;
+ char check = 0;
+
+ header = heap_start;
+ //if (act == 0) // This should never happen
+ // act = heap_end;
+
+ while (header < act) {
+
+ if (((struct chunk *) header)->inuse == 0) {
+ if (firstfree == 0) {
+ /* First free block in a row, only save address */
+ firstfree = header;
+
+ } else {
+ /* more than one free block in a row, merge them! */
+ ((struct chunk *) firstfree)->length +=
+ ((struct chunk *) header)->length +
+ sizeof(struct chunk);
+ check = 1;
+ }
+ } else {
+ firstfree = 0;
+
+ }
+
+ header = header + sizeof(struct chunk)
+ + ((struct chunk *) header)->length;
+
+ }
+
+ return check;
+}
diff --git a/lib/libc/stdlib/malloc_defs.h b/lib/libc/stdlib/malloc_defs.h
new file mode 100644
index 0000000..59fcd91
--- /dev/null
+++ b/lib/libc/stdlib/malloc_defs.h
@@ -0,0 +1,16 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+struct chunk {
+ unsigned inuse : 4;
+ unsigned length : 28;
+} __attribute__((packed));
diff --git a/lib/libc/stdlib/memalign.c b/lib/libc/stdlib/memalign.c
new file mode 100644
index 0000000..0bb430e
--- /dev/null
+++ b/lib/libc/stdlib/memalign.c
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdlib.h"
+
+
+void *
+memalign(size_t blocksize, size_t bytes)
+{
+ void *x;
+
+ x = malloc(bytes + blocksize);
+ x = (void *) (((unsigned long) x + blocksize - 1) & ~(blocksize - 1));
+
+ return (void *) x;
+}
diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c
new file mode 100644
index 0000000..d3a0254
--- /dev/null
+++ b/lib/libc/stdlib/rand.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+
+
+static unsigned long _rand = 1;
+
+int
+rand(void)
+{
+ _rand = _rand * 25364735 + 34563;
+
+ return ((unsigned int) (_rand << 16) & RAND_MAX);
+}
diff --git a/lib/libc/stdlib/realloc.c b/lib/libc/stdlib/realloc.c
new file mode 100644
index 0000000..d1dfdfb
--- /dev/null
+++ b/lib/libc/stdlib/realloc.c
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+
+#include "stdlib.h"
+#include "string.h"
+#include "malloc_defs.h"
+
+void *
+realloc(void *ptr, size_t size)
+{
+ struct chunk *header;
+ char *newptr, *start;
+
+ header = (struct chunk *) ptr;
+ header--;
+
+ if (size <= header->length)
+ return ptr;
+
+ newptr = (char *) malloc(size);
+ if (newptr == NULL)
+ return 0;
+
+ start = newptr;
+ memcpy((void *) newptr, (const void *) ptr, header->length);
+
+ header->inuse = 0;
+
+ return start;
+}
diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c
new file mode 100644
index 0000000..ee14a39
--- /dev/null
+++ b/lib/libc/stdlib/strtol.c
@@ -0,0 +1,114 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+long int strtol(const char *S, char **PTR,int BASE)
+{
+ long rval = 0;
+ short int negative = 0;
+ short int digit;
+ // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
+ char* ptr;
+ if (PTR == 0)
+ {
+ //override
+ PTR = &ptr;
+ }
+ // i use PTR to advance through the string
+ *PTR = (char *) S;
+ //check if BASE is ok
+ if ((BASE < 0) || BASE > 36)
+ {
+ return 0;
+ }
+ // ignore white space at beginning of S
+ while ((**PTR == ' ')
+ || (**PTR == '\t')
+ || (**PTR == '\n')
+ || (**PTR == '\r')
+ )
+ {
+ (*PTR)++;
+ }
+ // check if S starts with "-" in which case the return value is negative
+ if (**PTR == '-')
+ {
+ negative = 1;
+ (*PTR)++;
+ }
+ // if BASE is 0... determine the base from the first chars...
+ if (BASE == 0)
+ {
+ // if S starts with "0x", BASE = 16, else 10
+ if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
+ {
+ BASE = 16;
+ (*PTR)++;
+ (*PTR)++;
+ }
+ else
+ {
+ BASE = 10;
+ }
+ }
+ if (BASE == 16)
+ {
+ // S may start with "0x"
+ if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
+ {
+ (*PTR)++;
+ (*PTR)++;
+ }
+ }
+ //until end of string
+ while (**PTR)
+ {
+ if (((**PTR) >= '0') && ((**PTR) <= '9'))
+ {
+ //digit (0..9)
+ digit = **PTR - '0';
+ }
+ else if (((**PTR) >= 'a') && ((**PTR) <='z'))
+ {
+ //alphanumeric digit lowercase(a (10) .. z (35) )
+ digit = (**PTR - 'a') + 10;
+ }
+ else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
+ {
+ //alphanumeric digit uppercase(a (10) .. z (35) )
+ digit = (**PTR - 'A') + 10;
+ }
+ else
+ {
+ //end of parseable number reached...
+ break;
+ }
+ if (digit < BASE)
+ {
+ rval = (rval * BASE) + digit;
+ }
+ else
+ {
+ //digit found, but its too big for current base
+ //end of parseable number reached...
+ break;
+ }
+ //next...
+ (*PTR)++;
+ }
+ if (negative)
+ {
+ return rval * -1;
+ }
+ //else
+ return rval;
+}
+
diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c
new file mode 100644
index 0000000..74cdccd
--- /dev/null
+++ b/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+unsigned long int strtoul(const char *S, char **PTR,int BASE)
+{
+ unsigned long rval = 0;
+ short int digit;
+ // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
+ char* ptr;
+ if (PTR == 0)
+ {
+ //override
+ PTR = &ptr;
+ }
+ // i use PTR to advance through the string
+ *PTR = (char *) S;
+ //check if BASE is ok
+ if ((BASE < 0) || BASE > 36)
+ {
+ return 0;
+ }
+ // ignore white space at beginning of S
+ while ((**PTR == ' ')
+ || (**PTR == '\t')
+ || (**PTR == '\n')
+ || (**PTR == '\r')
+ )
+ {
+ (*PTR)++;
+ }
+ // if BASE is 0... determine the base from the first chars...
+ if (BASE == 0)
+ {
+ // if S starts with "0x", BASE = 16, else 10
+ if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
+ {
+ BASE = 16;
+ (*PTR)++;
+ (*PTR)++;
+ }
+ else
+ {
+ BASE = 10;
+ }
+ }
+ if (BASE == 16)
+ {
+ // S may start with "0x"
+ if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
+ {
+ (*PTR)++;
+ (*PTR)++;
+ }
+ }
+ //until end of string
+ while (**PTR)
+ {
+ if (((**PTR) >= '0') && ((**PTR) <='9'))
+ {
+ //digit (0..9)
+ digit = **PTR - '0';
+ }
+ else if (((**PTR) >= 'a') && ((**PTR) <='z'))
+ {
+ //alphanumeric digit lowercase(a (10) .. z (35) )
+ digit = (**PTR - 'a') + 10;
+ }
+ else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
+ {
+ //alphanumeric digit uppercase(a (10) .. z (35) )
+ digit = (**PTR - 'A') + 10;
+ }
+ else
+ {
+ //end of parseable number reached...
+ break;
+ }
+ if (digit < BASE)
+ {
+ rval = (rval * BASE) + digit;
+ }
+ else
+ {
+ //digit found, but its too big for current base
+ //end of parseable number reached...
+ break;
+ }
+ //next...
+ (*PTR)++;
+ }
+ //done
+ return rval;
+}
+
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
new file mode 100644
index 0000000..e857bbc
--- /dev/null
+++ b/lib/libc/string/Makefile.inc
@@ -0,0 +1,22 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+STRING_SRC_C = strcat.c strchr.c strcmp.c strcpy.c strlen.c strncmp.c \
+ strncpy.c strstr.c memset.c memcpy.c memmove.c memchr.c \
+ memcmp.c strcasecmp.c strncasecmp.c
+STRING_SRC_ASM =
+STRING_SRCS = $(STRING_SRC_C:%=$(STRINGCMNDIR)/%) $(STRING_SRC_ASM:%=$(STRINGCMNDIR)/%)
+STRING_OBJS = $(STRING_SRC_C:%.c=%.o) $(STRING_SRC_ASM:%.S=%.o)
+
+%.o : $(STRINGCMNDIR)/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/lib/libc/string/memchr.c b/lib/libc/string/memchr.c
new file mode 100644
index 0000000..d4e9b7f
--- /dev/null
+++ b/lib/libc/string/memchr.c
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+
+
+void *
+memchr(const void *ptr, int c, size_t n)
+{
+ unsigned char ch = (unsigned char)c;
+ const unsigned char *p = ptr;
+
+ while (n-- > 0) {
+ if (*p == ch)
+ return (void *)p;
+ p += 1;
+ }
+
+ return NULL;
+}
diff --git a/lib/libc/string/memcmp.c b/lib/libc/string/memcmp.c
new file mode 100644
index 0000000..b64d560
--- /dev/null
+++ b/lib/libc/string/memcmp.c
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+
+
+int
+memcmp(const void *ptr1, const void *ptr2, size_t n)
+{
+ const unsigned char *p1 = ptr1;
+ const unsigned char *p2 = ptr2;
+
+ while (n-- > 0) {
+ if (*p1 != *p2)
+ return (*p1 - *p2);
+ p1 += 1;
+ p2 += 1;
+ }
+
+ return 0;
+}
diff --git a/lib/libc/string/memcpy.c b/lib/libc/string/memcpy.c
new file mode 100644
index 0000000..36a4a3c
--- /dev/null
+++ b/lib/libc/string/memcpy.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+
+void *
+memcpy(void *dest, const void *src, size_t n)
+{
+ char *cdest;
+ const char *csrc = src;
+
+ cdest = dest;
+ while (n-- > 0) {
+ *cdest++ = *csrc++;
+ }
+
+ return dest;
+}
diff --git a/lib/libc/string/memmove.c b/lib/libc/string/memmove.c
new file mode 100644
index 0000000..7ceee33
--- /dev/null
+++ b/lib/libc/string/memmove.c
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+
+
+void *
+memmove(void *dest, const void *src, size_t n)
+{
+ char *cdest;
+ const char *csrc;
+ int i;
+
+ /* Do the buffers overlap in a bad way? */
+ if (src < dest && src + n >= dest) {
+ /* Copy from end to start */
+ cdest = dest + n - 1;
+ csrc = src + n - 1;
+ for (i = 0; i < n; i++) {
+ *cdest-- = *csrc--;
+ }
+ }
+ else {
+ /* Normal copy is possible */
+ cdest = dest;
+ csrc = src;
+ for (i = 0; i < n; i++) {
+ *cdest++ = *csrc++;
+ }
+ }
+
+ return dest;
+}
diff --git a/lib/libc/string/memset.c b/lib/libc/string/memset.c
new file mode 100644
index 0000000..0f5a660
--- /dev/null
+++ b/lib/libc/string/memset.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "string.h"
+
+void *
+memset(void *dest, int c, size_t size)
+{
+ unsigned char *d = (unsigned char *)dest;
+
+ while (size-- > 0) {
+ *d++ = (unsigned char)c;
+ }
+
+ return dest;
+}
diff --git a/lib/libc/string/strcasecmp.c b/lib/libc/string/strcasecmp.c
new file mode 100644
index 0000000..98cde44
--- /dev/null
+++ b/lib/libc/string/strcasecmp.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+
+int
+strcasecmp(const char *s1, const char *s2)
+{
+ while (*s1 != 0 && *s2 != 0) {
+ if (toupper(*s1) != toupper(*s2))
+ break;
+ ++s1;
+ ++s2;
+ }
+
+ return *s1 - *s2;
+}
+
diff --git a/lib/libc/string/strcat.c b/lib/libc/string/strcat.c
new file mode 100644
index 0000000..eadd6b9
--- /dev/null
+++ b/lib/libc/string/strcat.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+char *
+strcat(char *dst, const char *src)
+{
+ int p;
+
+ p = strlen(dst);
+ strcpy(&dst[p], src);
+
+ return dst;
+}
diff --git a/lib/libc/string/strchr.c b/lib/libc/string/strchr.c
new file mode 100644
index 0000000..214eaa9
--- /dev/null
+++ b/lib/libc/string/strchr.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+char *
+strchr(const char *s, int c)
+{
+ char cb = c;
+
+ while (*s != 0) {
+ if (*s == cb) {
+ return (char *)s;
+ }
+ s += 1;
+ }
+
+ return NULL;
+}
diff --git a/lib/libc/string/strcmp.c b/lib/libc/string/strcmp.c
new file mode 100644
index 0000000..4a765ea
--- /dev/null
+++ b/lib/libc/string/strcmp.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+
+int
+strcmp(const char *s1, const char *s2)
+{
+ while (*s1 != 0 && *s2 != 0) {
+ if (*s1 != *s2)
+ break;
+ s1 += 1;
+ s2 += 1;
+ }
+
+ return *s1 - *s2;
+}
+
diff --git a/lib/libc/string/strcpy.c b/lib/libc/string/strcpy.c
new file mode 100644
index 0000000..4c888ca
--- /dev/null
+++ b/lib/libc/string/strcpy.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+char *
+strcpy(char *dst, const char *src)
+{
+ char *ptr = dst;
+
+ do {
+ *ptr++ = *src;
+ } while (*src++ != 0);
+
+ return dst;
+}
diff --git a/lib/libc/string/strlen.c b/lib/libc/string/strlen.c
new file mode 100644
index 0000000..c091f75
--- /dev/null
+++ b/lib/libc/string/strlen.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+size_t
+strlen(const char *s)
+{
+ int len = 0;
+
+ while (*s != 0) {
+ len += 1;
+ s += 1;
+ }
+
+ return len;
+}
+
diff --git a/lib/libc/string/strncasecmp.c b/lib/libc/string/strncasecmp.c
new file mode 100644
index 0000000..1aa6639
--- /dev/null
+++ b/lib/libc/string/strncasecmp.c
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+
+
+int
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ if (n < 1)
+ return 0;
+
+ while (*s1 != 0 && *s2 != 0 && --n > 0) {
+ if (toupper(*s1) != toupper(*s2))
+ break;
+ ++s1;
+ ++s2;
+ }
+
+ return toupper(*s1) - toupper(*s2);
+}
+
diff --git a/lib/libc/string/strncmp.c b/lib/libc/string/strncmp.c
new file mode 100644
index 0000000..357d113
--- /dev/null
+++ b/lib/libc/string/strncmp.c
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+ if (n < 1)
+ return 0;
+
+ while (*s1 != 0 && *s2 != 0 && --n > 0) {
+ if (*s1 != *s2)
+ break;
+ s1 += 1;
+ s2 += 1;
+ }
+
+ return *s1 - *s2;
+}
+
diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c
new file mode 100644
index 0000000..a2667d8
--- /dev/null
+++ b/lib/libc/string/strncpy.c
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+char *
+strncpy(char *dst, const char *src, size_t n)
+{
+ char *ret = dst;
+
+ /* Copy string */
+ while (*src != 0 && n > 0) {
+ *dst++ = *src++;
+ n -= 1;
+ }
+
+ /* strncpy always clears the rest of destination string... */
+ while (n > 0) {
+ *dst++ = 0;
+ n -= 1;
+ }
+
+ return ret;
+}
diff --git a/lib/libc/string/strstr.c b/lib/libc/string/strstr.c
new file mode 100644
index 0000000..f94af6d
--- /dev/null
+++ b/lib/libc/string/strstr.c
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <string.h>
+
+char *
+strstr(const char *hay, const char *needle)
+{
+ char *pos;
+ int hlen, nlen;
+
+ if (hay == NULL || needle == NULL)
+ return NULL;
+
+ hlen = strlen(hay);
+ nlen = strlen(needle);
+ if (nlen < 1)
+ return (char *)hay;
+
+ for (pos = (char *)hay; pos < hay + hlen; pos++) {
+ if (strncmp(pos, needle, nlen) == 0) {
+ return pos;
+ }
+ }
+
+ return NULL;
+}
+
diff --git a/lib/libipmi/Makefile b/lib/libipmi/Makefile
new file mode 100644
index 0000000..4777f9e
--- /dev/null
+++ b/lib/libipmi/Makefile
@@ -0,0 +1,28 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+LIBIPMICMNDIR = $(shell pwd)
+
+include $(TOPCMNDIR)/make.rules
+
+TARGET = ../libipmi.a
+
+all: $(TARGET)
+
+$(TARGET):
+ cp libipmi.oco $@
+
+clean:
+
+distclean:
diff --git a/lib/libipmi/libipmi.code b/lib/libipmi/libipmi.code
new file mode 100644
index 0000000..761a50d
--- /dev/null
+++ b/lib/libipmi/libipmi.code
@@ -0,0 +1,105 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <libipmi.h>
+
+// : ipmi-kcs-cmd ( in-buf in-len out-buf out-maxlen -- out-len errorcode )
+PRIM(IPMI_X2d_KCS_X2d_CMD)
+ cell maxlen = TOS; POP;
+ cell outbuf = TOS; POP;
+ int len = TOS.n; POP;
+ cell inbuf = TOS;
+ int retval;
+ retval = ipmi_kcs_cmd(inbuf.a, outbuf.a, maxlen.n, (uint32_t *) &len);
+ TOS.n = len;
+ PUSH; TOS.n = retval;
+MIRP
+
+
+PRIM(IPMI_X2d_SYSTEM_X2d_REBOOT)
+ ipmi_system_reboot();
+MIRP
+
+
+PRIM(IPMI_X2d_POWER_X2d_OFF)
+ ipmi_power_off();
+MIRP
+
+
+// : ipmi-oem-stop-bootwatchdog ( -- errorcode )
+PRIM(IPMI_X2d_OEM_X2d_STOP_X2d_BOOTWATCHDOG)
+ PUSH;
+ TOS.n = ipmi_oem_stop_bootwatchdog();
+MIRP
+
+
+// : ipmi-oem-set-bootwatchdog ( seconds -- errorcode )
+PRIM(IPMI_X2d_OEM_X2d_SET_X2d_BOOTWATCHDOG)
+ int sec = TOS.n;
+ TOS.n = ipmi_oem_set_bootwatchdog(sec);
+MIRP
+
+
+// : ipmi-oem-reset-bootwatchdog ( -- errorcode )
+PRIM(IPMI_X2d_OEM_X2d_RESET_X2d_BOOTWATCHDOG)
+ PUSH;
+ TOS.n = ipmi_oem_reset_bootwatchdog();
+MIRP
+
+
+// : ipmi-oem-led-set ( type instance state -- errorcode )
+PRIM(IPMI_X2d_OEM_X2d_LED_X2d_SET)
+ int state = TOS.n; POP;
+ int instance = TOS.n; POP;
+ int type = TOS.n;
+ TOS.n = ipmi_oem_led_set(type, instance, state);
+MIRP
+
+
+// : ipmi-oem-read-vpd ( offset length dst -- status )
+PRIM(IPMI_X2d_OEM_X2d_READ_X2d_VPD)
+ cell dest = TOS; POP;
+ int len = TOS.n; POP;
+ int offset = TOS.n;
+ TOS.n = ipmi_oem_read_vpd(dest.a, len, offset);
+MIRP
+
+// : ipmi-oem-write-vpd ( offset length src -- status )
+PRIM(IPMI_X2d_OEM_X2d_WRITE_X2d_VPD)
+ cell src = TOS; POP;
+ int len = TOS.n; POP;
+ int offset = TOS.n;
+ TOS.n = ipmi_oem_write_vpd(src.a, len, offset);
+MIRP
+
+
+// : ipmi-oem-get-blade-descr ( buf maxlen -- len status )
+PRIM(IPMI_X2d_OEM_X2d_GET_X2d_BLADE_X2d_DESCR)
+ int maxlen = TOS.n; POP;
+ cell buf = TOS;
+ int len = 0;
+ int retval;
+ retval = ipmi_oem_get_blade_descr(buf.a, maxlen, (uint32_t *) &len);
+ TOS.n = len;
+ PUSH; TOS.n = retval;
+MIRP
+
+
+// : ipmi-oem-bios2sp ( str-ptr str-len swid type -- errorcode )
+PRIM(IPMI_X2d_OEM_X2d_BIOS2SP)
+ int type = TOS.n; POP;
+ int swid = TOS.n; POP;
+ int len = TOS.n; POP;
+ void* addr = TOS.a;
+ TOS.n = ipmi_oem_bios2sp(swid, type, addr, len);
+MIRP
+
diff --git a/lib/libipmi/libipmi.h b/lib/libipmi/libipmi.h
new file mode 100644
index 0000000..5651180
--- /dev/null
+++ b/lib/libipmi/libipmi.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef __LIBIPMI_H
+#define __LIBIPMI_H
+
+#include <stdint.h>
+
+extern int ipmi_kcs_cmd(uint8_t *, uint8_t *, uint32_t, uint32_t *);
+
+extern void ipmi_system_reboot(void);
+extern void ipmi_power_off(void);
+
+extern int ipmi_oem_stop_bootwatchdog(void);
+extern int ipmi_oem_set_bootwatchdog(uint16_t seconds);
+extern int ipmi_oem_reset_bootwatchdog(void);
+extern int ipmi_oem_led_set(int type, int instance, int state);
+extern uint32_t ipmi_oem_read_vpd(uint8_t *dst, uint32_t len, uint32_t offset);
+extern uint32_t ipmi_oem_write_vpd(uint8_t *src, uint32_t len, uint32_t offset);
+extern uint32_t ipmi_oem_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len);
+extern int ipmi_oem_bios2sp(int swid, int type, char *data, int len);
+
+#endif
diff --git a/lib/libipmi/libipmi.in b/lib/libipmi/libipmi.in
new file mode 100644
index 0000000..a0d0f12
--- /dev/null
+++ b/lib/libipmi/libipmi.in
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+cod(IPMI-KCS-CMD)
+cod(IPMI-SYSTEM-REBOOT)
+cod(IPMI-POWER-OFF)
+cod(IPMI-OEM-STOP-BOOTWATCHDOG)
+cod(IPMI-OEM-SET-BOOTWATCHDOG)
+cod(IPMI-OEM-RESET-BOOTWATCHDOG)
+cod(IPMI-OEM-LED-SET)
+cod(IPMI-OEM-READ-VPD)
+cod(IPMI-OEM-WRITE-VPD)
+cod(IPMI-OEM-GET-BLADE-DESCR)
+cod(IPMI-OEM-BIOS2SP)
diff --git a/llfw/boot_abort.S b/llfw/boot_abort.S
new file mode 100644
index 0000000..e35bd25
--- /dev/null
+++ b/llfw/boot_abort.S
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include "macros.h"
+#include "termctrl.h"
+#include "boot_abort.h"
+#include <cpu.h>
+
+#define MSG_LOOK_HDR TERM_CTRL_BRIGHT, TERM_BG_RED, TERM_FG_WHITE
+
+ASM_ENTRY(msg_e_crc)
+ .ascii MSG_LOOK_HDR
+ .ascii "\n\r\n\rE1001 - Boot ROM CRC failure\n\r"
+ .ascii TERM_CTRL_RESET, "\0"
+ .align 2
+
+ASM_ENTRY(msg_e_nomem)
+ .ascii MSG_LOOK_HDR
+ .ascii "\n\r\n\rE1002 - Memory could not be initialized\n\r"
+ .ascii TERM_CTRL_RESET, "\0"
+ .align 2
+
+ASM_ENTRY(msg_e_nofile)
+ .ascii MSG_LOOK_HDR
+ .ascii "\n\r\n\rE1003 - Firmware image incomplete"
+ .ascii TERM_CTRL_RESET
+ .ascii "\n\r internal FLS1-FFS-0.\0"
+ .align 2
+
+ASM_ENTRY(msg_e_ierror)
+ .ascii MSG_LOOK_HDR
+ .ascii "\n\r\n\rE1004 - Unspecified Internal Firmware Error"
+ .ascii TERM_CTRL_RESET
+ .ascii "\n\r internal FLSX-SE-0.\0"
+ .align 2
+
+/* E1005 : used in memory init code */
+
+/*****************************************************************************
+ * Boot Abort Handler
+ *
+ * Input:
+ * R3 - capability informatin (i/o etc.)
+ * R4 - handling suggestion
+ * R5 - error string reference
+ * R6 - error number
+ *
+ * Return:
+ * if possible input to H8 and NVRAM log and console , then reboot/halt
+ *
+ * Input definitions:
+ *
+ * R3 bits: 63 (h8/console possible) ... add more
+ * R4 bits: 63 (do not attempt reboot)
+ * R5 reference to error message string
+ * R6 32-bit error enumerator
+ *
+ ******************************************************************************/
+ASM_ENTRY(boot_abort)
+ /* save arguments */
+ mr r31, r3
+ mr r30, r4
+ mr r29, r5
+ mr r28, r6
+
+ /* check if i/o is possible, if yes then print message */
+ li r10, ABORT_CANIO
+ andi. r3, r31, r10
+ bne abort_noio
+
+ /* use i/o ..., first print reference message */
+ /* then add internal number if != 0 */
+ mr r3, r29
+ mfspr r4, HSPRG0 /* get runbase */
+ or r3, r3, r4
+ bl io_print
+ mr r3, r28
+ li r28, 0
+ cmpd r3, r28
+ beq 0f
+ bl io_printhex32
+0:
+
+ abort_noio:
+ b $ // FIXME
+ /* never reached */
+
diff --git a/llfw/boot_abort.h b/llfw/boot_abort.h
new file mode 100644
index 0000000..abf9269
--- /dev/null
+++ b/llfw/boot_abort.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef BOOT_ABORT_H
+#define BOOT_ABORT_H
+
+/* boot abort function suitable for assembly */
+#define BOOT_ABORT(cap, action, msg, numhint) \
+ li r3, cap; \
+ li r4, action; \
+ LOAD32(r5, msg); \
+ LOAD32(r6, numhint); \
+ bl boot_abort
+
+/* boot abort function suitable called from c (takes r3 as hint) */
+#define BOOT_ABORT_R3HINT(cap, action, msg) \
+ mr r6, r3; \
+ li r3, cap; \
+ li r4, action; \
+ LOAD32(r5, msg); \
+ bl boot_abort
+
+#define ABORT_CANIO (1 << 0)
+#define ABORT_NOIO (1 << 1)
+
+#define ALTBOOT (1 << 0)
+#define HALT (1 << 1)
+
+#endif
diff --git a/llfw/clib/Makefile.inc b/llfw/clib/Makefile.inc
new file mode 100644
index 0000000..2de8e94
--- /dev/null
+++ b/llfw/clib/Makefile.inc
@@ -0,0 +1,42 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include ../../make.rules
+
+CFLAGS_COMLIB = -pedantic -std=gnu99 -O0
+ASFLAGS_COMLIB =
+
+
+COMLIBDIR = $(LLFWCMNDIR)/clib
+
+COMLIB_SRC_ASM =
+COMLIB_SRC_C = iolib.c
+
+COMLIB_SRCS = $(COMLIB_SRC_ASM:%=$(COMLIBDIR)/%) \
+ $(COMLIB_SRC_C:%=$(COMLIBDIR)/%)
+COMLIB_OBJ_ASM = $(COMLIB_SRC_ASM:%.S=%.o)
+COMLIB_OBJ_C = $(COMLIB_SRC_C:%.c=%.o)
+
+
+comlib.o: $(COMLIB_OBJ_C) $(COMLIB_OBJ_ASM)
+ $(LD) $(LDFLAGS) $^ -o $@ -r
+
+%.o: $(LLFWCMNDIR)/clib/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_COMLIB) -c $< -o $@
+
+%.o: $(LLFWCMNDIR)/clib/%.S
+ $(CC) $(CPPFLAGS) $(ASFLAGS) $(ASFLAGS_COMLIB) -c $< -o $@
+
+LLFW_CLEAN_TARGETS += clean_clib
+.PHONY : clean_clib
+clean_clib:
+ rm -f $(COMLIB_OBJ_C) $(COMLIB_OBJ_ASM) comlib.o
diff --git a/llfw/clib/iolib.c b/llfw/clib/iolib.c
new file mode 100644
index 0000000..9d202f4
--- /dev/null
+++ b/llfw/clib/iolib.c
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "types.h"
+#include <stddef.h>
+#include <unistd.h>
+#include "iolib.h"
+
+void uart_send_byte(unsigned char b)
+{
+ asm volatile ("":::"3","4","5","6","7");
+ io_putchar(b);
+}
+
+/**
+ * Standard write function for the libc.
+ *
+ * @param fd file descriptor (should always be 1 or 2)
+ * @param buf pointer to the array with the output characters
+ * @param count number of bytes to be written
+ * @return the number of bytes that have been written successfully
+ */
+ssize_t write(int fd, const void *buf, size_t count)
+{
+ size_t i;
+ char *ptr = (char *)buf;
+
+ if (fd != 1 && fd != 2)
+ return 0;
+
+ for (i = 0; i < count; i++) {
+ if (*ptr == '\n')
+ uart_send_byte('\r');
+ uart_send_byte(*ptr++);
+ }
+
+ return i;
+}
+
+
+/**
+ * @brief C-routine to delay for a number of milliseconds.
+ * @param delay interval in terms of ms
+ */
+void delay_ms( unsigned int ms )
+{
+ uint32_t ticks_per_ms;
+
+ ticks_per_ms = tb_frequency() / 1000;
+
+ while (0 < ms) {
+ set_dec(ticks_per_ms);
+ while( ((get_dec()) & 0x80000000) == 0 );
+ ms--;
+ }
+}
diff --git a/llfw/clib/iolib.h b/llfw/clib/iolib.h
new file mode 100644
index 0000000..fbe161d
--- /dev/null
+++ b/llfw/clib/iolib.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef IOLIB_H
+#define IOLIB_H
+#include <types.h>
+
+#define addr_t volatile unsigned int
+#define addr8_t volatile unsigned char
+
+extern void out32 (uint64_t base, uint64_t addr, uint32_t val);
+extern void out16 (uint64_t base, uint64_t addr, uint16_t val);
+extern void out8 (uint64_t base, uint64_t addr, uint8_t val);
+extern uint32_t in32 (uint64_t base, uint64_t addr);
+extern uint16_t in16 (uint64_t base, uint64_t addr);
+extern uint8_t in8 (uint64_t base, uint64_t addr);
+
+extern void halt_sys (unsigned int);
+
+extern uint32_t get_sb_version (void);
+
+extern void init_uart (void);
+extern void uart_send_byte(unsigned char b);
+extern void io_putchar(unsigned char);
+
+extern uint64_t tb_frequency(void);
+extern uint64_t be_frequency(void);
+
+extern uint32_t get_dec(void);
+extern void set_dec(uint32_t);
+extern void delay_ms( unsigned int ms );
+
+#endif
diff --git a/llfw/clib/types.h b/llfw/clib/types.h
new file mode 100644
index 0000000..e11a4cf
--- /dev/null
+++ b/llfw/clib/types.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _TYPES_H
+#define _TYPES_H
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+
+#endif
diff --git a/llfw/io_generic/Makefile.inc b/llfw/io_generic/Makefile.inc
new file mode 100644
index 0000000..4aa6d6e
--- /dev/null
+++ b/llfw/io_generic/Makefile.inc
@@ -0,0 +1,38 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+IOGENERICDIR = $(LLFWCMNDIR)/io_generic
+
+IO_GENERIC_SRC_ASM = io_generic.S
+IO_GENERIC_SRC_C =
+
+IO_GENERIC_SRCS = $(IO_GENERIC_SRC_ASM:%=$(IOGENERICDIR)/%) \
+ $(IO_GENERIC_SRC_C:%=$(IOGENERICDIR)/%)
+IO_GENERIC_OBJ_ASM = $(IO_GENERIC_SRC_ASM:%.S=%.o)
+IO_GENERIC_OBJ_C = $(IO_GENERIC_SRC_C:%.c=%.o)
+
+
+io_generic_lib.o: $(IO_GENERIC_OBJ_ASM) $(IO_GENERIC_OBJ_C)
+ $(LD) $(LDFLAGS) $^ -o $@ -r
+
+
+%.o: $(IOGENERICDIR)/%.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+%.o: $(IOGENERICDIR)/%.S
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c $< -o $@
+
+
+LLFW_CLEAN_TARGETS += clean_io_generic
+.PHONY : clean_io_generic
+clean_io_generic:
+ rm -f $(IO_GENERIC_OBJ_C) $(IO_GENERIC_OBJ_ASM) io_generic_lib.o
diff --git a/llfw/io_generic/io_generic.S b/llfw/io_generic/io_generic.S
new file mode 100644
index 0000000..e639124
--- /dev/null
+++ b/llfw/io_generic/io_generic.S
@@ -0,0 +1,129 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include "macros.h"
+#include "calculatecrc.h"
+#include "calculatecrc.h"
+
+ .text
+
+/****************************************************************************
+ * prints a 0-terminated string to serial console
+ *
+ * Input:
+ * R3 - pointer to string in memory
+ *
+ * Returns: -
+ *
+ * Modifies Registers:
+ * R3, R4, R5, R6, R7, R8, R9
+ ****************************************************************************/
+ASM_ENTRY(io_print)
+ mflr r8
+ mr r9, r3
+
+0:
+ lbz r3, 0(r9)
+ cmpwi r3, 0
+ beq 1f
+ bl io_putchar
+ addi r9, r9, 1
+ b 0b
+1:
+ mtlr r8
+ blr
+
+/****************************************************************************
+ * prints Hex integer to the UART and the NVRAM (using board io_putchar)
+ *
+ * Input:
+ * R3 - integer to print
+ *
+ * Returns: -
+ *
+ * Modifies Registers:
+ * R3, R4, R5, R6, R7, R8, R9
+ ****************************************************************************/
+#define _io_gen_print_nib(reg, src, shift) \
+ srdi reg, src, shift; \
+ andi. reg, reg, 0x0F; \
+ cmpwi reg, 0x0A; \
+ blt 0f; \
+ addi reg, reg, ('A'-'0'-10); \
+0:; \
+ addi reg, reg, '0'; \
+ bl io_putchar
+
+ASM_ENTRY(io_printhex64)
+ mflr r8
+ mr r9, r3
+
+_io_printhex64:
+ _io_gen_print_nib(r3, r9, 60)
+ _io_gen_print_nib(r3, r9, 56)
+ _io_gen_print_nib(r3, r9, 52)
+ _io_gen_print_nib(r3, r9, 48)
+ _io_gen_print_nib(r3, r9, 44)
+ _io_gen_print_nib(r3, r9, 40)
+ _io_gen_print_nib(r3, r9, 36)
+ _io_gen_print_nib(r3, r9, 32)
+_io_printhex32:
+ _io_gen_print_nib(r3, r9, 28)
+ _io_gen_print_nib(r3, r9, 24)
+ _io_gen_print_nib(r3, r9, 20)
+ _io_gen_print_nib(r3, r9, 16)
+_io_printhex16:
+ _io_gen_print_nib(r3, r9, 12)
+ _io_gen_print_nib(r3, r9, 8)
+_io_printhex8:
+ _io_gen_print_nib(r3, r9, 4)
+ _io_gen_print_nib(r3, r9, 0)
+
+ mtlr r8
+ blr
+
+ASM_ENTRY(io_printhex32)
+ mflr r8
+ mr r9, r3
+ b _io_printhex32
+
+ASM_ENTRY(io_printhex16)
+ mflr r8
+ mr r9, r3
+ b _io_printhex16
+
+ASM_ENTRY(io_printhex8)
+ mflr r8
+ mr r9, r3
+ b _io_printhex8
+
+
+/****************************************************************************
+ * print the address and its contents as 64-bit hex values
+ *
+ * Input:
+ * R3 - Address to read from
+ *
+ * Returns: -
+ *
+ * Modifies Registers:
+ * R3, R4, R5, R6, R7, R8, R9, R10
+ ****************************************************************************/
+#if 0 /* currently unused */
+ASM_ENTRY(io_dump)
+ mflr r10
+ bl io_printhex64
+ li r3,':'
+ bl io_putchar
+ ld r9,0(r9)
+ mr r8,r10
+ b _io_printhex64
+#endif
diff --git a/llfw/nvramlog.S b/llfw/nvramlog.S
new file mode 100644
index 0000000..d44e534
--- /dev/null
+++ b/llfw/nvramlog.S
@@ -0,0 +1,340 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <macros.h>
+#include <nvramlog.h>
+#include <southbridge.h>
+#include <calculatecrc.h>
+
+// detect overflow: if(a<b) return a else return 0
+#define NVRAM_LOG_DATA_OVERFLOW( a, b) \
+ cmpd 7, a, b; \
+ blt+ 7, 0f; \
+ li a, 0; \
+ 0:
+
+// get Pointer(pointer) to next byte in NVRAM data section
+// and size of this data sechtion (modulo)
+// modifies register pointer, modulo
+#define NVRAM_POINTER_DATASIZE_BE0(pointer, modulo, address) \
+ LOAD64( modulo, LLFW_LOG_BE0_LENGTH); \
+ lwz pointer, LLFW_LOG_POS_POINTER(address); \
+ sldi modulo, modulo, 4; \
+ addi modulo, modulo,-LLFW_LOG_BE0_DATA_OFFSET
+#define NVRAM_POINTER_DATASIZE_BE1(pointer, modulo, address) \
+ LOAD64( modulo, LLFW_LOG_BE1_LENGTH); \
+ lwz pointer, LLFW_LOG_POS_POINTER(address); \
+ sldi modulo, modulo, 4; \
+ addi modulo, modulo,-LLFW_LOG_BE1_DATA_OFFSET
+
+/****************************************************************************
+ * checkLogHeaderData
+ * compare the fixed values in the header if any change was done since
+ * last initialisation.
+ * Flags are not checked!
+ *
+ * Retrun 0 if no manimulation was found 1 else
+ *
+ * input:
+ * r3 - NVRAM Base Address
+ *
+ * output:
+ * r3 - status: 0 = ok, 1 = corrupt
+ * r4 - NVRAM Base Address
+ *
+ ***************************************************************************/
+ASM_ENTRY(checkLogHeaderData)
+ li r4, 0 // init error flag
+ lbz r5, 0(r3) // check signature
+ addi r5, r5, -LLFW_LOG_BE0_SIGNATURE
+ add r4, r4, r5
+
+ lhz r5, LLFW_LOG_POS_LENGTH(r3) // check length
+ addi r5, r5, -LLFW_LOG_BE0_LENGTH
+ add r4, r4, r5
+
+ lwz r5, LLFW_LOG_POS_NAME(r3) // check name prefix
+ LOAD64( r6, LLFW_LOG_BE0_NAME_PREFIX)
+ subf r5, r6, r5
+ add r4, r4, r5
+
+ ld r5, (LLFW_LOG_POS_NAME+4)(r3) // check name
+ LOAD64( r6, LLFW_LOG_BE0_NAME)
+ subf r5, r6, r5
+ add r4, r4, r5
+
+ lhz r5, LLFW_LOG_POS_DATA_OFFSET(r3) //check data offset
+ addi r5, r5, -LLFW_LOG_BE0_DATA_OFFSET
+ add r4, r4, r5
+
+ lhz r5, LLFW_LOG_POS_FLAGS(r3) //check flags
+ addi r5, r5, -LLFW_LOG_BE0_FLAGS
+ add r4, r4, r5
+
+ cmpldi 7, r4, 0
+ beq+ 7, 0f
+ li r4, 1
+0:
+ mr r5, r3
+ mr r3, r4
+ mr r4, r5
+ blr
+/*****************************************************************************
+ * checkLogPartition: check Partition Header entries and Checksum
+ * check also the NVRAM-Log-Partition CRC
+ * if Partition is not ok set the following bits to 1
+ * bit 1: if Partiton Header Checksum is corrupt
+ * bit 2: if CRC is corrupt
+ * bit 3: if Header entries are corrupt
+ *
+ * input:
+ * r3 - NVRAM log address (BASE + NVRAM_LOG_OFFSET)
+ *
+ * output:
+ * r3 - CRC status
+ * r4 - NVRAM log address
+ *
+ * Modifies Register: R3, R4, R5, R6, R7, R8, R9
+ ****************************************************************************/
+ASM_ENTRY(.checkLogPartition)
+ mflr r8
+ mr r4, r3 // emulate "bl updateCRC_NVRAM"
+ li r3, 0 // with successfull CRC check
+ li r7, 0
+ cmpwi 7, r3, 0
+ beq+ 7, 0f
+ li r7, 2
+0:
+ mr r3, r4
+ bl .calPartitionHeaderChecksum // r3=checksum, r4=NVARM addr
+ lbz r6, LLFW_LOG_POS_CHECKSUM(r4)
+ cmpw 7, r3, r6
+ beq+ 7, 0f // cal checksum must eq checksum
+ ori r7, r7, 1
+0:
+ cmpwi 7, r3, 0
+ bne+ 7, 0f
+ ori r7, r7, 1 // 0 as checksum is invalid
+0:
+ mr r3, r4
+ bl checkLogHeaderData
+ cmpdi 7, r3, 0
+ beq+ 7, 0f
+ ori r7, r7, 4
+0:
+ mr r3, r7
+ mtlr r8
+ blr
+/*****************************************************************************
+ * checkinitLog: check the NVRAM Log Partition Header
+ * initialize the NVRAM if the Header was modified
+ *
+ * input:
+ * r3 - NVRAM BASE address
+ *
+ * output:
+ * r3 - 0 = check ok, no new header written
+ * r3 - 1 = check not ok, header and NVRAM initialized
+ * r4 - NVRAM log address
+ *
+ * Modifies Register: R3, R4, R5, R6, R7, r8, r9
+ ****************************************************************************/
+// init is done if checkLogPartiton returns not 0 (= check failed)
+ASM_ENTRY(.checkinitLog)
+ASM_ENTRY(checkinitLog)
+ mflr r9
+ bl .checkLogPartition //r3..r8, r4_out = r3_in
+ mtlr r9
+
+ cmpwi 7, r3, 0
+ mr r3, r4 // r3=NVRAM_LOG address
+ bne- 7, .initLog // if header is not ok, init header
+ li r3, 0
+ blr // header OK, return 0
+
+
+/* this is basically just a copy of .initLog
+ registers used: r3, r4, r5, r6, r7, r9*/
+init_log_2nd_be:
+ mflr r9
+ li r6, LLFW_LOG_BE0_LENGTH
+ mulli r6, r6, 0x10
+ add r6, r7, r6
+ li r5, LLFW_LOG_BE1_SIGNATURE
+ li r4, LLFW_LOG_BE1_LENGTH
+ stb r5, 0(r6)
+ sth r4, LLFW_LOG_POS_LENGTH(r6)
+ li r5, LLFW_LOG_BE1_DATA_OFFSET
+ li r4, LLFW_LOG_BE1_FLAGS
+ sth r5, LLFW_LOG_POS_DATA_OFFSET(r6)
+ sth r4, LLFW_LOG_POS_FLAGS(r6)
+ li r5, 1
+
+ LOAD32( r4, LLFW_LOG_BE1_NAME_PREFIX)
+ stw r5, LLFW_LOG_POS_POINTER(r6)
+ stw r4, (LLFW_LOG_POS_NAME+0x00)(r6)
+ LOAD64( r5, LLFW_LOG_BE1_NAME)
+ std r5, (LLFW_LOG_POS_NAME+0x04)(r6)
+ mr r3, r6
+ bl .calPartitionHeaderChecksum
+ stb r3, LLFW_LOG_POS_CHECKSUM(r6)
+ mtlr r9
+ blr
+/*****************************************************************************
+ * initLog: initialize the NVRAM with 0
+ * write a new NVRAM Log-Partition-Header
+ *
+ * input:
+ * r3 - NVRAM BASE address
+ *
+ * output:
+ * r3 - 0 = check ok, no new header written
+ * r3 - 1 = check not ok, header and NVRAM initialized
+ * r4 - NVRAM log address
+ *
+ * Modifies Register: R3, R4, R5, R6, R7, r8, r9
+ ****************************************************************************/
+ASM_ENTRY(.initLog)
+ mflr r8
+ mr r7, r3
+
+ bl clearNVRAM
+0:
+ li r5, LLFW_LOG_BE0_SIGNATURE
+ li r4, LLFW_LOG_BE0_LENGTH
+ stb r5, 0(r7)
+ sth r4, LLFW_LOG_POS_LENGTH(r7)
+ li r5, LLFW_LOG_BE0_DATA_OFFSET
+ li r4, LLFW_LOG_BE0_FLAGS
+ sth r5, LLFW_LOG_POS_DATA_OFFSET(r7)
+ sth r4, LLFW_LOG_POS_FLAGS(r7)
+ li r5, 1
+
+ LOAD32( r4, LLFW_LOG_BE0_NAME_PREFIX)
+ stw r5, LLFW_LOG_POS_POINTER(r7)
+ stw r4, (LLFW_LOG_POS_NAME+0x00)(r7)
+ LOAD64( r5, LLFW_LOG_BE0_NAME)
+ std r5, (LLFW_LOG_POS_NAME+0x04)(r7)
+ bl .calPartitionHeaderChecksum
+ stb r3, LLFW_LOG_POS_CHECKSUM(r7)
+ bl init_log_2nd_be // create a second log partition for BE1
+ mr r4, r7
+ li r3, 1
+ mtlr r8
+ blr
+/*****************************************************************************
+ * clearNVRAM: set all not used NVRAM memory to zero
+ *
+ *
+ * input:
+ * R3 - NVRAM BASE ADDRESS
+ *
+ * output:
+ * R3 - NVARM END ADDRESS
+ *
+ * Modifies Register: r4, r5
+ ****************************************************************************/
+ASM_ENTRY(clearNVRAM)
+ LOAD64( r4, NVRAM_LENGTH)
+ srdi r4, r4, 3
+ mtctr r4
+ li r5, 0x0
+ LOAD64( r4, NVRAM_EMPTY_PATTERN)
+0:
+ stdx r4, r3,r5
+ addi r5, r5, 8
+ bdnz+ 0b
+ blr
+/*****************************************************************************
+ * writeNVRAMbyte: write next log into NVRAM
+ *
+ *
+ * input:
+ * R3 - byte to be written
+ * R4 - NVRAM Base Address
+ *
+ * output:
+ * R3 - byte that was written
+ * R4 - NVRAM Base Address
+ *
+ * Modifies Register: R3, R4, R5, R6
+ ****************************************************************************/
+ASM_ENTRY(.writeNVRAMbyte)
+ENTRY(writeLogByte)
+ NVRAM_POINTER_DATASIZE_BE0( r5, r6, r4) // get pointer,size of data
+ NVRAM_LOG_DATA_OVERFLOW( r5, r6) // check for overflow
+ addi r5, r5, 1 // increment pointer
+ stw r5, LLFW_LOG_POS_POINTER(r4) // store pointer
+ addi r5, r5, -1 // restore old pointer
+ add r6, r4, r5 // byte address in data section
+
+ stb r3, LLFW_LOG_BE0_DATA_OFFSET(r6)
+ blr
+
+/*****************************************************************************
+ * writeNVRAMbyte: write next log into NVRAM
+ *
+ *
+ * input:
+ * R3 - byte to be written
+ * R4 - NVRAM Base Address
+ *
+ * output:
+ * R3 - byte that was written
+ * R4 - NVRAM Base Address
+ *
+ * Modifies Register: R3, R4, R5, R6
+ ****************************************************************************/
+ENTRY(writeLogByteBE1)
+ li r6, LLFW_LOG_BE0_LENGTH
+ mulli r6, r6, 0x10
+ add r4, r6, r4
+ NVRAM_POINTER_DATASIZE_BE1( r5, r6, r4) // get pointer,size of data
+ NVRAM_LOG_DATA_OVERFLOW( r5, r6) // check for overflow
+ addi r5, r5, 1 // increment pointer
+ stw r5, LLFW_LOG_POS_POINTER(r4) // store pointer
+ addi r5, r5, -1 // restore old pointer
+ add r6, r4, r5 // byte address in data section
+
+ stb r3, LLFW_LOG_BE1_DATA_OFFSET(r6)
+ blr
+
+/*****************************************************************************
+ * calPartitionHeaderChecksum: calculate the Checksum of the
+ * Partition Header as described in ....
+ *
+ * input: r3 - NVRAM BASE adresse
+ *
+ * output: R3 - the calculated checksum as 8 bit value
+ * R4 - NVRAM log address
+ *
+ * Modifies Register: R3, R4, R5, R6
+ ****************************************************************************/
+ASM_ENTRY(.calPartitionHeaderChecksum)
+ mr r6, r3
+ lbz r3,0(r6) // load first byte
+ LOAD64( r4, LLFW_LOG_POS_LENGTH) // load position of 3rd byte
+.L6:
+ lbzx r5, r4, r6 // r5 nexed byte
+ addi r4, r4, 1 // r4++ (index)
+ add r5, r5, r3 // r5 new sum =sum + nexed byte
+ rldicl r5, r5, 0, 56
+ cmpld 7, r5, r3
+ cmpldi 6, r4, LLFW_LOG_POS_DATA_OFFSET
+ bge+ 7,.L5 // if new sum > sum
+ addi r5, r5, 1 // new sum ++
+ rldicl r5, r5, 0, 56
+.L5:
+ mr r3,r5 // sum = new sum
+ blt+ 6,.L6
+
+ mr r4, r6
+ blr
diff --git a/llfw/romfs.S b/llfw/romfs.S
new file mode 100644
index 0000000..e57823f
--- /dev/null
+++ b/llfw/romfs.S
@@ -0,0 +1,362 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include "macros.h"
+#include "romfs.h"
+
+/*******************************************************************
+ * Wrapper for romfs_lookup.
+ *
+ * Input:
+ * R3 = address of filename string
+ * R4 = address of struct romfs_t
+ * 0: file size (return)
+ * 8: flags (return)
+ * 10: fileaddr (return and input: tells if first search)
+ * 18: nextfile (return)
+ * 20: namep (return)
+ *
+ * Find File Procedure
+ * - set filename and rombase, on return 0 file properties are stored
+ * in romfs_t else struct not valid
+ *
+ * Listing procedure
+ * - clear romfs_t (important!)
+ * - set filename = NULL and rombase and call returns first file
+ * with properties in romfs_t including next-file pointer
+ * - if nextpointer is non-zero then just the next file is returned
+ *
+ * Returns:
+ * <Sucess>:
+ * R3 = 0
+ * romfs_t is updated
+ * <FileNotFound>:
+ * R3 = 1
+ * romfs_t not touched
+ *
+ * Potenially modifies the following registers:
+ *
+
+ Example usage from C:
+
+ int list_bootrom()
+ {
+ struct romfs_t rfs;
+ int i;
+
+ printf("Build: "__TIME__" "__DATE__" \n");
+
+ i = 0;
+ memset((void*) &rfs, 0, sizeof(struct romfs_t));
+ printf(" No. File Data Size Name\n");
+
+ while (romfs_stat(NULL, &rfs) == 0) {
+ i++;
+ printf(" %02d: %08X %08X %7d %s\n",
+ i, rfs.fileaddr, rfs.datap,
+ rfs.size, rfs.namep);
+ }
+ if (0 == i) {
+ printf("Error in reading ROMFS\n");
+ return 1;
+ }
+ return 0;
+ }
+ *******************************************************************/
+#define RFS_T_SIZE 0x00
+#define RFS_T_FLAGS 0x08
+#define RFS_T_FILEADDR 0x10
+#define RFS_T_NEXT 0x18
+#define RFS_T_NAME 0x20
+#define RFS_T_DATA 0x28
+
+#define RFS_H_NEXT 0x00
+#define RFS_H_SIZE 0x08
+#define RFS_H_FLAGS 0x10
+#define RFS_H_DATA 0x18
+#define RFS_H_NAME 0x20
+
+ENTRY(romfs_stat_file)
+ /* save link register and romfs_t pointer */
+ mflr r15
+ mr r16, r4
+
+ /* if filename R3 is 0 then its a listing request */
+ /* if not then just continue to lookup name */
+ /* save R4 to R8 which is the address of header */
+ li r7, 0
+ cmpd r3, r7
+ beq romfs_list
+ bl romfs_lookup
+ mfsprg r8, 1
+
+ /* if file found then go to romfs_fill_properties */
+ /* else return 1 to caller */
+ cmpwi r3, 0
+ beq romfs_fill_properties
+ b romfs_stat_end
+
+ romfs_list:
+ /* check if fileaddr == 0, in this case its */
+ /* the first search on this handle, so return all */
+ /* info for file at rombase (R8=R4) */
+ ld r6, RFS_T_FILEADDR(r4)
+ mfsprg r8, 1
+ li r7, 0
+ cmpd r7, r6
+ beq romfs_fill_properties
+
+ /* check if next file != 0 by looking into */
+ /* romfs_t, if not then return (next = 0) 1 */
+ li r7, 0
+ ld r4, RFS_T_NEXT(r4)
+ cmpd r7, r4
+ li r3, 1
+ beq romfs_stat_end
+
+ /* now next file is available so move R8 to next */
+ /* file address */
+ mr r8, r4
+
+ romfs_fill_properties:
+ /* set properties in romfs_t takes R8 as address */
+ /* to file header and R16 as address of romfs_t */
+ mfsprg r3, 1
+ std r8, RFS_T_FILEADDR(r16)
+
+ ld r4, RFS_H_NEXT(r8)
+ li r7, 0
+ cmpd r7, r4
+ beq $ + (2 * 4) /* =0 so add no rombase */
+ add r4, r4, r3
+ std r4, RFS_T_NEXT(r16)
+
+ ld r4, RFS_H_SIZE(r8)
+ std r4, RFS_T_SIZE(r16)
+ ld r4, RFS_H_FLAGS(r8)
+ std r4, RFS_T_FLAGS(r16)
+
+ ld r4, RFS_H_DATA(r8)
+ add r4, r4, r3
+ std r4, RFS_T_DATA(r16)
+
+ addi r4, r8, RFS_H_NAME
+ std r4, RFS_T_NAME(r16)
+
+ li r3, 0
+
+ /* restore romfs_t pointer and link register */
+ romfs_stat_end:
+ mr r5, r16
+ mtlr r15
+ blr
+
+/*******************************************************************
+ * Copies the data of file referenced by name string to address
+ * requires root address of filesystem.
+ * FIXME: ignores flags
+ *
+ * Input:
+ * R3 = address of filename string
+ * R4 = ROMBASE
+ * R5 = destination address
+ *
+ * Returns:
+ * <Sucess>: R3 = 0, R6 = size, <FileNotFound>: R3 = 1
+ * R5 is kept
+ *
+ * Potenially modifies the following registers:
+ * ctr, r15, r16, r17, r18
+ *
+ * Uses the following calls with subsequent register modification:
+ * - romfs_lookup
+ *******************************************************************/
+ASM_ENTRY(romfs_load)
+ mflr r15
+
+ /* save R5 twice */
+ /* lookup file, input regs */
+ /* are already set */
+ /* if not found, just return */
+ mr r16, r5
+ mr r17, r5
+ bl romfs_lookup
+ cmpwi r3, 1
+ bne 0f
+ mtlr r15
+ blr /* abort, not found */
+
+ /* save data size for return */
+ /* found, copy data */
+ /* data size is in R6 */
+0:
+ //mr r3, r6
+ mtctr r6
+ addi r16, r16, -1 /* dest */
+ addi r5, r5, -1 /* source*/
+
+ /* data is expected to be */
+ /* 8 byte aligned */
+ /* copy loop */
+0: lbzu r18, 1(r5)
+ stbu r18, 1(r16)
+ bdnz 0b
+
+ /* restore size, keep padding */
+ /* restore target address */
+ /* return */
+ mr r5, r17
+ mtlr r15
+ blr
+
+/*******************************************************************
+ * looks up a file based on filename
+ *
+ * Input:
+ * R3 = address of filename string
+ * R4 = ROMBASE
+ *
+ * Returns:
+ * <Sucess>:
+ * R3 = 0
+ * R4 = address of file header
+ * R5 = address of data (real address)
+ * R6 = size of data
+ * R7 = flags for file
+ * <FileNotFound>:
+ * R3 = 1
+ *
+ * Potenially modifies the following registers:
+ * R3, R4, R5, R6, R7, R8, R9
+ *
+ * Uses the following calls with subsequent register modification:
+ * - romfs_namematch
+ *******************************************************************/
+ASM_ENTRY(romfs_lookup)
+ mflr r9
+
+ romfs_lookup_next:
+ /* save current file base */
+ mr r8, r4
+ /* name to look for */
+ mr r10, r3
+ /* name of file */
+ mr r5, r4
+ addi r5, r5, (4 /* elems */ * 8 /* elem-size */)
+ mr r11, r5 /* for namematch */
+ /* compare */
+ bl romfs_namematch
+ cmpwi r12, 1
+ bne romfs_lookup_match
+
+ /* load next pointer */
+ /* check if next is 0 */
+ /* apply root-offset */
+ ld r5, 0(r4)
+ cmpwi r5, 0
+ add r4, r4, r5
+ bne romfs_lookup_next
+ /* last file reached, abort */
+ li r3, 1
+ mtlr r9
+ blr
+
+ /* here the name did match */
+ /* r4 is still usable here and */
+ /* pointing to the initial file */
+ /* load r5 with data ptr */
+ /* load r6 with data size */
+ /* load r7 with flags */
+ /* get abs addr of data */
+ romfs_lookup_match:
+ li r3, 0
+ ld r5, (3 * 8)(r4) /* data */
+ ld r6, (1 * 8)(r4) /* len */
+ ld r7, (2 * 8)(r4) /* flags */
+ add r5, r5, r8
+ mtlr r9
+ blr
+
+/*******************************************************************
+ * compares two strings in memory,
+ * both must be null-terminated and 8-byte aligned
+ *
+ * Input:
+ * R10 = string 1
+ * R11 = string 2
+ *
+ * Returns:
+ * <Match>: R12 = 0 <NoMatch>: R12 = 1
+ *
+ * Potenially modifies the following registers:
+ * R10, R11, r12, r13, r14
+ *******************************************************************/
+romfs_namematch:
+ subi r10, r10, 8
+ subi r11, r11, 8
+
+ /*
+ * load chars as 8byte chunk from current pos, name is
+ * always 8 byte aligned :)
+ */
+ romfs_cmp_loop:
+ ldu r13, 8(r10) /* A */
+ ldu r14, 8(r11) /* B */
+
+ cmpd r13, r14
+ li r12, 1
+ beq 1f
+ blr
+
+1: andi. r14, r14, 0xff
+ bne romfs_cmp_loop
+
+ li r12, 0
+ blr
+
+/*******************************************************************
+ * wrapper for romfs_lookup
+ * this function saves the registers from r13 - r15 on the stack
+ * calls romfs_lookup
+ * restores the saved registers
+ *
+ * the return parameters are copied to (r5) and (r5) has to
+ * be 0x20 big
+ *******************************************************************/
+ENTRY(c_romfs_lookup)
+ stdu r1,-0x50(r1) # allocate space on stack
+
+ mflr r0 # save link register
+ std r0,0x30(r1)
+
+ std r15,0x38(r1) # save r15
+ std r14,0x40(r1) # save r14
+ std r13,0x48(r1) # and r13
+
+ mr r15,r5 # save the pointer for the return value
+
+ bl romfs_lookup # do the thing
+
+ ld r0,0x30(r1) # restore link register
+ mtlr r0
+
+ std r4,0x00(r15) # copy return values
+ std r5,0x08(r15) # to the return pointer
+ std r6,0x10(r15)
+ std r7,0x18(r15)
+
+ ld r13,0x48(r1) # restore registers from stack
+ ld r14,0x40(r1)
+ ld r15,0x38(r1)
+
+ addi r1,r1,0x50 # cleanup stack
+
+ blr
diff --git a/llfw/romfs_wrap.c b/llfw/romfs_wrap.c
new file mode 100644
index 0000000..649f5c0
--- /dev/null
+++ b/llfw/romfs_wrap.c
@@ -0,0 +1,22 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <romfs.h>
+
+int romfs_stat(char *filename, struct romfs_t *hnd)
+{
+ asm volatile ("":::"3","4","5","6","7","9","10");
+ asm volatile ("":::"11","12");
+ asm volatile ("":::"13","14","15","16","17","18");
+
+ return romfs_stat_file(filename, hnd);
+}
diff --git a/make.rules b/make.rules
new file mode 100644
index 0000000..cad7aa8
--- /dev/null
+++ b/make.rules
@@ -0,0 +1,41 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+#############################################################################
+# BUILD ENV SETTINGS
+#############################################################################
+
+CROSS ?= powerpc64-linux-
+
+HOSTCC ?= gcc
+HOSTCFLAGS = -g -Wall -W -O2 -I. -I../include
+DD = dd
+ONLY_LD = $(CROSS)ld -melf64ppc
+
+ifdef NEW_BUILD
+MAKEFLAGS = --silent
+CC = echo -e "\t[CC]\t$(DIRECTORY)$@"; $(CROSS)gcc -m64
+AS = echo -e "\t[AS]\t$(DIRECTORY)$@"; $(CROSS)as -m64
+LD = echo -e "\t[LD]\t$(DIRECTORY)$@"; $(ONLY_LD)
+CLEAN = echo -e "\t[CLEAN]\t$(DIRECTORY)$$dir"
+else
+CC = $(CROSS)gcc -m64
+AS = $(CROSS)as -m64
+LD = $(ONLY_LD)
+CLEAN = echo -n
+endif
+
+OBJCOPY = $(CROSS)objcopy
+OBJDUMP = $(CROSS)objdump
+STRIP = $(CROSS)strip
+AR = $(CROSS)ar
+RANLIB = $(CROSS)ranlib
diff --git a/other-licence/Makefile b/other-licence/Makefile
new file mode 100644
index 0000000..fde091e
--- /dev/null
+++ b/other-licence/Makefile
@@ -0,0 +1,26 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+SUBDIRS=common bcm
+
+all :
+ for subdir in $(SUBDIRS) ; do $(MAKE) -C $${subdir} || exit 1 ; done
+
+# Common targets for all subdirectories:
+clean distclean depend:
+ for subdir in $(SUBDIRS) ; do $(MAKE) -C $${subdir} $@ ; done
diff --git a/other-licence/bcm/Makefile b/other-licence/bcm/Makefile
new file mode 100644
index 0000000..0df7dc0
--- /dev/null
+++ b/other-licence/bcm/Makefile
@@ -0,0 +1,57 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS = -O2 -I. -I../common -fno-builtin -ffreestanding -msoft-float -Wall
+
+SRCS = bcm57xx.c
+
+COMMONOBJS = ../common/module_entry.o
+
+OBJS += $(COMMONOBJS) $(SRCS:.c=.o)
+
+
+all: Makefile.dep net_bcm57xx.bin
+
+bcm57xx_net.o: $(OBJS)
+ $(LD) $(LDFLAGS) $^ -o $@ -T ../common/module.lds -N
+
+net_bcm57xx.bin: bcm57xx_net.o
+ $(OBJCOPY) -O binary $^ $@
+
+# A rule for making the object files in the common directory:
+../common/%.o: ../common/%.c
+ $(MAKE) -C ../common all
+
+
+clean:
+ $(RM) -f *.o *.a *.i *.bin
+
+distclean : clean
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(CC) -MM $(CFLAGS) $(SRCS) > Makefile.dep
+Makefile.dep:
+ $(MAKE) depend
+
+# Include dependency file if available:
+ifneq (,$(wildcard Makefile.dep))
+include Makefile.dep
+endif
diff --git a/other-licence/bcm/bcm57xx.c b/other-licence/bcm/bcm57xx.c
new file mode 100644
index 0000000..5cedb6f
--- /dev/null
+++ b/other-licence/bcm/bcm57xx.c
@@ -0,0 +1,3410 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*
+ *
+ ******************************************************************************
+ * reference:
+ * Broadcom 57xx
+ * Host Programmer Interface Specification for the
+ * NetXtreme Family of Highly-Integrated Media Access Controlers
+ */
+#include "types.h"
+#include "bcm57xx.h"
+
+
+/*
+ * local defines
+ ******************************************************************************
+ */
+
+
+// #define BCM_VLAN_TAG ( (u32_t) 0x1 )
+
+// number of tx/rx rings
+// NOTE: 5714 only uses 1 rx/tx ring, but memory
+// for the other rings is cleaned anyways for
+// sanity & future use
+#define BCM_MAX_TX_RING 16
+#define BCM_MAX_RXRET_RING 16
+#define BCM_MAX_RXPROD_RCB 3
+
+// bd descriptions
+#define BCM_RXPROD_RING_SIZE 512 // don't change
+#define BCM_RXRET_RING_SIZE 512 // don't change
+#define BCM_TX_RING_SIZE 512 // don't change
+#define BCM_BUF_SIZE 1536 // don't change
+#define BCM_MTU_MAX_LEN 1522
+#define BCM_MAX_RX_BUF 64
+#define BCM_MAX_TX_BUF 16
+
+// number of MAC addresses in NIC
+#define BCM_NUM_MAC_ADDR 4
+#define BCM_NUM_MAC5704_ADDR 12
+// offset of mac address field(s) in bcm register space
+#define MAC5704_ADDR_OFFS ( (u16_t) 0x0530 )
+
+// offset of NIC memory start address from base address
+#define BCM_MEMORY_OFFS ( (u64_t) 0x8000 )
+
+// offset of statistics block in NIC memory
+#define BCM_STATISTIC_OFFS ( (u64_t) 0x0300 )
+// size of statistic block in NIC memory
+#define BCM_STATISTIC_SIZE 0x800
+
+// offsets of NIC rx/tx rings in NIC memory
+#define BCM_NIC_TX_OFFS ( (u16_t) 0x4000 )
+#define BCM_NIC_RX_OFFS ( (u16_t) 0x6000 )
+#define BCM_NIC_TX_SIZE ( (u16_t) ( ( BCM_TX_RING_SIZE * BCM_RCB_SIZE_u16 ) / 4 ) )
+
+// device mailboxes
+#define BCM_FW_MBX ( (u16_t) 0x0b50 )
+#define BCM_FW_MBX_CMD ( (u16_t) 0x0b78 )
+#define BCM_FW_MBX_LEN ( (u16_t) 0x0b7c )
+#define BCM_FW_MBX_DATA ( (u16_t) 0x0b80 )
+#define BCM_NICDRV_STATE_MBX ( (u16_t) 0x0c04 )
+
+// device mailbox commands
+#define BCM_NICDRV_ALIVE ( (u32_t) 0x00000001 )
+#define BCM_NICDRV_PAUSE_FW ( (u32_t) 0x00000002 )
+
+// device values
+#define BCM_MAGIC_NUMBER ( (u32_t) 0x4b657654 )
+
+// device states
+#define NIC_FWDRV_STATE_START ( (u32_t) 0x00000001 )
+#define NIC_FWDRV_STATE_START_DONE ( (u32_t) 0x80000001 )
+#define NIC_FWDRV_STATE_UNLOAD ( (u32_t) 0x00000002 )
+#define NIC_FWDRV_STATE_UNLOAD_DONE ( (u32_t) 0x80000002 )
+#define NIC_FWDRV_STATE_SUSPEND ( (u32_t) 0x00000004 )
+
+// timer prescaler value
+#define BCM_TMR_PRESCALE ( (u32_t) 0x41 )
+
+// offset of transmit rcb's in NIC memory
+#define BCM_TX_RCB_OFFS ( (u16_t) 0x0100 )
+// offset of receive return rcb's in NIC memory
+#define BCM_RXRET_RCB_OFFS ( (u16_t) 0x0200 )
+
+// register offsets for ring indices
+#define TX_PROD_IND ( (u16_t) 0x0304 )
+#define TX_CONS_IND ( (u16_t) 0x3cc0 )
+#define RXPROD_PROD_IND ( (u16_t) 0x026c )
+#define RXPROD_CONS_IND ( (u16_t) 0x3c54 )
+#define RXRET_PROD_IND ( (u16_t) 0x3c80 )
+#define RXRET_CONS_IND ( (u16_t) 0x0284 )
+// NIC producer index only needed for initialization
+#define TX_NIC_PROD_IND ( (u16_t) 0x0384 )
+
+/*
+ * predefined register values used during initialization
+ * may be adapted by user
+ */
+#define DMA_RW_CTRL_VAL_5714 ( (u32_t) 0x76144000 )
+#define DMA_RW_CTRL_VAL ( (u32_t) 0x760F0000 )
+#define TX_MAC_LEN_VAL ( (u32_t) 0x00002620 )
+
+#define RX_LST_PLC_CFG_VAL ( (u32_t) 0x00000109 )
+#define RX_LST_PLC_STAT_EN_VAL ( (u32_t) 0x007e000f )
+#define NVM_ADDR_MSK ( (u32_t) 0x000fffff )
+
+// Number of Receive Rules /w or /wo SOL enabled
+#define RX_RULE_CFG_VAL ( (u32_t) 0x00000008 )
+#define NUM_RX_RULE ( (u32_t) 16 )
+#define NUM_RX_RULE_ASF ( (u32_t) ( NUM_RX_RULE - 4 ) )
+
+// RCB register offsets
+#define BCM_RXPROD_RCB_JUM ( (u16_t) 0x2440 )
+#define BCM_RXPROD_RCB_STD ( (u16_t) 0x2450 )
+#define BCM_RXPROD_RCB_MIN ( (u16_t) 0x2460 )
+
+// macros needed for new addressing method
+#define BCM_RCB_HOSTADDR_HI_u16( rcb ) ( (u16_t) rcb + 0x00 )
+#define BCM_RCB_HOSTADDR_LOW_u16( rcb ) ( (u16_t) rcb + 0x04 )
+#define BCM_RCB_LENFLAG_u16( rcb ) ( (u16_t) rcb + 0x08 )
+#define BCM_RCB_NICADDR_u16( rcb ) ( (u16_t) rcb + 0x0c )
+#define BCM_RCB_SIZE_u16 ( (u16_t) 0x0010 )
+
+// RCB flags
+#define RCB_FLAG_RING_DISABLED BIT32( 1 )
+
+// BCM device ID masks
+#define BCM_DEV_5714 ( (u64_t) 0x1 )
+#define BCM_DEV_5704 ( (u64_t) 0x2 )
+#define BCM_DEV_5703 ( (u64_t) 0x4 )
+#define BCM_DEV_SERDES ( (u64_t) 0x80000000 )
+#define BCM_DEV_COPPER ( (u64_t) 0x40000000 )
+
+#define IS_5714 ( ( bcm_device_u64 & BCM_DEV_5714 ) != 0 )
+#define IS_5704 ( ( bcm_device_u64 & BCM_DEV_5704 ) != 0 )
+#define IS_5703 ( ( bcm_device_u64 & BCM_DEV_5703 ) != 0 )
+#define IS_SERDES ( ( bcm_device_u64 & BCM_DEV_SERDES ) != 0 )
+#define IS_COPPER_PHY ( ( bcm_device_u64 & BCM_DEV_COPPER ) != 0 )
+
+#define BUFFERED_FLASH_PAGE_POS 9
+#define BUFFERED_FLASH_BYTE_ADDR_MASK ((<<BUFFERED_FLASH_PAGE_POS) - 1)
+#define BUFFERED_FLASH_PAGE_SIZE 264
+#define BUFFERED_FLASH_PHY_SIZE 512
+#define MANUFACTURING_INFO_SIZE 140
+#define CRC32_POLYNOMIAL 0xEDB88320
+
+/*
+ * local types
+ ******************************************************************************
+ */
+typedef struct {
+ u32_t m_dev_u32;
+ u64_t m_devmsk_u64;
+} bcm_dev_t;
+
+/*
+ * BCM common data structures
+ * BCM57xx Programmer's Guide: Section 5
+ */
+
+/*
+ * 64bit host address in a way the NIC is able to understand it
+ */
+typedef struct {
+ u32_t m_hi_u32;
+ u32_t m_lo_u32;
+} bcm_addr64_t;
+/*
+ * ring control block
+ */
+typedef struct {
+ bcm_addr64_t m_hostaddr_st;
+ u32_t m_lenflags_u32; // upper 16b: len, lower 16b: flags
+ u32_t m_nicaddr_u32;
+} bcm_rcb_t;
+
+/*
+ * tx buffer descriptor
+ */
+typedef struct {
+ bcm_addr64_t m_hostaddr_st;
+ u32_t m_lenflags_u32; // upper 16b: len, lower 16b: flags
+ u32_t m_VLANtag_u32; // lower 16b: vtag
+} bcm_txbd_t;
+
+/*
+ * rx buffer descriptor
+ */
+typedef struct {
+ bcm_addr64_t m_hostaddr_st;
+ u32_t m_idxlen_u32; // upper 16b: idx, lower 16b: len
+ u32_t m_typeflags_u32; // upper 16b: type, lower 16b: flags
+ u32_t m_chksum_u32; // upper 16b: ip, lower 16b: tcp/udp
+ u32_t m_errvlan_u32; // upper 16b: err, lower 16b: vlan tag
+ u32_t m_reserved_u32;
+ u32_t m_opaque_u32;
+} bcm_rxbd_t;
+
+/*
+ * bcm status block
+ * NOTE: in fact the status block is not used and configured
+ * so that it is not updated by the NIC. Still it has to be
+ * set up so the NIC is satisfied
+ */
+typedef struct {
+ u32_t m_st_word_u32;
+ u32_t m_st_tag_u32;
+ u16_t m_rxprod_cons_u16;
+ u16_t m_unused_u16;
+ u32_t m_unused_u32;
+ u16_t m_tx_cons_u16;
+ u16_t m_rxret_prod_u16;
+} bcm_status_t;
+
+/*
+ * local constants
+ ******************************************************************************
+ */
+static const bcm_dev_t bcm_dev[] = {
+ { 0x166b, BCM_DEV_5714 },
+ { 0x1668, BCM_DEV_5714 },
+ { 0x1669, BCM_DEV_5714 },
+ { 0x166a, BCM_DEV_5714 },
+ { 0x1648, BCM_DEV_5704 },
+ { 0x1649, BCM_DEV_5704 | BCM_DEV_SERDES },
+ { 0x16a8, BCM_DEV_5704 | BCM_DEV_SERDES },
+ { 0x16a7, BCM_DEV_5703 | BCM_DEV_SERDES },
+ { 0x16c7, BCM_DEV_5703 | BCM_DEV_SERDES },
+ { 0 , 0 }
+};
+
+/*
+ * local variables
+ ******************************************************************************
+ */
+static u64_t bcm_device_u64;
+static u32_t bcm_rxret_ring_sz;
+static u64_t bcm_baseaddr_u64;
+static u64_t bcm_memaddr_u64;
+
+/*
+ * rings & their buffers
+ */
+// the rings made of buffer descriptors
+static bcm_txbd_t bcm_tx_ring[BCM_TX_RING_SIZE];
+static bcm_rxbd_t bcm_rxprod_ring[BCM_RXPROD_RING_SIZE];
+static bcm_rxbd_t bcm_rxret_ring[BCM_RXRET_RING_SIZE*2];
+
+// the buffers used in the rings
+static u08_t bcm_tx_buffer_pu08[BCM_MAX_TX_BUF][BCM_BUF_SIZE];
+static u08_t bcm_rx_buffer_pu08[BCM_MAX_RX_BUF][BCM_BUF_SIZE];
+
+// tx ring index of first/last bd
+static u32_t bcm_tx_start_u32;
+static u32_t bcm_tx_stop_u32;
+static u32_t bcm_tx_bufavail_u32;
+
+// PCI device location needed for indirect addressing
+static u64_t bcm_pcicfg_puid;
+static u08_t bcm_pcicfg_bus;
+static u08_t bcm_pcicfg_devfn;
+
+/*
+ * status block
+ */
+static bcm_status_t bcm_status;
+
+/*
+ * implementation
+ ******************************************************************************
+ */
+
+
+/*
+ * global functions
+ ******************************************************************************
+ */
+int
+check_driver( pci_config_t *pcicfg );
+
+
+/*
+ * local helper functions
+ ******************************************************************************
+ */
+static char *
+memcpy( char *dest, const char *src, size_t n )
+{
+ char *ret = dest;
+ while( n-- ) {
+ *dest++ = *src++;
+ }
+
+ return( ret );
+}
+
+static char *
+memset_ci( char *dest, int c, size_t n )
+{
+ char *ret = dest;
+
+ while( n-- ) {
+ wr08( dest, c );
+ dest++;
+ }
+
+ return( ret );
+}
+
+static char *
+memset( char *dest, int c, size_t n )
+{
+ char *ret = dest;
+ while( n-- ) {
+ *dest++ = (char) c;
+ }
+
+ return( ret );
+}
+
+static u32_t
+bcm_nvram_logical_to_physical_address(u32_t address)
+{
+ u32_t page_no = address / BUFFERED_FLASH_PAGE_SIZE;
+ u32_t page_addr = address % BUFFERED_FLASH_PAGE_SIZE;
+
+ return (page_no << BUFFERED_FLASH_PAGE_POS) + page_addr;
+}
+
+
+/*
+ * local inline functions for endian swapping
+ ******************************************************************************
+ */
+
+static u16_t
+bswap_16 (u16_t x) {
+ return ((x&0xff00) >> 8)
+ | ((x&0x00ff) << 8);
+}
+
+u32_t
+static bswap_32 (u32_t x) {
+ return bswap_16((x&0xffff0000) >> 16)
+ | (bswap_16(x&0x0000ffff) << 16);
+}
+
+/*
+ * read/write functions to access NIC registers & memory
+ * NOTE: all functions are executed with cache inhibitation (dead slow :-) )
+ */
+static u32_t
+bcm_read_mem32( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ return rd32( bcm_memaddr_u64 + (u64_t) f_offs_u16 );
+}
+
+/* not used so far
+static u16_t
+bcm_read_mem16( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ return rd16( bcm_memaddr_u64 + (u64_t) f_offs_u16 );
+}*/
+/* not used so far
+static u08_t
+bcm_read_mem08( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ return rd08( bcm_memaddr_u64 + (u64_t) f_offs_u16 );
+}*/
+
+static u32_t
+bcm_read_reg32_indirect( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ snk_kernel_interface->pci_config_write( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ REG_BASE_ADDR_REG,
+ f_offs_u16 );
+ return (u32_t) bswap_32( snk_kernel_interface->pci_config_read( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ REG_DATA_REG ) ) ;
+}
+
+static u32_t
+bcm_read_reg32( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ if(f_offs_u16 >= 0x200 && f_offs_u16 <0x400)
+ return bcm_read_reg32_indirect( f_offs_u16 + 0x5600 );
+ return rd32( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+}
+
+static u16_t
+bcm_read_reg16( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ return rd16( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+}
+/* not used so far
+static u08_t
+bcm_read_reg08( u16_t f_offs_u16 )
+{ // caution: shall only be used after initialization!
+ return rd08( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+}*/
+
+static void
+bcm_write_mem32_indirect( u16_t f_offs_u16, u32_t f_val_u32 )
+{ // caution: shall only be used after initialization!
+ snk_kernel_interface->pci_config_write( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ MEM_BASE_ADDR_REG,
+ f_offs_u16 );
+ snk_kernel_interface->pci_config_write( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ MEM_DATA_REG,
+ bswap_32 ( f_val_u32 ) );
+}
+
+static void
+bcm_write_mem32( u16_t f_offs_u16, u32_t f_val_u32 )
+{ // caution: shall only be used after initialization!
+ if(f_offs_u16 >= BCM_RXRET_RCB_OFFS &&
+ f_offs_u16 < BCM_RXRET_RCB_OFFS + (BCM_MAX_RXRET_RING*BCM_RCB_SIZE_u16))
+ bcm_write_mem32_indirect( f_offs_u16, f_val_u32 );
+ else if(f_offs_u16 >= BCM_TX_RCB_OFFS &&
+ f_offs_u16 < BCM_TX_RCB_OFFS + (BCM_MAX_TX_RING*BCM_RCB_SIZE_u16))
+ bcm_write_mem32_indirect( f_offs_u16, f_val_u32 );
+ else
+ wr32( bcm_memaddr_u64 + (u64_t) f_offs_u16, f_val_u32 );
+}
+/* not used so far
+static void
+bcm_write_mem16( u16_t f_offs_u16, u16_t f_val_u16 )
+{ // caution: shall only be used after initialization!
+ wr16( bcm_memaddr_u64 + (u64_t) f_offs_u16, f_val_u16 );
+}*/
+/* not used so far
+static void
+bcm_write_mem08( u16_t f_offs_u16, u08_t f_val_u08 )
+{ // caution: shall only be used after initialization!
+ wr08( bcm_memaddr_u64 + (u64_t) f_offs_u16, f_val_u08 );
+}*/
+
+static void
+bcm_write_reg32_indirect( u16_t f_offs_u16, u32_t f_val_u32 )
+{ // caution: shall only be used after initialization!
+ snk_kernel_interface->pci_config_write( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ REG_BASE_ADDR_REG,
+ f_offs_u16 );
+ snk_kernel_interface->pci_config_write( bcm_pcicfg_puid,
+ 4,
+ bcm_pcicfg_bus,
+ bcm_pcicfg_devfn,
+ REG_DATA_REG,
+ bswap_32 ( f_val_u32 ) );
+}
+
+static void
+bcm_write_reg32( u16_t f_offs_u16, u32_t f_val_u32 )
+{ // caution: shall only be used after initialization!
+ if(f_offs_u16 >= 0x200 && f_offs_u16 <0x400)
+ bcm_write_reg32_indirect( f_offs_u16 + 0x5600, f_val_u32 );
+ else
+ wr32( bcm_baseaddr_u64 + (u64_t) f_offs_u16, f_val_u32 );
+}
+
+static void
+bcm_write_reg16( u16_t f_offs_u16, u16_t f_val_u16 )
+{ // caution: shall only be used after initialization!
+ wr16( bcm_baseaddr_u64 + (u64_t) f_offs_u16, f_val_u16 );
+}
+/* not used so far
+static void
+bcm_write_reg08( u16_t f_offs_u16, u08_t f_val_u08 )
+{ // caution: shall only be used after initialization!
+ wr08( bcm_baseaddr_u64 + (u64_t) f_offs_u16, f_val_u08 );
+}*/
+
+static void
+bcm_setb_reg32( u16_t f_offs_u16, u32_t f_mask_u32 )
+{
+ u32_t v;
+
+ v = bcm_read_reg32( f_offs_u16 );
+ v |= f_mask_u32;
+ bcm_write_reg32( f_offs_u16, v );
+}
+/* not used so far
+static void
+bcm_setb_reg16( u16_t f_offs_u16, u16_t f_mask_u16 )
+{
+ u16_t v;
+ v = rd16( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+ v |= f_mask_u16;
+ wr16( bcm_baseaddr_u64 + (u64_t) f_offs_u16, v );
+}*/
+/* not used so far
+static void
+bcm_setb_reg08( u16_t f_offs_u16, u08_t f_mask_u08 )
+{
+ u08_t v;
+ v = rd08( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+ v |= f_mask_u08;
+ wr08( bcm_baseaddr_u64 + (u64_t) f_offs_u16, v );
+}*/
+
+static void
+bcm_clrb_reg32( u16_t f_offs_u16, u32_t f_mask_u32 )
+{
+ u32_t v;
+
+ v = bcm_read_reg32( f_offs_u16 );
+ v &= ~f_mask_u32;
+ bcm_write_reg32( f_offs_u16, v );
+}
+
+static void
+bcm_clrb_reg16( u16_t f_offs_u16, u16_t f_mask_u16 )
+{
+ u16_t v;
+
+ v = bcm_read_reg16( f_offs_u16 );
+ v &= ~f_mask_u16;
+ bcm_write_reg16( f_offs_u16, v );
+}
+/* not used so far
+static void
+bcm_clrb_reg08( u16_t f_offs_u16, u08_t f_mask_u08 )
+{
+ u08_t v;
+ v = rd08( bcm_baseaddr_u64 + (u64_t) f_offs_u16 );
+ v &= ~f_mask_u32;
+ wr08( bcm_baseaddr_u64 + (u64_t) f_offs_u16, v );
+}*/
+
+static void
+bcm_clr_wait_bit32( u16_t r, u32_t b )
+{
+ u32_t i;
+
+ bcm_clrb_reg32( r, b );
+
+ i = 1000;
+ while( --i ) {
+
+ if( ( bcm_read_reg32( r ) & b ) == 0 ) {
+ break;
+ }
+
+ us_delay( 10 );
+ }
+#ifdef BCM_DEBUG
+ if( ( bcm_read_reg32( r ) & b ) != 0 ) {
+ printk( "bcm57xx: bcm_clear_wait_bit32 failed (0x%04X)!\n", r );
+ }
+#endif
+}
+
+/*
+ * (g)mii bus access
+ */
+#if 0
+// not used so far
+static i32_t
+bcm_mii_write16( u32_t f_reg_u32, u16_t f_value_u16 )
+{
+ static const u32_t WR_VAL = ( ( ((u32_t) 0x1) << 21 ) | BIT32( 29 ) | BIT32( 26 ) );
+ i32_t l_autopoll_i32 = 0;
+ u32_t l_wrval_u32;
+ u32_t i;
+
+ /*
+ * only 0x00-0x1f are valid registers
+ */
+ if( f_reg_u32 > (u32_t) 0x1f ) {
+ return -1;
+ }
+
+ /*
+ * disable auto polling if enabled
+ */
+ if( ( bcm_read_reg32( MI_MODE_R ) & BIT32( 4 ) ) != 0 ) {
+ l_autopoll_i32 = (i32_t) !0;
+ bcm_clrb_reg32( MI_MODE_R, BIT32( 4 ) );
+ us_delay( 40 );
+ }
+
+ /*
+ * construct & write mi com register value
+ */
+ l_wrval_u32 = ( WR_VAL | ( f_reg_u32 << 16 ) | (u32_t) f_value_u16 );
+ bcm_write_reg32( MI_COM_R, l_wrval_u32 );
+
+ /*
+ * wait for transaction to complete
+ */
+ i = 25;
+ while( ( --i ) &&
+ ( ( bcm_read_reg32( MI_COM_R ) & BIT32( 29 ) ) != 0 ) ) {
+ us_delay( 10 );
+ }
+
+ /*
+ * re-enable auto polling if necessary
+ */
+ if( l_autopoll_i32 ) {
+ bcm_setb_reg32( MI_MODE_R, BIT32( 4 ) );
+ }
+
+ // return on error
+ if( i == 0 ) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static i32_t
+bcm_mii_read16( u32_t f_reg_u32, u16_t *f_value_pu16 )
+{
+ static const u32_t RD_VAL = ( ( ((u32_t) 0x1) << 21 ) | BIT32( 29 ) | BIT32( 27 ) );
+ i32_t l_autopoll_i32 = 0;
+ u32_t l_rdval_u32;
+ u32_t i;
+
+ /*
+ * only 0x00-0x1f are valid registers
+ */
+ if( f_reg_u32 > (u32_t) 0x1f ) {
+ return -1;
+ }
+
+ /*
+ * disable auto polling if enabled
+ */
+ if( ( bcm_read_reg32( MI_MODE_R ) & BIT32( 4 ) ) != 0 ) {
+ l_autopoll_i32 = ( i32_t ) !0;
+ bcm_clrb_reg32( MI_MODE_R, BIT32( 4 ) );
+ us_delay( 40 );
+ }
+
+ /*
+ * construct & write mi com register value
+ */
+ l_rdval_u32 = ( RD_VAL | ( f_reg_u32 << 16 ) );
+ bcm_write_reg32( MI_COM_R, l_rdval_u32 );
+
+ /*
+ * wait for transaction to complete
+ */
+ i = 25;
+ l_rdval_u32 = bcm_read_reg32( MI_COM_R );
+ while( ( --i ) &&
+ ( ( l_rdval_u32 & BIT32( 29 ) ) != 0 ) ) {
+ us_delay( 10 );
+ l_rdval_u32 = bcm_read_reg32( MI_COM_R );
+ }
+
+ /*
+ * re-enable autopolling if necessary
+ */
+ if( l_autopoll_i32 ) {
+ bcm_setb_reg32( MI_MODE_R, BIT32( 4 ) );
+ }
+
+ /*
+ * return on read transaction error
+ * (check read failed bit)
+ */
+ if( ( i == 0 ) ||
+ ( ( l_rdval_u32 & BIT32( 28 ) ) != 0 ) ) {
+ return -1;
+ }
+
+ /*
+ * return read value
+ */
+ *f_value_pu16 = (u16_t) ( l_rdval_u32 & (u32_t) 0xffff );
+
+ return 0;
+}
+
+/*
+ * ht2000 dump (not complete)
+ */
+#if 0
+static void
+bcm_dump( void )
+{
+ u32_t i, j;
+
+ printk( "*** DUMP ***********************************************************************\n\n" );
+
+ printk( "* PCI Configuration Registers:\n" );
+ for( i = 0, j = 0; i < 0x40; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Private PCI Configuration Registers:\n" );
+ for( i = 0x68, j = 0; i < 0x88; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* VPD Config:\n" );
+ printk( "%04X: %08X \n", 0x94, bcm_read_reg32( 0x94 ) );
+
+ printk( "\n* Dual MAC Control Registers:\n" );
+ for( i = 0xb8, j = 0; i < 0xd0; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Ethernet MAC Control Registers:\n" );
+ for( i = 0x400, j = 0; i < 0x590; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Send Data Initiator Control:\n" );
+ for( i = 0xc00, j = 0; i < 0xc10; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Send Data Completion Control:\n" );
+ printk( "%04X: %08X ", 0x1000, bcm_read_reg32( 0x1000 ) );
+ printk( "%04X: %08X \n", 0x1008, bcm_read_reg32( 0x1008 ) );
+
+ printk( "\n* Send BD Ring Selector Control:\n" );
+ printk( "%04X: %08X ", 0x1400, bcm_read_reg32( 0x1400 ) );
+ printk( "%04X: %08X ", 0x1404, bcm_read_reg32( 0x1404 ) );
+ printk( "%04X: %08X \n", 0x1408, bcm_read_reg32( 0x1408 ) );
+
+ printk( "\n* Send BD Initiator Control:\n" );
+ printk( "%04X: %08X ", 0x1800, bcm_read_reg32( 0x1800 ) );
+ printk( "%04X: %08X \n", 0x1804, bcm_read_reg32( 0x1804 ) );
+
+ printk( "\n* Send BD Completion Control:\n" );
+ printk( "%04X: %08X ", 0x1c00, bcm_read_reg32( 0x1c00 ) );
+
+ printk( "\n* Receive List Placement Control:\n" );
+ for( i = 0x2000, j = 0; i < 0x2020; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Receive Data & Receive BD Initiator Control:\n" );
+ printk( "%04X: %08X ", 0x2400, bcm_read_reg32( 0x2400 ) );
+ printk( "%04X: %08X \n", 0x2404, bcm_read_reg32( 0x2404 ) );
+
+ printk( "\n* Jumbo Receive BD Ring RCB:\n" );
+ for( i = 0x2440, j = 0; i < 0x2450; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Standard Receive BD Ring RCB:\n" );
+ for( i = 0x2450, j = 0; i < 0x2460; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Mini Receive BD Ring RCB:\n" );
+ for( i = 0x2460, j = 0; i < 0x2470; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\nRDI Timer Mode Register:\n" );
+ printk( "%04X: %08X \n", 0x24f0, bcm_read_reg32( 0x24f0 ) );
+
+ printk( "\n* Receive BD Initiator Control:\n" );
+ for( i = 0x2c00, j = 0; i < 0x2c20; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+
+ printk( "\n* Receive BD Completion Control:\n" );
+ for( i = 0x3000, j = 0; i < 0x3014; i += 4 ) {
+
+ printk( "%04X: %08X ", i, bcm_read_reg32( i ) );
+
+ if( ( ++j & 0x3 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+}
+#endif
+
+
+
+/*
+ * NVRAM access
+ */
+
+static int
+bcm_nvram_lock( void )
+{
+ int i;
+
+ /*
+ * Acquire NVRam lock (REQ0) & wait for arbitration won (ARB0_WON)
+ */
+// bcm_setb_reg32( SW_ARB_R, BIT32( 0 ) );
+ bcm_setb_reg32( SW_ARB_R, BIT32( 1 ) );
+
+ i = 2000;
+ while( ( --i ) &&
+// ( bcm_read_reg32( SW_ARB_R ) & BIT32( 8 ) ) == 0 ) {
+ ( bcm_read_reg32( SW_ARB_R ) & BIT32( 9 ) ) == 0 ) {
+ ms_delay( 1 );
+ }
+
+ // return on error
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk("bcm57xx: failed to lock nvram");
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+bcm_nvram_unlock( void )
+{
+ /*
+ * release NVRam lock (CLR0)
+ */
+// bcm_setb_reg32( SW_ARB_R, BIT32( 4 ) );
+ bcm_setb_reg32( SW_ARB_R, BIT32( 5 ) );
+}
+
+static void
+bcm_nvram_init( void )
+{
+ /*
+ * enable access to NVRAM registers
+ */
+ if(IS_5714) {
+ bcm_setb_reg32( NVM_ACC_R, BIT32( 1 ) | BIT32( 0 ) );
+ }
+
+ /*
+ * disable bit-bang method 19& disable interface bypass
+ */
+ bcm_clrb_reg32( NVM_CFG1_R, BIT32( 31 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 14 ) | BIT32( 16 ) );
+ bcm_setb_reg32( NVM_CFG1_R, BIT32 ( 13 ) | BIT32 ( 17 ));
+
+ /*
+ * enable Auto SEEPROM Access
+ */
+ bcm_setb_reg32( MISC_LOCAL_CTRL_R, BIT32 ( 24 ) );
+
+ /*
+ * NVRAM write enable
+ */
+ bcm_setb_reg32( MODE_CTRL_R, BIT32 ( 21 ) );
+}
+
+static i32_t
+bcm_nvram_read( u32_t f_addr_u32, u32_t *f_val_pu32, u32_t lock )
+{
+ u32_t i;
+
+ /*
+ * parameter check
+ */
+ if( f_addr_u32 > NVM_ADDR_MSK ) {
+ return -1;
+ }
+
+ /*
+ * Acquire NVRam lock (REQ0) & wait for arbitration won (ARB0_WON)
+ */
+ if( lock && (bcm_nvram_lock() == -1) ) {
+ return -1;
+ }
+
+ /*
+ * setup address to read
+ */
+ bcm_write_reg32( NVM_ADDR_R,
+ bcm_nvram_logical_to_physical_address(f_addr_u32) );
+// bcm_write_reg32( NVM_ADDR_R, f_addr_u32 );
+
+ /*
+ * get the command going
+ */
+ bcm_write_reg32( NVM_COM_R, BIT32( 8 ) | BIT32( 7 ) |
+ BIT32( 4 ) | BIT32( 3 ) );
+
+ /*
+ * wait for command completion
+ */
+ i = 2000;
+ while( ( --i ) &&
+ ( ( bcm_read_reg32( NVM_COM_R ) & BIT32( 3 ) ) == 0 ) ) {
+ ms_delay( 1 );
+ }
+
+ /*
+ * read back data if no error
+ */
+ if( i != 0 ) {
+ /*
+ * read back data
+ */
+ *f_val_pu32 = bcm_read_reg32( NVM_READ_R );
+ }
+
+ if(lock)
+ bcm_nvram_unlock();
+
+ // error
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk("bcm57xx: reading from NVRAM failed\n");
+#endif
+ return -1;
+ }
+
+ // success
+ return 0;
+}
+
+static i32_t
+bcm_nvram_write( u32_t f_addr_u32, u32_t f_value_u32, u32_t lock )
+{
+ u32_t i;
+
+ /*
+ * parameter check
+ */
+ if( f_addr_u32 > NVM_ADDR_MSK ) {
+ return -1;
+ }
+
+ /*
+ * Acquire NVRam lock (REQ0) & wait for arbitration won (ARB0_WON)
+ */
+ if( lock && (bcm_nvram_lock() == -1) ) {
+ return -1;
+ }
+
+ /*
+ * setup address to write
+ */
+ bcm_write_reg32( NVM_ADDR_R, bcm_nvram_logical_to_physical_address( f_addr_u32 ) );
+
+ /*
+ * setup write data
+ */
+ bcm_write_reg32( NVM_WRITE_R, f_value_u32 );
+
+ /*
+ * get the command going
+ */
+ bcm_write_reg32( NVM_COM_R, BIT32( 8 ) | BIT32( 7 ) |
+ BIT32( 5 ) | BIT32( 4 ) | BIT32( 3 ) );
+
+ /*
+ * wait for command completion
+ */
+ i = 2000;
+ while( ( --i ) &&
+ ( ( bcm_read_reg32( NVM_COM_R ) & BIT32( 3 ) ) == 0 ) ) {
+ ms_delay( 1 );
+ }
+
+ /*
+ * release NVRam lock (CLR0)
+ */
+ if(lock)
+ bcm_nvram_unlock();
+
+ // error
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk("bcm57xx: writing to NVRAM failed\n");
+#endif
+ return -1;
+ }
+
+ // success
+ return 0;
+}
+
+/*
+ * PHY initialization
+ */
+static i32_t
+bcm_mii_phy_init( void )
+{
+ static const u32_t PHY_STAT_R = (u32_t) 0x01;
+ static const u32_t AUX_STAT_R = (u32_t) 0x19;
+ static const u32_t MODE_GMII = BIT32( 3 );
+ static const u32_t MODE_MII = BIT32( 2 );
+ static const u32_t MII_MSK = ( MODE_GMII | MODE_MII );
+ static const u16_t GIGA_ETH = ( BIT16( 10 ) | BIT16( 9 ) );
+ i32_t i;
+ u16_t v;
+
+ /*
+ * enable MDI communication
+ */
+ bcm_write_reg32( MDI_CTRL_R, (u32_t) 0x0 );
+
+ /*
+ * check link up
+ */
+ i = 2500;
+ do {
+ ms_delay( 1 );
+ // register needs to be read twice!
+ bcm_mii_read16( PHY_STAT_R, &v );
+ bcm_mii_read16( PHY_STAT_R, &v );
+ } while( ( --i ) &&
+ ( ( v & BIT16( 2 ) ) == 0 ) );
+
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: link is down\n" );
+#endif
+ return -1;
+ }
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: link is up\n" );
+#endif
+ if( !IS_COPPER_PHY ) {
+ return 0;
+ }
+
+ /*
+ * setup GMII or MII interface
+ */
+ i = bcm_read_reg32( ETH_MAC_MODE_R );
+ /*
+ * read status register twice, since the first
+ * read fails once between here and the moon...
+ */
+ bcm_mii_read16( AUX_STAT_R, &v );
+ bcm_mii_read16( AUX_STAT_R, &v );
+
+ if( ( v & GIGA_ETH ) == GIGA_ETH ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: running PHY in GMII mode (1000BaseT)\n" );
+#endif
+ // GMII device
+ if( ( i & MII_MSK ) != MODE_GMII ) {
+ i &= ~MODE_MII;
+ i |= MODE_GMII;
+ }
+
+ } else {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: running PHY in MII mode (10/100BaseT)\n" );
+#endif
+ // MII device
+ if( ( i & MII_MSK ) != MODE_MII ) {
+ i &= ~MODE_GMII;
+ i |= MODE_MII;
+ }
+
+ }
+
+ bcm_write_reg32( ETH_MAC_MODE_R, i );
+
+ return 0;
+}
+
+static i32_t
+bcm_tbi_phy_init( void )
+{
+ i32_t i;
+#if 0
+ /*
+ * set TBI mode full duplex
+ */
+ bcm_clrb_reg32( ETH_MAC_MODE_R, BIT32( 1 ) );
+ bcm_setb_reg32( ETH_MAC_MODE_R, BIT32( 2 ) | BIT32( 3 ) );
+
+ /*
+ * enable MDI communication
+ */
+ bcm_write_reg32( MDI_CTRL_R, (u32_t) 0x0 );
+
+ /* Disable link change interrupt. */
+ bcm_write_reg32( ETH_MAC_EVT_EN_R, 0 );
+
+ /*
+ * set link polarity
+ */
+ bcm_clrb_reg32( ETH_MAC_MODE_R, BIT32( 10 ) );
+
+ /*
+ * wait for sync/config changes
+ */
+ for( i = 0; i < 100; i++ ) {
+ bcm_write_reg32( ETH_MAC_STAT_R,
+ BIT32( 3 ) | BIT32( 4 ) );
+
+ us_delay( 20 );
+
+ if( ( bcm_read_reg32( ETH_MAC_STAT_R ) &
+ ( BIT32( 3 ) | BIT32( 4 ) ) ) == 0 ) {
+ break;
+ }
+
+ }
+#endif
+ /*
+ * wait for sync to come up
+ */
+ for( i = 0; i < 100; i++ ) {
+
+ if( ( bcm_read_reg32( ETH_MAC_STAT_R ) & BIT32( 0 ) ) != 0 ) {
+ break;
+ }
+
+ us_delay( 20 );
+ }
+
+ if( ( bcm_read_reg32( ETH_MAC_STAT_R ) & BIT32( 0 ) ) == 0) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: link is down\n" );
+#endif
+ return -1;
+ }
+#if 0
+ /*
+ * clear all attentions
+ */
+ bcm_write_reg32( ETH_MAC_STAT_R, (u32_t) ~0 );
+#endif
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: link is up\n" );
+#endif
+ return 0;
+}
+
+static i32_t
+bcm_phy_init( void )
+{
+ static const u16_t SRAM_HW_CFG = (u16_t) 0x0b58;
+ u32_t l_val_u32;
+ i32_t l_ret_i32 = 0;
+
+ /*
+ * get HW configuration from SRAM
+ */
+ l_val_u32 = bcm_read_mem32( SRAM_HW_CFG );
+ l_val_u32 &= ( BIT32( 5 ) | BIT32( 4 ) );
+
+ switch( l_val_u32 ) {
+ case 0x10: {
+ #ifdef BCM_DEBUG
+ printk( "bcm57xx: copper PHY detected\n" );
+ #endif
+
+ bcm_device_u64 |= BCM_DEV_COPPER;
+ l_ret_i32 = bcm_mii_phy_init();
+ } break;
+
+ case 0x20: {
+ #ifdef BCM_DEBUG
+ printk( "bcm57xx: fiber PHY detected\n" );
+ #endif
+
+ if( !IS_SERDES ) {
+ #ifdef BCM_DEBUG
+ printk( "bcm57xx: running PHY in gmii/mii mode\n" );
+ #endif
+ l_ret_i32 = bcm_mii_phy_init();
+ } else {
+ #ifdef BCM_DEBUG
+ printk( "bcm57xx: running PHY in tbi mode\n" );
+ #endif
+ l_ret_i32 = bcm_tbi_phy_init();
+ }
+
+ } break;
+
+ default: {
+ #ifdef BCM_DEBUG
+ printk( "bcm57xx: unknown PHY type detected, terminating\n" );
+ #endif
+ l_ret_i32 = -1;
+ }
+
+ }
+
+ return l_ret_i32;
+}
+
+/*
+ * ring initialization
+ */
+static void
+bcm_init_rxprod_ring( void )
+{
+ u32_t v;
+ u32_t i;
+
+ /*
+ * clear out the whole rx prod ring for sanity
+ */
+ memset( (void *) &bcm_rxprod_ring,
+ 0,
+ BCM_RXPROD_RING_SIZE * sizeof( bcm_rxbd_t ) );
+ mb();
+
+ /*
+ * assign buffers & indices to the ring members
+ */
+ for( i = 0; i < BCM_MAX_RX_BUF; i++ ) {
+ bcm_rxprod_ring[i].m_hostaddr_st.m_hi_u32 =
+ (u32_t) ( (u64_t) &bcm_rx_buffer_pu08[i] >> 32 );
+ bcm_rxprod_ring[i].m_hostaddr_st.m_lo_u32 =
+ (u32_t) ( (u64_t) &bcm_rx_buffer_pu08[i] &
+ (u64_t) 0xffffffff );
+ bcm_rxprod_ring[i].m_idxlen_u32 = ( i << 16 );
+ bcm_rxprod_ring[i].m_idxlen_u32 += BCM_BUF_SIZE;
+ }
+
+ /*
+ * clear rcb registers & disable rings
+ * NOTE: mini & jumbo rings are not supported,
+ * still rcb's are cleaned out for sanity
+ */
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_JUM ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_JUM ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_JUM ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_JUM ), 0 );
+
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_STD ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_STD ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_STD ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_STD ), 0 );
+
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_MIN ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_MIN ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_MIN ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_MIN ), 0 );
+
+ /*
+ * clear rx producer index of std producer ring
+ */
+ bcm_write_reg32( RXPROD_PROD_IND, 0 );
+
+ /*
+ * setup rx standard rcb using recommended NIC addr (hard coded)
+ */
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_STD ),
+ (u32_t) ( (u64_t) &bcm_rxprod_ring >> 32 ) );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_STD ),
+ (u32_t) ( (u64_t) &bcm_rxprod_ring & (u64_t) 0xffffffff ) );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_STD ),
+ (u32_t) BCM_NIC_RX_OFFS );
+
+ if( IS_5704 || IS_5703 ) {
+ // 5704: length field = max buffer len
+ v = (u32_t) BCM_BUF_SIZE << 16;
+ } else {
+ // 5714: length field = number of ring entries
+ v = (u32_t) BCM_RXPROD_RING_SIZE << 16;
+ }
+
+ v &= (u32_t) ~RCB_FLAG_RING_DISABLED;
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_STD ), v );
+}
+
+static void
+bcm_init_rxret_ring( void )
+{
+ u32_t i;
+ u16_t v;
+
+ /*
+ * clear out the whole rx ret ring for sanity
+ */
+ memset( (void *) &bcm_rxret_ring,
+ 0,
+ 2 * BCM_RXRET_RING_SIZE * sizeof( bcm_rxbd_t ) );
+ mb();
+
+ /*
+ * setup return ring size dependent on installed device
+ */
+ bcm_rxret_ring_sz = BCM_RXRET_RING_SIZE;
+ if( IS_5704 || IS_5703 ) {
+ bcm_rxret_ring_sz *= 2;
+ }
+
+ /*
+ * clear rcb memory & disable rings
+ * NOTE: 5714 only supports one return ring,
+ * still all possible rcb's are cleaned out for sanity
+ */
+ v = BCM_RXRET_RCB_OFFS;
+ for( i = 0; i < BCM_MAX_RXRET_RING; i++ ) {
+ bcm_write_mem32( BCM_RCB_LENFLAG_u16( v ), RCB_FLAG_RING_DISABLED );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( v ), 0 );
+
+ v += BCM_RCB_SIZE_u16;
+ }
+
+ /*
+ * clear rx consumer index of return ring
+ */
+ bcm_write_reg32( RXRET_CONS_IND, 0 );
+
+ /*
+ * setup rx ret rcb
+ * NOTE: NIC address not aplicable in return rings
+ */
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXRET_RCB_OFFS ),
+ (u32_t) ( (u64_t) &bcm_rxret_ring >> 32 ) );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXRET_RCB_OFFS ),
+ (u32_t) ( (u64_t) &bcm_rxret_ring &
+ (u64_t) 0xffffffff ) );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( BCM_RXRET_RCB_OFFS ), 0 );
+
+ i = bcm_rxret_ring_sz;
+ i <<= 16;
+ i &= (u32_t) ~RCB_FLAG_RING_DISABLED;
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXRET_RCB_OFFS ), i );
+}
+
+static void
+bcm_init_tx_ring( void )
+{
+ u32_t i;
+ u16_t v;
+
+ /*
+ * clear out the whole tx ring for sanity
+ */
+ memset( (void *) &bcm_tx_ring,
+ 0,
+ BCM_TX_RING_SIZE * sizeof( bcm_txbd_t ) );
+ mb();
+
+ /*
+ * assign buffers to the ring members & setup invariant flags
+ */
+ for( i = 0; i < BCM_MAX_TX_BUF; i++ ) {
+ bcm_tx_ring[i].m_hostaddr_st.m_hi_u32 =
+ (u32_t) ( (u64_t) &bcm_tx_buffer_pu08[i] >> 32 );
+ bcm_tx_ring[i].m_hostaddr_st.m_lo_u32 =
+ (u32_t) ( (u64_t) &bcm_tx_buffer_pu08[i] &
+ (u64_t) 0xffffffff );
+ // flags: indicate last packet & coal now
+ // -last packet is always true (only one send packet supported)
+ // -coal now needed to always get the consumed bd's (since
+ // only a few bd's are set up which permanently are recycled)
+ bcm_tx_ring[i].m_lenflags_u32 = ( BIT32( 2 ) | BIT32( 7 ) );
+ bcm_tx_ring[i].m_VLANtag_u32 = (u32_t) 0; // not used
+ }
+
+ /*
+ * clear rcb memory & disable rings
+ * NOTE: 5714 only supports one send ring,
+ * still all possible rcb's are cleaned out for sanity
+ */
+ v = BCM_TX_RCB_OFFS;
+ for( i = 0; i < BCM_MAX_TX_RING; i++ ) {
+ bcm_write_mem32( BCM_RCB_LENFLAG_u16( v ), RCB_FLAG_RING_DISABLED );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( v ), 0 );
+
+ v += BCM_RCB_SIZE_u16;
+ }
+
+ /*
+ * clear host/nic producer indices
+ */
+ bcm_write_reg32( TX_NIC_PROD_IND, 0 );
+ bcm_write_reg32( TX_PROD_IND, 0 );
+
+ /*
+ * setup tx rcb using recommended NIC addr (hard coded)
+ */
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( BCM_TX_RCB_OFFS ),
+ (u32_t) ( (u64_t) &bcm_tx_ring >> 32 ) );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( BCM_TX_RCB_OFFS ),
+ (u32_t) ( (u64_t) &bcm_tx_ring &
+ (u64_t) 0xffffffff ) );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( BCM_TX_RCB_OFFS ),
+ (u32_t) BCM_NIC_TX_OFFS );
+
+ if( IS_5704 || IS_5703 ) {
+ // 5704: length field = max buffer len
+ i = (u32_t) BCM_BUF_SIZE << 16;
+ } else {
+ // 5714: length field = number of ring entries
+ i = (u32_t) BCM_TX_RING_SIZE << 16;
+ }
+
+ i &= ( u32_t ) ~RCB_FLAG_RING_DISABLED;
+ bcm_write_mem32( BCM_RCB_LENFLAG_u16( BCM_TX_RCB_OFFS ), i );
+
+ /*
+ * remember the next bd index to be used
+ * & number of available buffers
+ */
+ bcm_tx_stop_u32 = BCM_MAX_TX_BUF;
+ bcm_tx_bufavail_u32 = BCM_MAX_TX_BUF;
+}
+
+static i32_t
+bcm_mac_init( u08_t *f_mac_pu08 )
+{
+ static const u16_t MEM_MAC_LO = (u16_t) 0x0c18;
+ static const u16_t MEM_MAC_HI = (u16_t) 0x0c14;
+
+ u32_t NVR_MAC_LO = (u16_t) 0x80;
+ u32_t NVR_MAC_HI = (u16_t) 0x7c;
+
+ bcm_addr64_t l_mac_st;
+ u32_t i;
+ u32_t v;
+
+ /*
+ * Use MAC address from device tree if possible
+ */
+ for( i = 0, v = 0; i < 6; i++ ) {
+ v += (u32_t) f_mac_pu08[i];
+ }
+
+ if( v != 0 ) {
+ l_mac_st.m_hi_u32 = ( ( (u32_t) f_mac_pu08[0]) << 8 );
+ l_mac_st.m_hi_u32 |= ( ( (u32_t) f_mac_pu08[1]) << 0 );
+ l_mac_st.m_lo_u32 = ( ( (u32_t) f_mac_pu08[2]) << 24 );
+ l_mac_st.m_lo_u32 |= ( ( (u32_t) f_mac_pu08[3]) << 16 );
+ l_mac_st.m_lo_u32 |= ( ( (u32_t) f_mac_pu08[4]) << 8 );
+ l_mac_st.m_lo_u32 |= ( ( (u32_t) f_mac_pu08[5]) << 0 );
+ } else {
+ /*
+ * try to read MAC address from MAC mailbox
+ */
+ l_mac_st.m_hi_u32 = bcm_read_mem32( MEM_MAC_HI );
+
+ if( ( l_mac_st.m_hi_u32 >> 16 ) == (u32_t) 0x484b ) {
+ l_mac_st.m_hi_u32 &= (u32_t) 0xffff;
+ l_mac_st.m_lo_u32 = bcm_read_mem32( MEM_MAC_LO );
+ } else {
+ i32_t l_err_i32;
+
+ /*
+ * otherwise retrieve MAC address from NVRam
+ */
+ if( ( bcm_read_reg32( MAC_FUNC_R ) & BIT32( 2 ) ) != 0 ) {
+ // secondary MAC is in use, address in NVRAM changes
+ NVR_MAC_LO += 0x50;
+ NVR_MAC_HI += 0x50;
+ }
+
+ l_err_i32 = bcm_nvram_read( NVR_MAC_LO, &l_mac_st.m_lo_u32, 1 );
+ l_err_i32 += bcm_nvram_read( NVR_MAC_HI, &l_mac_st.m_hi_u32, 1 );
+
+ // return on read error
+ if( l_err_i32 < 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: failed to retrieve MAC address\n" );
+#endif
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * write the mac addr into the NIC's register area
+ */
+ bcm_write_reg32( MAC_ADDR_OFFS_HI(0), l_mac_st.m_hi_u32 );
+ bcm_write_reg32( MAC_ADDR_OFFS_LO(0), l_mac_st.m_lo_u32 );
+ for( i = 1; i < BCM_NUM_MAC_ADDR; i++ ) {
+ bcm_write_reg32( MAC_ADDR_OFFS_HI(i), 0 );
+ bcm_write_reg32( MAC_ADDR_OFFS_LO(i), 0 );
+ }
+
+ /*
+ * WY 26.01.07
+ * not needed anymore, s.a.
+ if( IS_5704 != 0 ) {
+
+ v = MAC5704_ADDR_OFFS;
+ for( i = 0; i < BCM_NUM_MAC5704_ADDR; i++ ) {
+ bcm_write_reg32( v, l_mac_st.m_hi_u32 );
+ v += sizeof( u32_t );
+ bcm_write_reg32( v, l_mac_st.m_lo_u32 );
+ v += sizeof( u32_t );
+ }
+
+ }
+ */
+
+ /*
+ * return MAC address as string
+ */
+ f_mac_pu08[0] = (u08_t) ( ( l_mac_st.m_hi_u32 >> 8 ) & (u32_t) 0xff );
+ f_mac_pu08[1] = (u08_t) ( ( l_mac_st.m_hi_u32 ) & (u32_t) 0xff );
+ f_mac_pu08[2] = (u08_t) ( ( l_mac_st.m_lo_u32 >> 24 ) & (u32_t) 0xff );
+ f_mac_pu08[3] = (u08_t) ( ( l_mac_st.m_lo_u32 >> 16 ) & (u32_t) 0xff );
+ f_mac_pu08[4] = (u08_t) ( ( l_mac_st.m_lo_u32 >> 8 ) & (u32_t) 0xff );
+ f_mac_pu08[5] = (u08_t) ( ( l_mac_st.m_lo_u32 ) & (u32_t) 0xff );
+
+#ifdef BCM_DEBUG
+ do {
+ i32_t i;
+ printk( "bcm57xx: retrieved MAC address " );
+
+ for( i = 0; i < 6; i++ ) {
+ printk( "%02X", f_mac_pu08[i] );
+
+ if( i != 5 ) {
+ printk( ":" );
+ }
+
+ }
+
+ printk( "\n" );
+ } while( 0 );
+#endif
+
+ return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * ASF Firmware
+ ******************************************************************************
+ */
+
+
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_ASF_REGS
+static void
+bcm_asf_check_register( void )
+{
+ u32_t i;
+
+ i = bcm_read_reg32( ASF_CTRL_R );
+ printk( "bcm57xx: ASF control : %x\n", i );
+
+ i = bcm_read_reg32( ASF_WATCHDOG_TIMER_R );
+ printk( "bcm57xx: ASF Watchdog Timer : %x\n", i );
+
+ i = bcm_read_reg32( ASF_HEARTBEAT_TIMER_R );
+ printk( "bcm57xx: ASF Heartbeat Timer : %x\n", i );
+
+ i = bcm_read_reg32( ASF_POLL_TIMER_R );
+ printk( "bcm57xx: ASF Poll Timer : %x\n", i );
+
+ i = bcm_read_reg32( POLL_LEGACY_TIMER_R );
+ printk( "bcm57xx: Poll Legacy Timer : %x\n", i );
+
+ i = bcm_read_reg32( RETRANSMISSION_TIMER_R );
+ printk( "bcm57xx: Retransmission Timer : %x\n", i );
+
+ i = bcm_read_reg32( TIME_STAMP_COUNTER_R );
+ printk( "bcm57xx: Time Stamp Counter : %x\n", i );
+
+ i = bcm_read_reg32( RX_CPU_MODE_R );
+ printk( "bcm57xx: RX RISC Mode : %x\n", i );
+
+ i = bcm_read_reg32( RX_CPU_STATE_R );
+ printk( "bcm57xx: RX RISC State : %x\n", i );
+
+ i = bcm_read_reg32( RX_CPU_PC_R );
+ printk( "bcm57xx: RX RISC Prg. Counter : %x\n", i );
+}
+#endif
+#endif
+
+static int
+bcm_fw_halt( void )
+{
+ int i;
+
+ bcm_write_mem32( BCM_FW_MBX_CMD, BCM_NICDRV_PAUSE_FW );
+ bcm_setb_reg32( RX_CPU_EVENT_R, BIT32( 14 ) );
+
+ /* Wait for RX cpu to ACK the event. */
+ for (i = 0; i < 100; i++) {
+ if(bcm_read_reg32( RX_CPU_EVENT_R ) & BIT32( 14 ))
+ break;
+ ms_delay(1);
+ }
+ if( i>= 100)
+ return -1;
+ return 0;
+}
+
+
+#ifdef BCM_SW_AUTONEG
+static void
+bcm_sw_autoneg( pci_config_t *pcicfg ) {
+ u32_t i, j, k;
+ u32_t SerDesCfg;
+ u32_t SgDigControl;
+ u32_t SgDigStatus;
+ u32_t ExpectedSgDigControl;
+ int AutoNegJustInitiated = 0;
+
+ // step 1: init TX 1000BX Autoneg. Register to zero
+ bcm_write_reg32(TX_1000BX_AUTONEG_R, 0);
+
+ // step 2&3: set TBI mode
+ bcm_setb_reg32( ETH_MAC_MODE_R, BIT32( 2 ) | BIT32( 3 ) );
+ us_delay(10);
+
+ // step 4: enable link attention
+ bcm_setb_reg32( ETH_MAC_EVT_EN_R, BIT32( 12 ) );
+
+ // step 5: preserve voltage regulator bits
+ SerDesCfg = bcm_read_reg32(SERDES_CTRL_R) & ( BIT32( 20 ) | BIT32( 21 )
+ | BIT32( 22 ) | BIT32( 23 ) );
+
+ // step 6: preserve voltage regulator bits
+ SgDigControl = bcm_read_reg32(HW_AUTONEG_CTRL_R);
+
+ // step 7: if device is NOT set-up for auto negotiation, then go to step 26
+ // goto bcm_setup_phy_step26;
+
+ // We want to use auto negotiation
+
+ // step 8: we don't want to use flow control
+ ExpectedSgDigControl = 0x81388400; // no flow control
+
+ // step 9: compare SgDigControl with 0x81388400
+ if(SgDigControl == ExpectedSgDigControl) {
+ goto bcm_setup_phy_step17;
+ }
+#ifdef BCM_DEBUG
+ printk("bcm57xx: SgDigControl = %08X\n", SgDigControl);
+#endif
+ // step 10
+ bcm_write_reg32(SERDES_CTRL_R, SerDesCfg | 0xC011880);
+
+ // step 11: restart auto negotiation
+ bcm_write_reg32(HW_AUTONEG_CTRL_R, ExpectedSgDigControl | BIT32( 30 ) );
+
+ // step 12: read back HW_AUTONEG_CTRL_R
+ bcm_read_reg32(HW_AUTONEG_CTRL_R);
+
+ // step 13
+ us_delay( 5 );
+
+ // step 14,15,16: same as step 11, but don't restart auto neg.
+ bcm_write_reg32(HW_AUTONEG_CTRL_R, ExpectedSgDigControl);
+ AutoNegJustInitiated = 1;
+ goto bcm_setup_phy_step30;
+
+ // step 17:
+ bcm_setup_phy_step17:
+ if( ( bcm_read_reg32(ETH_MAC_STAT_R) & ( BIT32( 1 ) | BIT32( 0 ) ) ) == 0 ) {
+ goto bcm_setup_phy_step30;
+ }
+
+ // step 18: Get HW Autoneg. Status
+ SgDigStatus = bcm_read_reg32(HW_AUTONEG_STAT_R);
+
+ // step 19:
+ if( ( SgDigStatus & BIT32(1) )
+ && ( bcm_read_reg32(ETH_MAC_STAT_R) & BIT32(0) ) ) {
+ // resolve the current flow control?
+ AutoNegJustInitiated = 0;
+ goto bcm_setup_phy_step30;
+ }
+
+ // step 20
+ if( SgDigStatus & BIT32(1) ) {
+ goto bcm_setup_phy_step30;
+ }
+ if( AutoNegJustInitiated != 0) {
+ AutoNegJustInitiated = 0;
+ goto bcm_setup_phy_step29;
+ }
+
+ // step 21, 22, 23, 24: fallback to 1000Mbps-FullDuplex forced mode
+ if( ( bcm_read_reg32( MAC_FUNC_R ) & BIT32( 2 ) ) == 0 ) {
+ // port 0
+ bcm_write_reg32( SERDES_CTRL_R, 0xC010880 );
+ }
+ else { // port 1
+ bcm_write_reg32( SERDES_CTRL_R, 0x4010880 );
+ }
+ // set to 1000Mbps-FullDuplex
+ bcm_write_reg32(HW_AUTONEG_CTRL_R, 0x1388400);
+ // read back
+ bcm_read_reg32(HW_AUTONEG_CTRL_R);
+ us_delay( 40 );
+
+ // step 25: a little bit reduces...
+ goto bcm_setup_phy_step30;
+
+ // step 26: check if auto negotiation bit is NOT set
+// bcm_setup_phy_step26:
+ if( ( SgDigControl & BIT32(31) )== 0 ) {
+ printk("No autoneg.\n");
+ goto bcm_setup_phy_step29;
+ }
+
+ // step 27:
+ if( ( bcm_read_reg32( MAC_FUNC_R ) & BIT32( 2 ) ) == 0 ) {
+ // port 0
+ bcm_write_reg32( SERDES_CTRL_R, 0xC010880 );
+ }
+ else { // port 1
+ bcm_write_reg32( SERDES_CTRL_R, 0x4010880 );
+ }
+
+ // step 28: disable auto neg. and force 1000FD mode
+ bcm_write_reg32(HW_AUTONEG_CTRL_R, 0x1388400);
+
+ // step 29-31: omitted for 5704S
+ bcm_setup_phy_step29:
+ bcm_setup_phy_step30:
+
+ // step 32: clear link attentions
+ i = bcm_read_reg32( ETH_MAC_STAT_R ) | BIT32( 3 ) | BIT32( 4 );
+ k = 100;
+ do {
+ bcm_write_reg32( ETH_MAC_STAT_R, i );
+ j = bcm_read_reg32( ETH_MAC_STAT_R );
+ if( ( j & BIT32( 3 ) ) != 0 )
+ i = i & ~(BIT32( 3 ));
+ if( ( j & BIT32( 4 ) ) != 0 )
+ i = i & ~(BIT32( 4 ));
+ --k;
+ } while( i & k);
+
+ // step 33
+ if( ( bcm_read_reg32( ETH_MAC_STAT_R ) & BIT32( 0 ) ) == 0 ) {
+ goto bcm_setup_phy_step35;
+ }
+
+ // step 34
+ i = bcm_read_reg32( ETH_MAC_MODE_R );
+ i|= BIT32( 17 );
+ bcm_write_reg32( ETH_MAC_MODE_R, i );
+
+ us_delay( 1 );
+
+ i = bcm_read_reg32( ETH_MAC_STAT_R );
+ i&= ~BIT32( 17 );
+ bcm_write_reg32( ETH_MAC_STAT_R, i );
+
+ // step 35 & 36: done
+ bcm_setup_phy_step35:
+#ifdef BCM_DEBUG
+ printk("bcm57xx: SetupPhy\n");
+#endif
+ return;
+}
+#endif
+
+static int
+bcm_handle_events( pci_config_t *pcicfg ) {
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_ASF_REGS
+ // ASF REGISTER CHECK
+ // ------------------
+ // check if watchdog timer expired
+ if( bcm_read_reg32( ASF_WATCHDOG_TIMER_R ) == 0 ) {
+ // Show ASF registers
+ bcm_asf_check_register();
+
+ // rearm watchdog timer
+ bcm_write_reg32( ASF_WATCHDOG_TIMER_R, 5 );
+ }
+#endif
+#endif
+
+#ifdef BCM_SW_AUTONEG
+ // AUTO NEGOTIATION
+ // ----------------
+
+ // Check event for Auto Negotiation
+ if( ( bcm_read_reg32( ETH_MAC_STAT_R ) &
+ ( BIT32( 12 ) | BIT32( 3 ) | BIT32( 0 ) ) ) != 0 ) {
+ // link timer procedure
+ bcm_sw_autoneg( pcicfg );
+ }
+#endif
+
+ // ASF FW HEARTBEAT
+ // ----------------
+
+ // check if heartsbeat timer expired
+ if( bcm_read_reg32( ASF_HEARTBEAT_TIMER_R ) <= 2) {
+ int i;
+
+ // Send heartbeat event
+ bcm_write_mem32( BCM_FW_MBX_CMD, BCM_NICDRV_ALIVE );
+ bcm_write_mem32( BCM_FW_MBX_LEN, 4 );
+ bcm_write_mem32( BCM_FW_MBX_DATA, 5 );
+ bcm_setb_reg32( RX_CPU_EVENT_R, BIT32( 14 ) );
+
+ // Wait for RX cpu to ACK the event.
+ for (i = 100; i > 0; i--) {
+ if(bcm_read_reg32( RX_CPU_EVENT_R ) & BIT32( 14 ))
+ break;
+ ms_delay(1);
+ }
+ if( i == 0) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: RX cpu did not acknowledge heartbeat event\n" );
+#endif
+ return -1;
+ }
+
+ // rearm heartbeat timer
+ bcm_write_reg32( ASF_HEARTBEAT_TIMER_R, 5 );
+ }
+ return 0;
+}
+
+/*
+ * interface
+ ******************************************************************************
+ */
+
+/*
+ * bcm_receive
+ */
+static int
+bcm_receive( pci_config_t *pcicfg, char *f_buffer_pc, int f_len_i )
+{
+ u32_t l_rxret_prod_u32 = bcm_read_reg32( RXRET_PROD_IND );
+ u32_t l_rxret_cons_u32 = bcm_read_reg32( RXRET_CONS_IND );
+ u32_t l_rxprod_prod_u32 = bcm_read_reg32( RXPROD_PROD_IND );
+ int l_ret_i;
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_RCV_DATA
+ int i, j;
+#endif
+#endif
+
+ /*
+ * NOTE: dummy read to ensure data has already been DMA'd is
+ * done by the indice reads
+ */
+
+ bcm_handle_events( pcicfg );
+
+ /*
+ * if producer index == consumer index then nothing was received
+ */
+ if( l_rxret_prod_u32 == l_rxret_cons_u32 ) {
+ return 0;
+ }
+
+ /*
+ * discard erroneous packets
+ */
+ if( ( bcm_rxret_ring[l_rxret_cons_u32].m_typeflags_u32 & BIT32( 10 ) ) != 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: erroneous frame received\n" );
+ printk( " : frame discarded\n" );
+#endif
+ l_ret_i = 0;
+ } else {
+ /*
+ * get packet length, throw away checksum (last 4 bytes)
+ */
+ l_ret_i = (int) ( bcm_rxret_ring[l_rxret_cons_u32].m_idxlen_u32 &
+ (u32_t) 0xffff ) - (int) 4;
+
+ /*
+ * discard oversized packets
+ */
+ if( l_ret_i > f_len_i ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: receive packet length error:\n" );
+ printk( " : incoming 0x%X bytes, available buffer 0x%X bytes\n", l_ret_i, f_len_i );
+ printk( " : frame discarded\n" );
+#endif
+ l_ret_i = 0;
+ }
+
+ }
+
+ /*
+ * copy & update data & indices
+ */
+ if( l_ret_i != 0 ) {
+ u64_t l_cpyaddr_u64;
+
+ l_cpyaddr_u64 =
+ ( (u64_t) bcm_rxret_ring[l_rxret_cons_u32].m_hostaddr_st.m_hi_u32 << 32 );
+ l_cpyaddr_u64 +=
+ ( (u64_t) bcm_rxret_ring[l_rxret_cons_u32].m_hostaddr_st.m_lo_u32 );
+
+// FIXME:
+ if(l_cpyaddr_u64 == 0) {
+#ifdef BCM_DEBUG
+ printk("bcm57xx: NULL address\n");
+#endif
+ return 0;
+ }
+//
+ memcpy( (void *) f_buffer_pc,
+ (void *) l_cpyaddr_u64,
+ (size_t) l_ret_i );
+
+ }
+
+ /*
+ * replenish bd to producer ring
+ */
+ bcm_rxprod_ring[l_rxprod_prod_u32] =
+ bcm_rxret_ring[l_rxret_cons_u32];
+ bcm_rxprod_ring[l_rxprod_prod_u32].m_idxlen_u32 =
+ ( l_rxprod_prod_u32 << 16 );
+ bcm_rxprod_ring[l_rxprod_prod_u32].m_idxlen_u32 +=
+ (u32_t) BCM_BUF_SIZE;
+
+ /*
+ * update producer ring's producer index
+ */
+ l_rxprod_prod_u32 = ( l_rxprod_prod_u32 + 1 ) & ( BCM_RXPROD_RING_SIZE - 1 );
+
+ /*
+ * move to the next bd in return ring
+ */
+ l_rxret_cons_u32 = ( l_rxret_cons_u32 + 1 ) & ( bcm_rxret_ring_sz - 1 );
+
+ /*
+ * synchronize before new indices are send to NIC
+ */
+ mb();
+
+ /*
+ * write back new indices
+ */
+ bcm_write_reg32( RXRET_CONS_IND, l_rxret_cons_u32 );
+ bcm_write_reg32( RXPROD_PROD_IND, l_rxprod_prod_u32 );
+
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_RCV
+ if( l_ret_i != 0 ) {
+ printk( "bcm57xx: received bytes: %d\n", l_ret_i );
+ }
+#ifdef BCM_SHOW_RCV_DATA
+ for( i = 0, j = 0; i < l_ret_i; i++ ) {
+ printk( "%02X ", ( u32_t ) f_buffer_pc[i] );
+
+ if( ( ++j % 0x18 ) == 0 ) {
+ printk( "\n" );
+ }
+ }
+
+ if( ( i % 0x18 ) != 0 ) {
+ printk( "\n" );
+ }
+#endif
+#endif
+#endif
+
+ /*
+ * return packet length
+ */
+ return l_ret_i;
+}
+
+static int
+bcm_xmit( pci_config_t *pcicfg, char *f_buffer_pc, int f_len_i )
+{
+ u32_t l_tx_cons_u32 = bcm_read_reg32( TX_CONS_IND );
+ u32_t l_tx_prod_u32 = bcm_read_reg32( TX_PROD_IND );
+ u64_t l_cpyaddr_u64;
+
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_XMIT_DATA
+ int i, j;
+#endif
+#ifdef BCM_SHOW_IDX
+ printk( "\n" );
+ printk( "bcm57xx: TX_PROD_IND : 0x%03X\n", l_tx_prod_u32 );
+ printk( "bcm57xx: TX_CONS_IND : 0x%03X\n", l_tx_cons_u32 );
+ printk( "bcm57xx: RXPROD_PROD_IND: 0x%03X\n", bcm_read_reg32( RXPROD_PROD_IND ) );
+ printk( "bcm57xx: RXPROD_CONS_IND: 0x%03X\n", bcm_read_reg32( RXPROD_CONS_IND ) );
+ printk( "bcm57xx: RXRET_PROD_IND : 0x%03X\n", bcm_read_reg32( RXRET_PROD_IND ) );
+ printk( "bcm57xx: RXRET_CONS_IND : 0x%03X\n", bcm_read_reg32( RXRET_CONS_IND ) );
+ printk( "bcm57xx: available txb : 0x%03X\n", bcm_tx_bufavail_u32 );
+#endif
+#ifdef BCM_SHOW_STATS
+ printk( "bcm57xx: bcm_status.m_st_word_u32: %08X\n", bcm_status.m_st_word_u32 );
+ printk( "bcm57xx: bcm_status.m_st_tag_u32 : %08X\n", bcm_status.m_st_tag_u32 );
+ printk( "bcm57xx: bcm_status.m_rxprod_cons_u16: %04X\n", ( u32_t ) bcm_status.m_rxprod_cons_u16 );
+ printk( "bcm57xx: bcm_status.m_unused_u16: %04X\n", ( u32_t ) bcm_status.m_unused_u16 );
+ printk( "bcm57xx: bcm_status.m_unused_u32: %08X\n", bcm_status.m_unused_u32 );
+ printk( "bcm57xx: bcm_status.m_tx_cons_u16: %04X\n", ( u32_t ) bcm_status.m_tx_cons_u16 );
+ printk( "bcm57xx: bcm_status.m_rxret_prod_u16: %04X\n", ( u32_t ) bcm_status.m_rxret_prod_u16 );
+#endif
+#endif
+
+ bcm_handle_events( pcicfg );
+
+ /*
+ * make all consumed bd's available in the ring again
+ * this way only a few buffers are needed instead of
+ * having 512 buffers allocated
+ */
+ while( bcm_tx_start_u32 != l_tx_cons_u32 ) {
+ bcm_tx_ring[bcm_tx_stop_u32] = bcm_tx_ring[bcm_tx_start_u32];
+ bcm_tx_stop_u32 = ( bcm_tx_stop_u32 + 1 ) & ( BCM_TX_RING_SIZE - 1 );
+ bcm_tx_start_u32 = ( bcm_tx_start_u32 + 1 ) & ( BCM_TX_RING_SIZE - 1 );
+ bcm_tx_bufavail_u32++;
+ }
+
+ /*
+ * check for tx buffer availability
+ */
+ if( bcm_tx_bufavail_u32 == 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: no more transmit buffers available\n" );
+#endif
+ return 0;
+ }
+
+ /*
+ * setup next available bd in tx ring
+ */
+ bcm_tx_ring[l_tx_prod_u32].m_lenflags_u32 = ( BIT32( 2 ) | BIT32( 7 ) /*| BIT32( 6 )*/ );
+ bcm_tx_ring[l_tx_prod_u32].m_lenflags_u32 += ( (u32_t) f_len_i << 16 );
+// bcm_tx_ring[l_tx_prod_u32].m_VLANtag_u32 = BCM_VLAN_TAG;
+
+ l_cpyaddr_u64 = ( (u64_t) bcm_tx_ring[l_tx_prod_u32].m_hostaddr_st.m_hi_u32 << 32 );
+ l_cpyaddr_u64 += ( (u64_t) bcm_tx_ring[l_tx_prod_u32].m_hostaddr_st.m_lo_u32 );
+
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_XMIT_STATS
+ printk("bcm57xx: xmit: l_cpyaddr_u64: 0x%lx\n", l_cpyaddr_u64 );
+ printk(" f_buffer_pc : 0x%lx\n", f_buffer_pc );
+ printk(" f_len_i : %d\n", f_len_i );
+#endif
+#endif
+ memcpy( (void *) l_cpyaddr_u64, (void *) f_buffer_pc, (size_t) f_len_i );
+
+ /*
+ * update tx producer index & available buffers
+ */
+ l_tx_prod_u32 = ( l_tx_prod_u32 + 1 ) & ( BCM_TX_RING_SIZE - 1 );
+ bcm_tx_bufavail_u32--;
+
+ /*
+ * synchronize before new index is send to NIC
+ */
+ mb();
+
+ bcm_write_reg32( TX_PROD_IND, l_tx_prod_u32 );
+
+#ifdef BCM_DEBUG
+#ifdef BCM_SHOW_XMIT
+ printk( "bcm57xx: sent bytes: %d\n", f_len_i );
+#ifdef BCM_SHOW_XMIT_DATA
+ for( i = 0, j = 0; i < f_len_i; i++ ) {
+ printk( "%02X ", ( u32_t ) f_buffer_pc[i] );
+
+ if( ( ++j % 0x18 ) == 0 ) {
+ printk( "\n" );
+ }
+
+ }
+ if( ( i % 0x18 ) != 0 ) {
+ printk( "\n" );
+ }
+#endif
+#endif
+
+#ifdef BCM_SHOW_STATS
+ // coalesce status block now
+ bcm_setb_reg32( HOST_COAL_MODE_R, BIT32( 3 ) | BIT32( 1 ) );
+#endif
+
+#endif
+ return f_len_i;
+}
+
+int
+check_driver( pci_config_t *pcicfg )
+{
+ u64_t i;
+
+ /*
+ * checks whether the driver is handling this device
+ * by verifying vendor & device id
+ * vendor id 0x14e4 == Broadcom
+ */
+ if( pcicfg->vendor_id != 0x14e4 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: netdevice not supported, illegal vendor id\n" );
+#endif
+ return -1;
+ }
+
+ for( i = 0; bcm_dev[i].m_dev_u32 != 0; i++ ) {
+ if( bcm_dev[i].m_dev_u32 ==
+ (u32_t) pcicfg->device_id ) {
+ // success
+ bcm_device_u64 = bcm_dev[i].m_devmsk_u64;
+ return 0;
+ }
+ }
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: netdevice not supported, illegal device ID\n" );
+#endif
+
+ return -1;
+}
+
+static void
+bcm_wol_activate( pci_config_t *pcicfg )
+{
+#ifdef BCM_DEBUG
+ u16_t reg_pwr_cap;
+#endif
+ u16_t reg_pwr_crtl;
+ u32_t wol_mode;
+
+ wol_mode = bcm_read_reg32( WOL_MODE_R );
+ bcm_write_reg32( WOL_MODE_R, wol_mode | BIT32(0) );
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: WOL activating..." );
+#endif
+
+// bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_WOL );
+// ms_delay( 100 );
+
+#ifdef BCM_DEBUG
+ reg_pwr_cap = snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ 0x4a );
+ printk( "bcm57xx: PM Capability Register: %04X\n", reg_pwr_cap );
+#endif
+ /* get curretn power control register */
+ reg_pwr_crtl = snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ 0x4c );
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: PM Control/Status Register: %04X\n", reg_pwr_crtl );
+#endif
+
+ /* switch to power state D0 */
+ reg_pwr_crtl |= 0x8000;
+ reg_pwr_crtl &= ~(0x0003);
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ 0x4c,
+ reg_pwr_crtl );
+ ms_delay(10);
+
+/*
+ bcm_write_mem32( BCM_NICDRV_WOL_MBX, BCM_WOL_MAGIC_NUMBER |
+ NIC_WOLDRV_STATE_SHUTDOWN |
+ NIC_WOLDRV_WOL |
+ NIC_WOLDRV_SET_MAGIC_PKT );
+*/
+
+ /* switch to power state D3hot */
+/*
+ reg_pwr_crtl |= 0x0103;
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ 0x4c,
+ reg_pwr_crtl );
+ ms_delay(10);
+*/
+
+#ifdef BCM_DEBUG
+ reg_pwr_crtl = snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ 0x4c );
+
+ printk( "bcm57xx: PM Control/Status Register: %04X\n", reg_pwr_crtl );
+#endif
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: WOL activated" );
+#endif
+}
+
+static int
+bcm_init( pci_config_t *pcicfg, char *mac_addr )
+{
+ static const u32_t lc_Maxwait_u32 = (u32_t) 1000;
+ u32_t l_baseaddrL_u32;
+ u32_t l_baseaddrH_u32;
+ u32_t i;
+
+ /*
+ * initialize static variables
+ */
+ bcm_device_u64 = 0;
+ bcm_rxret_ring_sz = 0;
+ bcm_baseaddr_u64 = 0;
+ bcm_memaddr_u64 = 0;
+
+ bcm_tx_start_u32 = 0;
+ bcm_tx_stop_u32 = 0;
+ bcm_tx_bufavail_u32 = 0;
+
+ /*
+ * check driver
+ */
+ if( check_driver( pcicfg ) < 0 ) {
+ return -1;
+ }
+
+ bcm_pcicfg_puid = pcicfg->puid;
+ bcm_pcicfg_bus = pcicfg->bus;
+ bcm_pcicfg_devfn = pcicfg->devfn;
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: detected device " );
+ if( IS_5703 ) {
+ printk( "5703S\n" );
+ } else if( IS_5704 ) {
+ printk( "5704" );
+
+ if( IS_SERDES ) {
+ printk( "S\n" );
+ } else {
+ printk( "C\n" );
+ }
+
+ } else if( IS_5714 ) {
+ printk( "5714\n" );
+ }
+#endif
+ /*
+ * setup register & memory base addresses of NIC
+ */
+ l_baseaddrL_u32 = ( (u32_t) ~0xf &
+ (u32_t) snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_BAR1_R ) );
+
+ l_baseaddrH_u32 =
+ (u32_t) snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_BAR2_R );
+ bcm_baseaddr_u64 = (u64_t) l_baseaddrH_u32;
+ bcm_baseaddr_u64 <<= 32;
+ bcm_baseaddr_u64 += (u64_t) l_baseaddrL_u32;
+ snk_kernel_interface->translate_addr(((void *)&(bcm_baseaddr_u64)));
+ bcm_memaddr_u64 = bcm_baseaddr_u64 + BCM_MEMORY_OFFS;
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: PCI-Puid = 0x%X\n", pcicfg->puid );
+ printk( "bcm57xx: PCI-Bus = 0x%X\n", pcicfg->bus );
+ printk( "bcm57xx: PCI-DevFn = 0x%X\n", pcicfg->devfn );
+ printk( "bcm57xx: device's register base high address = 0x%08X\n", l_baseaddrH_u32 );
+ printk( "bcm57xx: device's register base low address = 0x%08X\n", l_baseaddrL_u32 );
+ printk( "bcm57xx: device's register address = 0x%lx\n", bcm_baseaddr_u64 );
+#endif
+
+ /*
+ * 57xx hardware initialization
+ * BCM57xx Programmer's Guide: Section 8, "Initialization"
+ * steps 1 through 101
+ */
+
+ // step 1: enable bus master & memory space in command reg
+ i = ( BIT32( 10 ) | BIT32( 2 ) | BIT32( 1 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_COM_R,
+ ( int ) i );
+ // step 2: disable & mask interrupts & enable pci byte/word swapping & enable indirect addressing mode
+ i = ( BIT32( 8 ) | BIT32( 7 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+
+ /*
+ * from now on access may be made through the local
+ * read/write functions
+ */
+
+ // step 3: Save ahche line size register
+ // omitted, because register is not used for 5704
+
+ // step 4: acquire the nvram lock
+ if( bcm_nvram_lock() != 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: locking NVRAM failed\n" );
+#endif
+ return -1;
+ }
+
+ // step 5: prepare the chip for writing TG3_MAGIC_NUMBER
+ bcm_setb_reg32( MEMARB_MODE_R, BIT32( 1 ) );
+ i = ( BIT32( 8 ) | BIT32( 7 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+ bcm_write_reg32( MODE_CTRL_R, BIT32( 23 ) | BIT32( 20 ) |
+ BIT32( 17 ) | BIT32( 16 ) |
+ BIT32( 14 ) | BIT32( 13 ) |
+ BIT32( 5 ) | BIT32( 4 ) |
+ BIT32( 2 ) | BIT32( 1 ) );
+
+ // step 6: write TG3_MAGIC_NUMBER
+ bcm_write_mem32( BCM_FW_MBX, BCM_MAGIC_NUMBER );
+
+ // step 7: reset core clocks
+
+ if( IS_5714 ) {
+ bcm_setb_reg32( MISC_CFG_R, BIT32( 26 ) | BIT32( 0 ) );
+ } else {
+ bcm_setb_reg32( MISC_CFG_R, BIT32( 0 ) );
+ }
+ // step 8
+ ms_delay( 20 );
+
+ // step 9: disable & mask interrupts & enable indirect addressing mode &
+ // enable pci byte/word swapping initialize the misc host control register
+ i = ( BIT32( 8 ) | BIT32( 7 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+
+ // step 10: set but master et cetera
+ i = ( BIT32( 10 ) | BIT32( 2 ) | BIT32( 1 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_COM_R,
+ ( int ) i );
+
+ // step 11: disable PCI-X relaxed ordering
+ bcm_clrb_reg16( PCI_X_COM_R, BIT16( 1 ) );
+
+ // step 12: enable the MAC memory arbiter
+ bcm_setb_reg32( MEMARB_MODE_R, BIT32( 1 ) );
+
+ // step 13: omitted, only for BCM5700
+ // step 14: s. step 10
+ i = ( BIT32( 8 ) | BIT32( 7 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+ // step 15: set byte swapping (incl. step 27/28/29/30)
+ // included prohibition of tx/rx interrupts
+ bcm_write_reg32( MODE_CTRL_R, BIT32( 23 ) | BIT32( 20 ) |
+ BIT32( 17 ) | BIT32( 16 ) |
+ BIT32( 14 ) | BIT32( 13 ) |
+ BIT32( 5 ) | BIT32( 4 ) |
+ BIT32( 2 ) | BIT32( 1 ) );
+ // step 16: omitted
+ i = 1000;
+ while( ( --i ) &&
+ ( bcm_read_mem32( BCM_FW_MBX ) != ~BCM_MAGIC_NUMBER ) ) {
+//#ifdef BCM_DEBUG
+ printk( "." );
+//#endif
+ ms_delay( 1 );
+ }
+
+ // return on error
+ if( bcm_read_mem32( BCM_FW_MBX ) != ~BCM_MAGIC_NUMBER ) {
+ printk( "bootcode not loaded: %x\n", bcm_read_mem32( BCM_FW_MBX ) );
+#ifdef BCM_DEBUG
+ printk( "failed\n" );
+#endif
+ return -1;
+ }
+
+
+ // if ASF Firmware enabled
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_START );
+ ms_delay( 10 );
+
+ // step 17: write ethernet mac mode register
+ /*
+ * WY 07.02.07
+ * omitted for correct SOL function
+ */
+ /*
+ if( IS_SERDES ) {
+ bcm_write_reg32( ETH_MAC_MODE_R, (u32_t) 0xc );
+ } else {
+ bcm_write_reg32( ETH_MAC_MODE_R, (u32_t) 0x0 );
+ }
+ */
+
+ // step 18/19: omitted
+ // step 20: enable hw bugfix for 5704
+ if( IS_5704 || IS_5703 ) {
+ bcm_setb_reg32( MSG_DATA_R, BIT32( 26 ) |
+ BIT32( 28 ) |
+ BIT32( 29 ) );
+ }
+
+ // step 21: omitted
+ // step 22: omitted
+ // step 23: 5704 clear statistics block
+ if( IS_5703 || IS_5704 ) {
+ memset_ci( (void *) ( bcm_memaddr_u64 + BCM_STATISTIC_OFFS ),
+ 0,
+ BCM_STATISTIC_SIZE );
+ }
+
+ // step 24/25: omitted
+ // step 26: set DMA Read/Write Control register
+ // NOTE: recommended values from the spec are used here
+ if( IS_5714 ) {
+ bcm_write_reg32( DMA_RW_CTRL_R, DMA_RW_CTRL_VAL_5714 );
+ } else {
+ u32_t l_PCIState_u32 = bcm_read_reg32( PCI_STATE_R );
+ u32_t l_DMAVal_u32 = DMA_RW_CTRL_VAL;
+
+ if( ( l_PCIState_u32 & BIT32( 2 ) ) != 0 ) { // PCI
+ l_DMAVal_u32 |= (u32_t) 0x300000;
+ } else { // PCI-X
+ l_DMAVal_u32 |= (u32_t) 0x900000;
+
+ if( ( bcm_read_reg32( PCI_CLK_CTRL_R ) & (u32_t) 0x1f )
+ >= (u32_t) 6 ) {
+ l_DMAVal_u32 |= (u32_t) 0x4000;
+ }
+
+ }
+
+ bcm_write_reg32( DMA_RW_CTRL_R, l_DMAVal_u32 );
+ }
+
+ // step 27/28/29: s. step 14
+
+ // step 30: Configure TCP/UDP pseudo header checksum offloading
+ // already done in step 14: offloading disabled
+
+ // step 31: setup timer prescaler
+ i = bcm_read_reg32( MISC_CFG_R );
+ i &= (u32_t) ~0xfe; // clear bits 7-1 first
+ i |= ( BCM_TMR_PRESCALE << 1 );
+ bcm_write_reg32( MISC_CFG_R, i );
+
+ // step 32: 5703/4 configure Mbuf pool address/length
+ // step 33: 5703/4 configure MAC DMA resource pool
+ // step 34: configure MAC memory pool watermarks
+ // step 35: 5703/4 configure DMA resource watermarks
+ // using recommended settings (hard coded)
+ if( IS_5703 || IS_5704 ) {
+
+ if( IS_5703 ) {
+ bcm_write_reg32( MBUF_POOL_ADDR_R, (u32_t) 0x8000 );
+ bcm_write_reg32( MBUF_POOL_LEN_R, (u32_t) 0x18000 );
+ } else {
+ bcm_write_reg32( MBUF_POOL_ADDR_R, (u32_t) 0x10000 );
+ bcm_write_reg32( MBUF_POOL_LEN_R, (u32_t) 0x10000 );
+ }
+
+ bcm_write_reg32( DMA_DESC_POOL_ADDR_R, (u32_t) 0x2000 );
+ bcm_write_reg32( DMA_DESC_POOL_LEN_R, (u32_t) 0x2000 );
+
+ bcm_write_reg32( DMA_RMBUF_LOW_WMARK_R, (u32_t) 0x50 );
+ bcm_write_reg32( MAC_RXMBUF_LOW_WMARK_R, (u32_t) 0x20 );
+ bcm_write_reg32( MBUF_HIGH_WMARK_R, (u32_t) 0x60 );
+
+ bcm_write_reg32( DMA_DESC_LOW_WM_R, (u32_t) 5 );
+ bcm_write_reg32( DMA_DESC_HIGH_WM_R, (u32_t) 10 );
+ } else {
+ bcm_write_reg32( DMA_RMBUF_LOW_WMARK_R, (u32_t) 0x00 );
+ bcm_write_reg32( MAC_RXMBUF_LOW_WMARK_R, (u32_t) 0x10 );
+ bcm_write_reg32( MBUF_HIGH_WMARK_R, (u32_t) 0x60 );
+ }
+
+ // step 35: omitted
+ // step 36: Configure flow control behaviour
+ // using recommended settings (hard coded)
+ bcm_write_reg32( LOW_WMARK_MAX_RXFRAM_R, (u32_t) 0x02 );
+
+ // step 37/38: enable buffer manager & wait for successful start
+ bcm_setb_reg32( BUF_MAN_MODE_R, BIT32( 2 ) | BIT32( 1 ) );
+
+ i = lc_Maxwait_u32;
+ while( ( --i ) &&
+ ( ( bcm_read_reg32( BUF_MAN_MODE_R ) & BIT32( 1 ) ) == 0 ) ) {
+ us_delay( 10 );
+ }
+
+ // return on error
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: init step 38: enable buffer manager failed\n" );
+#endif
+ return -1;
+ }
+
+ // step 39: enable internal hardware queues
+ bcm_write_reg32( FTQ_RES_R, (u32_t) ~0 );
+ bcm_write_reg32( FTQ_RES_R, (u32_t) 0 );
+
+ // step 40/41/42: initialize rx producer ring
+ bcm_init_rxprod_ring();
+
+ // step 43: set rx producer ring replenish threshhold
+ // using recommended setting of maximum allocated BD's/8
+ bcm_write_reg32( STD_RXPR_REP_THR_R, (u32_t) BCM_MAX_RX_BUF / 8 );
+
+ // step 44/45/46: initialize send rings
+ bcm_init_tx_ring();
+ bcm_init_rxret_ring();
+
+ // steps 47-50 done in ring init functions
+ // step 51: configure MAC unicast address
+ bcm_nvram_init();
+ if( bcm_mac_init( (u08_t *) mac_addr ) < 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: init step 51: configure MAC unicast address failed\n" );
+#endif
+ return -1;
+ }
+
+ // step 52: configure backoff random seed for transmit
+ // using recommended algorithm
+ i = (u32_t) mac_addr[0] + (u32_t) mac_addr[1] +
+ (u32_t) mac_addr[2] + (u32_t) mac_addr[3] +
+ (u32_t) mac_addr[4] + (u32_t) mac_addr[5];
+ i &= (u32_t) 0x03ff;
+ bcm_write_reg32( ETH_TX_RND_BO_R, i );
+
+ // step 53: configure message transfer unit MTU size
+ bcm_write_reg32( RX_MTU_SIZE_R, (u32_t) BCM_MTU_MAX_LEN );
+
+ // step 54: configure IPG for transmit
+ // using recommended value (through #define)
+ bcm_write_reg32( TX_MAC_LEN_R, TX_MAC_LEN_VAL );
+
+ // step 55: configure receive rules
+
+ // set RX rule default class
+ bcm_write_reg32( RX_RULE_CFG_R, RX_RULE_CFG_VAL );
+
+ // step 56: configure the number of receive lists
+ bcm_write_reg32( RX_LST_PLACE_CFG_R, RX_LST_PLC_CFG_VAL );
+ bcm_write_reg32( RX_LST_PLACE_STAT_EN_R, RX_LST_PLC_STAT_EN_VAL );
+
+/*
+ // rule 1: accept frames for our MAC address
+ bcm_write_reg32( RX_RULE_CTRL_R ( 0 ),
+ BIT32( 31 ) | // enable rule
+ BIT32( 30 ) | // and with next
+ BIT32( 26 ) | // split value register
+ BIT32( 8 ) ); // class 1
+ bcm_write_reg32( RX_RULE_VAL_R ( 0 ),
+ (u32_t) 0xffff0000 |
+ ( bcm_read_reg32( MAC_ADDR_OFFS_HI(0) ) &
+ (u32_t) 0xffff ) );
+
+ bcm_write_reg32( RX_RULE_CTRL_R ( 1 ),
+ BIT32( 31 ) | // enable rule
+ BIT32( 8 ) | // class 1
+ BIT32( 1 ) ); // offset 2
+ bcm_write_reg32( RX_RULE_VAL_R ( 1 ),
+ bcm_read_reg32( MAC_ADDR_OFFS_LO(0) ) );
+
+ // rule 2: accept broadcast frames
+ bcm_write_reg32( RX_RULE_CTRL_R ( 2 ),
+ BIT32( 31 ) | // enable rule
+ BIT32( 30 ) | // and with next
+ BIT32( 26 ) | // split value register
+ BIT32( 8 ) ); // class 1
+ bcm_write_reg32( RX_RULE_VAL_R ( 2 ),
+ (u32_t) ~0 );
+
+ bcm_write_reg32( RX_RULE_CTRL_R ( 3 ),
+ BIT32( 31 ) | // enable rule
+ BIT32( 8 ) | // class 1
+ BIT32( 1 ) ); // offset 2
+ bcm_write_reg32( RX_RULE_VAL_R ( 3 ),
+ (u32_t) ~0 );
+*/
+ for( i=0; i<NUM_RX_RULE_ASF; ++i) {
+ bcm_write_reg32( RX_RULE_CTRL_R ( i ), 0 );
+ bcm_write_reg32( RX_RULE_VAL_R ( i ), 0 );
+ }
+
+ // step 57-60: enable rx/tx statistics
+ // omitted, no need for statistics (so far)
+
+ // step 61/62: disable host coalescing engine/wait 20ms
+ bcm_write_reg32( HOST_COAL_MODE_R, (u32_t) 0 );
+
+ i = lc_Maxwait_u32 * 2;
+ while( ( --i ) &&
+ ( bcm_read_reg32( HOST_COAL_MODE_R ) != 0 ) ) {
+ us_delay( 10 );
+ }
+
+ // return on error
+ if( i == 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: init step 62: disable host coal. engine failed\n" );
+#endif
+ return -1;
+ }
+
+ // step 63-66: initialize coalescing engine
+ // NOTE: status block is unused in this driver,
+ // therefore the coal. engine status block
+ // automatic update is disabled (by writing
+ // 0 to every counter
+ bcm_write_reg32( RX_COAL_TICKS_R, 0 );
+ bcm_write_reg32( TX_COAL_TICKS_R, 0 );
+ bcm_write_reg32( RX_COAL_MAX_BD_R, 0 );
+ bcm_write_reg32( TX_COAL_MAX_BD_R, 0 );
+ bcm_write_reg32( RX_COAL_TICKS_INT_R, 0 );
+ bcm_write_reg32( TX_COAL_TICKS_INT_R, 0 );
+ bcm_write_reg32( RX_COAL_MAX_BD_INT_R, 0 );
+ bcm_write_reg32( TX_COAL_MAX_BD_INT_R, 0 );
+
+ // step 67: initialize host status block address
+ // NOTE: status block is not needed in this driver,
+ // still it needs to be set up
+ i = (u32_t) ( (u64_t) &bcm_status >> 32 );
+ bcm_write_reg32( STB_HOST_ADDR_HI_R, i );
+ i = (u32_t) ( (u64_t) &bcm_status & (u64_t) 0xffffffff );
+ bcm_write_reg32( STB_HOST_ADDR_LO_R, i );
+
+ // 5704/3 adaption
+ if( IS_5703 || IS_5704 ) {
+ // step 68: 5704, for now omitted
+ // step 69: 5704 set the statistics coalescing tick counter
+ bcm_write_reg32( STAT_TICK_CNT_R, 0 );
+ // step 70: 5704 configure statistics block address in NIC memory
+ // using recommended values (hard coded)
+ bcm_write_reg32( STAT_NIC_ADDR_R, (u32_t) 0x300 );
+ // step 71: 5704 configure status block address in NIC memory
+ // using recommended values (hard coded)
+ bcm_write_reg32( STB_NIC_ADDR_R, (u32_t) 0xb00 );
+ }
+
+ // step 72: enable host coalescing engine
+ bcm_setb_reg32( HOST_COAL_MODE_R, BIT32( 12 ) | BIT32( 11 ) | BIT32( 1 ) );
+
+ // step 73: enable rx bd completion functional block
+ bcm_write_reg32( RX_BD_COMPL_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+
+ // step 74: enable rx list placement functional block
+ bcm_write_reg32( RX_LST_PLACE_MODE_R, BIT32( 1 ) );
+ // 5704/3 adaption
+ if( IS_5703 || IS_5704 ) {
+ // step 75: 5704/3 enable receive list selector func block
+ bcm_write_reg32( RX_LST_SEL_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+ }
+
+ // step 76: enable DMA engines
+ bcm_setb_reg32( ETH_MAC_MODE_R, BIT32( 23 ) | BIT32( 22 ) | BIT32( 21 ) );
+ /*
+ * WY 26.10.07 This is wrong for 5714, better leave it alone
+ if( IS_5714 ) {
+ bcm_setb_reg32( ETH_MAC_MODE_R, BIT32( 20 ) );
+ }
+ */
+
+ // step 77: omitted, statistics are not used
+ // step 78: Configure the General Misc Local Control register
+ // NOTE: as known so far nothing needs to be done here,
+ // default values should work fine
+ //bcm_setb_reg32( MISC_LOCAL_CTRL_R, 0 );
+
+ // step 79: clear interrupts in INT_MBX0_R low word
+ bcm_write_reg32( INT_MBX0_R, 0 );
+ // 5704/3 adaption
+ // step 80: 5704/3 enable DMA completion functional block
+ if( IS_5703 || IS_5704 ) {
+ bcm_write_reg32( DMA_COMPL_MODE_R, BIT32( 1 ) );
+ }
+
+ // step 81/82: configure write/read DMA mode registers
+ // disable MSI
+ bcm_write_reg32( RD_DMA_MODE_R, BIT32( 10 ) | BIT32( 9 ) | BIT32( 8 ) |
+ BIT32( 7 ) | BIT32( 6 ) | BIT32( 5 ) |
+ BIT32( 4 ) | BIT32( 3 ) | BIT32( 2 ) |
+ BIT32( 1 ) );
+ bcm_write_reg32( WR_DMA_MODE_R, BIT32( 9 ) | BIT32( 8 ) | BIT32( 7 ) |
+ BIT32( 6 ) | BIT32( 5 ) | BIT32( 4 ) |
+ BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) );
+ bcm_clrb_reg32( MSI_MODE_R, BIT32( 1 ) );
+ us_delay( 100 );
+
+ // step 83-91: enable all these functional blocks...
+ bcm_write_reg32( RX_DAT_COMPL_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+
+ if( IS_5703 || IS_5704 ) {
+ bcm_write_reg32( MBUF_CLSTR_FREE_MODE_R, BIT32( 1 ) );
+ }
+
+ bcm_write_reg32( TX_DAT_COMPL_MODE_R, BIT32( 1 ) );
+ bcm_write_reg32( TX_BD_COMPL_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+ bcm_write_reg32( RX_BD_INIT_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+ bcm_write_reg32( RX_DAT_BD_INIT_MODE_R, BIT32( 1 ) );
+ bcm_write_reg32( TX_DAT_INIT_MODE_R, BIT32( 1 ) | BIT32( 3 ) );
+ bcm_write_reg32( TX_BD_INIT_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+ bcm_write_reg32( TX_BD_RING_SEL_MODE_R, BIT32( 1 ) | BIT32( 2 ) );
+
+ // step 92: omitted
+ // step 93/94: Enable Tx/Rx MAC
+ bcm_setb_reg32( TX_MAC_MODE_R, BIT32( 1 ) );
+// bcm_setb_reg32( RX_MAC_MODE_R, BIT32( 1 ) | BIT32( 2 ) ); // set BIT32( 8 ) for promiscious mode!
+ bcm_setb_reg32( RX_MAC_MODE_R, BIT32( 1 ) ); // set BIT32( 8 ) for promiscious mode!
+ // set BIT32( 10) for VLAN
+
+ // step 95: disable auto polling:
+ // bcm_phy_init takes care of this
+ // step 96: omitted
+ // step 97: omitted, may change though, but is not important
+ // step 98: activate link & enable MAC functional block
+ // NOTE autopolling is enabled so bit 0 needs not to be set
+ //bcm_setb_reg32( MI_STATUS_R, BIT32( 0 ) );
+
+ // step 99: setup PHY
+ // return if link is down
+ if( bcm_phy_init() < 0 ) {
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: init step 99: PHY initialization failed\n" );
+#endif
+ return -1;
+ }
+
+ // step 100: setup multicast filters
+ bcm_write_reg32( MAC_HASH0_R, (u32_t) 0 );
+ bcm_write_reg32( MAC_HASH1_R, (u32_t) 0 );
+ bcm_write_reg32( MAC_HASH2_R, (u32_t) 0 );
+ bcm_write_reg32( MAC_HASH3_R, (u32_t) 0 );
+/*
+ // accept all multicast frames
+ bcm_write_reg32( MAC_HASH0_R, (u32_t) 0xffffffff );
+ bcm_write_reg32( MAC_HASH1_R, (u32_t) 0xffffffff );
+ bcm_write_reg32( MAC_HASH2_R, (u32_t) 0xffffffff );
+ bcm_write_reg32( MAC_HASH3_R, (u32_t) 0xffffffff );
+*/
+ // step 101: omitted, no interrupts used
+
+ // make initial receive buffers available for NIC
+ // this step has to be done here after RX DMA engine has started (step 94)
+ bcm_write_reg32( RXPROD_PROD_IND, BCM_MAX_RX_BUF );
+
+ // if ASF Firmware enabled
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_START_DONE );
+ ms_delay( 10 );
+
+ // enable heartbeat timer
+
+ bcm_write_reg32( ASF_HEARTBEAT_TIMER_R, 0x5 );
+ // off we go..
+ return 0;
+}
+
+static int
+bcm_reset( pci_config_t *pcicfg )
+{
+ u32_t i;
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: resetting controller.." );
+#endif
+
+ bcm_write_mem32( BCM_FW_MBX, BCM_MAGIC_NUMBER );
+
+ if( IS_5714 ) {
+ bcm_setb_reg32( MISC_CFG_R, BIT32( 26 ) | BIT32( 0 ) );
+ } else {
+ bcm_setb_reg32( MISC_CFG_R, BIT32( 0 ) );
+ }
+
+ ms_delay( 20 );
+
+ /*
+ * after reset local read/write functions cannot be used annymore
+ * until bus master & stuff is set up again
+ */
+
+ i = ( BIT32( 10 ) | BIT32( 2 ) | BIT32( 1 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_COM_R,
+ ( int ) i );
+
+ // step 9 & 13: disable & mask interrupts & enable indirect addressing mode &
+ // enable pci byte/word swapping initialize the misc host control register
+ i = ( BIT32( 7 ) | BIT32( 5 ) | BIT32( 4 ) |
+ BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+
+ // step 16: poll for bootcode completion by waiting for the one's
+ // complement of the magic number previously written
+ i = 1000;
+ while( ( --i ) &&
+ ( bcm_read_mem32( BCM_FW_MBX ) != ~BCM_MAGIC_NUMBER ) ) {
+#ifdef BCM_DEBUG
+ printk( "." );
+#else
+ ms_delay( 1 );
+#endif
+ }
+
+ // return on error
+ if( bcm_read_mem32( BCM_FW_MBX ) != ~BCM_MAGIC_NUMBER ) {
+#ifdef BCM_DEBUG
+ printk( "failed\n" );
+#endif
+ return -1;
+ }
+
+#ifdef BCM_DEBUG
+ printk( "done\n" );
+#endif
+ return 0;
+}
+
+static int
+bcm_term( pci_config_t *pcicfg )
+{
+ u32_t i;
+ u16_t v;
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: driver shutdown.." );
+#endif
+
+ /*
+ * halt ASF firmware
+ */
+ bcm_fw_halt();
+
+ /*
+ * unload ASF firmware
+ */
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_UNLOAD );
+
+ /*
+ * disable RX producer rings
+ */
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_JUM ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_JUM ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_JUM ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_JUM ), 0 );
+
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_STD ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_STD ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_STD ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_STD ), 0 );
+
+ bcm_write_reg32( BCM_RCB_LENFLAG_u16( BCM_RXPROD_RCB_MIN ), RCB_FLAG_RING_DISABLED );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_HI_u16( BCM_RXPROD_RCB_MIN ), 0 );
+ bcm_write_reg32( BCM_RCB_HOSTADDR_LOW_u16( BCM_RXPROD_RCB_MIN ), 0 );
+ bcm_write_reg32( BCM_RCB_NICADDR_u16( BCM_RXPROD_RCB_MIN ), 0 );
+
+ /*
+ * disable RX return rings
+ */
+ v = BCM_RXRET_RCB_OFFS;
+ for( i = 0; i < BCM_MAX_RXRET_RING; i++ ) {
+ bcm_write_mem32( BCM_RCB_LENFLAG_u16( v ), RCB_FLAG_RING_DISABLED );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( v ), 0 );
+
+ v += BCM_RCB_SIZE_u16;
+ }
+
+ /*
+ * disable TX rings
+ */
+ v = BCM_TX_RCB_OFFS;
+ for( i = 0; i < BCM_MAX_TX_RING; i++ ) {
+ bcm_write_mem32( BCM_RCB_LENFLAG_u16( v ), RCB_FLAG_RING_DISABLED );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_HI_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_HOSTADDR_LOW_u16( v ), 0 );
+ bcm_write_mem32( BCM_RCB_NICADDR_u16( v ), 0 );
+
+ v += BCM_RCB_SIZE_u16;
+ }
+
+ /*
+ * remove receive rules
+ */
+ bcm_write_reg32( RX_RULE_CTRL_R ( 0 ), 0 );
+ bcm_write_reg32( RX_RULE_VAL_R ( 0 ), 0 );
+ bcm_write_reg32( RX_RULE_CTRL_R ( 1 ), 0 );
+ bcm_write_reg32( RX_RULE_VAL_R ( 1 ), 0 );
+
+ /*
+ * shutdown sequence
+ * BCM57xx Programmer's Guide: Section 8, "Shutdown"
+ * the enable bit of every state machine of the 57xx
+ * has to be reset.
+ */
+
+ /*
+ * receive path shutdown sequence
+ */
+ bcm_clr_wait_bit32( RX_MAC_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RX_LST_PLACE_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RX_BD_INIT_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RX_DAT_BD_INIT_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RX_DAT_COMPL_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RX_BD_COMPL_MODE_R, BIT32( 1 ) );
+
+ if( IS_5704 || IS_5703 ) {
+ bcm_clr_wait_bit32( RX_LST_SEL_MODE_R, BIT32( 1 ) );
+ }
+
+ /*
+ * transmit path & memory shutdown sequence
+ */
+ bcm_clr_wait_bit32( TX_BD_RING_SEL_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( TX_BD_INIT_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( TX_DAT_INIT_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( RD_DMA_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( TX_DAT_COMPL_MODE_R, BIT32( 1 ) );
+
+ if( IS_5704 ) {
+ bcm_clr_wait_bit32( DMA_COMPL_MODE_R, BIT32( 1 ) );
+ }
+
+ bcm_clr_wait_bit32( TX_BD_COMPL_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( ETH_MAC_MODE_R, BIT32( 21 ) );
+ bcm_clr_wait_bit32( TX_MAC_MODE_R, BIT32( 1 ) );
+
+ bcm_clr_wait_bit32( HOST_COAL_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( WR_DMA_MODE_R, BIT32( 1 ) );
+
+ if( IS_5704 || IS_5703 ) {
+ bcm_clr_wait_bit32( MBUF_CLSTR_FREE_MODE_R, BIT32( 1 ) );
+ }
+
+ bcm_write_reg32( FTQ_RES_R, (u32_t) ~0 );
+ bcm_write_reg32( FTQ_RES_R, (u32_t) 0 );
+
+ if( IS_5704 || IS_5703 ) {
+ bcm_clr_wait_bit32( BUF_MAN_MODE_R, BIT32( 1 ) );
+ bcm_clr_wait_bit32( MEMARB_MODE_R, BIT32( 1 ) );
+ }
+
+#ifdef BCM_DEBUG
+ printk( "done.\n" );
+#endif
+ /*
+ * controller reset
+ */
+ if( bcm_reset( pcicfg ) != 0 ) {
+ return -1;
+ }
+
+ /*
+ * restart ASF firmware
+ */
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_UNLOAD );
+ ms_delay( 10 );
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_UNLOAD_DONE );
+ ms_delay( 100 );
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_START );
+ ms_delay( 10 );
+ bcm_write_mem32( BCM_NICDRV_STATE_MBX, NIC_FWDRV_STATE_START_DONE );
+
+ /*
+ * activate Wake-on-LAN
+ */
+ bcm_wol_activate( pcicfg );
+
+ /*
+ * PCI shutdown
+ */
+ bcm_clrb_reg32( PCI_MISC_HCTRL_R, BIT32( 3 ) | BIT32( 2 ) );
+
+ /*
+ * from now on local rw functions cannot be used anymore
+ */
+
+// bcm_clrb_reg32( PCI_COM_R, BIT32( 10 ) | BIT32( 2 ) | BIT32( 1 ) );
+
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_COM_R,
+ BIT32(8) | BIT32(6) );
+
+ // no more networking...
+ return 0;
+}
+
+static int
+bcm_getmac(u32_t addr, char mac[6])
+{
+ u32_t t1, t2;
+ u64_t t3;
+
+ if (bcm_nvram_read(addr, &t1, 1) != 0)
+ return -1;
+ if (bcm_nvram_read(addr+4, &t2, 1) != 0)
+ return -1;
+ t3 = ((u64_t)t1 << 32) + t2;
+
+ mac[0] = (t3 >> 40) & 0xFF;
+ mac[1] = (t3 >> 32) & 0xFF;
+ mac[2] = (t3 >> 24) & 0xFF;
+ mac[3] = (t3 >> 16) & 0xFF;
+ mac[4] = (t3 >> 8) & 0xFF;
+ mac[5] = (t3 >> 0) & 0xFF;
+
+ return 0;
+}
+
+static char*
+print_itoa(char *text, u32_t value)
+{
+ if(value >= 10)
+ text = print_itoa(text, value / 10);
+ *text = '0' + (value % 10);
+ ++text;
+ return text;
+}
+
+static int
+bcm_get_version(char *text)
+{
+ u32_t t1;
+
+ if (bcm_nvram_read(0x94, &t1, 1) != 0)
+ return -1;
+
+ text = print_itoa(text, (t1 >> 8) & 0xFF);
+ text[0] = '.';
+ text = print_itoa(&text[1], t1 & 0xFF);
+ text[0] = '\n';
+ return 0;
+}
+
+static u32_t
+util_gen_crc( char *pcDatabuf, u32_t ulDatalen, u32_t ulCrc_in)
+{
+ unsigned char data;
+ u32_t idx, bit, crc = ulCrc_in;
+
+ for(idx = 0; idx < ulDatalen; idx++) {
+ data = *pcDatabuf++;
+ for(bit = 0; bit < 8; bit++, data >>= 1) {
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ?
+ CRC32_POLYNOMIAL : 0);
+ }
+ }
+ return bswap_32(~crc);
+}
+
+static int
+bcm_setmac(char mac_addr1[6], char mac_addr2[6])
+{
+ u64_t mac1 = 0, mac2 = 0;
+ u32_t manu[MANUFACTURING_INFO_SIZE/4];
+ int addr, i;
+ u32_t crc, val1, val2, val3, val4;
+
+#ifdef BCM_DEBUG
+ printk("Flashing MAC 1: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ ((unsigned int) mac_addr1[0]) & 0xFF,
+ ((unsigned int) mac_addr1[1]) & 0xFF,
+ ((unsigned int) mac_addr1[2]) & 0xFF,
+ ((unsigned int) mac_addr1[3]) & 0xFF,
+ ((unsigned int) mac_addr1[4]) & 0xFF,
+ ((unsigned int) mac_addr1[5]) & 0xFF);
+
+ printk("Flashing MAC 2: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ ((unsigned int) mac_addr2[0]) & 0xFF,
+ ((unsigned int) mac_addr2[1]) & 0xFF,
+ ((unsigned int) mac_addr2[2]) & 0xFF,
+ ((unsigned int) mac_addr2[3]) & 0xFF,
+ ((unsigned int) mac_addr2[4]) & 0xFF,
+ ((unsigned int) mac_addr2[5]) & 0xFF);
+#endif
+
+ mac1 |= ((u64_t) mac_addr1[0]) & 0xFF; mac1 = mac1 << 8;
+ mac1 |= ((u64_t) mac_addr1[1]) & 0xFF; mac1 = mac1 << 8;
+ mac1 |= ((u64_t) mac_addr1[2]) & 0xFF; mac1 = mac1 << 8;
+ mac1 |= ((u64_t) mac_addr1[3]) & 0xFF; mac1 = mac1 << 8;
+ mac1 |= ((u64_t) mac_addr1[4]) & 0xFF; mac1 = mac1 << 8;
+ mac1 |= ((u64_t) mac_addr1[5]) & 0xFF;
+
+ mac2 |= ((u64_t) mac_addr2[0]) & 0xFF; mac2 = mac2 << 8;
+ mac2 |= ((u64_t) mac_addr2[1]) & 0xFF; mac2 = mac2 << 8;
+ mac2 |= ((u64_t) mac_addr2[2]) & 0xFF; mac2 = mac2 << 8;
+ mac2 |= ((u64_t) mac_addr2[3]) & 0xFF; mac2 = mac2 << 8;
+ mac2 |= ((u64_t) mac_addr2[4]) & 0xFF; mac2 = mac2 << 8;
+ mac2 |= ((u64_t) mac_addr2[5]) & 0xFF;
+
+ /* Extract the manufacturing data, starts at 0x74 */
+ if(bcm_nvram_lock() == -1) {
+ return -1;
+ }
+
+ addr = 0x74;
+ for (i = 0; i < (MANUFACTURING_INFO_SIZE/4); i++) {
+ if (bcm_nvram_read(addr, &manu[i], 0) != 0) {
+ printk("\nREAD FAILED\n");
+ bcm_nvram_unlock();
+ return -1;
+ }
+ addr+=4;
+ }
+ bcm_nvram_unlock();
+
+ /* Store the new MAC address in the manufacturing data */
+ val1 = mac1 >> 32;
+ val2 = mac1 & 0xFFFFFFFF;
+ val3 = mac2 >> 32;
+ val4 = mac2 & 0xFFFFFFFF;
+ manu[(0x7C-0x74)/4] = val1;
+ manu[(0x80-0x74)/4] = val2;
+ manu[(0xCC-0x74)/4] = val3;
+ manu[(0xD0-0x74)/4] = val4;
+
+ /* Calculate the new manufacturing datas CRC */
+ crc = util_gen_crc(((char *)manu),
+ MANUFACTURING_INFO_SIZE - 4, 0xFFFFFFFF);
+
+ /* Now write the new MAC addresses and CRC */
+ if ((bcm_nvram_write(0x7C, val1, 1) != 0) ||
+ (bcm_nvram_write(0x80, val2, 1) != 0) ||
+ (bcm_nvram_write(0xCC, val3, 1) != 0) ||
+ (bcm_nvram_write(0xD0, val4, 1) != 0) ||
+ (bcm_nvram_write(0xFC, crc, 1) != 0) )
+ {
+ /* Disastor ! */
+#ifdef BCM_DEBUG
+ printk("failed to write MAC address\n");
+#endif
+ return -1;
+ }
+
+ /* Success !!!! */
+ return 0;
+}
+
+static int
+bcm_ioctl( pci_config_t *pcicfg, int request, void* data )
+{
+ u32_t l_baseaddrL_u32;
+ u32_t l_baseaddrH_u32;
+ u32_t i;
+ int ret_val = 0;
+ char mac_addr[6];
+ ioctl_net_data_t *ioctl_data = (ioctl_net_data_t*) data;
+
+ if(request != SIOCETHTOOL) {
+ return -1;
+ }
+
+ /*
+ * check driver
+ */
+ if( check_driver( pcicfg ) < 0 ) {
+ return -1;
+ }
+
+ bcm_pcicfg_puid = pcicfg->puid;
+ bcm_pcicfg_bus = pcicfg->bus;
+ bcm_pcicfg_devfn = pcicfg->devfn;
+
+#ifdef BCM_DEBUG
+ printk( "bcm57xx: detected device " );
+ if( IS_5703 ) {
+ printk( "5703S" );
+ } else if( IS_5704 ) {
+ printk( "5704" );
+ if( IS_SERDES ) {
+ printk( "S\n" );
+ } else {
+ printk( "C\n" );
+ }
+ } else if( IS_5714 ) {
+ printk( "5714\n" );
+ }
+#endif
+ /*
+ * setup register & memory base addresses of NIC
+ */
+ l_baseaddrL_u32 = ( (u32_t) ~0xf &
+ (u32_t) snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_BAR1_R ) );
+
+ l_baseaddrH_u32 =
+ (u32_t) snk_kernel_interface->pci_config_read( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_BAR2_R );
+
+ bcm_baseaddr_u64 = (u64_t) l_baseaddrH_u32;
+ bcm_baseaddr_u64 <<= 32;
+ bcm_baseaddr_u64 += (u64_t) l_baseaddrL_u32;
+ snk_kernel_interface->translate_addr(((void *)&(bcm_baseaddr_u64)));
+ bcm_memaddr_u64 = bcm_baseaddr_u64 + BCM_MEMORY_OFFS;
+
+ /*
+ * 57xx hardware initialization
+ * BCM57xx Programmer's Guide: Section 8, "Initialization"
+ * steps 1 through 101
+ */
+
+ // step 1: enable bus master & memory space in command reg
+ i = ( BIT32( 10 ) | BIT32( 2 ) | BIT32( 1 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 2,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_COM_R,
+ ( int ) i );
+
+ // step 2: disable & mask interrupts & enable pci byte/word swapping & enable indirect addressing mode
+ i = ( BIT32( 7 ) | BIT32( 3 ) | BIT32( 2 ) | BIT32( 1 ) | BIT32( 0 ) );
+ snk_kernel_interface->pci_config_write( pcicfg->puid,
+ 4,
+ pcicfg->bus,
+ pcicfg->devfn,
+ PCI_MISC_HCTRL_R,
+ ( int ) i );
+
+ bcm_nvram_init();
+
+ switch(ioctl_data->subcmd) {
+ case ETHTOOL_GMAC:
+ switch(ioctl_data->data.mac.idx) {
+ case 0:
+ ret_val = bcm_getmac(0x7C, ioctl_data->data.mac.address);
+ break;
+ case 1:
+ ret_val = bcm_getmac(0xCC, ioctl_data->data.mac.address);
+ break;
+ default:
+ ret_val = -1;
+ break;
+ }
+ break;
+ case ETHTOOL_SMAC:
+ switch(ioctl_data->data.mac.idx) {
+ case 0:
+ ret_val = bcm_getmac(0xCC, mac_addr);
+ if(ret_val == 0)
+ ret_val = bcm_setmac(ioctl_data->data.mac.address, mac_addr);
+ break;
+ case 1:
+ ret_val = bcm_getmac(0x7C, mac_addr);
+ if(ret_val == 0)
+ ret_val = bcm_setmac(mac_addr, ioctl_data->data.mac.address);
+ break;
+ default:
+ ret_val = -1;
+ break;
+ }
+ break;
+ case ETHTOOL_VERSION: {
+ char *text = ioctl_data->data.version.text;
+ memcpy(text, " BCM57xx Boot code level: ", 27);
+ ret_val = bcm_get_version(&text[27]);
+ break;
+ }
+ default:
+ ret_val = -1;
+ break;
+ }
+
+ bcm_term(pcicfg);
+ return ret_val;
+}
+
+/*
+ * snk module interface
+ ******************************************************************************
+ */
+snk_module_t snk_module_interface = {
+ .version = 1,
+ .net_init = bcm_init,
+ .net_term = bcm_term,
+ .net_xmit = bcm_xmit,
+ .net_receive = bcm_receive,
+ .net_ioctl = bcm_ioctl
+};
+
diff --git a/other-licence/bcm/bcm57xx.h b/other-licence/bcm/bcm57xx.h
new file mode 100644
index 0000000..e6c8937
--- /dev/null
+++ b/other-licence/bcm/bcm57xx.h
@@ -0,0 +1,296 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "netdriver_int.h"
+#include "types.h"
+
+// compiler switches
+
+// Debug switches
+//#define BCM_DEBUG // main debug switch, w/o it the other ones don't work
+//#define BCM_SHOW_RCV
+//#define BCM_SHOW_RCV_DATA
+//#define BCM_SHOW_XMIT
+//#define BCM_SHOW_XMIT_DATA
+//#define BCM_SHOW_XMIT_STATS
+//#define BCM_SHOW_IDX
+//#define BCM_SHOW_STATS
+//#define BCM_SHOW_ASF_REGS
+
+// Switch to enable SW AUTO-NEG
+// don't try, it's still incomplete
+//#define BCM_SW_AUTONEG
+
+/*
+ * used register offsets
+ */
+// PCI command register
+#define PCI_COM_R ( (u16_t) 0x0004 )
+// PCI Cache Line Size register
+#define PCI_CACHELS_R ( (u16_t) 0x000c )
+// PCI bar1 register
+#define PCI_BAR1_R ( (u16_t) 0x0010 )
+// PCI bar2 register
+#define PCI_BAR2_R ( (u16_t) 0x0014 )
+// PCI bar1 register
+#define PCI_SUBID_R ( (u16_t) 0x002e )
+// PCI-X Comand register
+#define PCI_X_COM_R ( (u16_t) 0x0042 )
+// Message Data Register
+#define MSG_DATA_R ( (u16_t) 0x0064 )
+// PCI misc host contrl register
+#define PCI_MISC_HCTRL_R ( (u16_t) 0x0068 )
+// DMA Read/Write Control register
+#define DMA_RW_CTRL_R ( (u16_t) 0x006c )
+// PCI State register
+#define PCI_STATE_R ( (u16_t) 0x0070 )
+// PCI_Clock Control register
+#define PCI_CLK_CTRL_R ( (u16_t) 0x0074 )
+// Register Base Address Register
+#define REG_BASE_ADDR_REG ( (u16_t) 0x0078 )
+// Memory Window Base Address Register
+#define MEM_BASE_ADDR_REG ( (u16_t) 0x007c )
+// Register Data Register
+#define REG_DATA_REG ( (u16_t) 0x0080 )
+// Memory Window Data Register
+#define MEM_DATA_REG ( (u16_t) 0x0084 )
+// MAC Function register
+#define MAC_FUNC_R ( (u16_t) 0x00b8 )
+// Interrupt Mailbox 0 register
+#define INT_MBX0_R ( (u16_t) 0x0204 )
+// Ethernet MAC Mode register
+#define ETH_MAC_MODE_R ( (u16_t) 0x0400 )
+// Ethernet MAC Addresses registers
+#define MAC_ADDR_OFFS_HI( idx ) ( (u16_t) ( (idx*2 + 0)*sizeof( u32_t ) + 0x0410 ) )
+#define MAC_ADDR_OFFS_LO( idx ) ( (u16_t) ( (idx*2 + 1)*sizeof( u32_t ) + 0x0410 ) )
+// Ethernet MAC Status register
+#define ETH_MAC_STAT_R ( (u16_t) 0x0404 )
+// Ethernet MAC Event Enable register
+#define ETH_MAC_EVT_EN_R ( (u16_t) 0x0408 )
+// Ethernet Transmit Random Backoff register
+#define ETH_TX_RND_BO_R ( (u16_t) 0x0438 )
+// Receive MTU Size register
+#define RX_MTU_SIZE_R ( (u16_t) 0x043c )
+// Transmit 1000BASE-X Auto Negotiation register
+#define TX_1000BX_AUTONEG_R ( (u16_t) 0x0444 )
+// Receive 1000BASE-X Auto Negotiation register
+#define RX_1000BX_AUTONEG_R ( (u16_t) 0x0448 )
+// MI Communication register
+#define MI_COM_R ( (u16_t) 0x044c )
+// MI Status Register
+#define MI_STATUS_R ( (u16_t) 0x0450 )
+// MI Mode register
+#define MI_MODE_R ( (u16_t) 0x0454 )
+// Transmit MAC Mode register
+#define TX_MAC_MODE_R ( (u16_t) 0x045c )
+// Transmit MAC Length register
+#define TX_MAC_LEN_R ( (u16_t) 0x0464 )
+// Receive MAC Mode register
+#define RX_MAC_MODE_R ( (u16_t) 0x0468 )
+// MAC Hash 0 register* VPD Config:
+#define MAC_HASH0_R ( (u16_t) 0x0470 )
+// MAC Hash 1 register
+#define MAC_HASH1_R ( (u16_t) 0x0474 )
+// MAC Hash 2 register
+#define MAC_HASH2_R ( (u16_t) 0x0478 )
+// MAC Hash 3 register
+#define MAC_HASH3_R ( (u16_t) 0x047c )
+// Receive Rules Control register
+#define RX_RULE_CTRL_R( idx ) ( (u16_t) ( idx*8 + 0x0480 ) )
+// Receive Rules Value register
+#define RX_RULE_VAL_R( idx ) ( (u16_t) ( idx*8 + 0x0484 ) )
+// Receive Rules Configuration register
+#define RX_RULE_CFG_R ( (u16_t) 0x0500 )
+// Low Watermark Max Receive Frames register
+#define LOW_WMARK_MAX_RXFRAM_R ( (u16_t) 0x0504 )
+// SerDes Control Register
+#define SERDES_CTRL_R ( (u16_t) 0x0590 )
+// Hardware Auto Negotiation Control Register
+#define HW_AUTONEG_CTRL_R ( (u16_t) 0x05B0 )
+// Hardware Auto Negotiation Status Register
+#define HW_AUTONEG_STAT_R ( (u16_t) 0x05B4 )
+// Send Data Initiator Mode register
+#define TX_DAT_INIT_MODE_R ( (u16_t) 0x0c00 )
+// Send Data Completion Mode register
+#define TX_DAT_COMPL_MODE_R ( (u16_t) 0x1000 )
+// Send BD Ring Selector Mode register
+#define TX_BD_RING_SEL_MODE_R ( (u16_t) 0x1400 )
+// Send BD Initiator Mode register
+#define TX_BD_INIT_MODE_R ( (u16_t) 0x1800 )
+// Send BD Completion Mode register
+#define TX_BD_COMPL_MODE_R ( (u16_t) 0x1c00 )
+// Receive List Placement Mode register
+#define RX_LST_PLACE_MODE_R ( (u16_t) 0x2000 )
+// Receive List Placement Configuration register
+#define RX_LST_PLACE_CFG_R ( (u16_t) 0x2010 )
+// Receive List Placement Statistics Enable Mask register
+#define RX_LST_PLACE_STAT_EN_R ( (u16_t) 0x2018 )
+// Receive Data & Receive BD Initiator Mode register
+#define RX_DAT_BD_INIT_MODE_R ( (u16_t) 0x2400 )
+// Receive Data Completion Mode register
+#define RX_DAT_COMPL_MODE_R ( (u16_t) 0x2800 )
+// Receive BD Initiator Mode register
+#define RX_BD_INIT_MODE_R ( (u16_t) 0x2c00 )
+// Standard Receive Producer Ring Replenish Threshhold register
+#define STD_RXPR_REP_THR_R ( (u16_t) 0x2c18 )
+// Receive BD Completion Mode register
+#define RX_BD_COMPL_MODE_R ( (u16_t) 0x3000 )
+// Receive List Selector Mode register
+#define RX_LST_SEL_MODE_R ( (u16_t) 0x3400 )
+// MBUF Cluster Free Mode register
+#define MBUF_CLSTR_FREE_MODE_R ( (u16_t) 0x3800 )
+// Host Coalescing Mode register
+#define HOST_COAL_MODE_R ( (u16_t) 0x3c00 )
+// Receive Coalescing Ticks register
+#define RX_COAL_TICKS_R ( (u16_t) 0x3c08 )
+// Send Coalescing Ticks register
+#define TX_COAL_TICKS_R ( (u16_t) 0x3c0c )
+// Receive Max Coalesced BD Count register
+#define RX_COAL_MAX_BD_R ( (u16_t) 0x3c10 )
+// Send Max Coalesced BD Count register
+#define TX_COAL_MAX_BD_R ( (u16_t) 0x3c14 )
+// Receive Coalescing Ticks During Int register
+#define RX_COAL_TICKS_INT_R ( (u16_t) 0x3c18 )
+// Send Coalescing Ticks During Int register
+#define TX_COAL_TICKS_INT_R ( (u16_t) 0x3c1c )
+// Receive Max Coalesced BD Count During Int register
+#define RX_COAL_MAX_BD_INT_R ( (u16_t) 0x3c18 )
+// Send Max Coalesced BD Count During Int register
+#define TX_COAL_MAX_BD_INT_R ( (u16_t) 0x3c1c )
+// Statistics Ticks Counter register
+#define STAT_TICK_CNT_R ( (u16_t) 0x3c28 )
+// Status Block Host Address Low register
+#define STB_HOST_ADDR_HI_R ( (u16_t) 0x3c38 )
+// Status Block Host Address High register
+#define STB_HOST_ADDR_LO_R ( (u16_t) 0x3c3c )
+// Statistsics Base Adress register
+#define STAT_NIC_ADDR_R ( (u16_t) 0x3c40 )
+// Status Block Base Address register
+#define STB_NIC_ADDR_R ( (u16_t) 0x3c44 )
+// Memory Arbiter Mode register
+#define MEMARB_MODE_R ( (u16_t) 0x4000 )
+// Buffer Manager Mode register
+#define BUF_MAN_MODE_R ( (u16_t) 0x4400 )
+// MBuf Pool Address register
+#define MBUF_POOL_ADDR_R ( (u16_t) 0x4408 )
+// MBuf Pool Length register
+#define MBUF_POOL_LEN_R ( (u16_t) 0x440c )
+// Read DMA Mbuf Low Watermark register
+#define DMA_RMBUF_LOW_WMARK_R ( (u16_t) 0x4410 )
+// MAC Rx Mbuf Low Watermark register
+#define MAC_RXMBUF_LOW_WMARK_R ( (u16_t) 0x4414 )
+// Mbuf High Watermark register
+#define MBUF_HIGH_WMARK_R ( (u16_t) 0x4418 )
+// DMA Descriptor Pool Address register
+#define DMA_DESC_POOL_ADDR_R ( (u16_t) 0x442c )
+// DMA Descriptor Pool Length register
+#define DMA_DESC_POOL_LEN_R ( (u16_t) 0x4430 )
+// DMA Descriptor Low Watermark register
+#define DMA_DESC_LOW_WM_R ( (u16_t) 0x4434 )
+// DMA Descriptor HIGH Watermark register
+#define DMA_DESC_HIGH_WM_R ( (u16_t) 0x4438 )
+// Read DMA Mode register
+#define RD_DMA_MODE_R ( (u16_t) 0x4800 )
+// Write DMA Mode register
+#define WR_DMA_MODE_R ( (u16_t) 0x4c00 )
+// FTQ Reset register
+#define FTQ_RES_R ( (u16_t) 0x5c00 )
+// MSI Mode register
+#define MSI_MODE_R ( (u16_t) 0x6000 )
+// DMA completion Mode register
+#define DMA_COMPL_MODE_R ( (u16_t) 0x6400 )
+// Mode Control register
+#define MODE_CTRL_R ( (u16_t) 0x6800 )
+// Misc Configuration register
+#define MISC_CFG_R ( (u16_t) 0x6804 )
+// Misc Local Control register
+#define MISC_LOCAL_CTRL_R ( (u16_t) 0x6808 )
+// RX-Risc Mode Register
+#define RX_CPU_MODE_R ( (u16_t) 0x5000 )
+// RX-Risc State Register
+#define RX_CPU_STATE_R ( (u16_t) 0x5004 )
+// RX-Risc Program Counter
+#define RX_CPU_PC_R ( (u16_t) 0x501c )
+// RX-Risc Event Register
+#define RX_CPU_EVENT_R ( (u16_t) 0x6810 )
+// MDI Control register
+#define MDI_CTRL_R ( (u16_t) 0x6844 )
+// WOL Mode register
+#define WOL_MODE_R ( (u16_t) 0x6880 )
+// WOL Config register
+#define WOL_CFG_R ( (u16_t) 0x6884 )
+// WOL Status register
+#define WOL_STATUS_R ( (u16_t) 0x6888 )
+
+// ASF Control register
+#define ASF_CTRL_R ( (u16_t) 0x6c00 )
+// ASF Watchdog Timer register
+#define ASF_WATCHDOG_TIMER_R ( (u16_t) 0x6c0c )
+// ASF Heartbeat Timer register
+#define ASF_HEARTBEAT_TIMER_R ( (u16_t) 0x6c10 )
+// Poll ASF Timer register
+#define ASF_POLL_TIMER_R ( (u16_t) 0x6c14 )
+// Poll Legacy Timer register
+#define POLL_LEGACY_TIMER_R ( (u16_t) 0x6c18 )
+// Retransmission Timer register
+#define RETRANSMISSION_TIMER_R ( (u16_t) 0x6c1c )
+// Time Stamp Counter register
+#define TIME_STAMP_COUNTER_R ( (u16_t) 0x6c20 )
+
+// NVM Command register
+#define NVM_COM_R ( (u16_t) 0x7000 )
+// NVM Write register
+#define NVM_WRITE_R ( (u16_t) 0x7008 )
+// NVM Address register
+#define NVM_ADDR_R ( (u16_t) 0x700c )
+// NVM Read registertg3_phy_copper_begin
+#define NVM_READ_R ( (u16_t) 0x7010 )
+// NVM Access register
+#define NVM_ACC_R ( (u16_t) 0x7024 )
+// NVM Config 1 register
+#define NVM_CFG1_R ( (u16_t) 0x7014 )
+// Software arbitration register
+#define SW_ARB_R ( (u16_t) 0x7020 )
+
+/*
+ * useful def's
+ */
+#define rd08(a) (u08_t) snk_kernel_interface->io_read((void*)(a),1)
+#define rd16(a) (u16_t) snk_kernel_interface->io_read((void*)(a),2)
+#define rd32(a) (u32_t) snk_kernel_interface->io_read((void*)(a),4)
+#define wr08(a,v) snk_kernel_interface->io_write((void*)(a),(u32_t)(v),1)
+#define wr16(a,v) snk_kernel_interface->io_write((void*)(a),(u32_t)(v),2)
+#define wr32(a,v) snk_kernel_interface->io_write((void*)(a),(u32_t)(v),4)
+#define printk snk_kernel_interface->print
+#define us_delay snk_kernel_interface->us_delay
+#define ms_delay snk_kernel_interface->ms_delay
+
+#define BIT08( bit ) ( (u08_t) 0x1 << (bit) )
+#define BIT16( bit ) ( (u16_t) 0x1 << (bit) )
+#define BIT32( bit ) ( (u32_t) 0x1 << (bit) )
+
+/*
+ * type definition
+ */
+
+extern snk_kernel_t *snk_kernel_interface;
+
+
+/*
+ * inline functions
+ */
+// memory barrier function implementation
+static inline void
+mb()
+{
+ asm volatile( "sync;" );
+}
diff --git a/other-licence/bcm/types.h b/other-licence/bcm/types.h
new file mode 100644
index 0000000..b33a931
--- /dev/null
+++ b/other-licence/bcm/types.h
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+typedef unsigned char u08_t;
+typedef unsigned short u16_t;
+typedef unsigned int u32_t;
+typedef unsigned long long u64_t;
+
+typedef signed char i08_t;
+typedef signed short i16_t;
+typedef signed int i32_t;
+typedef signed long long i64_t;
+
+#endif
diff --git a/other-licence/common/Makefile b/other-licence/common/Makefile
new file mode 100644
index 0000000..bdff820
--- /dev/null
+++ b/other-licence/common/Makefile
@@ -0,0 +1,45 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS = -O2 -I./ -fno-builtin -ffreestanding -msoft-float -Wall
+
+SRCS = module_entry.c
+
+OBJS = $(SRCS:.c=.o)
+
+
+all: Makefile.dep $(OBJS)
+
+
+clean:
+ $(RM) -f *.o *.a *.i *.bin
+
+distclean : clean
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(CC) -MM $(CFLAGS) $(SRCS) > Makefile.dep
+Makefile.dep:
+ $(MAKE) depend
+
+# Include dependency file if available:
+ifneq (,$(wildcard Makefile.dep))
+include Makefile.dep
+endif
diff --git a/other-licence/common/module.lds b/other-licence/common/module.lds
new file mode 100644
index 0000000..5427279
--- /dev/null
+++ b/other-licence/common/module.lds
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(module_init)
+
+SECTIONS {
+ .code 0xF800000:
+ {
+ ../common/module_entry.o(.opd)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.opd)
+ }
+ .got :
+ {
+ _got = .;
+ *(.got .toc)
+ }
+ .bss : {
+ __bss_start = .;
+ *(*COM* .bss .gnu.linkonce.b.*)
+ __bss_end = .;
+ }
+ __bss_size = (__bss_end - __bss_start);
+ __end = .;
+}
diff --git a/other-licence/common/module_entry.c b/other-licence/common/module_entry.c
new file mode 100644
index 0000000..314babf
--- /dev/null
+++ b/other-licence/common/module_entry.c
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include "netdriver_int.h"
+extern snk_module_t snk_module_interface;
+snk_kernel_t *snk_kernel_interface = 0;
+
+extern int
+check_driver( pci_config_t *pcicfg );
+
+
+static void*
+memset( void *dest, int c, size_t n )
+{
+ while( n-- ) {
+ *( char * ) dest++ = ( char ) c;
+ }
+ return dest;
+}
+
+
+extern char __bss_start;
+extern char __bss_size;
+
+snk_module_t*
+module_init( snk_kernel_t *snk_kernel_int, pci_config_t *pciconf )
+{
+ /* Need to clear bss, heavy linker script dependency, expert change only */
+ char *bss = &__bss_start;
+ unsigned long long bss_size = (unsigned long long) &__bss_size;
+
+ if(((unsigned long long) bss) + bss_size >= 0xFF00000) {
+ snk_kernel_int->print("BSS size too big!\n");
+ return 0;
+ }
+
+ memset( bss, 0, bss_size );
+
+ if( snk_kernel_int->version != snk_module_interface.version ) {
+ return 0;
+ } else {
+ snk_kernel_interface = snk_kernel_int;
+ }
+
+ /* Check if this is the right driver */
+ if( check_driver( pciconf ) < 0 ) {
+ return 0;
+ }
+ return &snk_module_interface;
+}
diff --git a/other-licence/common/netdriver_int.h b/other-licence/common/netdriver_int.h
new file mode 100644
index 0000000..68c1cc9
--- /dev/null
+++ b/other-licence/common/netdriver_int.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef _NETDRIVER_INT_H
+#define _NETDRIVER_INT_H
+#include <stddef.h>
+
+/* Constants for different kinds of IOCTL requests
+ */
+
+#define SIOCETHTOOL 0x1000
+
+typedef struct {
+ unsigned int addr;
+ unsigned int size;
+ int type;
+} bar_t;
+
+typedef struct {
+ unsigned long long puid;
+ unsigned int bus;
+ unsigned int devfn;
+ unsigned int vendor_id;
+ unsigned int device_id;
+ unsigned int revision_id;
+ unsigned int class_code;
+ bar_t bars[6];
+ unsigned int interrupt_line;
+} pci_config_t;
+
+typedef int (*net_init_t) (pci_config_t * conf, char *mac_addr);
+typedef int (*net_term_t) (pci_config_t * conf);
+typedef int (*net_receive_t) (pci_config_t * conf, char *buffer, int len);
+typedef int (*net_xmit_t) (pci_config_t * conf, char *buffer, int len);
+typedef int (*net_ioctl_t) (pci_config_t * conf, int request, void *data);
+
+typedef struct {
+ int version;
+ net_init_t net_init;
+ net_term_t net_term;
+ net_receive_t net_receive;
+ net_xmit_t net_xmit;
+ net_ioctl_t net_ioctl;
+} snk_module_t;
+
+
+typedef int (*print_t) (const char *, ...);
+typedef void (*us_delay_t) (unsigned int);
+typedef void (*ms_delay_t) (unsigned int);
+typedef int (*pci_config_read_t) (long long puid, int size,
+ int bus, int devfn, int offset);
+typedef int (*pci_config_write_t) (long long puid, int size,
+ int bus, int devfn, int offset, int value);
+typedef void *(*malloc_aligned_t) (size_t, int);
+typedef unsigned int (*io_read_t) (void *, size_t);
+typedef int (*io_write_t) (void *, unsigned int, size_t);
+typedef unsigned int (*romfs_lookup_t) (const char *name, void **addr);
+typedef void (*translate_addr_t) (unsigned long *);
+
+typedef struct {
+ int version;
+ print_t print;
+ us_delay_t us_delay;
+ ms_delay_t ms_delay;
+ pci_config_read_t pci_config_read;
+ pci_config_write_t pci_config_write;
+ malloc_aligned_t k_malloc_aligned;
+ io_read_t io_read;
+ io_write_t io_write;
+ romfs_lookup_t k_romfs_lookup;
+ translate_addr_t translate_addr;
+} snk_kernel_t;
+
+
+/* special structure and constants for IOCTL requests of type ETHTOOL
+ */
+
+#define ETHTOOL_GMAC 0x03
+#define ETHTOOL_SMAC 0x04
+#define ETHTOOL_VERSION 0x05
+
+typedef struct {
+ int idx;
+ char address[6];
+} ioctl_ethtool_mac_t;
+
+typedef struct {
+ unsigned int length;
+ char *text;
+} ioctl_ethtool_version_t;
+
+
+/* default structure and constants for IOCTL requests
+ */
+
+#define IF_NAME_SIZE 0xFF
+
+typedef struct {
+ char if_name[IF_NAME_SIZE];
+ int subcmd;
+ union {
+ ioctl_ethtool_mac_t mac;
+ ioctl_ethtool_version_t version;
+ } data;
+} ioctl_net_data_t;
+
+/* Entry of module */
+snk_module_t *module_init(snk_kernel_t * snk_kernel_int,
+ pci_config_t * pciconf);
+#endif /* _NETDRIVER_INT_H */
diff --git a/romfs/header.img b/romfs/header.img
new file mode 100644
index 0000000..794129c
--- /dev/null
+++ b/romfs/header.img
@@ -0,0 +1 @@
+Key.Polynome....XXXXXXXX..Mask..XXXXXXXX.Polynome.Length....XXXX.Header.and.File.lengthXXXXXXXX... und weiter im Text!
diff --git a/romfs/tools/Makefile b/romfs/tools/Makefile
new file mode 100644
index 0000000..dcdba83
--- /dev/null
+++ b/romfs/tools/Makefile
@@ -0,0 +1,45 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+
+include $(TOPCMNDIR)/make.rules
+
+
+CPPFLAGS = -I$(INCLCMNDIR) -I$(INCLBRDDIR) -I.
+CFLAGS += $(FLAG)
+
+SRCS = build_ffs.c cfg_parse.c create_flash.c create_crc.c
+OBJS = $(SRCS:%.c=%.o)
+
+build_romfs: $(OBJS)
+ $(HOSTCC) $(HOSTCFLAGS) $(FLAG) -o $@ $^
+
+%.o: %.c
+ $(HOSTCC) $(CPPFLAGS) $(HOSTCFLAGS) $(FLAG) -c $< -o $@
+
+clean:
+ rm -f build_romfs *.o
+
+distclean: clean
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ rm -f Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+ $(HOSTCC) -MM $(CPPFLAGS) $(CFLAGS) $(SRCS) > Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/romfs/tools/build_ffs.c b/romfs/tools/build_ffs.c
new file mode 100644
index 0000000..1374123
--- /dev/null
+++ b/romfs/tools/build_ffs.c
@@ -0,0 +1,370 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cfgparse.h>
+#include <createcrc.h>
+
+#define FFS_TARGET_HEADER_SIZE (4 * 8)
+
+/* put this somewhere else */
+#define FLAG_LLFW 1
+
+unsigned int glob_rom_pos = 0;
+unsigned int glob_num_files = 0;
+
+typedef struct {
+ uint32_t high;
+ uint32_t low;
+} uint64s_t;
+
+int file_exist(char *, int);
+/* change done 2005-March-09 */
+int write_to_file(int fd, unsigned char *buf, int size);
+/* by Rolf Schaefer */
+
+#define pad8_num(x) ((x) + (-(x) & 7))
+
+int build_ffs(struct ffs_chain_t *fs, char *outfile)
+{
+ int ofdCRC; /* change done 2005-April-07 by Rolf Schaefer */
+ int ofd, ffsize, datasize, imgfd, i, cnt;
+ int tokensize, hdrsize, ffile_offset, hdrbegin;
+ struct ffs_header_t *hdr;
+ unsigned char *ffile, c;
+ struct stat fileinfo;
+ uint64s_t val64;
+
+ if (NULL == fs->first) {
+ return 1;
+ }
+ hdr = fs->first;
+
+ /* check output file and open it for creation */
+ if (file_exist(outfile, 0)) {
+ printf("Output file (%s) will be overwritten\n",
+ outfile);
+ }
+
+ ofd = open(".crc_flash", O_CREAT | O_WRONLY | O_TRUNC, 0666);
+ ofdCRC = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0666); /* change done 2005-April-07 by Rolf Schaefer */
+ if (0 > ofd || 0 > ofdCRC) {
+ perror(outfile);
+ return 1;
+ }
+
+ while (1) {
+ /*
+ * first estimate the size of the file including header
+ * to allocate the memory in advance.
+ */
+ if (NULL == hdr->linked_to) {
+ memset((void*)&fileinfo, 0, sizeof(struct stat));
+ if (stat(hdr->imagefile, &fileinfo) != 0) {
+ perror(hdr->imagefile);
+ return 1;
+ }
+ datasize = fileinfo.st_size;
+ } else {
+ datasize = 0;
+ }
+ ffile_offset = 0,
+ tokensize = pad8_num(strlen(hdr->token) + 1 /* ens trl 0 */);
+ hdrsize = FFS_TARGET_HEADER_SIZE + tokensize;
+ ffsize = hdrsize + pad8_num(datasize) + 8 /* -1 */;
+
+ /* get the mem */
+ ffile = (unsigned char*) malloc(ffsize);
+ if (NULL == ffile) {
+ perror("alloc mem for ffile");
+ return 1;
+ }
+ memset((void*)ffile, 0 , ffsize);
+
+ /* check if file wants a specific address */
+ if ((hdr->romaddr > 0) || (0 != (hdr->flags & FLAG_LLFW))) {
+ /* check if romaddress is below current position */
+ if (hdr->romaddr < (glob_rom_pos + hdrsize)) {
+ printf("[%s] ERROR: requested impossible "
+ "romaddr of %llx\n",
+ hdr->token, hdr->romaddr);
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+
+ /* spin offset to new positon */
+ if (pad8_num(hdr->romaddr) != hdr->romaddr) {
+ printf("BUG!!!! pad8_num(hdr->romaddr) != hdr->romaddr\n");
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+ i = hdr->romaddr - glob_rom_pos - hdrsize;
+ while (0 < i) {
+ c = 0;
+/* change done 09.03.2005 */
+ if (0 != write_to_file(ofd, &c, 1)) {
+/* by Rolf Schaefer */
+ printf("write failed\n");
+ close(ofd);
+ free(ffile);
+ }
+ glob_rom_pos++;
+ i--;
+ }
+ if (glob_rom_pos != (hdr->romaddr - hdrsize)) {
+ printf("BUG!!! hdr->romaddr != glob_rom_pos (%llx, %x)\n",
+ hdr->romaddr, glob_rom_pos);
+ }
+ if (0 == glob_num_files) {
+ printf("\nWARNING: The filesystem will have no "
+ "entry header !\n"
+ " It is still usable but you need "
+ "to find\n"
+ " the FS by yourself in the image.\n\n");
+ }
+ }
+ hdrbegin = glob_rom_pos;
+ ///printf("OFFS=%6x FSIZE=%6d ", glob_rom_pos, ffsize);
+
+ /* write header ********************************************/
+ /* next addr ***********************************************/
+ val64.high= 0;
+ val64.low = 0;
+ //printf("\n\n\nFFS_TARGET_HEADER_SIZE = %d\n", FFS_TARGET_HEADER_SIZE);
+ //printf( "FFS_TARGET_HEADER_SIZE = 0x%x\n", FFS_TARGET_HEADER_SIZE);
+ //printf( "glob_rom_pos = 0x%x\n", glob_rom_pos);
+ //printf( "ffsize = %d\n", ffsize);
+ //printf( "ffsize = 0x%x\n", ffsize);
+
+ if (NULL != hdr->next) {
+ //printf( "next-romaddr = 0x%lx\n", hdr->next->romaddr);
+ //printf( "strlen(hdr->next->token= %d\n", pad8_num(strlen(hdr->next->token)));
+ //printf( "strlen(hdr->next->token= 0x%d\n", pad8_num(strlen(hdr->next->token)));
+ if (hdr->next->romaddr > 0) {
+ /* FIXME this is quite ugly, any other idea? */
+ val64.low = hdr->next->romaddr -
+ (FFS_TARGET_HEADER_SIZE +
+ pad8_num(strlen(hdr->next->token)));
+ val64.low -= glob_rom_pos;
+ val64.low = htonl(val64.low);
+ }
+ //printf( "val64.low = 0x%lx\n", val64.low);
+
+ if (0 == val64.low) {
+ //next address relative to rombase
+ //val64.low = htonl(glob_rom_pos + ffsize);
+ //
+ //changed next pointer to be relative
+ //to current fileposition; needed to glue
+ //different romfs-volumes together
+ val64.low = htonl(ffsize);
+ }
+ }
+ //printf("\n\n\n");
+
+ memcpy(ffile + ffile_offset, &val64, 8);
+ glob_rom_pos += 8;
+ ffile_offset += 8;
+
+ /* length **************************************************/
+ if (NULL == hdr->linked_to) {
+ val64.low = htonl(datasize);
+ hdr->save_data_len = datasize;
+ } else {
+ printf("\nBUG!!! links not supported anymore\n");
+ close(ofd);
+ free(ffile);
+ return 1;
+
+ /*
+ if (0 == hdr->linked_to->save_data_valid) {
+ printf("ERROR: this version does not support"
+ "forward references in links\n");
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+ val64.low = htonl(hdr->linked_to->save_data_len);
+ */
+ }
+ memcpy(ffile + ffile_offset, &val64, 8);
+ glob_rom_pos += 8;
+ ffile_offset += 8;
+
+ /* flags ***************************************************/
+ val64.low = htonl(hdr->flags);
+ memcpy(ffile + ffile_offset, &val64, 8);
+ glob_rom_pos += 8;
+ ffile_offset += 8;
+
+ /* datapointer *********************************************/
+ if (NULL == hdr->linked_to) {
+ //save-data pointer is relative to rombase
+ hdr->save_data = hdrbegin + hdrsize;
+ hdr->save_data_valid = 1;
+ //pointer relative to rombase:
+ //val64.low = htonl(hdr->save_data);
+ //
+ //changed pointers to be relative to file:
+ val64.low = htonl(hdr->save_data - hdrbegin);
+ } else {
+ printf("\nBUG!!! links not supported anymore\n");
+ close(ofd);
+ free(ffile);
+ return 1;
+
+ /*
+ if (0 == hdr->linked_to->save_data_valid) {
+ printf("ERROR: this version does not support"
+ "forward references in links\n");
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+ val64.low = htonl(hdr->linked_to->save_data);
+ */
+ }
+ memcpy(ffile + ffile_offset, &val64, 8);
+ glob_rom_pos += 8;
+ ffile_offset += 8;
+
+ /* name (token) ********************************************/
+ memset(ffile + ffile_offset, 0, tokensize);
+ strcpy((char *)ffile + ffile_offset, hdr->token);
+ glob_rom_pos += tokensize;
+ ffile_offset += tokensize;
+
+ /* image file **********************************************/
+ if (NULL == hdr->linked_to) {
+ if (! file_exist(hdr->imagefile, 1)) {
+ printf("access error to file: %s\n", hdr->imagefile);
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+
+ imgfd = open(hdr->imagefile, O_RDONLY);
+ if (0 >= imgfd) {
+ perror(hdr->imagefile);
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+
+ /* now copy file to file buffer */
+ cnt = 0;
+ while (1) {
+ i = read(imgfd, ffile + ffile_offset, ffsize-ffile_offset);
+ if (i <= 0) break;
+ glob_rom_pos += i;
+ ffile_offset += i;
+ cnt += i;
+ }
+
+ /* pad file */
+ glob_rom_pos += pad8_num(datasize) - datasize;
+ ffile_offset += pad8_num(datasize) - datasize;
+
+ /* sanity check */
+ if (cnt != datasize) {
+ printf("BUG!!! copy error on image file [%s](e%d, g%d)\n",
+ hdr->imagefile, datasize, cnt);
+ close(imgfd);
+ close(ofd);
+ free(ffile);
+ return 1;
+ }
+ close(imgfd);
+ }
+
+ /* limiter *************************************************/
+ val64.low = -1;
+ val64.high = -1;
+ memcpy(ffile + ffile_offset, &val64, 8);
+ glob_rom_pos += 8;
+ ffile_offset += 8;
+
+ /* *********************************************************/
+ ///printf("FLEN=%6d TOK=%-11s FILE=%s\n",
+ /// ffsize,
+ /// hdr->token,
+ /// hdr->imagefile);
+/* change done 9.3.2005*/
+ if (write_to_file(ofd, ffile, ffsize) != 0) {
+ printf("Failed while processing file '%s' (size = %d bytes)\n",
+ hdr->imagefile, datasize);
+ return 1;
+ }
+/* by Rolf Schaefer */
+ free(ffile);
+ hdr = hdr->next;
+ glob_num_files++;
+
+ if (NULL == hdr) break;
+ }
+/* change done 09.03.2005 */
+ writeDataStream(ofdCRC);
+/* by Rolf Schaefer */
+ close(ofd);
+ close(ofdCRC);
+
+ return 0;
+}
+
+int file_exist(char *name, int errdisp)
+{
+ struct stat fileinfo;
+
+ memset((void*)&fileinfo, 0, sizeof(struct stat));
+ if (stat(name, &fileinfo) != 0) {
+ if (0 != errdisp) {
+ perror(name);
+ }
+ return 0;
+ }
+ if (S_ISREG(fileinfo.st_mode)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* changes done 2005_March-09 */
+int write_to_file(int fd, unsigned char *buf, int size)
+{
+ int i;
+
+ if (buildDataStream(buf, size) != 0)
+ return -1;
+
+ for ( ; size; size -= i, buf += i) {
+ i = write(fd, buf, size);
+ if (i < 0) {
+ perror("write to image");
+ return 1;
+ }
+ }
+
+/*by Rolf Schaefer */
+
+ return 0;
+}
diff --git a/romfs/tools/cfg_parse.c b/romfs/tools/cfg_parse.c
new file mode 100644
index 0000000..da4d75b
--- /dev/null
+++ b/romfs/tools/cfg_parse.c
@@ -0,0 +1,383 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cfgparse.h>
+
+int glob_come_from_cr = 0;
+
+int find_next_entry(int file, struct ffs_chain_t *chain)
+{
+#define MAX_LINE_SIZE 1024
+ char lnbuf[MAX_LINE_SIZE], b0=0, b1=0;
+ char *start, *end, *next;
+ struct ffs_header_t *hdr; //, *hdr2;
+ int lc, rc;
+ char c;
+
+ /* search for new config line */
+ if (0 == glob_come_from_cr) {
+ while (1 == (rc = read(file, &c, 1))) {
+ //printf("b0=%c b1=%c c=%c\n",
+ // b0, b1, c);
+ b0 = b1;
+ b1 = c;
+ /* this looks for starting sign "<CR>[^#]" */
+ if ( ((0x0a == b0) || (0x0d == b0)) &&
+ (('#' != b1) && (0x0a != b1) &&
+ (0x0d != b1))) {
+ break;
+ }
+ }
+ } else {
+ /* normalize */
+ while (1 == (rc = read(file, &c, 1))) {
+ //printf("read c=%c\n", c);
+ if ((0x0a != c) && (0x0d != c)) {
+ break;
+ }
+ }
+ glob_come_from_cr = 0;
+ //printf("debug: glob_come_from_cr = 0\n");
+ }
+ if (1 != rc) {
+ return 1;
+ }
+
+ /* now buffer it until end of line */
+ memset((void*) lnbuf, 0, MAX_LINE_SIZE);
+ lnbuf[0] = c;
+ lc = 1;
+ while ((1 == read(file, &(lnbuf[lc]), 1)) && (lc < MAX_LINE_SIZE)) {
+ //printf("read lnbuf=%c\n", lnbuf[lc]);
+ if ((0x0a == lnbuf[lc]) || (0x0d == lnbuf[lc])) {
+ glob_come_from_cr = 1;
+ //printf("debug: glob_come_from_cr = 1\n");
+ break;
+ }
+ lc++;
+ }
+
+ /* allocate header */
+ hdr = malloc(sizeof(struct ffs_header_t));
+ if (NULL == hdr) {
+ perror("alloc memory");
+ return 2;
+ }
+ memset((void*)hdr, 0, sizeof(struct ffs_header_t));
+
+ /* attach header to chain */
+ if (0 != add_header(chain, hdr)) {
+ return 2;
+ }
+
+ /**********************************************************/
+ /* extract token name *********************************** */
+ start = NULL;
+ if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) {
+ printf("parsing error 1");
+ return 2;
+ }
+ /* get memory for it */
+ hdr->token = malloc(end - start + 1);
+ if (NULL == hdr->token) {
+ return 2;
+ }
+ /* set string */
+ strncpy(hdr->token, start, end - start + 1);
+ hdr->token[end - start] = 0;
+
+ /**********************************************************/
+ /* extract file name *********************************** */
+ if (NULL == next) {
+ return 2;
+ }
+ start = next;
+ if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) {
+ printf("parsing error 1");
+ return 2;
+ }
+
+ /* get memory for it */
+ hdr->imagefile = malloc(end - start + 1);
+ if (NULL == hdr->imagefile) {
+ return 2;
+ }
+
+ /* check if file is existing */
+
+ /* set string */
+ strncpy(hdr->imagefile, start, end - start + 1);
+ hdr->imagefile[end - start] = 0;
+
+ /* check if entry is linked to another header */
+ if (':' == *start) {
+ printf("\nERROR: links are removed as feature in this version\n");
+ return 2;
+
+ /*
+ start++;
+ if (0 != find_entry_by_token(chain, hdr->imagefile+1, &hdr2)) {
+ printf("[%s]: link to [%s] not found\n",
+ hdr->token, hdr->imagefile+1);
+ dump_fs_contents(chain);
+ return 2;
+ }
+ hdr->linked_to = hdr2;
+ */
+ }
+
+ /**********************************************************/
+ /* extract flags name *********************************** */
+ if (NULL == next) {
+ return 2;
+ }
+ start = next;
+ if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) {
+ printf("parsing error 1");
+ return 2;
+ }
+ hdr->flags = strtoul(start, NULL, 16);
+
+ /**********************************************************/
+ /* extract rom start name *********************************** */
+ if (NULL == next) {
+ return 2;
+ }
+ start = next;
+ if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) {
+ printf("parsing error 1");
+ return 2;
+ }
+ if ('-' == *start) {
+ /* this means not specific address request for data */
+ hdr->romaddr = 0;
+ } else {
+ /* data has to begin at specific address */
+ hdr->romaddr = strtoul(start, NULL, 16);
+ }
+
+ return 0;
+}
+
+void debug_print_range(char *s, char *e)
+{
+ while (s < e) {
+ printf("%c", *s);
+ s++;
+ }
+}
+
+int inbetween_white(char *s, int max, char **start, char **end, char **next)
+{
+ int pos = 0, posalt;
+
+ if (NULL != *start) {
+ pos = *start - s;
+ s = *start;
+ }
+
+ /* wind to first non white */
+ while (pos < max) {
+ if ((' ' == *s) || (' ' == *s)) {
+ s++;
+ pos++;
+ continue;
+ }
+ break;
+ }
+ if (pos >= max) {
+ /* no non-white found */
+ return 1;
+ }
+
+ /* assign start */
+ *start = s;
+
+ /* wind to end of non white or end of buffer */
+ posalt = pos;
+ while (pos < max) {
+ if ((' ' == *s) || (' ' == *s) ||
+ (0x0a == *s) || (0x0d == *s)) {
+ break;
+ }
+ s++;
+ pos++;
+ }
+
+ if (pos == posalt) {
+ return 1;
+ }
+
+ *end = s;
+
+ if ((pos + 1) >= max) {
+ *next = NULL;
+ } else {
+ *next = s;
+ }
+
+ return 0;
+}
+
+int add_header(struct ffs_chain_t *chain, struct ffs_header_t *hdr)
+{
+ struct ffs_header_t *next;
+
+ if (NULL == chain->first) {
+ chain->first = hdr;
+ return 0;
+ }
+ next = chain->first;
+
+ /* find last */
+ while (NULL != next->next) {
+ next = next->next;
+ }
+ next->next = hdr;
+
+ return 0;
+}
+
+int find_entry_by_token(struct ffs_chain_t *chain, char *token,
+ struct ffs_header_t **hdr)
+{
+ struct ffs_header_t *next;
+
+ if (NULL == chain->first) {
+ *hdr = NULL;
+ return 1;
+ }
+ next = chain->first;
+
+ //printf("debug: search for [%s]...\n", token);
+
+ while (1) {
+ //printf(" > [%s]\n", next->token);
+ if (strcmp(token, next->token) == 0) {
+ *hdr = next;
+ //printf(" > found\n");
+ break;
+ }
+ if (NULL == next->next) {
+ //printf(" > reached end of chain, not found\n");
+ return 1;
+ }
+ next = next->next;
+ }
+ return 0;
+}
+
+void dump_fs_contents(struct ffs_chain_t *chain)
+{
+ struct ffs_header_t *next;
+
+ if (NULL == chain->first) {
+ printf("no contents in fs\n");
+ return;
+ }
+ next = chain->first;
+
+ while (1) {
+ if (NULL != next->token) {
+ printf("Token [%s] ", next->token);
+ } else {
+ printf(" [not-set], ");
+ }
+
+ if (NULL != next->imagefile) {
+ printf(" <%s>, ", next->imagefile);
+ } else {
+ printf(" file<not-set>, ");
+ }
+
+ printf("flags<%llx>, ", next->flags);
+ printf("romaddr<%llx>, ", next->romaddr);
+
+ if (NULL != next->linked_to) {
+ printf("linked to [%s]", next->linked_to->token);
+ }
+
+ printf("\n");
+ if (NULL == next->next) {
+ break;
+ }
+
+ next = next->next;
+ }
+
+}
+
+void free_chain_memory(struct ffs_chain_t *chain)
+{
+ struct ffs_header_t *hdr, *next_hdr;
+
+ if (NULL != chain->first) {
+ hdr = chain->first;
+ chain->first = NULL;
+ } else {
+ return;
+ }
+
+ while (NULL != hdr) {
+ //printf("%p ", hdr);
+ if (NULL != hdr->token) {
+ //printf("free up %s\n", hdr->token);
+ free(hdr->token);
+ }
+ if (NULL != hdr->imagefile) {
+ free(hdr->imagefile);
+ }
+ next_hdr = hdr->next;
+ free(hdr);
+ hdr = next_hdr;
+ }
+}
+
+
+/*
+ * Detect duplicate entries in the romfs list
+ */
+void find_duplicates(struct ffs_chain_t *chain)
+{
+ struct ffs_header_t *act, *sub;
+
+ if (NULL == chain->first) {
+ printf("no contents in fs\n");
+ return;
+ }
+ act = chain->first;
+
+ do {
+ sub = act->next;
+ while (sub != NULL) {
+
+ if (act->token == NULL || sub->token == NULL) {
+ printf("find_duplicates: token not set!\n");
+ }
+ else if (strcmp(act->token, sub->token) == 0) {
+ printf("*** NOTE: duplicate romfs file '%s'.\n", act->token);
+ }
+ sub = sub->next;
+ }
+
+ act = act->next;
+
+ } while (act != NULL);
+
+}
diff --git a/romfs/tools/cfgparse.h b/romfs/tools/cfgparse.h
new file mode 100644
index 0000000..7ccf9b7
--- /dev/null
+++ b/romfs/tools/cfgparse.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef CFGPARSE_H
+#define CFGPARSE_H
+
+struct ffs_chain_t {
+ struct ffs_header_t *first;
+};
+
+struct ffs_header_t {
+ unsigned long long flags;
+ unsigned long long romaddr;
+ char *token;
+ char *imagefile;
+ int imagefile_length;
+ struct ffs_header_t *linked_to;
+ struct ffs_header_t *next;
+ unsigned long long save_data;
+ unsigned long long save_data_len;
+ int save_data_valid;
+};
+
+int find_next_entry(int file, struct ffs_chain_t *chain);
+int inbetween_white(char *s, int max, char **start, char **end, char **next);
+void debug_print_range(char *s, char *e);
+void free_chain_memory(struct ffs_chain_t *chain);
+int add_header(struct ffs_chain_t *, struct ffs_header_t *);
+int find_entry_by_token(struct ffs_chain_t *, char *, struct ffs_header_t **);
+void dump_fs_contents(struct ffs_chain_t *chain);
+void find_duplicates(struct ffs_chain_t *chain);
+
+int build_ffs(struct ffs_chain_t *fs, char *outfile);
+#endif
diff --git a/romfs/tools/create_crc.c b/romfs/tools/create_crc.c
new file mode 100644
index 0000000..2db79b7
--- /dev/null
+++ b/romfs/tools/create_crc.c
@@ -0,0 +1,483 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <cfgparse.h>
+#include <time.h>
+#include <calculatecrc.h>
+#include <product.h>
+#include <byteswap.h>
+#include <endian.h>
+
+int createHeaderImage(void);
+unsigned int calCRCEthernet32(unsigned char *TextPtr, unsigned long int TextLength, unsigned int AccumCRC);
+int createCRCParameter(uint64_t *ui64RegisterMask, unsigned int *iRegisterLength);
+uint64_t calCRCbyte(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC);
+uint64_t calCRCword(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC);
+uint64_t checkCRC(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC);
+int insert64bit(uint64_t ui64CRC, uint32_t uliPosition);
+
+static uint64_t ui64globalFileSize=0; // file length in bytes
+static unsigned char pucFileStream[4400000]; // space for the file stream >= 4MB + 4bytes
+static uint64_t ui64globalHeaderSize=0; // header length in bytes
+static int iglobalHeaderFlag = 1; // flag to filter detect the header in buildDataStream()
+static uint64_t ui64Generator1;
+/*----------------------------------------------------------------------*/
+/* */
+/* Build the file image and store it as Data Stream of bytes */
+/* calculate a first CRC for the first file and */
+/* chatch the position of this CRC */
+/*----------------------------------------------------------------------*/
+int buildDataStream(unsigned char *pucbuf, int size)
+{
+ if (ui64globalFileSize + size > sizeof(pucFileStream)) {
+ printf("Error: File size is too big!\n");
+ return -1;
+ }
+
+ for( ; size; size -=1, pucbuf +=1) {
+
+ pucFileStream[ui64globalFileSize] = *pucbuf;
+ ui64globalFileSize++;
+ }
+ if(iglobalHeaderFlag == 1) { // catch header
+
+ ui64globalHeaderSize = ui64globalFileSize;
+ iglobalHeaderFlag = 0;
+ }
+
+ return 0;
+}
+/*--------------------------------------------------------------------------------- */
+/* +
++ write Header.img +
++ +
++ note: use insert64bit to write all uint64_t variables because of +
++ Big Endian - Little Endian problem between Intel CPU and PowerPC CPU */
+/* -------------------------------------------------------------------------------- */
+int createHeaderImage(void)
+{
+ int iCounter;
+ uint64_t ui64RomAddr, ui64DataAddr, ui64FlashlenAddr;
+ time_t caltime;
+ struct tm *tm;
+ char *pcVersion;
+ char dastr[16];
+ unsigned long long da;
+
+ union {
+ unsigned char pcArray[FLASHFS_HEADER_DATA_SIZE];
+ struct stH stHeader;
+ } uHeader;
+
+ memset(uHeader.pcArray,0x00, FLASHFS_HEADER_DATA_SIZE); // initialize Header
+
+ /* read driver info */
+ if(NULL != (pcVersion = getenv("DRIVER_NAME"))) {
+ strncpy(uHeader.stHeader.version, pcVersion,16);
+ }
+ else if (NULL != (pcVersion = getenv("USER")) ) {
+ strncpy(uHeader.stHeader.version, pcVersion,16);
+ }
+ else if(pcVersion == NULL) {
+ strncpy(uHeader.stHeader.version, "No known user!",16 );
+ }
+
+ /* read time and write it into data stream */
+ if ( (caltime = time(NULL)) ==-1) {
+ printf("time error\n");
+ }
+ if ( (tm = localtime(&caltime)) == NULL) {
+ printf("local time error\n");
+ }
+
+ // length must be 13 instead 12 because of terminating NUL. Therefore uH.stH.platform_revison
+ // must be writen later to overwrite the terminating NUL
+ if(strftime(dastr, 15, "0x%Y%m%d%H%M", tm) == 0) {
+ printf("strftime error\n");
+ }
+ da=strtoll(dastr,NULL, 16);
+ #if __BYTE_ORDER == __LITTLE_ENDIAN
+ da=__bswap_64(da) >> 16;
+ #else
+ da = da << 16;
+ #endif
+ memcpy(uHeader.stHeader.date, &da, 8);
+
+ strcpy(uHeader.stHeader.magic,FLASHFS_MAGIC); // write Magic value into data stream
+ strcpy(uHeader.stHeader.platform_name,FLASHFS_PLATFORM_MAGIC); // write platform name into data stream
+ strcpy(uHeader.stHeader.platform_revision,FLASHFS_PLATFORM_REVISION); // write platform recision into data stream
+
+
+ /* fill end of file info (8 bytes of FF) into data stream */
+ uHeader.stHeader.ui64FileEnd = (uint64_t)(0xFFFFFFFF);
+ uHeader.stHeader.ui64FileEnd = (uHeader.stHeader.ui64FileEnd << 32) + (uint64_t)0xFFFFFFFF;
+
+ /* read address of next file and address of header date, both are 64 bit values */
+ ui64RomAddr = 0;
+ ui64DataAddr = 0;
+ for(iCounter = 0; iCounter < 8; iCounter++) {
+
+ ui64RomAddr = ( ui64RomAddr << 8 ) + pucFileStream[FLASHFS_ROMADDR + iCounter]; // addr of next file
+ ui64DataAddr = ( ui64DataAddr << 8) + pucFileStream[FLASHFS_DATADDR + iCounter]; // addr of header data
+ }
+
+ /* calculate final flash-header-size and flash-file-size */
+ ui64globalHeaderSize = (uint32_t)ui64DataAddr + (uint32_t)FLASHFS_HEADER_DATA_SIZE; // calculate end addr of header
+ ui64globalHeaderSize -=8; // cut 64 bit to place CRC for File-End
+ ui64globalFileSize += 8; // add 64 bit to place CRC behind File-End
+
+ if( ui64globalHeaderSize < ui64RomAddr ) {
+ memset( &pucFileStream[ui64DataAddr], 0, (ui64RomAddr-ui64DataAddr)); // fill free space in Header with zeros
+ // place data to header
+ memcpy( &pucFileStream[ui64DataAddr], uHeader.pcArray, FLASHFS_HEADER_DATA_SIZE); // insert header data
+
+ // insert header length into data stream
+ ui64FlashlenAddr = (uint64_t)FLASHFS_HEADER_SIZE_ADDR;
+ insert64bit(ui64globalHeaderSize, ui64FlashlenAddr );
+
+ // insert flash length into data stream
+ ui64FlashlenAddr = ((uint64_t)ui64DataAddr +(uint64_t)FLASHFS_FILE_SIZE_ADDR );
+ insert64bit(ui64globalFileSize, ui64FlashlenAddr);
+
+ // insert zeros as placeholder for CRC
+ insert64bit(0, (ui64globalHeaderSize -8) );
+ insert64bit(0, (ui64globalFileSize -8) );
+
+ return 0;
+ }
+ else {
+ printf("%s\n","--- Header File to long");
+ return 1;
+ }
+}
+/*--------------------------------------------------------------------- */
+/* */
+/* calculate standart ethernet 32 bit CRC */
+/* generator polynome is 0x104C11DB7 */
+/* this algorithm can be used for encoding and decoding */
+/*----------------------------------------------------------------------*/
+unsigned int calCRCEthernet32(unsigned char *TextPtr, unsigned long int TextLength, unsigned int AccumCRC) {
+ const unsigned int CrcTableHigh[16] = {
+ 0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90,
+ 0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7,
+ 0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E,
+ 0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09
+ };
+ const unsigned CrcTableLow[16] = {
+ 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
+ 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
+ 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
+ 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
+ };
+
+ unsigned char* Buffer = TextPtr;
+ unsigned long int Residual = TextLength;
+
+
+ while ( Residual > 0 ) {
+ unsigned int Temp = ((AccumCRC >> 24) ^ *Buffer) & 0x000000ff;
+ AccumCRC <<= 8;
+ AccumCRC ^= CrcTableHigh[ Temp/16 ];
+ AccumCRC ^= CrcTableLow[ Temp%16 ];
+ ++Buffer;
+ --Residual;
+ }
+ return AccumCRC;
+}
+/*------------------------------------------------------- calculate CRC */
+/* */
+/* */
+/*----------------------------------------------------------------------*/
+/* create CRC Parameter: CRC Polynome, Shiftregister Mask and length */
+// ui64Generator[0] = 0;
+// ui64Generator[1] = 0x42F0E1EB;
+// ui64Generator[1] = (ui64Generator[1] << 32) + 0xA9EA3693;
+// iRegisterLength = 63;
+// ui64RegisterMask = 0xffffffff;
+// ui64RegisterMask = ((ui64RegisterMask) << 32) + 0xffffffff;
+/* ucl=0x00000000ffffffff = Mask for 32 bit LSFR to cut down number of bits
+ in the variable to get the same length as LFSR
+
+ il = length of LSFR = degree of generator polynom reduce il by one to calculate the degree
+ of the highest register in LSFR
+
+ Examples:
+ CRC-16 for Tap: x16 + x15 + x2 + 1
+ generator = 0x8005, il = 16, ucl = 0x000000000000FFFF
+
+ CRC-16 for Floppy: x16 + x12 + x5 +1
+ generator = 0x1021, il = 16, ucl = 0x000000000000FFFF
+
+ CRC-32 for Ethernet: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+ generator = 0x04C11DB7, il = 32, ucl = 0x00000000FFFFFFFF
+
+ CRC-64 SP-TrEMBL x64 + x4 + x3 + x + 1 (maximal-length LFSR)
+ renerator = 0x1B, il = 64, ucl = 0xFFFFFFFFFFFFFFFF
+
+ CRC-64 improved x64 + x63 + x61 + x59 + x58 + x56 + x55 + x52 + x49 + x48 + x47 + x46+ x44 +
+ x41 + x37 + x36 + x34 + x32 + x31 + x28 + x26 + x23 + x22 + x19 + x16 + x13 +
+ x12 + x10 + x9 + x6 + x4 + x3 + 1 (see http://www.cs.ud.ac.uk/staff/D.Jones/crcbote.pdf)
+ grenerator = 0xAD93D23594C9362D, il = 64, ucl = 0xFFFFFFFFFFFFFFFF
+
+ CRC-64 DLT1 spec x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 +
+ x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 +
+ x10 + x9 + x7 + x4 + x + 1
+ (see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf -> page63)
+ generator = 0x42F0E1EBA9EA3693
+
+ CRC-64 from internet G(x)= 1006003C000F0D50B
+*/
+
+/*--------------------------------------------------------------------- */
+int createCRCParameter(uint64_t *ui64RegisterMask, unsigned int *uiRegisterLength)
+{
+ enum Generators {Tape_16, Floppy_16, Ethernet_32, SPTrEMBL_64, SPTrEMBL_improved_64,DLT1_64};
+ enum Generators Generator;
+
+ Generator = CRC_METHODE;
+ switch (Generator){
+ case Tape_16:{
+ *ui64RegisterMask = 0x0000ffff;
+ ui64Generator1 = 0x00008005;
+ *uiRegisterLength = 16;
+ break;
+ }
+ case Floppy_16: {
+ *ui64RegisterMask = 0x0000ffff;
+ ui64Generator1 = 0x00001021;
+ *uiRegisterLength = 16;
+ break;
+ }
+ case Ethernet_32: {
+ *ui64RegisterMask = 0xffffffff;
+ ui64Generator1 = 0x04C11DB7;
+ *uiRegisterLength = 32;
+ break;
+ }
+ case SPTrEMBL_64: {
+ *ui64RegisterMask = 0xffffffff;
+ *ui64RegisterMask = ((*ui64RegisterMask) << 32) + 0xffffffff;
+ ui64Generator1 = 0x0000001B;
+ *uiRegisterLength = 64;
+ break;
+ }
+ case SPTrEMBL_improved_64: {
+ *ui64RegisterMask = 0xffffffff;
+ *ui64RegisterMask = ((*ui64RegisterMask) << 32) + 0xffffffff;
+ ui64Generator1 = 0xAD93D235;
+ ui64Generator1 = (ui64Generator1 << 32) + 0x94C9362D;
+ *uiRegisterLength = 64;
+ break;
+ }
+ case DLT1_64:{
+ *ui64RegisterMask = 0xffffffff;
+ *ui64RegisterMask = ((*ui64RegisterMask) << 32) + 0xffffffff;
+ ui64Generator1 = 0x42F0E1EB;
+ ui64Generator1 = (ui64Generator1 << 32) + 0xA9EA3693;
+ *uiRegisterLength = 64;
+ break;
+ }
+ }
+ (*uiRegisterLength)--;
+
+ return 0;
+}
+/*------------------------------------------------ create CRC Parameter */
+/* */
+/* Check CRC by using Linear Feadback Shift Register (LFSR) */
+/*----------------------------------------------------------------------*/
+uint64_t calCRCbyte(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) {
+
+ uint64_t ui64Mask, ui64Generator0;
+ uint8_t ui8Buffer;
+ unsigned int uiRegisterLength;
+ int iShift;
+
+ createCRCParameter(&ui64Mask, &uiRegisterLength);
+
+ ui8Buffer = (*cPtr);
+ while ( ui32NoWords > 0) {
+ for (iShift = 7;iShift >= 0; iShift--) {
+
+ ui64Generator0 = (AccumCRC >> uiRegisterLength);
+ AccumCRC <<= 1;
+ ui64Generator0 &= 0x01;
+ ui64Generator0 = (0-ui64Generator0);
+ AccumCRC ^= (ui64Generator1 & ui64Generator0);
+ }
+ AccumCRC ^= ui8Buffer;
+ AccumCRC &= ui64Mask;
+ ui32NoWords -= 1;
+ cPtr += 1;
+ ui8Buffer = (*cPtr);
+ }
+ return AccumCRC;
+}
+/*--------------------------------------------------------------checkCRC */
+/* */
+/* Check CRC by using Linear Feadback Shift Register (LFSR) */
+/*----------------------------------------------------------------------*/
+uint64_t calCRCword(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) {
+
+ uint64_t ui64Mask, ui64Generator0;
+ uint16_t ui16Buffer;
+ unsigned int uiRegisterLength;
+ int iShift;
+
+ createCRCParameter(&ui64Mask, &uiRegisterLength);
+
+ if( (ui32NoWords%2) != 0) { // if Data string does not end at word boundery add one byte
+ ui32NoWords++;
+ cPtr[ui32NoWords] = 0;
+ }
+ ui16Buffer = ( (*(cPtr+0)) * 256) + (*(cPtr+1));
+ while ( ui32NoWords > 0) {
+ for (iShift = 15;iShift >= 0; iShift--) {
+ ui64Generator0 = (AccumCRC >> uiRegisterLength);
+ AccumCRC <<= 1;
+ ui64Generator0 &= 0x01;
+ ui64Generator0 = (0-ui64Generator0);
+ AccumCRC ^= (ui64Generator1 & ui64Generator0);
+ }
+ AccumCRC ^= ui16Buffer;
+ AccumCRC &= ui64Mask;
+ ui32NoWords -= 2;
+ cPtr += 2;
+ ui16Buffer = ( (*(cPtr+0)) * 256) + (*(cPtr+1));
+ }
+ return AccumCRC;
+}
+/*------------------------------------------------------------- checkCRCnew */
+/* */
+/* */
+/*------------------------------------------------------------------------- */
+uint64_t checkCRC(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) {
+
+ enum Generators {Ethernet_32};
+ enum Generators Generator;
+ uint64_t ui64Buffer = AccumCRC;
+
+ Generator = CRC_METHODE;
+
+ switch (Generator) {
+ case Ethernet_32: {
+ // (ui32NoWords - 4),no need of 4 bytes 0x as with shift-register method
+ AccumCRC = calCRCEthernet32( cPtr, (ui32NoWords-4), AccumCRC );
+ break;
+ }
+ default :{
+ AccumCRC = calCRCword( cPtr, ui32NoWords, AccumCRC);
+ break;
+ }
+ }
+
+ if( calCRCbyte(cPtr, ui32NoWords, ui64Buffer) != AccumCRC) {
+ printf("\n --- big Endian - small Endian problem --- \n");
+ AccumCRC--;
+ }
+
+ return( AccumCRC);
+}
+
+
+/*--------------------------------------------------------------------- CRC */
+/* */
+/* Insert 64 bit as Big Endian */
+/* into DataStream starting at (uli)Position */
+/*------------------------------------------------------------------------- */
+int insert64bit(uint64_t ui64CRC, uint32_t ui32Position)
+{
+
+ pucFileStream[ui32Position] = (char) ((ui64CRC >> 56) & 0x00FF);
+ pucFileStream[ui32Position+1] = (char) ((ui64CRC >> 48) & 0x00FF);
+ pucFileStream[ui32Position+2] = (char) ((ui64CRC >> 40) & 0x00FF);
+ pucFileStream[ui32Position+3] = (char) ((ui64CRC >> 32) & 0x00FF);
+
+ pucFileStream[ui32Position+4] = (char) ((ui64CRC >> 24) & 0x00FF);
+ pucFileStream[ui32Position+5] = (char) ((ui64CRC >> 16) & 0x00FF);
+ pucFileStream[ui32Position+6] = (char) ((ui64CRC >> 8) & 0x00FF);
+ pucFileStream[ui32Position+7] = (char) (ui64CRC & 0x00FF);
+
+ return 0;
+}
+/*----------------------------------------------------------- insertCRC */
+/* */
+/* insert header and file CRC into data stream */
+/* do CRC check on header and file */
+/* write data stream to disk */
+/*----------------------------------------------------------------------*/
+int writeDataStream(int iofd)
+{
+ uint64_t ui64FileCRC=0, ui64HeaderCRC=0, ui64RegisterMask;
+ unsigned int uiRegisterLength;
+
+ if(0 != createHeaderImage()) {
+ return 1;
+ }
+
+ createCRCParameter( &ui64RegisterMask, &uiRegisterLength);
+
+/* calculate CRC---------------------------------------------------- */
+ ui64HeaderCRC = checkCRC(pucFileStream, ui64globalHeaderSize, 0);
+ insert64bit(ui64HeaderCRC, (ui64globalHeaderSize-8) );
+
+ ui64FileCRC = checkCRC(pucFileStream, ui64globalFileSize, 0);
+ insert64bit(ui64FileCRC, (ui64globalFileSize -8) );
+
+/* report CRCs and proof if CRCs are correct implemented */
+ //printf("\n");
+ //printf("%s%X%X\n","Generator = 0x1",(uint32_t)(ui64Generator1>>32),(uint32_t)ui64Generator1);
+
+ //printf("%s%x%s%u%-9s%s%X%X\n","header size = 0x", (uint32_t)ui64globalHeaderSize, "/", (uint32_t)ui64globalHeaderSize," bytes","file CRC = 0x",(uint32_t)(ui64HeaderCRC >> 32),(uint32_t)ui64HeaderCRC);
+
+ //printf("Firmware Header CRC = 0x%08x\n", (uint32_t)ui64HeaderCRC);
+ //printf("Flash Image CRC = 0x%08x\n", (uint32_t)ui64FileCRC);
+
+ //printf("%s%x%s%u%-9s%s%X%X\n","flash size = 0x", (uint32_t)ui64globalFileSize, "/", (uint32_t)ui64globalFileSize," bytes","file CRC = 0x",(uint32_t)(ui64FileCRC >> 32),(uint32_t)ui64FileCRC);
+
+/* check CRC-implementation */
+ ui64HeaderCRC = calCRCword( pucFileStream, ui64globalHeaderSize, 0);
+ ui64FileCRC = calCRCword( pucFileStream, ui64globalFileSize, 0);
+
+ //printf("%s%X%X\n","header CRC check = 0x", (uint32_t)(ui64HeaderCRC >> 32),(uint32_t)ui64HeaderCRC);
+ //printf("%s%X%X\n","flash CRC check = 0x", (uint32_t)(ui64FileCRC >> 32),(uint32_t)ui64FileCRC);
+
+ if( (ui64HeaderCRC == 0) && (ui64FileCRC == 0) ) {
+ //printf("\n%s\n","CRCs correct implemented. ---> Data will be written to disk.");
+ /* write file image to disk */
+ if (0 < write(iofd, pucFileStream, ui64globalFileSize)) {
+ return 0;
+ }
+ else {
+ printf("<< write failed >>\n");
+ return -1;
+ }
+
+ }
+ else {
+ printf("\n\n %s \n %s \n\n","CRCs not correct implemented."," ---> Data will not be written do disk.");
+ return -1;
+ }
+}
+/*----------------------------------------------------- writeDataStream */
+
+
diff --git a/romfs/tools/create_flash.c b/romfs/tools/create_flash.c
new file mode 100644
index 0000000..1c968bd
--- /dev/null
+++ b/romfs/tools/create_flash.c
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cfgparse.h>
+
+#undef DEBUGGING
+
+#ifdef DEBUGGING
+#define dprintf(_x...) printf(_x)
+#else
+#define dprintf(_x...)
+#endif
+
+void print_usage()
+{
+ printf("args: description_file output_file\n\n");
+}
+
+int main (int argc, char *argv[])
+{
+ int conf_file, rc;
+ struct ffs_chain_t ffs_chain;
+
+ if (argc != 3) {
+ print_usage();
+ return EXIT_FAILURE;
+ }
+
+ dprintf("ROMFS FILESYSTEM CREATION V0.1 (bad parser)\n");
+ dprintf("Build directory structure...\n");
+
+ memset((void*) &ffs_chain, 0, sizeof(struct ffs_chain_t));
+ conf_file = open(argv[1], O_RDONLY);
+ if (0 >= conf_file) {
+ perror("load config file:");
+ return EXIT_FAILURE;
+ }
+
+ while (0 == (rc = find_next_entry(conf_file, &ffs_chain)));
+
+ if (1 >= rc) {
+#ifdef DEBUGGING
+ dump_fs_contents(&ffs_chain);
+#endif
+ dprintf("Build ffs and write to image file...\n");
+ if (build_ffs(&ffs_chain, argv[2]) != 0) {
+ fprintf(stderr, "build ffs failed\n");
+ rc = EXIT_FAILURE;
+ } else {
+ rc = EXIT_SUCCESS;
+ }
+ } else {
+ fprintf(stderr, "flash cannot be built due to config errors\n");
+ rc = EXIT_FAILURE;
+ }
+
+ /* Check if there are any duplicate entries in the image: */
+ find_duplicates(&ffs_chain);
+
+ free_chain_memory(&ffs_chain);
+ close(conf_file);
+ dprintf("\n");
+
+ /* If the build failed, remove the target image file */
+ if (rc == EXIT_FAILURE) {
+ unlink(argv[2]);
+ }
+
+ return rc;
+}
+
diff --git a/romfs/tools/createcrc.h b/romfs/tools/createcrc.h
new file mode 100644
index 0000000..10490ad
--- /dev/null
+++ b/romfs/tools/createcrc.h
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef CREATECRC_H
+#define CREATECRC_H
+
+int buildDataStream(unsigned char *pucbuf, int size);
+int createHeaderImgage(char *pcFilename);
+void writeDataStream(int ofd);
+#endif
diff --git a/rtas/Makefile.inc b/rtas/Makefile.inc
new file mode 100644
index 0000000..30e8015
--- /dev/null
+++ b/rtas/Makefile.inc
@@ -0,0 +1,89 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+# Before including this Makefile, you should specify the following variables
+# in your Makefile:
+# - RTASCMNDIR : Points to the common RTAS directory
+# - RTASBRDDIR : Points to the board specific RTAS directory
+# - TOOLSDIR : Points to the common tools directory
+# - OBJS : A list with all object files that should be linked into rtas.bin
+# - BOARD_SRCS : A list with all board specific source code files
+# (needed for "make depend")
+
+
+LDFLAGS = -nostdlib
+CPPFLAGS += -I$(RTASBRDDIR) -I$(RTASCMNDIR) \
+ -I$(INCLCMNDIR) -I$(INCLBRDDIR) \
+ -I$(LIBCMNDIR)/libc/include \
+ -I$(INCLCMNDIR)/$(CPUARCH)
+ASFLAGS = $(PLATFORM) -Wa,-mregnames $(FLAG)
+CFLAGS += -g -nostdinc -ffreestanding -Wall -Wextra -O2 -msoft-float \
+ -mno-altivec -mabi=no-altivec $(PLATFORM) $(FLAG)
+
+# Common RTAS files:
+RTAS_SRC_ASM = reloc.S rtas_common.S rtas_entry.S rtas_term.S \
+ rtas_cpu.S rtas_flash_asm.S rtas_mem.S rtas_ras.S
+RTAS_SRC_C = rtas_call.c rtas_flash_c.c rtas_h8.c \
+ rtas_nvramlog.c rtas_sensor.c rtas_init.c \
+ rtas_flash_cfi.c
+RTAS_SRCS = $(RTAS_SRC_ASM) $(RTAS_SRC_C)
+RTAS_OBJ_ASM = $(RTAS_SRC_ASM:%.S=%.o)
+RTAS_OBJ_C = $(RTAS_SRC_C:%.c=%.o)
+
+# Common build rules:
+$(RTAS_OBJ_C):
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $(@:%.o=$(RTASCMNDIR)/%.c) -o $@
+
+$(RTAS_OBJ_ASM):
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c $(@:%.o=$(RTASCMNDIR)/%.S) -o $@
+
+$(TOOLSDIR)/gen_reloc_table: $(TOOLSDIR)/gen_reloc_table.c
+ $(MAKE) -C $(TOOLSDIR) gen_reloc_table
+
+
+# Rules for building rtas.bin:
+rtas.bin: rtas
+ $(OBJCOPY) -O binary $< $@
+
+rtas: $(RTASCMNDIR)/rtas.lds $(OBJS) reloc_table.o $(LIBCMNDIR)/libc.a
+ $(LD) $(LDFLAGS) -o $@ -T $(RTASCMNDIR)/rtas.lds $(OBJS) \
+ reloc_table.o $(LIBCMNDIR)/libc.a
+
+reloc_table.o: $(TOOLSDIR)/gen_reloc_table $(OBJS) $(LIBCMNDIR)/libc.a
+ $(TOOLSDIR)/create_reloc_table.sh --ld "$(ONLY_LD)" --ldflags "$(LDFLAGS)" \
+ --lds "$(RTASCMNDIR)/rtas.lds" --objcopy "$(OBJCOPY)" $(OBJS) $(LIBCMNDIR)/libc.a
+
+
+$(LIBCMNDIR)/libc.a:
+ $(MAKE) -C $(LIBCMNDIR) libc
+
+
+# Rules for cleaning up:
+clean_rtas:
+ rm -f $(OBJS) reloc_table.o rtas rtas.bin
+ rm -f $(RTASCMNDIR)/*~ $(RTASCMNDIR)/*.o
+
+distclean_rtas: clean_rtas
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ rm -f Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile $(RTASCMNDIR)/Makefile.inc
+ $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(RTAS_SRCS:%=$(RTASCMNDIR)/%) > Makefile.dep
+ $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(BOARD_SRCS) >> Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/rtas/flash/block_lists.c b/rtas/flash/block_lists.c
new file mode 100644
index 0000000..52f4ee5
--- /dev/null
+++ b/rtas/flash/block_lists.c
@@ -0,0 +1,274 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <product.h>
+#include <stdio.h>
+
+unsigned char sig_org[] = FLASHFS_PLATFORM_MAGIC;
+
+/* this function is part of the crc_lib assembler code */
+unsigned long check_flash_image(unsigned long, unsigned long, unsigned long);
+
+/* this functions needs to be implemented by the board specific flash code
+ * the functions always get 32 bytes and needs to deal with the data */
+void write_flash(unsigned long, unsigned short *);
+
+int progress = 0;
+
+int
+print_progress()
+{
+ static int i = 3;
+ switch (i--) {
+ case 3:
+ printf("\b|");
+ break;
+ case 2:
+ printf("\b/");
+ break;
+ case 1:
+ printf("\b-");
+ break;
+ case 0:
+ printf("\b\\");
+ default:
+ i = 3;
+ }
+ return 0;
+}
+
+void
+print_hash()
+{
+ printf("\b# ");
+}
+
+void
+print_writing()
+{
+ int counter = 42;
+ printf("\nWriting Flash: |");
+ while (counter--)
+ printf(" ");
+ printf("|");
+ counter = 41;
+ while (counter--)
+ printf("\b");
+
+}
+
+int
+get_block_list_version(unsigned char *data)
+{
+ if (data[0] == 0x01)
+ return 1;
+ return 0;
+}
+
+static long
+get_image_size(unsigned long *data, unsigned long length)
+{
+ long size = 0;
+ unsigned long i;
+ for (i = 0; i < length / 8; i += 2) {
+ size += data[1 + i];
+ }
+ return size;
+}
+
+static long
+get_image_size_v0(unsigned long *data)
+{
+ unsigned long bl_size = data[0];
+ return get_image_size(data + 1, bl_size - 8);
+}
+
+static long
+get_image_size_v1(unsigned long *data)
+{
+ unsigned long *bl_addr = data;
+ unsigned long bl_size;
+ unsigned long *next;
+ long size = 0;
+ while (bl_addr) {
+ bl_size = bl_addr[0];
+ next = (unsigned long *) bl_addr[1];
+ bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL;
+ size += get_image_size(bl_addr + 2, bl_size - 0x10);
+ bl_addr = next;
+ }
+ return size;
+}
+
+long
+get_size(unsigned long *data, int version)
+{
+ if (version == 1)
+ return get_image_size_v1(data);
+ return get_image_size_v0(data);
+}
+
+static unsigned long
+write_one_block(unsigned long *block, unsigned long length,
+ unsigned long offset)
+{
+ unsigned long block_addr = (unsigned long) block;
+ unsigned long i = 0;
+ static unsigned int hash;
+ if (offset == 0)
+ hash = 0;
+
+ for (i = 0; i < length; i += 32, offset += 32, block_addr += 32) {
+ write_flash(offset, (unsigned short *) block_addr);
+ if (offset % 10 == 0) {
+ print_progress();
+ }
+ if (offset > hash * progress) {
+ print_hash();
+ hash++;
+ }
+ }
+
+ return offset;
+}
+
+static unsigned long
+write_one_list(unsigned long *bl, unsigned long length, unsigned long offset)
+{
+ unsigned long i;
+ // 0x10: /8 for pointer /2 it has to be done in steps of 2
+ for (i = 0; i < length / 0x10; i++) {
+ offset =
+ write_one_block((unsigned long *) *bl, *(bl + 1), offset);
+ bl += 2;
+ }
+ return offset;
+}
+
+void
+write_block_list(unsigned long *bl, int version)
+{
+ unsigned long offset = 0;
+ unsigned long *bl_addr = bl;
+ unsigned long bl_size;
+ unsigned long *next;
+
+ if (version == 0) {
+ // -8 = removed header length
+ write_one_list(bl + 1, *(bl) - 8, offset);
+ return;
+ }
+
+ while (bl_addr) {
+ bl_size = bl_addr[0];
+ next = (unsigned long *) bl_addr[1];
+ bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL;
+ // -0x10 = removed header length
+ offset = write_one_list(bl_addr + 2, bl_size - 0x10, offset);
+ bl_addr = next;
+ }
+
+}
+
+static int
+check_one_list(unsigned long *bl, unsigned long length, unsigned long crc)
+{
+ unsigned long i;
+ // 0x10: /8 for pointer /2 it has to be done in steps of 2
+ for (i = 0; i < length / 0x10; i++) {
+ crc = check_flash_image((unsigned long) *bl, *(bl + 1), crc);
+ bl += 2;
+ }
+ return crc;
+}
+
+int
+image_check_crc(unsigned long *bl, int version)
+{
+ unsigned long *bl_addr = bl;
+ unsigned long bl_size;
+ unsigned long *next;
+ unsigned long crc = 0;
+
+ if (version == 0) {
+ // -8 = removed header length
+ return check_one_list(bl + 1, *(bl) - 8, crc);
+ }
+
+ while (bl_addr) {
+ bl_size = bl_addr[0];
+ next = (unsigned long *) bl_addr[1];
+ bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL;
+ // -0x10 = removed header length
+ crc = check_one_list(bl_addr + 2, bl_size - 0x10, crc);
+ bl_addr = next;
+ }
+ return crc;
+}
+
+static int
+check_platform_one_list(unsigned long *bl, unsigned long bytesec)
+{
+ unsigned long pos = bytesec;
+ unsigned char *sig_tmp, *sig;
+ unsigned long size = 0;
+ sig = sig_org;
+
+ while (size < bytesec) {
+ size += bl[1];
+
+ while (size > pos) { // 32 == FLASHFS_PLATFORM_MAGIC length
+ sig_tmp = (unsigned char *) (bl[0] + pos);
+ if (*sig++ != *sig_tmp)
+ return -1;
+ if (*sig_tmp == '\0' || (pos == bytesec + 32)) {
+ pos = bytesec + 32;
+ break;
+ }
+ pos++;
+ }
+ if (pos == (bytesec + 32))
+ return 0;
+ bl += 2;
+ }
+ return 0;
+}
+
+int
+check_platform(unsigned long *bl, unsigned int bytesec, int version)
+{
+ unsigned long *bl_addr = bl;
+ unsigned long bl_size;
+ unsigned long *next;
+ unsigned long *ptr;
+ ptr = bl;
+
+ if (version == 0) {
+ ptr += 1; // -8 = removed header length
+ return check_platform_one_list(ptr, bytesec);
+ }
+ while (bl_addr) {
+ ptr = bl_addr + 2; // -0x10 = removed header length
+ bl_size = bl_addr[0];
+ next = (unsigned long *) bl_addr[1];
+ bl_size = bl_size & 0x00FFFFFFFFFFFFFFUL;
+ if ((bl_size - 0x10) == 0) {
+ bl_addr = next;
+ continue;
+ }
+ if (check_platform_one_list(ptr, bytesec) == 0)
+ return 0;
+
+ bl_addr = next;
+ }
+ return -1;
+}
diff --git a/rtas/flash/block_lists.h b/rtas/flash/block_lists.h
new file mode 100644
index 0000000..cad4668
--- /dev/null
+++ b/rtas/flash/block_lists.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+extern int progress;
+extern unsigned char sig_org[];
+
+void print_progress();
+void print_hash();
+int get_block_list_version(unsigned char *);
+int image_check_crc(unsigned long *, int);
+long get_size(unsigned long *, int);
+void print_writing();
+void write_block_list(unsigned long *, int);
+int check_platform(unsigned long *, unsigned int, int);
diff --git a/rtas/reloc.S b/rtas/reloc.S
new file mode 100644
index 0000000..eb54e44
--- /dev/null
+++ b/rtas/reloc.S
@@ -0,0 +1,183 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <rtas.h>
+
+/*
+Function:
+ Input:
+ r3: Destination to copy rtas code to
+ r4: Configuration
+ Output:
+ r3: Entry point for rtas calls
+Decription: Called by OpenFirmware to instantiate rtas, needs to copy
+ itself to destination, also do a relocations.
+
+*/
+
+.extern rtas_entry
+.extern .stack
+.extern _got
+.extern _got_end
+.extern __bss_start
+.extern __bss_end
+.extern rtas_config
+
+
+ .section ".rtasstart","ax";
+ .align 3
+ .globl _rtas_start
+_rtas_start:
+ mflr r10 # save link register
+ bcl 20,31,.over # branch (always) to .over
+
+.base:
+ .align 3
+
+/* Our Open Firmware needs to know the size of the RTAS binary and the
+ * size & address of the RTAS function jump table. SLOF always looks for this
+ * information in the following three quads here at the very beginning of the
+ * RTAS binary at offset 8. So DO NOT DELETE/MOVE them! */
+
+._rtas_size: .quad _rtas_end-_rtas_start
+._ptr_to_func_tab: .quad rtas_func_tab-_rtas_start
+._ptr_to_func_tab_size: .quad rtas_func_tab_size-_rtas_start
+
+/* The other variables are not accessed by SLOF anymore: */
+
+._rel_offset: .quad _reloc_table_start-_rtas_start
+._rel_end_offset: .quad _reloc_table_end-_rtas_start
+._bss_offset: .quad __bss_start-_rtas_start
+._bss_end_offset: .quad __bss_end-_rtas_start
+._rtas_entry_offset: .quad rtas_entry-_rtas_start
+._rtas_config_offset: .quad rtas_config-_rtas_start
+._rtas_stack: .quad .stack-_rtas_start+RTAS_STACKSIZE-0x60
+._rtas_toc: .quad _got-_rtas_start+0x8000
+
+.over:
+ mflr r8 # gpr 8 is the base
+ addi r8,r8,_rtas_start-.base # points to _rtas_start
+ mr r11,r4 # Save config value
+
+# Copy rtas code
+
+ ld r5,._rtas_size-_rtas_start(r8)
+ mr r4,r8 # Start of rtas
+ addi r6,r3,-8 # Destination
+ addi r4,r4,-8 # Source
+ srdi r5,r5,3 # Count in quads
+ mtctr r5
+0:
+ ldu r0,8(r4)
+ stdu r0,8(r6)
+ bdnz 0b
+
+# Clear bss
+
+ ld r4,._bss_offset-_rtas_start(r8)
+ ld r5,._bss_end_offset-_rtas_start(r8)
+ li r0,0
+ add r6,r3,r4 # Address bss in copied code
+ addi r6,r6,-8
+ sub r5,r5,r4 # Calculate bss size
+ srdi r5,r5,3 # Count in quads
+ mtctr r5
+0:
+ stdu r0,8(r6)
+ bdnz 0b
+
+# Relocate got
+
+ ld r4, ._rel_offset-_rtas_start(r8)
+ ld r5, ._rel_end_offset-_rtas_start(r8)
+ sub r5, r5,r4 # Calculate reloc table size
+ cmpdi r5, 0 # No reloc table ?
+ beq 1f
+
+ add r4, r4, r3 # Calculate reloc table address
+ addi r4, r4, -4
+ srdi r5, r5, 2 # Count in words
+ mtctr r5
+0:
+ lwzu r6, 4(r4) # Load offset out of reloc table
+ ldx r0, r6, r3 # Load value
+ add r0, r0, r3 # Add relocation offset = load address
+ stdx r0, r6, r3
+ bdnz 0b
+1:
+
+# Save config data
+
+ ld r5,._rtas_config_offset-_rtas_start(r8)
+ add r5,r5,r3
+ std r11,0(r5)
+
+# Flush to memory
+
+ mr r4,r3 # Destination address
+ ld r5,._rtas_size-_rtas_start(r8)
+
+ add r5,r5,r4
+ addi r5,r5,127
+ rlwinm r4,r4,0,0,24
+ rlwinm r5,r5,0,0,24
+ sub r5,r5,r4
+ srwi r5,r5,7
+ mtctr r5
+0:
+ dcbst 0,r4
+ sync
+ icbi 0,r4
+ sync
+ isync
+ addi r4,r4,128
+ bdnz 0b
+
+# Call init function
+ mfmsr r11 # Switch to 64 bit mode
+ mr r7,r11
+ rotldi r11,r11,1
+ ori r11,r11,1
+ rotldi r11,r11,63
+ mtmsrd r11
+ isync
+ mr r9,r1 # save old stack pointer
+ ld r1,._rtas_stack-_rtas_start(r8) # load new stack pointer
+ add r1,r1,r3
+ std r9,0(r1) # save stack pointer
+ std r2,64(r1) # save toc
+ std r7,72(r1) # save old msr value
+
+ ld r2,._rtas_toc-_rtas_start(r8) # load got pointer
+ add r2,r2,r3
+
+ bl save_regs_r3_r12
+ bl .rtas_init
+ bl restore_regs_r3_r12
+
+ ld r11,72(r1) # restore msr value
+ ld r2,64(r1) # restore toc
+ ld r1,0(r1) # get old stack
+
+ mtmsrd r11 # restore msr
+ isync
+
+
+# Return rtas entry
+
+ ld r4,._rtas_entry_offset-_rtas_start(r8)
+ add r3,r3,r4
+ mtlr r10
+ blr
+
+
+
diff --git a/rtas/rtas.lds b/rtas/rtas.lds
new file mode 100644
index 0000000..854485b
--- /dev/null
+++ b/rtas/rtas.lds
@@ -0,0 +1,49 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+
+SECTIONS {
+ .text 0:
+ {
+ *(.rtasstart)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.opd)
+ } =0x60000000
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ }
+ .got :
+ {
+ _got = .;
+ *(.got .toc)
+ }
+ .reloc :
+ {
+ . = ALIGN(4);
+ _reloc_table_start = .;
+ *(.reloc)
+ _reloc_table_end = .;
+ }
+ .bss :
+ {
+ __bss_start = .;
+ *(*COM* .bss .sbss .gnu.linkonce.b.*)
+ __bss_end = .;
+ }
+ __bss_size = (__bss_end - __bss_start);
+ _rtas_end = .;
+}
diff --git a/rtas/rtas_call.c b/rtas/rtas_call.c
new file mode 100644
index 0000000..6cc7351
--- /dev/null
+++ b/rtas/rtas_call.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <types.h>
+#include <rtas.h>
+#include "rtas_table.h"
+
+
+//#define _RTAS_TRACE
+//#define _RTAS_COUNT_CALLS
+
+
+#ifdef _RTAS_COUNT_CALLS
+int rtas_callcount[0x40] __attribute__((aligned (16)));
+#endif
+
+/* rtas_config is used to store the run-time configuration flags (which are
+ * provided by SLOF during instantiate-rtas) */
+long rtas_config;
+
+
+/*
+Function: rtas_call
+ Input:
+ rtas_args: pointer to RTAS arguments structure
+ Output:
+
+Decription: Handle RTAS call. This C function is called
+ from the asm function rtas_entry.
+*/
+
+void
+rtas_call (rtas_args_t *rtas_args)
+{
+ int idx;
+
+#ifdef _RTAS_COUNT_CALLS
+ /* Count how often every RTAS function is called. */
+ if (rtas_args->token < (int)(sizeof(rtas_callcount)/sizeof(rtas_callcount[0]))) {
+ static int callcount_initialized = 0;
+ /* If the array is used the first time, we have to set all entries to 0 */
+ if (!callcount_initialized) {
+ unsigned int i;
+ callcount_initialized = 1;
+ for (i = 0; i < sizeof(rtas_callcount)/sizeof(rtas_callcount[0]); i++)
+ rtas_callcount[i] = 0;
+ }
+ /* Increment the counter of the RTAS call */
+ rtas_callcount[rtas_args->token] += 1;
+ }
+#endif
+
+#ifdef _RTAS_TRACE
+ unsigned int parCnt = rtas_args->nargs;
+ unsigned int *pInt = rtas_args->args;
+ printf("\n\r*** rtas_call=0x%x", rtas_args->token);
+#ifdef _RTAS_COUNT_CALLS
+ printf(" count=0x%x", rtas_callcount[rtas_args->token]);
+#endif
+ printf(" len=0x%x", parCnt);
+ printf("\n\r ");
+ while(parCnt--) {
+ printf("0x%x ", *pInt++);
+ }
+#endif
+
+ idx = rtas_args->token - 1;
+
+ /* Check if there's a function for the token: */
+ if (idx >= 0 && idx < rtas_func_tab_size
+ && rtas_func_tab[idx].func != NULL) {
+ /* Now jump to the RTAS function: */
+ rtas_func_tab[idx].func(rtas_args);
+ }
+ else {
+ /* We didn't find a function - return error code: */
+ rtas_args->args[rtas_args->nargs] = -1;
+ }
+
+}
diff --git a/rtas/rtas_common.S b/rtas/rtas_common.S
new file mode 100644
index 0000000..010c413
--- /dev/null
+++ b/rtas/rtas_common.S
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+.globl save_regs_r3_r12
+.globl restore_regs_r3_r12
+.globl save_regs_r13_r25
+.globl restore_regs_r13_r25
+
+
+save_regs_r3_r12:
+ stdu r1,-0x80(r1) # allocate space on stack
+
+ std r3,0x30(r1)
+ std r4,0x38(r1)
+ std r5,0x40(r1)
+ std r6,0x48(r1)
+ std r7,0x50(r1)
+ std r8,0x58(r1)
+ std r9,0x60(r1)
+ std r10,0x68(r1)
+ std r11,0x70(r1)
+ std r12,0x78(r1)
+
+ blr
+
+restore_regs_r3_r12:
+ ld r3,0x30(r1)
+ ld r4,0x38(r1)
+ ld r5,0x40(r1)
+ ld r6,0x48(r1)
+ ld r7,0x50(r1)
+ ld r8,0x58(r1)
+ ld r9,0x60(r1)
+ ld r10,0x68(r1)
+ ld r11,0x70(r1)
+ ld r12,0x78(r1)
+
+ addi r1,r1,0x80 # cleanup stack
+
+ blr
+
+save_regs_r13_r25:
+ stdu r1,-0x98(r1) # allocate space on stack
+
+ std r13,0x30(r1)
+ std r14,0x38(r1)
+ std r15,0x40(r1)
+ std r16,0x48(r1)
+ std r17,0x50(r1)
+ std r18,0x58(r1)
+ std r19,0x60(r1)
+ std r20,0x68(r1)
+ std r21,0x70(r1)
+ std r22,0x78(r1)
+ std r23,0x80(r1)
+ std r24,0x88(r1)
+ std r25,0x90(r1)
+
+ blr
+
+restore_regs_r13_r25:
+ ld r13,0x30(r1) # restore registers from stack
+ ld r14,0x38(r1)
+ ld r15,0x40(r1)
+ ld r16,0x48(r1)
+ ld r17,0x50(r1)
+ ld r18,0x58(r1)
+ ld r19,0x60(r1)
+ ld r20,0x68(r1)
+ ld r21,0x70(r1)
+ ld r22,0x78(r1)
+ ld r23,0x80(r1)
+ ld r24,0x88(r1)
+ ld r25,0x90(r1)
+
+ addi r1,r1,0x98 # cleanup stack
+
+ blr
diff --git a/rtas/rtas_entry.S b/rtas/rtas_entry.S
new file mode 100644
index 0000000..35421d8
--- /dev/null
+++ b/rtas/rtas_entry.S
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <rtas.h>
+
+
+/*
+Function:
+ Input:
+ r3: rtas parm structure
+ r4: base address
+ Output:
+
+Decription: Main entry point, called from OS. Second parameter is not
+ used.
+
+*/
+ .globl rtas_entry
+rtas_entry:
+ mfmsr r11 # Get MSR to enable 64-bit mode
+ mr r7,r11
+ rotldi r11,r11,1
+ ori r11,r11,1 # Always enable 64-bit mode flag
+ rotldi r11,r11,63
+ mtmsrd r11 # Switch to 64-bit mode
+ isync
+
+ mr r9,r1 # save old stack pointer
+ mflr r10 # save link register
+ bcl 20,31,.over # branch to over
+.base:
+ .align 3
+..got: .quad _got-.base+0x8000
+..stack: .quad .stack+RTAS_STACKSIZE-0x60-.base
+.over:
+ mflr r8 # gpr 8 is the base
+ ld r1,..stack-.base(r8) # load new stack pointer
+ add r1,r1,r8 # add base
+ std r2,64(r1) # save toc
+ ld r2,..got-.base(r8) # load got pointer
+ std r7,72(r1) # save original msr
+ std r10,80(r1) # save link register
+ std r9,0(r1) # save stack pointer
+ add r2,r2,r8 # add base
+
+ bl save_regs_r3_r12
+ bl .rtas_call
+ bl restore_regs_r3_r12
+
+rtas_return:
+ ld r11,72(r1) # restore msr value
+ ld r0,80(r1) # restore link register value
+ ld r2,64(r1) # restore toc
+ ld r1,0(r1) # get old stack
+ mtmsrd r11 # restore msr (32 bit ?)
+ isync
+ mtlr r0
+ blr
+
+
+
+ .globl .stack
+ .lcomm .stack,RTAS_STACKSIZE
diff --git a/slof/Makefile.inc b/slof/Makefile.inc
new file mode 100644
index 0000000..57bfce3
--- /dev/null
+++ b/slof/Makefile.inc
@@ -0,0 +1,161 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+# Before including this Makefile, you should specify the following variables
+# in your Makefile:
+# - INCLCMNDIR : Points to the common include directory
+# - INCLCMNDIR : Points to the board specific include directory
+# - SLOFCMNDIR : Points to the common SLOF directory
+# - SLOFBRDDIR : Points to the board specific SLOF directory
+# - LLFWCMNDIR : Points to the common LLFW directory
+# - LLFWBRDDIR : Points to the board specific LLFW directory
+
+# Set LLFW directories (should normally be set from parent Makefile):
+TOPBRDDIR ?= $(shell cd .. && pwd)
+LLFWBRDDIR ?= $(TOPBRDDIR)/llfw
+LLFWCMNDIR ?= $(SLOFCMNDIR:%/slof=%/llfw)
+INCLBRDDIR ?= $(TOPBRDDIR)/include
+
+
+CPPFLAGS += -I. -I$(INCLCMNDIR) -I$(INCLBRDDIR) -I$(INCLCMNDIR)/$(CPUARCH)
+CFLAGS = -DTARG=$(TARG) -static -Wall -W -std=gnu99 \
+ -O2 -fomit-frame-pointer -msoft-float $(FLAG) $(CPUARCHDEF)
+ASFLAGS = -Wa,-mpower4 -Wa,-mregnames $(FLAG) $(CPUARCHDEF)
+
+LDFLAGS += -static -nostdlib
+
+ifneq ($(TARG),unix)
+CFLAGS += -nostdinc -fno-builtin
+CPPFLAGS += -I$(LIBCMNDIR)/libc/include
+SLOF_LIBS += $(LIBCMNDIR)/libc.a
+endif
+
+DICT = $(SLOFCMNDIR)/prim.in $(SLOFCMNDIR)/engine.in \
+ $(BOARD_SLOF_IN) $(SLOFCMNDIR)/$(TARG).in
+
+# Source code files with automatic dependencies:
+SLOF_BUILD_SRCS = paflof.c
+
+# Flags for pre-processing Forth code with CPP:
+FPPFLAGS = -nostdinc -traditional-cpp -undef -P -C $(FLAG)
+FPPINCLUDES ?= -I$(SLOFBRDDIR) -I$(SLOFCMNDIR)/fs
+
+# Rules for pre-processing Forth code:
+# - Use CPP for pre-processing #include directives
+# - Use sed to strip all white spaces at the beginning of a line
+# - Use sed to remove all lines that only contain a comment
+# - Use sed to remove all empty lines from the file
+%.fsi: %.fs
+ rm -f $@
+ cpp $(FPPFLAGS) $(FPPINCLUDES) $< > $@.tmp
+ sed -e 's/^[ \t]*//' < $@.tmp \
+ | sed -e '/^\\[ \t]/d' \
+ | sed -e '/^([ \t][^)]*[ \t])[ \t]*$$/d' \
+ | sed -e '/^$$/d' > $@
+ rm -f $@.tmp
+
+
+OF.o: OF.fsi
+ $(LD) -o $@ -r -bbinary $<
+
+
+dict.xt: $(DICT) $(SLOFCMNDIR)/ref.pl
+ cat $(DICT) | perl $(SLOFCMNDIR)/ref.pl > dict.xt
+
+ifdef BOARD_SLOF_CODE
+board.code: $(BOARD_SLOF_CODE)
+ cat $(BOARD_SLOF_CODE) > $@
+else
+board.code:
+ echo > $@
+endif
+
+paflof: $(SLOFCMNDIR)/OF.lds $(SLOFCMNDIR)/ofw.o paflof.o $(SLOFCMNDIR)/entry.o \
+ romfs.o OF.o nvramlog.o $(LLFWBRDDIR)/board_io.o \
+ $(LLFWBRDDIR)/io_generic_lib.o $(SLOF_LIBS)
+ $(CC) -T$(SLOFCMNDIR)/OF.lds $(SLOFCMNDIR)/ofw.o paflof.o \
+ $(SLOFCMNDIR)/entry.o romfs.o OF.o nvramlog.o $(LLFWBRDDIR)/board_io.o \
+ $(LLFWBRDDIR)/io_generic_lib.o $(LDFLAGS) $(SLOF_LIBS) -o $@
+
+paflof.o:
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(SLOFCMNDIR)/paflof.c
+
+$(SLOFCMNDIR)/xvect.bin: $(SLOFCMNDIR)/lowmem.o
+ $(CC) $(LDFLAGS) -Wl,--oformat,binary -Ttext=0x100 -o xvect.bin.tmp $<
+ dd if=xvect.bin.tmp of=$(SLOFCMNDIR)/xvect.bin bs=256 skip=1 2>/dev/null
+ rm -f xvect.bin.tmp
+
+slof.bin: paflof
+ $(OBJCOPY) -Obinary paflof $@
+
+romfs.o:
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c -o $@ $(LLFWCMNDIR)/romfs.S
+
+nvramlog.o:
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c -o $@ $(LLFWCMNDIR)/nvramlog.S
+
+checkpoint.o:
+ $(CC) $(CPPFLAGS) $(ASFLAGS) -c -o $@ $(LLFWCMNDIR)/checkpoint.S
+
+$(LLFWBRDDIR)/board_io.o:
+ make -C $(LLFWBRDDIR) board_io.o
+
+$(LLFWBRDDIR)/io_generic_lib.o:
+ make -C $(LLFWBRDDIR) io_generic_lib.o
+
+default-font.o: $(SLOFCMNDIR)/default-font.c
+ $(CC) $(CPPFLAGS) $< -c -o default-font.o
+
+$(SLOFBRDDIR)/default-font.bin: default-font.o
+ $(OBJCOPY) -Obinary default-font.o $@
+
+.PHONY : create_OF.ffs clean_slof distclean_slof depend
+
+
+# Create OF.ffs automatically from file list in OF_FFS_FILES variable.
+# We have to use absolute path names there, so we have to use `pwd` to
+# find them out:
+create_OF_ffs:
+ rm -f OF.ffs
+ @for i in $(OF_FFS_FILES) ; do \
+ pushd . >/dev/null ; cd `dirname $$i` ; \
+ DIRNAME=`pwd` ; popd >/dev/null; \
+ echo `basename $$i | sed -e s/\.fsi/\.fs/` \
+ $$DIRNAME/`basename $$i` 0 0 >> OF.ffs ; \
+ done
+
+
+# Targets for cleaning up:
+clean_slof:
+ rm -f $(SLOFCMNDIR)/*.o $(SLOFCMNDIR)/*.bin $(SLOFCMNDIR)/*.elf
+ rm -f dict.xt board.code paflof slof.bin default-font.bin
+ rm -f $(filter %.fsi,$(OF_FFS_FILES))
+
+distclean_slof: clean_slof
+ rm -f Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ rm -f Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile $(SLOFCMNDIR)/Makefile.inc OF.fs
+ $(CC) -M -MG $(CPPFLAGS) $(CFLAGS) $(SLOF_BUILD_SRCS:%=$(SLOFCMNDIR)/%) > Makefile.dep
+ cpp -M -MG $(FPPFLAGS) $(FPPINCLUDES) -MT OF.fsi OF.fs >> Makefile.dep
+ for i in $(filter %.fsi,$(OF_FFS_FILES)) ; do \
+ cpp -M -MG $(FPPFLAGS) $(FPPINCLUDES) -MT $$i \
+ `echo $$i | sed -e 's/\.fsi/\.fs/'` >> Makefile.dep ; \
+ done
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/slof/OF.lds b/slof/OF.lds
index 133cb8b..44d710b 100644
--- a/slof/OF.lds
+++ b/slof/OF.lds
@@ -1,29 +1,62 @@
-/* ============================================================================= */
-/* * Copyright (c) 2004, 2005 IBM Corporation
-/* * All rights reserved.
-/* * This program and the accompanying materials
-/* * are made available under the terms of the BSD License
-/* * which accompanies this distribution, and is available at
-/* * http://www.opensource.org/licenses/bsd-license.php
-/* *
-/* * Contributors:
-/* * IBM Corporation - initial implementation
-/* ============================================================================= */
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
OUTPUT_ARCH(powerpc:common64)
+ENTRY(_start_OF)
+
SECTIONS
{
- .slof.vectors 0 : { *(.slof.vectors) }
+ . = 0xE100000;
+ _slof_start = .;
+ . = 0x0E10C000;
+ .slof.loader : { *(.slof.loader) }
+ . = 0x0E110000; /* + SIZEOF_HEADERS; */
+ _slof_text = .;
+ _start_OF = .;
+/* .rela : { *(.rela.*) } */
+ .text : { *(.entry_text) *(.text) } = 0x60000000
+ _slof_text_end = .;
+ . = ALIGN(8);
+ _slof_text_size = (_slof_text_end - _slof_text);
- .slof.text 0x1110000 : { *(.text) } = 0x60000000
-
- .slof.data 0x1120000 : {
- KEEP (*(.opd))
- . = ALIGN(8);
+ . = ALIGN(0x1000);
+ .opd :
+ {
+ _slof_data = .;
+ *(.opd)
+ }
+ . = ALIGN(8);
+ .got :
+ {
*(.got .toc)
- *(.data .data.*)
}
+ .data : { *(.rodata .rodata.*) *(.data .data.*) }
+ .comment : { *(.comment) }
+ .branch_lt : { *(.branch_lt) }
+
+ . = ALIGN(8);
+ _slof_data_end = .;
+ _slof_data_size = (_slof_data_end - _slof_data);
+
+ .bss :
+ {
+ _slof_bss = .;
+ *(*COM* .bss .sbss .gnu.linkonce.b.*)
+ _slof_bss_end = .;
+ }
+ _slof_bss_size = (_slof_bss_end - _slof_bss);
+
+ . = ALIGN(0x1000);
+ _slof_here_start = .;
}
diff --git a/slof/default-font.c b/slof/default-font.c
new file mode 100644
index 0000000..f3cfcd2
--- /dev/null
+++ b/slof/default-font.c
@@ -0,0 +1,1653 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/* Bitmap font 8x16.
+ FIXME: Only characters from 0x20 - 0x7f
+
+
+*/
+
+const char bmfont_8x16[] =
+{
+ /* 0x20 " " */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x21 "!" */
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x22 """ */
+ 0x00,
+ 0x00,
+ 0x28,
+ 0x28,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x23 "#" */
+ 0x00,
+ 0x00,
+ 0x24,
+ 0x24,
+ 0x7e,
+ 0x24,
+ 0x24,
+ 0x7e,
+ 0x24,
+ 0x24,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x24 "$" */
+ 0x00,
+ 0x08,
+ 0x1c,
+ 0x2a,
+ 0x28,
+ 0x28,
+ 0x1c,
+ 0x0a,
+ 0x0a,
+ 0x2a,
+ 0x1c,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x25 "%" */
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x48,
+ 0x30,
+ 0x02,
+ 0x0c,
+ 0x30,
+ 0x40,
+ 0x0c,
+ 0x12,
+ 0x0c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x26 "&" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x40,
+ 0x22,
+ 0x54,
+ 0x48,
+ 0x54,
+ 0x22,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x27 "'" */
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x28 "(" */
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x10,
+ 0x10,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x29 ")" */
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x08,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x08,
+ 0x08,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2a "*" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x28,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2b "+" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2c "," */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x18,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2d "-" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2e "." */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x30,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x2f "/" */
+ 0x00,
+ 0x00,
+ 0x02,
+ 0x04,
+ 0x04,
+ 0x08,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x20,
+ 0x20,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x30 "0" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x31 "1" */
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x18,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x1c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x32 "2" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x04,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x40,
+ 0x78,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x33 "3" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x18,
+ 0x04,
+ 0x04,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x34 "4" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x48,
+ 0x48,
+ 0x7e,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x35 "5" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x78,
+ 0x04,
+ 0x02,
+ 0x02,
+ 0x04,
+ 0x78,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x36 "6" */
+ 0x00,
+ 0x00,
+ 0x1c,
+ 0x20,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x78,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x37 "7" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x42,
+ 0x04,
+ 0x08,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x38 "8" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x39 "9" */
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x3c,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x3a ":" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x30,
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x30,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x3b ";" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x30,
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x30,
+ 0x20,
+ 0x40,
+ 0x00,
+ 0x00,
+ /* 0x3c "<" */
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x40,
+ 0x40,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x3d "=" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x00,
+ 0x7e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x3e ">" */
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x02,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x3f "?" */
+ 0x00,
+ 0x00,
+ 0x1c,
+ 0x22,
+ 0x02,
+ 0x02,
+ 0x04,
+ 0x18,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x40 "@" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x4e,
+ 0x52,
+ 0x4e,
+ 0x40,
+ 0x40,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x41 "A" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x18,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x42 "B" */
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x44 "C" */
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x22,
+ 0x60,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x60,
+ 0x22,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x45 "D" */
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x44,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x44,
+ 0x78,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x46 "E" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x7e,
+ 0x7e,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x7e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x47 "F" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x7e,
+ 0x7e,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x48 "G" */
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x4e,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x49 "H" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x49 "I" */
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4a "J" */
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4b "K" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x44,
+ 0x48,
+ 0x50,
+ 0x60,
+ 0x60,
+ 0x50,
+ 0x48,
+ 0x44,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4c "L" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x7e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4d "M" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x66,
+ 0x7e,
+ 0x5a,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4e "N" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x62,
+ 0x62,
+ 0x52,
+ 0x52,
+ 0x4a,
+ 0x4a,
+ 0x46,
+ 0x46,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x4f "O" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x50 "P" */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x48,
+ 0x44,
+ 0x44,
+ 0x48,
+ 0x70,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x51 "Q" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x4a,
+ 0x24,
+ 0x1a,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x52 "R" */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x48,
+ 0x44,
+ 0x44,
+ 0x48,
+ 0x70,
+ 0x50,
+ 0x48,
+ 0x44,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x53 "S" */
+ 0x00,
+ 0x00,
+ 0x1e,
+ 0x20,
+ 0x40,
+ 0x40,
+ 0x20,
+ 0x18,
+ 0x04,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x54 "T" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x55 "U" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x56 "V" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x57 "W" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x5a,
+ 0x66,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x58 "X" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x24,
+ 0x24,
+ 0x18,
+ 0x18,
+ 0x24,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x59 "Y" */
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x24,
+ 0x24,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5a "Z" */
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x42,
+ 0x04,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x20,
+ 0x42,
+ 0x7e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5b "[" */
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x30,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5c "\" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x20,
+ 0x20,
+ 0x10,
+ 0x10,
+ 0x08,
+ 0x08,
+ 0x04,
+ 0x04,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5d "]" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5e "^" */
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x3c,
+ 0x66,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x5f "_" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x00,
+ /* 0x60 "`" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x61 "a" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x04,
+ 0x3c,
+ 0x44,
+ 0x3a,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x62 "b" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x58,
+ 0x64,
+ 0x44,
+ 0x44,
+ 0x64,
+ 0x58,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x63 "c" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x40,
+ 0x40,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x64 "d" */
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x3c,
+ 0x4c,
+ 0x44,
+ 0x44,
+ 0x4c,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x65 "e" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x44,
+ 0x78,
+ 0x40,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x66 "f" */
+ 0x00,
+ 0x00,
+ 0x0c,
+ 0x12,
+ 0x10,
+ 0x10,
+ 0x38,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x67 "g" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x34,
+ 0x4c,
+ 0x44,
+ 0x4c,
+ 0x34,
+ 0x04,
+ 0x44,
+ 0x38,
+ 0x00,
+ 0x00,
+ /* 0x68 "h" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x58,
+ 0x64,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x69 "i" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x00,
+ 0x18,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x1c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x6a "j" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x48,
+ 0x30,
+ 0x00,
+ /* 0x6b "k" */
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x44,
+ 0x48,
+ 0x50,
+ 0x70,
+ 0x48,
+ 0x44,
+ 0x42,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x6c "l" */
+ 0x00,
+ 0x00,
+ 0x30,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x38,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x6d "m" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x54,
+ 0x2a,
+ 0x2a,
+ 0x2a,
+ 0x2a,
+ 0x6a,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x6e "n" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x58,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x76,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x6f "o" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x1c,
+ 0x22,
+ 0x22,
+ 0x22,
+ 0x22,
+ 0x1c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x70 "p" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x58,
+ 0x64,
+ 0x44,
+ 0x64,
+ 0x58,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x00,
+ 0x00,
+ /* 0x71 "q" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x34,
+ 0x4c,
+ 0x44,
+ 0x4c,
+ 0x34,
+ 0x04,
+ 0x04,
+ 0x04,
+ 0x00,
+ 0x00,
+ /* 0x72 "r" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x44,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x40,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x73 "s" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x10,
+ 0x08,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x74 "t" */
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x38,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x14,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x75 "u" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x24,
+ 0x1a,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x76 "v" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x28,
+ 0x28,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x77 "w" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x2a,
+ 0x2a,
+ 0x2a,
+ 0x2a,
+ 0x2a,
+ 0x14,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x78 "x" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x28,
+ 0x10,
+ 0x28,
+ 0x44,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x79 "y" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x22,
+ 0x22,
+ 0x14,
+ 0x14,
+ 0x08,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x00,
+ /* 0x7a "z" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x7b "{" */
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x10,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x00,
+ /* 0x7c "|" */
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+ /* 0x7d "}" */
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x00,
+ /* 0x7e "~" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x24,
+ 0x54,
+ 0x48,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ /* 0x7f "v" */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x28,
+ 0x28,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
diff --git a/slof/engine.in b/slof/engine.in
index 7b9dc82..3ab62da 100644
--- a/slof/engine.in
+++ b/slof/engine.in
@@ -1,13 +1,15 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
// ============================================================================
@@ -24,7 +26,6 @@
// use structural words (IF, THEN, BEGIN, etc.) or return-stack
// manipulation words (R> etc.) in the interpreter.
-
// The data stack pointer.
raw(HERE DOVAL _A(the_mem))
@@ -38,8 +39,10 @@ con(3 3)
con(4 4)
con(8 8)
con(H#10 0x10)
+con(H#20 0x20)
con(H#FF 0xff)
con(H#FFFF 0xffff)
+con(H#FFFFFFFF 0xffffffff)
con(D#10 0x0a)
@@ -47,19 +50,23 @@ con(D#10 0x0a)
con(/C 1)
con(/W 2)
con(/L 4)
+con(/X 8)
con(/N CELLSIZE)
con(CELL CELLSIZE)
col(/C* /C *)
col(/W* /W *)
col(/L* /L *)
+col(/X* /X *)
col(/N* /N *)
col(CA+ /C* +)
col(WA+ /W* +)
col(LA+ /L* +)
+col(XA+ /X* +)
col(NA+ /N* +)
col(CA1+ /C +)
col(WA1+ /W +)
col(LA1+ /L +)
+col(XA1+ /X +)
col(NA1+ /N +)
col(CHAR+ CA1+)
col(CELL+ NA1+)
@@ -91,6 +98,10 @@ col(-ROT SWAP >R SWAP R>)
col(2SWAP >R -ROT R> -ROT)
col(2ROT >R >R 2SWAP R> R> 2SWAP)
col(ROLL DUP ?DUP 0BRANCH(6) ROT >R 1 - BRANCH(-9) ?DUP 0BRANCH(6) R> -ROT 1 - BRANCH(-9))
+col(-ROLL DUP ?DUP 0BRANCH(9) >R ROT R> SWAP >R 1 - BRANCH(-12) ?DUP 0BRANCH(6) R> SWAP 1 - BRANCH(-9))
+col(2>R R> ROT >R SWAP >R >R)
+col(2R> R> R> R> ROT >R SWAP)
+col(2R@ R> R> R@ OVER >R ROT >R SWAP)
// Arithmetic.
@@ -154,7 +165,7 @@ col(D+ >R M+ R> +)
col(D- DNEGATE D+)
col(*' >R DUP 0< >R D2* R> 0BRANCH(2) R@ M+ R>)
col(UM* 0 -ROT LIT(8*CELLSIZE) 0 DODO *' DOLOOP(-3) DROP)
-col(M* 2DUP XOR >R >R ABS R> ABS UM* R> 0BRANCH(1) DNEGATE)
+col(M* 2DUP XOR >R >R ABS R> ABS UM* R> 0< 0BRANCH(1) DNEGATE)
col(/' >R DUP 0< >R D2* R> OVER R@ U>= OR 0BRANCH(6) >R 1 OR R> R@ - R>)
col(UM/MOD LIT(8*CELLSIZE) 0 DODO /' DOLOOP(-3) DROP SWAP)
col(SM/REM OVER >R >R DABS R@ ABS UM/MOD R> 0< 0BRANCH(1) NEGATE R> 0< 0BRANCH(4) NEGATE SWAP NEGATE SWAP)
@@ -173,14 +184,22 @@ col(*/ */MOD NIP)
// Splitting, joining, flipping the components of a number.
col(WBSPLIT DUP H#FF AND SWAP 8 RSHIFT)
col(LWSPLIT DUP H#FFFF AND SWAP H#10 RSHIFT)
+col(XLSPLIT DUP H#FFFFFFFF AND SWAP H#20 RSHIFT)
col(LBSPLIT LWSPLIT >R WBSPLIT R> WBSPLIT)
+col(XWSPLIT XLSPLIT >R LWSPLIT R> LWSPLIT)
+col(XBSPLIT XLSPLIT >R LBSPLIT R> LBSPLIT)
col(BWJOIN 8 LSHIFT OR)
col(WLJOIN H#10 LSHIFT OR)
col(BLJOIN BWJOIN >R BWJOIN R> WLJOIN)
col(WBFLIP WBSPLIT SWAP BWJOIN)
col(LWFLIP LWSPLIT SWAP WLJOIN)
+col(LXJOIN H#20 LSHIFT OR)
+col(XLFLIP XLSPLIT SWAP LXJOIN)
col(LBFLIP LBSPLIT SWAP 2SWAP SWAP BLJOIN)
-
+col(WXJOIN WLJOIN >R WLJOIN R> LXJOIN)
+col(XWFLIP XWSPLIT SWAP 2SWAP SWAP WXJOIN)
+col(BXJOIN BLJOIN >R BLJOIN R> LXJOIN)
+col(XBFLIP XLSPLIT LBFLIP SWAP LBFLIP LXJOIN)
// Aligning to cell size.
col(ALIGNED /N 1- + /N NEGATE AND)
@@ -194,16 +213,19 @@ col(UNLOOP R> R> R> 2DROP >R)
// Memory accesses.
col(+! TUCK @ + SWAP !)
-col(COMP 0 DO?DO(27) OVER I + C@ OVER I + C@ 2DUP < 0BRANCH(6) 2DROP UNLOOP 2DROP LIT(-1) EXIT > 0BRANCH(4) UNLOOP 2DROP 1 EXIT DOLOOP(-27) 2DROP 0)
+cod(COMP)
col(OFF FALSE SWAP !)
col(ON TRUE SWAP !)
col(<W@ W@ DUP LIT(0x8000) >= 0BRANCH(3) LIT(0x10000) -)
-col(2@ DUP @ SWAP CELL+ @)
-col(2! DUP >R CELL+ ! R> !)
+col(2@ DUP CELL+ @ SWAP @)
+col(2! DUP >R ! R> CELL+ !)
col(WBFLIPS BOUNDS DO?DO(8) I W@ WBFLIP I W! /W DO+LOOP(-8))
col(LWFLIPS BOUNDS DO?DO(8) I L@ LWFLIP I L! /L DO+LOOP(-8))
col(LBFLIPS BOUNDS DO?DO(8) I L@ LBFLIP I L! /L DO+LOOP(-8))
-col(FILL -ROT BOUNDS DO?DO(5) DUP I C! DOLOOP(-5) DROP)
+col(XBFLIPS BOUNDS DO?DO(8) I X@ XBFLIP I X! /X DO+LOOP(-8))
+col(XWFLIPS BOUNDS DO?DO(8) I X@ XWFLIP I X! /X DO+LOOP(-8))
+col(XLFLIPS BOUNDS DO?DO(8) I X@ XLFLIP I X! /X DO+LOOP(-8))
+cod(FILL)
col(BLANK LIT(0x20) FILL)
col(ERASE LIT(0x00) FILL)
@@ -244,6 +266,7 @@ col(SPACES 0 DO?DO(3) SPACE DOLOOP(-3))
// Text manipulation.
col(COUNT DUP CHAR+ SWAP C@)
+col(PACK DUP >R SWAP MOVE R>)
col(UPC DUP LIT('a') LIT('z') BETWEEN 0BRANCH(3) LIT(0x20) - )
col(LCC DUP LIT('A') LIT('Z') BETWEEN 0BRANCH(3) LIT(0x20) + )
@@ -286,7 +309,7 @@ col(.R SWAP (.) ROT 2DUP < 0BRANCH(5) OVER - SPACES BRANCH(1) DROP TYPE)
col(U.R SWAP (U.) ROT 2DUP < 0BRANCH(5) OVER - SPACES BRANCH(1) DROP TYPE)
col(.D BASE @ SWAP DECIMAL . BASE !)
col(.H BASE @ SWAP HEX . BASE !)
-col(.S DEPTH 0 DO?DO(8) DEPTH I - 1- PICK . DOLOOP(-8))
+col(.S DEPTH DUP 0< 0BRANCH(2) DROP EXIT 0 DO?DO(8) DEPTH I - 1- PICK . DOLOOP(-8))
col(? @ .)
@@ -302,6 +325,7 @@ col(, HERE ! /N ALLOT)
col(C, HERE C! /C ALLOT)
col(W, HERE W! /W ALLOT)
col(L, HERE L! /L ALLOT)
+col(X, HERE X! /X ALLOT)
col(ALIGN HERE /N 1- AND 0BRANCH(4) 0 C, BRANCH(-10))
col(PLACE 2DUP C! CHAR+ SWAP CHARS BOUNDS DO?DO(9) DUP C@ I C! CHAR+ 1 CHARS DO+LOOP(-9) DROP)
col(STRING, HERE OVER 1+ CHARS ALLOT PLACE)
@@ -313,23 +337,24 @@ col(NOOP)
// Now it gets ugly: search-order and word-lisst infrastructure.
+raw(FORTH-WORDLIST DODOES _A(xt_NOOP+2+(8/sizeof(long))) _A(0) _A(0))
+ // Engine initialisation will set this last cell to the xt of LASTWORD.
-// LASTWORD must be the last thing in our dictionary!
-extern cell xt_LASTWORD[];
-
-raw(FORTH-WORDLIST DODOES _A(xt_NOOP+3) _A(0) _A(xt_LASTWORD))
- // +4 for 32-bit, +3 for 64-bit
-
-raw(CURRENT DOVAL _A(xt_FORTH_X2d_WORDLIST+5))
+// compilation dictionary
+raw(CURRENT DOVAL _A(xt_FORTH_X2d_WORDLIST+3+(16/sizeof(long))))
// +7 for 32-bit, +5 for 64-bit
col(LAST CURRENT CELL+)
-raw(SEARCH-ORDER DOVAR _A(xt_FORTH_X2d_WORDLIST+5) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0))
+// for context dictionaries
+raw(SEARCH-ORDER DOVAR _A(xt_FORTH_X2d_WORDLIST+3+(16/sizeof(long))) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0))
// +7 for 32-bit, +5 for 64-bit
-raw(CONTEXT DOVAL _A(xt_SEARCH_X2d_ORDER+4))
- // +6 for 32-bit, +4 for 64-bit
-
+// for context dictionaries
+//raw(SEARCH-ORDER DOVAR _A(xt_FORTH_X2d_WORDLIST+3+(sizeof(" FORTH-WORDLIST")/sizeof(long))) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0) _A(0))
+// +7 for 32-bit, +5 for 64-bit
+raw(CONTEXT DOVAL _A(xt_SEARCH_X2d_ORDER+2+(16/sizeof(long))))
+//raw(CONTEXT DOVAL _A(xt_SEARCH_X2d_ORDER+6))
+// +6 for 32-bit, +4 for 64-bit
// Dictionary structure.
col(LINK>NAME CELL+)
@@ -343,8 +368,9 @@ dfr((REVEAL))
col(HEADER ALIGN HERE LAST @ , LATEST ! 0 C, STRING, ALIGN)
col(REVEAL LATEST @ LINK>NAME NAME>STRING (REVEAL) LATEST @ LAST !)
+
// Finding words.
-col(STRING=CI >R SWAP DUP R> <> 0BRANCH(3) 3DROP FALSE EXIT CHARS BOUNDS DO?DO(18) DUP C@ UPC I C@ UPC <> 0BRANCH(4) DROP UNLOOP FALSE EXIT CHAR+ 1 CHARS DO+LOOP(-18) DROP TRUE)
+cod(STRING=CI)
// (find) ( str len head -- 0 | link )
dfr((FIND))
col(((FIND)) DUP 0BRANCH(15) >R 2DUP R@ LINK>NAME NAME>STRING STRING=CI 0BRANCH(3) 2DROP R> EXIT R> @ BRANCH(-18) 3DROP FALSE)
@@ -356,16 +382,15 @@ con('IMMEDIATE 1)
col(IMMEDIATE? 'IMMEDIATE AND 0<>)
col(IMMEDIATE LAST @ CELL+ DUP C@ 'IMMEDIATE OR SWAP C!)
-// Utility -- list all words in compilation wordlist.
-col(WORDS LAST @ ?DUP 0BRANCH(9) DUP CELL+ CHAR+ COUNT TYPE SPACE @ BRANCH(-12))
-
// Parsing.
col(FINDCHAR SWAP 0 DO?DO(24) OVER I + C@ OVER DUP BL = 0BRANCH(3) <= BRANCH(1) = 0BRANCH(6) I UNLOOP NIP NIP TRUE EXIT DOLOOP(-24) DROP DROP FALSE)
col(PARSE >R IB >IN @ + SPAN @ >IN @ - 2DUP R> FINDCHAR 0BRANCH(6) NIP DUP 1 + BRANCH(1) DUP >IN +!)
col(SKIPWS IB SPAN @ DUP >IN @ > 0BRANCH(14) OVER >IN @ + C@ BL <= 0BRANCH(5) 1 >IN +! BRANCH(-20) DROP DROP)
col(PARSE-WORD SKIPWS BL PARSE)
var(WHICHPOCKET 0)
-col(POCKET LIT(POCKETSIZE) WHICHPOCKET @ * POCKETS + 1 WHICHPOCKET @ - WHICHPOCKET !)
+// We reserved 0x1000 for the pockets. So we have 16 pockets a 0x100
+col(POCKET POCKETS WHICHPOCKET @ LIT(POCKETSIZE) * + WHICHPOCKET @ 1 + DUP LIT(16) = 0BRANCH(2) DROP 0 WHICHPOCKET !)
+
col(WORD POCKET >R PARSE DUP R@ C! BOUNDS R> DUP 2SWAP DO?DO(7) CHAR+ I C@ OVER C! DOLOOP(-7) DROP)
// Some simple parsing words.
@@ -376,44 +401,54 @@ imm(\ LINEFEED PARSE 2DROP)
// The compiler infrastructure.
var(STATE 0)
imm([ STATE OFF)
-col(] STATE ON)
+col(] LIT(0x100) STATE !)
+col(?COMP STATE @ 0BRANCH(1) EXIT LIT(-134) THROW)
+
col(COMPILE, ,)
col(: PARSE-WORD HEADER DOTICK DOCOL COMPILE, ])
col(:NONAME ALIGN HERE DOTICK DOCOL COMPILE, ])
-imm(; DOTICK EXIT COMPILE, REVEAL [)
+imm(; ?COMP DOTICK SEMICOLON COMPILE, REVEAL [)
// Compiling strings.
-imm(C" LIT('"') PARSE DOTICK SLITERAL COMPILE, DUP C, BOUNDS DO?DO(5) I C@ C, DOLOOP(-5) ALIGN)
+imm(C" ?COMP LIT('"') PARSE DOTICK SLITERAL COMPILE, DUP C, BOUNDS DO?DO(5) I C@ C, DOLOOP(-5) ALIGN)
imm(S" STATE @ 0BRANCH(5) C" DOTICK COUNT COMPILE, EXIT LIT('"') PARSE DUP >R POCKET DUP >R SWAP MOVE R> R>)
-imm(." S" DOTICK TYPE COMPILE,)
+imm(." STATE @ 0BRANCH(5) S" DOTICK TYPE COMPILE, EXIT LIT('"') PARSE TYPE)
imm(.( LIT(')') PARSE TYPE)
+col(COMPILE R> CELL+ DUP @ COMPILE, >R)
+
+var(THERE 0)
+col(+COMP STATE @ 1 STATE +! 0BRANCH(1) EXIT HERE THERE ! COMP-BUFFER DOTO HERE COMPILE DOCOL)
+col(-COMP -1 STATE +! STATE @ 0BRANCH(1) EXIT COMPILE EXIT THERE @ DOTO HERE COMP-BUFFER EXECUTE)
+
// Structure words.
col(RESOLVE-ORIG HERE OVER CELL+ - SWAP !)
-imm(AHEAD DOTICK DOBRANCH COMPILE, HERE 0 COMPILE,)
-imm(IF DOTICK DO0BRANCH COMPILE, HERE 0 COMPILE,)
-imm(THEN RESOLVE-ORIG)
-imm(ELSE DOTICK DOBRANCH COMPILE, HERE 0 COMPILE, SWAP RESOLVE-ORIG)
-imm(CASE 0)
-imm(ENDCASE DOTICK DROP COMPILE, ?DUP 0BRANCH(5) 1- SWAP THEN BRANCH(-8))
-imm(OF 1+ >R DOTICK OVER COMPILE, DOTICK = COMPILE, IF DOTICK DROP COMPILE, R>)
-imm(ENDOF >R ELSE R>)
+imm(AHEAD +COMP DOTICK DOBRANCH COMPILE, HERE 0 COMPILE,)
+imm(IF +COMP DOTICK DO0BRANCH COMPILE, HERE 0 COMPILE,)
+imm(THEN ?COMP RESOLVE-ORIG -COMP)
+imm(ELSE ?COMP DOTICK DOBRANCH COMPILE, HERE 0 COMPILE, SWAP RESOLVE-ORIG)
+
+imm(CASE +COMP 0)
+imm(ENDCASE ?COMP DOTICK DROP COMPILE, ?DUP 0BRANCH(5) 1- SWAP THEN BRANCH(-8) -COMP)
+imm(OF ?COMP 1+ >R DOTICK OVER COMPILE, DOTICK = COMPILE, IF DOTICK DROP COMPILE, R>)
+imm(ENDOF ?COMP >R ELSE R>)
+
col(RESOLVE-DEST HERE CELL+ - COMPILE,)
-imm(BEGIN HERE)
-imm(AGAIN DOTICK DOBRANCH COMPILE, RESOLVE-DEST)
-imm(UNTIL DOTICK DO0BRANCH COMPILE, RESOLVE-DEST)
-imm(WHILE IF SWAP)
-imm(REPEAT AGAIN THEN)
+imm(BEGIN +COMP HERE)
+imm(AGAIN ?COMP DOTICK DOBRANCH COMPILE, RESOLVE-DEST -COMP)
+imm(UNTIL ?COMP DOTICK DO0BRANCH COMPILE, RESOLVE-DEST -COMP)
+imm(WHILE ?COMP IF SWAP)
+imm(REPEAT ?COMP AGAIN THEN)
// Counted loops.
var(LEAVES 0)
col(RESOLVE-LOOP LEAVES @ ?DUP 0BRANCH(10) DUP @ SWAP HERE OVER - SWAP ! BRANCH(-13) HERE - COMPILE, LEAVES !)
-imm(DO LEAVES @ HERE DOTICK DODO COMPILE, 0 LEAVES !)
-imm(?DO LEAVES @ DOTICK DODO?DO COMPILE, HERE HERE LEAVES ! 0 COMPILE,)
-imm(LOOP DOTICK DODOLOOP COMPILE, RESOLVE-LOOP)
-imm(+LOOP DOTICK DODO+LOOP COMPILE, RESOLVE-LOOP)
-imm(LEAVE DOTICK DODOLEAVE COMPILE, LEAVES @ HERE LEAVES ! COMPILE,)
-imm(?LEAVE DOTICK DODO?LEAVE COMPILE, LEAVES @ HERE LEAVES ! COMPILE,)
+imm(DO +COMP LEAVES @ HERE DOTICK DODO COMPILE, 0 LEAVES !)
+imm(?DO +COMP LEAVES @ DOTICK DODO?DO COMPILE, HERE HERE LEAVES ! 0 COMPILE,)
+imm(LOOP ?COMP DOTICK DODOLOOP COMPILE, RESOLVE-LOOP -COMP)
+imm(+LOOP ?COMP DOTICK DODO+LOOP COMPILE, RESOLVE-LOOP -COMP)
+imm(LEAVE ?COMP DOTICK DODOLEAVE COMPILE, LEAVES @ HERE LEAVES ! COMPILE,)
+imm(?LEAVE ?COMP DOTICK DODO?LEAVE COMPILE, LEAVES @ HERE LEAVES ! COMPILE,)
// Interpreter nesting.
col(SAVE-SOURCE R> IB >R #IB @ >R SOURCE-ID >R SPAN @ >R >IN @ >R >R)
@@ -423,7 +458,14 @@ col(RESTORE-SOURCE R> R> >IN ! R> SPAN ! R> DOTO SOURCE-ID R> #IB ! R> DOTO IB >
str(OK-STR "ok")
str(ABORTED-STR "Aborted")
str(EXCEPTION-STR "Exception #")
-col(PRINT-STATUS SPACE DUP 0= 0BRANCH(4) DOTICK OK-STR BRANCH(7) DUP -1 = 0BRANCH(6) DOTICK ABORTED-STR COUNT TYPE BRANCH(10) DUP LIT(-2) = 0BRANCH(7) ABORT"-STR @ COUNT TYPE DROP BRANCH(5) DOTICK EXCEPTION-STR COUNT TYPE . CR)
+str(UNKNOWN-STR "Undefined word")
+dfr(HW-EXCEPTION-HANDLER)
+val(SHOW-STACK? 0)
+col(SHOWSTACK -1 DOTO SHOW-STACK?)
+col(NOSHOWSTACK 0 DOTO SHOW-STACK?)
+col(PRINT-STACK SHOW-STACK? 0BRANCH(5) >R >R .S R> R> )
+col(PRINT-EXCEPTION DUP LIT(-99) = 0BRANCH(7) DOTICK UNKNOWN-STR COUNT TYPE CR DROP EXIT DUP LIT(0x100) = 0BRANCH(2) DROP EXIT HW-EXCEPTION-HANDLER )
+col(PRINT-STATUS SPACE DUP 0= 0BRANCH(5) PRINT-STACK DOTICK OK-STR BRANCH(7) DUP -1 = 0BRANCH(6) DOTICK ABORTED-STR COUNT TYPE BRANCH(10) DUP LIT(-2) = 0BRANCH(7) ABORT"-STR @ COUNT TYPE DROP BRANCH(1) PRINT-EXCEPTION CR)
// The compiler and interpreter.
col(COMPILE-WORD 2DUP $FIND 0BRANCH(10) IMMEDIATE? 0BRANCH(4) NIP NIP EXECUTE EXIT COMPILE, 2DROP EXIT 2DUP $NUMBER 0BRANCH(4) TYPE LIT(-99) THROW DOTICK DOLIT COMPILE, COMPILE, 2DROP)
@@ -431,7 +473,7 @@ col(INTERPRET-WORD 2DUP $FIND 0BRANCH(5) DROP NIP NIP EXECUTE EXIT 2DUP $NUMBER
col(INTERPRET 0 >IN ! PARSE-WORD DUP 0BRANCH(10) STATE @ 0BRANCH(3) COMPILE-WORD BRANCH(1) INTERPRET-WORD BRANCH(-14) 2DROP)
// Evaluate, the one word to rule them all. It is evil, btw.
-col(EVALUATE SAVE-SOURCE -1 DOTO SOURCE-ID DUP #IB ! SPAN ! DOTO IB INTERPRET RESTORE-SOURCE)
+col(EVALUATE SAVE-SOURCE -1 DOTO SOURCE-ID DUP #IB ! SPAN ! DOTO IB DOTICK INTERPRET CATCH RESTORE-SOURCE THROW)
col(EVAL EVALUATE)
// Abort with a message.
@@ -466,11 +508,11 @@ col(BUFFER: PARSE-WORD HEADER DOTICK DOBUFFER: COMPILE, ALLOT REVEAL)
col(DEFER PARSE-WORD HEADER DOTICK DODEFER COMPILE, DOTICK ABORT COMPILE, REVEAL)
col(ALIAS PARSE-WORD HEADER DOTICK DOALIAS COMPILE, ' COMPILE, REVEAL)
col(STRUCT 0)
+col(END-STRUCT DROP)
col(FIELD PARSE-WORD HEADER DOTICK DOFIELD COMPILE, OVER , + REVEAL)
// Words with (mostly) non-standard compilation behaviour.
imm(LITERAL DOTICK DOLIT COMPILE, COMPILE,)
-col(COMPILE R> CELL+ DUP @ COMPILE, >R)
imm([COMPILE] ' COMPILE,)
imm(POSTPONE PARSE-WORD $FIND 0= DOTICK UNDEFINED-STR DOABORT" IMMEDIATE? 0= 0BRANCH(6) DOTICK DOTICK COMPILE, COMPILE, DOTICK COMPILE, COMPILE,)
imm([CHAR] CHAR LITERAL)
@@ -488,3 +530,8 @@ col(BODY> 2 CELLS -)
// Making words recursive.
imm(RECURSIVE REVEAL)
imm(RECURSE LATEST @ LINK> COMPILE,)
+
+// Numeric input.
+imm(d# PARSE-WORD BASE @ >R DECIMAL EVALUATE R> BASE !)
+imm(h# PARSE-WORD BASE @ >R HEX EVALUATE R> BASE !)
+imm(o# PARSE-WORD BASE @ >R OCTAL EVALUATE R> BASE !)
diff --git a/slof/entry.S b/slof/entry.S
index 86e7680..f57ddab 100644
--- a/slof/entry.S
+++ b/slof/entry.S
@@ -1,89 +1,91 @@
-# =============================================================================
-# * Copyright (c) 2004, 2005 IBM Corporation
-# * All rights reserved.
-# * This program and the accompanying materials
-# * are made available under the terms of the BSD License
-# * which accompanies this distribution, and is available at
-# * http://www.opensource.org/licenses/bsd-license.php
-# *
-# * Contributors:
-# * IBM Corporation - initial implementation
-# =============================================================================
-
-
-#
-# The entry points into the engine, as well as everything else in low memory.
-#
-
- .section ".slof.vectors","ax"
-
- . = 0
-
- .asciz "SLOF, the SlimLine Open Firmware"
-
-
- #
- # The reset exception.
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <macros.h>
+
#
-
- . = 0x0100
- mtsprg 0,0
- li 0,0x0100
- b handler
-
-
-
+ # The generic exception code.
#
- # All other exceptions.
+ # Enter with GPR0 = vector, SPRG0 = saved GPR0
#
- .irp i, 0x0200,0x0300,0x0380,0x0400,0x0480,0x0500,0x0600,0x0700, \
- 0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \
- 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
- 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
- 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
- 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00
- . = \i
- mtsprg 0,0 ; li 0,\i ; b handler
- .endr
-
+ .section ".entry_text"
+the_handler:
+ .quad handler
- #
- # The generic exception code.
- #
- # Enter with GPR0 = vector, SPRG0 = saved GPR0.
- #
+eregs:
+ .quad _slof_start # XXX make configurable at startup time
+ # should stay page aligned!
- . = 0x3000
handler:
mtsprg 1,1 # SPRG1 = saved GPR1
- lis 1,0x0110 # GPR1 = address of register save area
+ bcl 20,31,$+4
+ mflr 1
+ ld 1,eregs-$+4(1) # GPR1 = address of register save area
.irp i, 2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
std \i,\i*8(1)
.endr # save GPR2..GPR31
- mr 3,0 # GPR3 = vector
-
- mfsprg 0,0 ; std 0,0(1) # save GPR0
- mfsprg 0,1 ; std 0,8(1) # save GPR1
-
- mfcr 0 ; std 0,0x100(1)
- mfxer 0 ; std 0,0x108(1)
- mflr 0 ; std 0,0x110(1)
- mfctr 0 ; std 0,0x118(1)
- mfsrr0 0 ; std 0,0x120(1)
- mfsrr1 0 ; std 0,0x128(1)
- mfdar 0 ; std 0,0x130(1)
- mfdsisr 0 ; std 0,0x138(1) # save special regs
-
- addi 1,1,0x7000 ; li 0,0 ; stdu 0,-16(1) # set up stack
- lis 2,engine@ha ; ld 2,8+engine@l(2) # set up TOC pointer
- b .engine # ...and go!
-
+ mr 3,0 // GPR3 = vector
+
+ mfsprg 0,0
+ std 0,0(1) # save GPR0
+ mfsprg 0,1
+ std 0,8(1) # save GPR1
+
+ cmpwi r3, 0x900 # Decrementer interrupt
+ bne 0f
+ mfdec r4 # Save old value of decrementer as reason
+ lis r0,0x7fff # Set decrementer to highest value
+ mtdec r0
+0:
+ cmpwi r3, 0x500 # External interrupt
+ bne 0f
+ LOAD64(r4, 0x20000508408)
+ ld r4, 0(r4) # Read destructive interrupt reason
+0:
+ mfcr 0
+ std 0,0x100(1)
+ mfxer 0
+ std 0,0x108(1)
+ mfsprg 0,3 # save lr
+ std 0,0x110(1)
+ mfsprg 0,2 # save ctr
+ std 0,0x118(1)
+ mfsrr0 0
+ std 0,0x120(1)
+ mfsrr1 0
+ std 0,0x128(1)
+ mfdar 0
+ std 0,0x130(1)
+ mfdsisr 0
+ std 0,0x138(1) # save special regs
+
+ addi 1,1,0x7000
+ li 0,0
+ stdu 0,-0x10(1)
+ stdu 1,-0x100(1) # set up stack
+
+ lis 2,engine@ha
+ ld 0,engine@l(2) # set up entry
+ mtsrr0 0
+
+ ld 2,8+engine@l(2) # set up TOC pointer
+
+ rfid
+# b .engine # ...and run!
@@ -92,7 +94,7 @@ handler:
#
swap_ci_regs:
- lis 8,0x0110
+ lis 8,_slof_start@ha
addi 8,8,0x0400
.irp i, 1,2,3,4,5,6,7, \
@@ -102,11 +104,19 @@ swap_ci_regs:
mr \i,0
.endr # swap GPR1..7, GPR13..31
- ld 0,0x100(8) ; mfcr 9 ; mtcrf 0xff,0 ; std 9,0x100(8) # swap CR
- ld 0,0x128(8) ; mfmsr 9 ; mtmsrd 0 ; sync ; isync ; std 9,0x128(8)
- # swap MSR
- blr
+ ld 0,0x100(8)
+ mfcr 9
+ mtcrf 0xff,0
+ std 9,0x100(8) # swap CR
+ ld 0,0x128(8)
+ mfmsr 9
+ mtmsrd 0
+ sync
+ isync
+ std 9,0x128(8) # swap MSR
+
+ blr
#
# Entry point for the OF client interface.
@@ -121,8 +131,11 @@ client_entry_point:
.type .client_entry_point,@function
.globl .client_entry_point
.client_entry_point:
- mflr 4 ; bl swap_ci_regs ; mtlr 4 ; li 3,0 ; blr
-
+ mflr 4
+ bl swap_ci_regs # swap regs
+ mtlr 4
+ li 3, 0 # client call
+ blr
#
# Start the client.
@@ -137,59 +150,12 @@ call_client:
.type .call_client,@function
.globl .call_client
-.call_client: # called with GPR3 = address, returns GPR3
- mflr 4 ; mtctr 3 ; bl swap_ci_regs ; bctrl
- bl swap_ci_regs ; mtlr 4 ; li 3,-1 ; blr
-
-
- .globl flush_cache
- .section ".opd","aw"
- .align 3
-flush_cache:
- .quad .flush_cache,.TOC.@tocbase,0
- .previous
- .type .flush_cache,@function
- .globl .flush_cache
-.flush_cache: # flush at GPR3 size GPR4
- add 4,4,3
- addi 4,4,127
- rlwinm 3,3,0,0,24
- rlwinm 4,4,0,0,24
- sub 4,4,3
- srwi 4,4,7
- mtctr 4
-0:
- dcbst 0,3
- sync
- icbi 0,3
- sync
- isync
- addi 3,3,128
- bdnz 0b
-
+.call_client: # called with r3 = address, returns r3
+ mflr 4
+ mtctr 3
+ bl swap_ci_regs
+ bctrl
+ bl swap_ci_regs
+ mtlr 4
+ li 3, -1 # client app return
blr
-
-
- #
- # This is where the secondary CPUs sit and wait.
- #
-
- . = 0x3f00
-slaveloop:
- lis 0,10
- mtctr 0
- bdnz $ # do some waiting, to prevent flooding the buses
- lwz 0,0x3f40(0)
- and. 0,0,0
- beq $-20 # wait for our flag
-
- lwz 0,0x3f80(0)
- lwz 3,0x3fc0(0)
- mtctr 0
- bctr # jump to specified address, with specified GPR3
-
-
-
-
-. = 0x3fff
-.byte 0x36 # to fill out to exactly 16kB
diff --git a/slof/fs/accept.fs b/slof/fs/accept.fs
index ad361fd..b700f4a 100644
--- a/slof/fs/accept.fs
+++ b/slof/fs/accept.fs
@@ -1,52 +1,338 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
-\ Implementation of ACCEPT. Nothing fancy for now; just handles CR and BS.
+\ Implementation of ACCEPT. Using ECMA-48 for terminal control.
-: TABLE-EXECUTE CREATE DOES> swap cells+ @ ?dup IF execute ELSE false THEN ;
+: beep bell emit ;
+
+: TABLE-EXECUTE
+ CREATE DOES> swap cells+ @ ?dup IF execute ELSE beep THEN ;
0 VALUE accept-adr
0 VALUE accept-max
0 VALUE accept-len
+0 VALUE accept-cur
-: handle-backspace accept-len ?dup IF 1- TO accept-len
- bs emit space bs emit THEN false ;
+: esc 1b emit ;
+: csi esc 5b emit ;
-: handle-enter space true ;
+: move-cursor
+ esc ." 8" accept-cur IF
+ csi base @ decimal accept-cur 0 .r base ! ." C" THEN ;
+: redraw-line
+ accept-cur accept-len = IF EXIT THEN
+ move-cursor
+ accept-adr accept-len accept-cur /string type csi ." K" move-cursor ;
+: full-redraw-line
+ accept-cur 0 to accept-cur move-cursor
+ accept-adr accept-len type csi ." K" to accept-cur move-cursor ;
+: redraw-prompt
+ cr depth . [char] > emit ;
-TABLE-EXECUTE handle-control
+: insert-char ( char -- )
+ accept-len accept-max = IF drop beep EXIT THEN
+ accept-cur accept-len <> IF csi ." @" dup emit
+ accept-adr accept-cur + dup 1+ accept-len accept-cur - move
+ ELSE dup emit THEN
+ accept-adr accept-cur + c!
+ accept-cur 1+ to accept-cur
+ accept-len 1+ to accept-len redraw-line ;
+: delete-char ( -- )
+ accept-cur accept-len = IF beep EXIT THEN
+ accept-len 1- to accept-len
+ accept-adr accept-cur + dup 1+ swap accept-len accept-cur - move
+ csi ." P" redraw-line ;
+
+STRUCT
+cell FIELD his>next
+cell FIELD his>prev
+cell FIELD his>len
+ 0 FIELD his>buf
+CONSTANT /his
+0 VALUE his-head
+0 VALUE his-tail
+0 VALUE his-cur
+: add-history
+ /his accept-len + alloc-mem
+ his-tail IF dup his-tail his>next ! ELSE dup to his-head THEN
+ his-tail over his>prev ! 0 over his>next ! dup to his-tail
+ accept-len over his>len ! accept-adr swap his>buf accept-len move ;
+: history
+ his-head BEGIN dup WHILE
+ cr dup his>buf over his>len @ type
+ his>next @ REPEAT drop ;
+: select-history ( his -- )
+ dup to his-cur dup IF
+ dup his>len @ accept-max min dup to accept-len to accept-cur
+ his>buf accept-adr accept-len move ELSE
+ drop 0 to accept-len 0 to accept-cur THEN
+ full-redraw-line ;
+
+\ tab completion state variables
+0 value ?tab-pressed
+0 value tab-last-adr
+0 value tab-last-len
+
+\ compares two strings and returns the longest equal substring.
+: $same-string ( addr-1 len-1 addr-2 len-2 -- addr-1 len-1' )
+ dup 0= IF \ The second parameter is not a string.
+ 2drop EXIT \ bail out
+ THEN
+ rot min 0 0 -rot ( addr1 addr2 0 len' 0 )
+ do ( addr1 addr2 len-1' )
+ 2 pick i + c@ lcc
+ 2 pick i + c@ lcc
+ = IF 1 + ELSE leave THEN
+ loop
+ nip
+ ;
+
+: $tab-sift-words ( text-addr text-len -- sift-count )
+ sift-compl-only >r true to sift-compl-only \ save sifting mode
+
+ last begin @ ?dup while \ loop over all words
+ $inner-sift IF \ any completions possible?
+ \ convert to lower case for user interface sanity
+ 2dup bounds do i c@ lcc i c! loop
+ ?tab-pressed IF 2dup type space THEN \ <tab><tab> prints possibilities
+ tab-last-adr tab-last-len $same-string \ find matching substring ...
+ to tab-last-len to tab-last-adr \ ... and save it
+ THEN
+ repeat
+ 2drop
+
+ #sift-count 0 to #sift-count \ how many words were found?
+ r> to sift-compl-only \ restore sifting completion mode
+ ;
+
+\ 8< node sifting for tab completion on device tree nodes below this line 8<
+
+#include <stack.fs>
+
+10 new-stack device-stack
+
+: (next-dev) ( node -- node' addr len )
+ device-stack
+ dup (node>path) rot
+ dup child IF dup push child -rot EXIT THEN
+ dup peer IF peer -rot EXIT THEN
+ drop
+ BEGIN
+ stack-depth
+ WHILE
+ pop peer ?dup IF -rot EXIT THEN
+ REPEAT
+ 0 -rot
+;
+
+: $inner-sift-nodes ( text-addr text-len node -- ... path-addr path-len true | false )
+ (next-dev) ( text-addr text-len node' path-addr path-len )
+ dup 0= IF drop false EXIT THEN
+ 2dup 6 pick 6 pick find-isubstr ( text-addr text-len node' path-addr path-len pos )
+ 0= IF
+ #sift-count 1+ to #sift-count \ count completions
+ true
+ ELSE
+ 2drop false
+ THEN
+;
+
+\
+\ test function for (next-dev)
+: .nodes ( -- )
+ s" /" find-node BEGIN dup WHILE
+ (next-dev)
+ type cr
+ REPEAT
+ drop
+ reset-stack
+;
+
+\ node sifting wants its own pockets
+create sift-node-buffer 1000 allot
+0 value sift-node-num
+: sift-node-buffer
+ sift-node-buffer sift-node-num 100 * +
+ sift-node-num 1+ dup 10 = IF drop 0 THEN
+ to sift-node-num
+;
+
+: $tab-sift-nodes ( text-addr text-len -- sift-count )
+ s" /" find-node BEGIN dup WHILE
+ $inner-sift-nodes IF \ any completions possible?
+ sift-node-buffer swap 2>r 2r@ move 2r> \ make an almost permanent copy without strdup
+ ?tab-pressed IF 2dup type space THEN \ <tab><tab> prints possibilities
+ tab-last-adr tab-last-len $same-string \ find matching substring ...
+ to tab-last-len to tab-last-adr \ ... and save it
+ THEN
+ REPEAT
+ 2drop drop
+ #sift-count 0 to #sift-count \ how many words were found?
+ reset-stack
+;
+
+: $tab-sift ( text-addr text-len -- sift-count )
+ ?tab-pressed IF beep space THEN \ cosmetical fix for <tab><tab>
+
+ dup IF bl rsplit dup IF 2swap THEN ELSE 0 0 THEN >r >r
+
+ 0 dup to tab-last-len to tab-last-adr \ reset last possible match
+ current-node @ IF \ if we are in a node?
+ 2dup 2>r \ save text
+ $tab-sift-words to #sift-count \ search in current node first
+ 2r> \ fetch text to complete, again
+ THEN
+ 2dup 2>r
+ current-node @ >r 0 set-node \ now search in global words
+ $tab-sift-words to #sift-count
+ r> set-node
+ 2r> $tab-sift-nodes
+ \ concatenate previous commands
+ r> r> dup IF s" " $cat THEN tab-last-adr tab-last-len $cat
+ to tab-last-len to tab-last-adr \ ... and save the whole string
+ ;
+
+\ 8< node sifting for tab completion on device tree nodes above this line 8<
+
+: handle-^A
+ 0 to accept-cur move-cursor ;
+: handle-^B
+ accept-cur ?dup IF 1- to accept-cur ( csi ." D" ) move-cursor THEN ;
+: handle-^D
+ delete-char ( redraw-line ) ;
+: handle-^E
+ accept-len to accept-cur move-cursor ;
+: handle-^F
+ accept-cur accept-len <> IF accept-cur 1+ to accept-cur csi ." C" THEN ;
+: handle-^H
+ accept-cur 0= IF beep EXIT THEN
+ handle-^B delete-char ;
+
+: handle-^I
+ accept-adr accept-len
+ $tab-sift 0 > IF
+ ?tab-pressed IF
+ redraw-prompt full-redraw-line
+ false to ?tab-pressed
+ ELSE
+ tab-last-adr accept-adr tab-last-len move \ copy matching substring
+ tab-last-len dup to accept-len to accept-cur \ len and cursor position
+ full-redraw-line \ redraw new string
+ true to ?tab-pressed \ second tab will print possible matches
+ THEN
+ THEN
+ ;
+
+: handle-^K
+ BEGIN accept-cur accept-len <> WHILE delete-char REPEAT ;
+: handle-^L
+ history redraw-prompt full-redraw-line ;
+: handle-^N
+ his-cur IF his-cur his>next @ ELSE his-head THEN
+ dup to his-cur select-history ;
+: handle-^P
+ his-cur IF his-cur his>prev @ ELSE his-tail THEN
+ dup to his-cur select-history ;
+: handle-^Q \ Does not handle terminal formatting yet.
+ key insert-char ;
+: handle-^R
+ full-redraw-line ;
+: handle-^U
+ 0 to accept-len 0 to accept-cur full-redraw-line ;
+
+: handle-fn
+ key drop beep ;
+
+TABLE-EXECUTE handle-CSI
+0 , ' handle-^P , ' handle-^N , ' handle-^F ,
+' handle-^B , 0 , 0 , 0 ,
+' handle-^A , 0 , 0 , ' handle-^E ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 ,
-' handle-backspace , 0 , 0 , 0 ,
-0 , ' handle-enter , 0 , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 ,
+
+TABLE-EXECUTE handle-meta
0 , 0 , 0 , 0 ,
+0 , 0 , 0 , 0 ,
+0 , 0 , 0 , 0 ,
+0 , 0 , 0 , ' handle-fn ,
+0 , 0 , 0 , 0 ,
+0 , 0 , 0 , 0 ,
+0 , 0 , 0 , ' handle-CSI ,
+0 , 0 , 0 , 0 ,
+
+: handle-ESC
+ key dup 5b = IF drop key
+ dup 33 = IF \ DEL
+ drop key drop ( drops closing 7e ) handle-^D
+ ELSE
+ 1f and handle-CSI
+ THEN
+ ELSE 1f and handle-meta THEN
+ ;
-: handle-normal
- dup emit
- accept-len accept-max < IF
- accept-adr accept-len chars+ c!
- accept-len 1+ TO accept-len
- ELSE drop THEN ;
+TABLE-EXECUTE handle-control
+0 , \ ^@:
+' handle-^A ,
+' handle-^B ,
+0 , \ ^C:
+' handle-^D ,
+' handle-^E ,
+' handle-^F ,
+0 , \ ^G:
+' handle-^H ,
+' handle-^I , \ tab
+0 , \ ^J:
+' handle-^K ,
+' handle-^L ,
+0 , \ ^M: enter: handled in main loop
+' handle-^N ,
+0 , \ ^O:
+' handle-^P ,
+' handle-^Q ,
+' handle-^R ,
+0 , \ ^S:
+0 , \ ^T:
+' handle-^U ,
+0 , \ ^V:
+0 , \ ^W:
+0 , \ ^X:
+0 , \ ^Y: insert save buffer
+0 , \ ^Z:
+' handle-ESC ,
+0 , \ ^\:
+0 , \ ^]:
+0 , \ ^^:
+0 , \ ^_:
: (accept) ( adr len -- len' )
- TO accept-max TO accept-adr 0 TO accept-len
- BEGIN key
- dup 7f = IF drop 8 THEN \ Handle DEL as if it was BS.
- dup bl < IF handle-control IF accept-len exit THEN
- ELSE handle-normal THEN
- AGAIN ;
-
-' (accept) TO accept
+ cursor-on
+ to accept-max to accept-adr
+ 0 to accept-len 0 to accept-cur
+ 0 to his-cur
+ 1b emit 37 emit
+ BEGIN key
+ dup 0d <> WHILE
+ dup 9 <> IF 0 to ?tab-pressed THEN \ reset state machine
+ dup 7f = IF drop 8 THEN \ Handle DEL as if it was BS. ??? bogus
+ dup bl < IF handle-control ELSE
+ dup 80 and IF dup a0 < IF 7f and handle-meta ELSE drop beep THEN ELSE
+ insert-char THEN THEN
+ REPEAT drop add-history
+ accept-len to accept-cur move-cursor space accept-len
+ cursor-off
+;
+
+' (accept) to accept
diff --git a/slof/fs/alloc-mem.fs b/slof/fs/alloc-mem.fs
index 7dc7bd4..89c6a61 100644
--- a/slof/fs/alloc-mem.fs
+++ b/slof/fs/alloc-mem.fs
@@ -1,19 +1,75 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+#include <claim.fs>
\ Memory "heap" (de-)allocation.
-\ For now, just allocate from the data space, and never take space back.
+\ Keep a linked list of free blocks per power-of-two size.
+\ Never coalesce entries when freed; split blocks when needed while allocating.
+
+\ 3f CONSTANT (max-heads#)
+heap-end heap-start - log2 1+ CONSTANT (max-heads#)
+
+CREATE heads (max-heads#) cells allot
+heads (max-heads#) cells erase
+
+
+: size>head ( size -- headptr ) log2 3 max cells heads + ;
+
+
+\ Allocate a memory block
+: alloc-mem ( len -- a-addr )
+ dup 0= IF EXIT THEN
+ 1 over log2 3 max ( len 1 log_len )
+ dup (max-heads#) >= IF cr ." Out of internal memory." cr 3drop 0 EXIT THEN
+ lshift >r ( len R: 1<<log_len )
+ size>head dup @ IF
+ dup @ dup >r @ swap ! r> r> drop EXIT
+ THEN ( headptr R: 1<<log_len)
+ r@ 2* recurse dup ( headptr a-addr2 a-addr2 R: 1<<log_len)
+ dup 0= IF r> 2drop 2drop 0 EXIT THEN
+ r> + >r 0 over ! swap ! r>
+;
+
+
+\ Free a memory block
+
+: free-mem ( a-addr len -- )
+ dup 0= IF 2drop EXIT THEN size>head 2dup @ swap ! !
+;
+
+
+: #links ( a -- n )
+ @ 0 BEGIN over WHILE 1+ swap @ swap REPEAT nip
+;
+
+
+: .free ( -- )
+ 0 (max-heads#) 0 DO
+ heads i cells + #links dup IF
+ cr dup . ." * " 1 i lshift dup . ." = " * dup .
+ THEN
+ +
+ LOOP
+ cr ." Total " .
+;
+
+
+\ Start with just one free block.
+heap-start heap-end heap-start - free-mem
+
+
+\ : free-mem ( a-addr len -- ) 2drop ;
+
+\ Uncomment the following line for debugging:
+\ #include <alloc-mem-debug.fs>
-: alloc-mem ( len -- a-addr ) align here swap allot ;
-: free-mem ( a-addr len -- ) 2drop ;
diff --git a/slof/fs/available.fs b/slof/fs/available.fs
new file mode 100644
index 0000000..da80c79
--- /dev/null
+++ b/slof/fs/available.fs
@@ -0,0 +1,72 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+VARIABLE chosen-memory-ih 0 chosen-memory-ih !
+
+\ +
+\ Maintain "available" property.
+\ Sun has a single memory node with "available" property
+\ and separate memory controller nodes.
+\ We corespond memory nodes with their respective memory controllers
+\ and use /chosen/memory as default memory node to hold the "available" map
+\ NOTE -> /chosen/memory is expected 2B initialized before using claim/release
+\ +
+
+: (chosen-memory-ph) ( -- phandle )
+ chosen-memory-ih @ ?dup 0= IF
+ s" memory" get-chosen IF
+ decode-int nip nip dup chosen-memory-ih !
+ ihandle>phandle
+ ELSE 0 THEN
+ ELSE ihandle>phandle THEN
+;
+
+: (set-available-prop) ( prop plen -- )
+ s" available"
+ (chosen-memory-ph) ?dup 0<> IF set-property ELSE
+ cr ." Can't find chosen memory node - "
+ ." no available property created" cr
+ 2dup 2dup
+ THEN
+;
+
+: update-available-property ( available-ptr -- )
+ dup >r available>size@
+ 0= r@ available AVAILABLE-SIZE /available * + >= or IF
+ available r> available - encode-bytes (set-available-prop)
+ ELSE
+ r> /available + RECURSE
+ THEN
+;
+
+: update-available-property available update-available-property ;
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ +
+\ IEEE 1275 implementation:
+\ claim
+\ Claim the region with given start address and size (if align parameter is 0);
+\ alternatively claim any region of given alignment
+\ +
+\ Throw an exception if failed
+\ +
+: claim ( [ addr ] len align -- base ) claim update-available-property ;
+
+\ +
+\ IEEE 1275 implementation:
+\ release
+\ Free the region with given start address and size
+\ +
+: release ( addr len -- ) release update-available-property ;
+
+update-available-property
+
diff --git a/slof/fs/banner.fs b/slof/fs/banner.fs
new file mode 100644
index 0000000..15527c6
--- /dev/null
+++ b/slof/fs/banner.fs
@@ -0,0 +1,23 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: banner
+ cr ." Type 'boot' and press return to continue booting the system."
+ s" /packages/sms" find-node IF
+ cr ." Type 'sms-start' and press return to enter the configuration menu."
+ THEN
+ cr ." Type 'reset-all' and press return to reboot the system."
+ cr cr
+;
+
+: .banner banner console-clean-fifo ;
+
diff --git a/slof/fs/base.fs b/slof/fs/base.fs
new file mode 100644
index 0000000..9327e53
--- /dev/null
+++ b/slof/fs/base.fs
@@ -0,0 +1,504 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Words missing in *.in files
+VARIABLE mask -1 mask !
+
+: default-hw-exception s" Exception #" type . ;
+
+' default-hw-exception to hw-exception-handler
+
+: diagnostic-mode? false ; \ 2B DOTICK'D later in envvar.fs
+
+: memory-test-suite ( addr len -- fail? )
+ diagnostic-mode? IF
+ ." Memory test mask value: " mask @ . cr
+ ." No memory test suite currently implemented! " cr
+ THEN
+ false
+;
+
+: 0.r 0 swap <# 0 ?DO # LOOP #> type ;
+
+\ count the number of bits equal 1
+\ the idea is to clear in each step the least significant bit
+\ v&(v-1) does exactly this, so count the steps until v == 0
+: cnt-bits ( 64-bit-value -- #bits=1 )
+ dup IF
+ 41 1 DO dup 1- and dup 0= IF drop i LEAVE THEN LOOP
+ THEN
+;
+
+: bcd-to-bin ( bcd -- bin )
+ dup f and swap 4 rshift a * +
+;
+
+\ calcs the exponent of the highest power of 2 not greater than n
+: 2log ( n -- lb{n} )
+ 8 cells 0 DO 1 rshift dup 0= IF drop i LEAVE THEN LOOP
+;
+
+\ calcs the exponent of the lowest power of 2 not less than n
+: log2 ( n -- log2-n )
+ 1- 2log 1+
+;
+
+\ Standard compliant $find
+: $find ( str len -- xt true | str len false )
+ 2dup $find
+ IF
+ drop nip nip TRUE
+ ELSE
+ FALSE
+ THEN
+;
+
+CREATE $catpad 100 allot
+: $cat ( str1 len1 str2 len2 -- str3 len3 )
+ >r >r dup >r $catpad swap move
+ r> dup $catpad + r> swap r@ move
+ r> + $catpad swap ;
+
+\ WARNING: The following two ($cat-comm & $cat-space) are dirty in a sense
+\ that they add 1 or 2 characters to str1 before executing $cat
+\ The ASSUMPTION is that str1 buffer provides that extra space and it is
+\ responsibility of the code owner to ensure that
+: $cat-comma ( str2 len2 str1 len1 -- "str1, str2" len1+len2+2 )
+ 2dup + s" , " rot swap move 2+ 2swap $cat
+;
+
+: $cat-space ( str2 len2 str1 len1 -- "str1 str2" len1+len2+1 )
+ 2dup + bl swap c! 1+ 2swap $cat
+;
+: $cathex ( str len val -- str len' )
+ (u.) $cat
+;
+
+
+
+: 2CONSTANT CREATE , , DOES> 2@ ;
+: $2CONSTANT $CREATE , , DOES> 2@ ;
+: 2VARIABLE CREATE 0 , 0 , DOES> ;
+
+: (is-user-word) ( name-str name-len xt -- ) -rot $CREATE , DOES> @ execute ;
+
+: zcount ( zstr -- str len ) dup BEGIN dup c@ WHILE char+ REPEAT over - ;
+: zplace ( str len buf -- ) 2dup + 0 swap c! swap move ;
+
+: strdup ( str len -- dupstr len ) here over allot swap 2dup 2>r move 2r> ;
+
+: str= ( str1 len1 str2 len2 -- equal? )
+ rot over <> IF 3drop false ELSE comp 0= THEN ;
+
+: #aligned ( adr alignment -- adr' ) negate swap negate and negate ;
+: #join ( lo hi #bits -- x ) lshift or ;
+: #split ( x #bits -- lo hi ) 2dup rshift dup >r swap lshift xor r> ;
+
+: /string ( str len u -- str' len' )
+ >r swap r@ chars + swap r> - ;
+: skip ( str len c -- str' len' )
+ >r BEGIN dup WHILE over c@ r@ = WHILE 1 /string REPEAT THEN r> drop ;
+: scan ( str len c -- str' len' )
+ >r BEGIN dup WHILE over c@ r@ <> WHILE 1 /string REPEAT THEN r> drop ;
+: split ( str len char -- left len right len )
+ >r 2dup r> findchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ;
+\ reverse findchar -- search from the end of the string
+: rfindchar ( str len char -- offs true | false )
+ swap 1 - 0 swap do
+ over i + c@
+ over dup bl = if <= else = then if
+ 2drop i dup dup leave
+ then
+ -1 +loop =
+;
+\ reverse split -- split at the last occurence of char
+: rsplit ( str len char -- left len right len )
+ >r 2dup r> rfindchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ;
+
+: left-parse-string ( str len char -- R-str R-len L-str L-len )
+ split 2swap ;
+: replace-char ( str len chout chin -- )
+ >r -rot BEGIN 2dup 4 pick findchar WHILE tuck - -rot + r@ over c! swap REPEAT
+ r> 2drop 2drop
+;
+\ Duplicate string and replace \ with /
+: \-to-/ ( str len -- str' len ) strdup 2dup [char] \ [char] / replace-char ;
+
+: // dup >r 1- + r> / ; \ division, round up
+
+: c@+ ( adr -- c adr' ) dup c@ swap char+ ;
+: 2c@ ( adr -- c1 c2 ) c@+ c@ ;
+: 4c@ ( adr -- c1 c2 c3 c4 ) c@+ c@+ c@+ c@ ;
+: 8c@ ( adr -- c1 c2 c3 c4 c5 c6 c7 c8 ) c@+ c@+ c@+ c@+ c@+ c@+ c@+ c@ ;
+
+
+: 4dup ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2 n3 n4 ) 2over 2over ;
+: 4drop ( n1 n2 n3 n4 -- ) 2drop 2drop ;
+
+\ yes sometimes even something like this is needed
+: 6dup ( 1 2 3 4 5 6 -- 1 2 3 4 5 6 1 2 3 4 5 6 )
+ 5 pick 5 pick 5 pick 5 pick 5 pick 5 pick
+;
+
+\ convert a 32 bit signed into a 64 signed
+\ ( propagate bit 31 to all bits 32:63 )
+: signed ( n1 -- n2 ) dup 80000000 and IF FFFFFFFF00000000 or THEN ;
+
+: <l@ ( addr -- x ) l@ signed ;
+
+: -leading BEGIN dup WHILE over c@ bl <= WHILE 1 /string REPEAT THEN ;
+: (parse-line) skipws 0 parse ;
+
+
+\ Append two character to hex byte, if possible
+
+: hex-byte ( char0 char1 -- value true|false )
+ 10 digit IF
+ swap 10 digit IF
+ 4 lshift or true EXIT
+ ELSE
+ 2drop 0
+ THEN
+ ELSE
+ drop
+ THEN
+ false EXIT
+;
+
+\ Parse hex string within brackets
+
+: parse-hexstring ( dst-adr -- dst-adr' )
+ [char] ) parse cr ( dst-adr str len )
+ bounds ?DO ( dst-adr )
+ i c@ i 1+ c@ hex-byte IF ( dst-adr hex-byte )
+ >r dup r> swap c! 1+ 2 ( dst-adr+1 2 )
+ ELSE
+ drop 1 ( dst-adr 1 )
+ THEN
+ +LOOP
+;
+
+\ Parse upto next "
+
+: parse-" ( dst-adr -- dst-adr' )
+ [char] " parse dup 3 pick + >r ( dst-adr str len R: dst-adr' )
+ >r swap r> move r> ( dst-adr' )
+;
+
+: (") ( dst-adr -- dst-adr' )
+ begin ( dst-adr )
+ parse-" ( dst-adr' )
+ ib >in @ + c@ [char] ( = IF
+ parse-hexstring
+ ELSE
+ EXIT
+ THEN
+ again
+;
+
+CREATE "pad 100 allot
+
+\ String with embedded hex strings
+\ Example: " ba"( 12 34,4567)ab" -> >x62x61x12x34x45x67x61x62<
+
+: " ( [text<">< >] -- text-str text-len )
+ state @ IF \ compile sliteral, pstr into dict
+ "pad dup (") over - ( str len )
+ ['] sliteral compile, dup c, ( str len )
+ bounds ?DO i c@ c, LOOP
+ align ['] count compile,
+ ELSE
+ pocket dup (") over - \ Interpretation, put string
+ THEN \ in temp buffer
+; immediate
+
+\ Hash for faster lookup
+#include <find-hash.fs>
+
+\ Remove command old-name and all subsequent definitions
+
+: $forget ( str len -- )
+ 2dup last @ ( str len str len last-bc )
+ BEGIN
+ dup >r ( str len str len last-bc R: last-bc )
+ cell+ char+ count ( str len str len found-str found-len R: last-bc )
+ string=ci IF ( str len R: last-bc )
+ r> @ last ! 2drop clean-hash EXIT ( -- )
+ THEN
+ 2dup r> @ dup 0= ( str len str len next-bc next-bc )
+ UNTIL
+ drop 2drop 2drop \ clean hash table
+;
+
+: forget ( "old-name<>" -- )
+ parse-word $forget
+;
+
+#include <search.fs>
+
+\ The following constants are required in some parts
+\ of the code, mainly instance variables and see. Having to reverse
+\ engineer our own CFAs seems somewhat weird, but we gained a bit speed.
+
+\ Each colon definition is surrounded by colon and semicolon
+\ constant below contain address of their xt
+
+: (function) ;
+defer (defer)
+0 value (value)
+0 constant (constant)
+variable (variable)
+create (create)
+alias (alias) (function)
+cell buffer: (buffer:)
+
+' (function) @ \ ( <colon> )
+' (function) cell + @ \ ( ... <semicolon> )
+' (defer) @ \ ( ... <defer> )
+' (value) @ \ ( ... <value> )
+' (constant) @ \ ( ... <constant> )
+' (variable) @ \ ( ... <variable> )
+' (create) @ \ ( ... <create> )
+' (alias) @ \ ( ... <alias> )
+' (buffer:) @ \ ( ... <buffer:> )
+
+\ now clean up the test functions
+forget (function)
+
+\ and remember the constants
+constant <buffer:>
+constant <alias>
+constant <create>
+constant <variable>
+constant <constant>
+constant <value>
+constant <defer>
+constant <semicolon>
+constant <colon>
+
+' lit constant <lit>
+' sliteral constant <sliteral>
+' 0branch constant <0branch>
+' branch constant <branch>
+' doloop constant <doloop>
+' dotick constant <dotick>
+' doto constant <doto>
+' do?do constant <do?do>
+' do+loop constant <do+loop>
+' do constant <do>
+' exit constant <exit>
+
+
+\ provide the memory management words
+\ #include <claim.fs>
+\ #include "memory.fs"
+#include <alloc-mem.fs>
+
+#include <node.fs>
+
+: find-substr ( basestr-ptr basestr-len substr-ptr substr-len -- pos )
+ \ if substr-len == 0 ?
+ dup 0 = IF
+ \ return 0
+ 2drop 2drop 0 exit THEN
+ \ if substr-len <= basestr-len ?
+ dup 3 pick <= IF
+ \ run J from 0 to "basestr-len"-"substr-len" and I from 0 to "substr-len"-1
+ 2 pick over - 1+ 0 DO dup 0 DO
+ \ substr-ptr[i] == basestr-ptr[j+i] ?
+ over i + c@ 4 pick j + i + c@ = IF
+ \ (I+1) == substr-len ?
+ dup i 1+ = IF
+ \ return J
+ 2drop 2drop j unloop unloop exit THEN
+ ELSE leave THEN
+ LOOP LOOP
+ THEN
+ \ if there is no match then exit with basestr-len as return value
+ 2drop nip
+;
+
+: find-isubstr ( basestr-ptr basestr-len substr-ptr substr-len -- pos )
+ \ if substr-len == 0 ?
+ dup 0 = IF
+ \ return 0
+ 2drop 2drop 0 exit THEN
+ \ if substr-len <= basestr-len ?
+ dup 3 pick <= IF
+ \ run J from 0 to "basestr-len"-"substr-len" and I from 0 to "substr-len"-1
+ 2 pick over - 1+ 0 DO dup 0 DO
+ \ substr-ptr[i] == basestr-ptr[j+i] ?
+ over i + c@ lcc 4 pick j + i + c@ lcc = IF
+ \ (I+1) == substr-len ?
+ dup i 1+ = IF
+ \ return J
+ 2drop 2drop j unloop unloop exit THEN
+ ELSE leave THEN
+ LOOP LOOP
+ THEN
+ \ if there is no match then exit with basestr-len as return value
+ 2drop nip
+;
+
+: find-nextline ( str-ptr str-len -- pos )
+ \ run I from 0 to "str-len"-1 and check str-ptr[i]
+ dup 0 ?DO over i + c@ CASE
+ \ 0x0a (=LF) found ?
+ 0a OF
+ \ if current cursor is at end position (I == "str-len"-1) ?
+ dup 1- i = IF
+ \ return I+1
+ 2drop i 1+ unloop exit THEN
+ \ if str-ptr[I+1] == 0x0d (=CR) ?
+ over i 1+ + c@ 0d = IF
+ \ return I+2
+ 2drop i 2+ ELSE
+ \ else return I+1
+ 2drop i 1+ THEN
+ unloop exit
+ ENDOF
+ \ 0x0d (=CR) found ?
+ 0d OF
+ \ if current cursor is at end position (I == "str-len"-1) ?
+ dup 1- i = IF
+ \ return I+1
+ 2drop i 1+ unloop exit THEN
+ \ str-ptr[I+1] == 0x0a (=LF) ?
+ over i 1+ + c@ 0a = IF
+ \ return I+2
+ 2drop i 2+ ELSE
+ \ return I+1
+ 2drop i 1+ THEN
+ unloop exit
+ ENDOF
+ ENDCASE LOOP nip
+;
+
+: string-at ( str1-ptr str1-len pos -- str2-ptr str2-len )
+ -rot 2 pick - -rot swap chars + swap
+;
+
+\ appends the string beginning at addr2 to the end of the string
+\ beginning at addr1
+\ !!! THERE MUST BE SUFFICIENT MEMORY RESERVED FOR THE STRING !!!
+\ !!! BEGINNING AT ADDR1 (cp. 'strcat' in 'C' ) !!!
+
+: string-cat ( addr1 len1 addr2 len2 -- addr1 len1+len2 )
+ \ len1 := len1+len2
+ rot dup >r over + -rot
+ ( addr1 len1+len2 dest-ptr src-ptr len2 )
+ 3 pick r> chars + -rot
+ ( ... dest-ptr src-ptr )
+ 0 ?DO
+ 2dup c@ swap c!
+ char+ swap char+ swap
+ LOOP 2drop
+;
+
+\ appends a character to the end of the string beginning at addr
+\ !!! THERE MUST BE SUFFICIENT MEMORY RESERVED FOR THE STRING !!!
+\ !!! BEGINNING AT ADDR1 (cp. 'strcat' in 'C' ) !!!
+
+: char-cat ( addr len character -- addr len+1 )
+ -rot 2dup >r >r 1+ rot r> r> chars + c!
+;
+
+\ Returns true if source and destination overlap
+: overlap ( src dest size -- true|false )
+ 3dup over + within IF 3drop true ELSE rot tuck + within THEN
+;
+
+: parse-2int ( str len -- val.lo val.hi )
+\ ." parse-2int ( " 2dup swap . . ." -- "
+ [char] , split ?dup IF eval ELSE drop 0 THEN
+ -rot ?dup IF eval ELSE drop 0 THEN
+\ 2dup swap . . ." )" cr
+;
+
+\ peek/poke minimal implementation, just to support FCode drivers
+\ Any implmentation with full error detection will be platform specific
+: cpeek ( addr -- false | byte true ) c@ true ;
+: cpoke ( byte addr -- success? ) c! true ;
+: wpeek ( addr -- false | word true ) w@ true ;
+: wpoke ( word addr -- success? ) w! true ;
+: lpeek ( addr -- false | lword true ) l@ true ;
+: lpoke ( lword addr -- success? ) l! true ;
+
+defer reboot ( -- )
+defer halt ( -- )
+defer disable-watchdog ( -- )
+defer reset-watchdog ( -- )
+defer set-watchdog ( +n -- )
+defer set-led ( type instance state -- status )
+defer get-flashside ( -- side )
+defer set-flashside ( side -- status )
+defer read-bootlist ( -- )
+defer furnish-boot-file ( -- adr len )
+defer set-boot-file ( adr len -- )
+defer mfg-mode? ( -- flag )
+defer of-prompt? ( -- flag )
+defer debug-boot? ( -- flag )
+defer bmc-version ( -- adr len )
+defer cursor-on ( -- )
+defer cursor-off ( -- )
+
+: nop-reboot ( -- ) ." reboot not available" abort ;
+: nop-halt ( -- ) ." halt not available" abort ;
+: nop-disable-watchdog ( -- ) ." disable-watchdog not available" cr ;
+: nop-reset-watchdog ( -- ) ." reset-watchdog not available" cr ;
+: nop-set-watchdog ( +n -- ) drop ." set-watchdog not available" cr ;
+: nop-set-led ( type instance state -- status ) drop drop drop ;
+: nop-get-flashside ( -- side ) ." Cannot get flashside" cr ABORT ;
+: nop-set-flashside ( side -- status ) ." Cannot set flashside" cr ABORT ;
+: nop-read-bootlist ( -- ) ;
+: nop-furnish-bootfile ( -- adr len ) s" :NONE" ;
+: nop-set-boot-file ( adr len -- ) 2drop ;
+: nop-mfg-mode? ( -- flag ) false ;
+: nop-of-prompt? ( -- flag ) false ;
+: nop-debug-boot? ( -- flag ) false ;
+: nop-bmc-version ( -- adr len ) s" XXXXX" ;
+: nop-cursor-on ( -- ) ;
+: nop-cursor-off ( -- ) ;
+
+' nop-reboot to reboot
+' nop-halt to halt
+' nop-disable-watchdog to disable-watchdog
+' nop-reset-watchdog to reset-watchdog
+' nop-set-watchdog to set-watchdog
+' nop-set-led to set-led
+' nop-get-flashside to get-flashside
+' nop-set-flashside to set-flashside
+' nop-read-bootlist to read-bootlist
+' nop-furnish-bootfile to furnish-boot-file
+' nop-set-boot-file to set-boot-file
+' nop-mfg-mode? to mfg-mode?
+' nop-of-prompt? to of-prompt?
+' nop-debug-boot? to debug-boot?
+' nop-bmc-version to bmc-version
+' nop-cursor-on to cursor-on
+' nop-cursor-off to cursor-off
+
+: reset-all reboot ;
+
+\ Load base
+10000000 value load-base
+2000000 value flash-load-base
+
+\ provide first level debug support
+#include "debug.fs"
+\ provide 7.5.3.1 Dictionary search
+#include "dictionary.fs"
+\ block data access for IO devices - ought to be implemented in engine
+#include "rmove.fs"
+\ provide a simple run time preprocessor
+#include <preprocessor.fs>
diff --git a/slof/fs/boot.fs b/slof/fs/boot.fs
new file mode 100644
index 0000000..ded2b0e
--- /dev/null
+++ b/slof/fs/boot.fs
@@ -0,0 +1,247 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ \\\\\\\\\\\\\\ Global Data
+CREATE (bootdevice) 2 cells allot (bootdevice) 2 cells erase
+CREATE bootargs 2 cells allot bootargs 2 cells erase
+CREATE load-list 2 cells allot load-list 2 cells erase
+
+' (bootdevice) to bootdevice
+
+0 VALUE load-size
+0 VALUE go-entry
+VARIABLE state-valid false state-valid !
+CREATE go-args 2 cells allot go-args 2 cells erase
+
+\ \\\\\\\\\\\\\\ Structure/Implementation Dependent Methods
+
+: $bootargs
+ bootargs 2@ ?dup IF
+ ELSE s" diagnostic-mode?" evaluate and IF s" diag-file" evaluate
+ ELSE s" boot-file" evaluate THEN THEN
+;
+
+: $bootdev
+ bootdevice 2@ ?dup IF
+ ELSE s" diagnostic-mode?" evaluate and IF
+ s" diag-device" evaluate
+ ELSE
+ s" boot-device" evaluate
+ THEN
+ THEN
+ ?dup 0= IF
+ disable-watchdog
+ drop ABORT" No boot device!"
+ THEN
+;
+
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ *
+\ *
+: set-boot-args ( str len -- ) dup IF strdup ELSE nip dup THEN bootargs 2! ;
+
+: (set-boot-device) ( str len -- )
+ ?dup IF 1+ strdup 1- ELSE drop 0 0 THEN bootdevice 2! ;
+
+' (set-boot-device) to set-boot-device
+
+: (add-boot-device) ( str len -- ) \ Concatenate " str" to "bootdevice"
+ bootdevice 2@ ?dup IF $cat-space ELSE drop THEN set-boot-device ;
+
+' (add-boot-device) to add-boot-device
+
+0 value claim-list
+
+: no-go ( -- ) -64 boot-exception-handler ABORT ;
+
+defer go ( -- )
+
+: go-32 ( -- )
+ state-valid @ IF
+ 0 ciregs >r3 ! 0 ciregs >r4 !
+ go-args 2@ go-entry start-elf client-data
+ claim-list elf-release 0 to claim-list
+ THEN
+ -6d boot-exception-handler ABORT" "
+;
+: go-64 ( -- )
+ state-valid @ IF
+ 0 ciregs >r3 ! 0 ciregs >r4 !
+ go-args 2@ go-entry start-elf64 client-data
+ claim-list elf-release 0 to claim-list
+ THEN
+ -6d boot-exception-handler ABORT" "
+;
+
+: load-elf-init ( arg len file-addr -- success )
+ false state-valid ! \ Not valid anymore ...
+ claim-list IF \ Release claimed mem
+ claim-list elf-release 0 to claim-list \ from last load
+ THEN
+
+ dup ['] elf-check-file CATCH IF
+ ( -64 THROW ) \ Not now, let the 'go' (i.e. no-go) whine about it
+ drop 0
+ THEN
+ CASE
+ 1 OF true swap ['] load-elf32-claim CATCH IF
+ 2drop drop -66 THROW
+ THEN
+ ['] go-32 ENDOF ( arg len true claim-list entry go )
+ 2 OF true swap ['] load-elf64-claim CATCH IF
+ 2drop drop -66 THROW
+ THEN
+ ['] go-64 ENDOF ( arg len true claim-list entry go )
+ dup OF drop ['] no-go to go
+ 2drop false EXIT ENDOF ( false )
+ ENDCASE
+
+ to go to go-entry to claim-list
+ dup state-valid ! -rot
+
+ 2 pick IF
+ go-args 2!
+ ELSE
+ 2drop
+ THEN
+;
+
+: init-program ( -- )
+ $bootargs LOAD-BASE ['] load-elf-init CATCH ?dup IF
+ boot-exception-handler
+ 2drop 2drop false \ Could not claim
+ ELSE IF
+ 0 ciregs 2dup >r3 ! >r4 ! \ Valid (ELF ) Image
+ THEN
+ THEN
+;
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ Generic device load method:
+\ *
+
+
+: do-load ( devstr len -- img-size ) \ Device method wrapper
+ 258 set-watchdog \ Set watchdog timer to 10 minutes
+ my-self >r current-node @ >r \ Save my-self
+ ." Trying to load: " $bootargs type ." from: " 2dup type ." ... "
+ 2dup open-dev dup IF
+ dup to my-self
+ dup ihandle>phandle set-node
+ -rot ( ihandle devstr len )
+ my-args nip 0= IF
+ 2dup 1- + c@ [char] : <> IF \ Add : to device path if missing
+ 1+ strdup 2dup 1- + [char] : swap c!
+ THEN
+ THEN
+ encode-string s" bootpath" set-chosen
+ $bootargs encode-string s" bootargs" set-chosen
+ LOAD-BASE s" load" 3 pick ['] $call-method CATCH IF
+ -67 boot-exception-handler 3drop drop false
+ ELSE
+ dup 0> IF
+ init-program
+ ELSE
+ false state-valid !
+ drop 0 \ Could not load
+ THEN
+ THEN
+ swap close-dev device-end dup to load-size
+ ELSE -68 boot-exception-handler 3drop false THEN
+ r> set-node r> to my-self \ Restore my-self
+;
+
+: parse-load ( "{devlist}" -- success ) \ Parse-execute boot-device list
+ cr BEGIN parse-word dup WHILE
+ ( de-alias ) do-load dup 0< IF drop 0 THEN IF
+ state-valid @ IF ." Successfully loaded" cr THEN
+ true 0d parse strdup load-list 2! EXIT
+ THEN
+ REPEAT 2drop 0 0 load-list 2! false
+;
+
+: load ( "{params}<eol>"} -- success ) \ Client interface to load
+ parse-word 0d parse -leading 2swap ?dup IF
+ de-alias
+ over c@ [char] / = IF
+ set-boot-device
+ ELSE
+ s" " 2swap $cat $cat
+ THEN
+ ELSE
+ drop
+ THEN
+ set-boot-args s" parse-load " $bootdev $cat strdup evaluate
+;
+
+: load-next ( -- success ) \ Continue after go failed
+ load-list 2@ ?dup IF s" parse-load " 2swap $cat strdup evaluate
+ ELSE drop false THEN
+;
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\
+\ load/go utilities
+\ -> Should be in loaders.fs
+\ *
+
+: noload false ;
+
+' no-go to go
+
+: (go-and-catch) ( -- )
+ ['] go behavior CATCH IF -69 boot-exception-handler THEN
+;
+
+
+\ if the board does not get the bootlist from the nvram
+\ then this word is supposed to be overloaded with the
+\ word to get the bootlist from VPD (or from wheresoever)
+read-bootlist
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ IEEE 1275 : load (user interface)
+\ *
+: boot
+ load IF
+ disable-watchdog (go-and-catch)
+ BEGIN load-next WHILE
+ (go-and-catch)
+ REPEAT
+
+ \ When we return from boot print the banner again.
+ .banner
+ ELSE
+ -65 boot-exception-handler
+ THEN
+;
+
+: load load 0= IF -65 boot-exception-handler THEN ;
+
+\ \\\\ Temporary hacks for backwards compatibility
+: yaboot ." use 'boot disk' instead " ;
+
+: netboot ( -- rc ) ." Use 'boot net' instead " ;
+
+: netboot-arg ( arg-string -- rc ) s" boot net " 2swap $cat (parse-line) $cat
+ evaluate ;
+
+: netload ( -- rc ) (parse-line)
+ load-base >r FLASH-LOAD-BASE to load-base
+ s" load net:" strdup 2swap $cat strdup evaluate
+ r> to load-base
+ load-size
+;
+: neteval ( -- ) FLASH-LOAD-BASE netload evaluate ;
+
diff --git a/slof/fs/bootmsg.fs b/slof/fs/bootmsg.fs
new file mode 100644
index 0000000..91cef6f
--- /dev/null
+++ b/slof/fs/bootmsg.fs
@@ -0,0 +1,74 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+create debugstr 255 allot
+0 VALUE debuglen
+\ tbl@ d# 1000 * 196e6aa / VALUE TIME1
+\ 0 VALUE TIME2
+
+\ Usage: 42 cp
+: cp ( checkpoint -- )
+ \ cr depth 2 0.r s" : " type .s cr \ DEBUG
+ \ cr ." time: " tbl@ d# 1000 * 196e6aa / dup TIME1 - dup . cr TIME2 + TO TIME2 TO TIME1
+ bootmsg-cp ;
+
+: (warning) ( id level ptr len -- )
+ dup 1 + TO debuglen
+ debugstr swap move \ copy into buffer
+ 0 debuglen debugstr + c! \ terminate '\0'
+ debugstr bootmsg-warning
+;
+
+\ Usage: 42 0 warning" warning-txt"
+: warning" ( id level [text<">] -- )
+ postpone s" state @
+ IF
+ ['] (warning) compile,
+ ELSE
+ (warning)
+ THEN
+; immediate
+
+: (debug-cp) ( id level ptr len -- )
+ dup 1 + TO debuglen
+ debugstr swap move \ copy into buffer
+ 0 debuglen debugstr + c! \ terminate '\0'
+ debugstr bootmsg-debugcp
+;
+
+\ Usage: 42 0 debug-cp" debug-cp-txt"
+: debug-cp" ( id level [text<">] -- )
+ postpone s" state @
+ IF
+ ['] (debug-cp) compile,
+ ELSE
+ (debug-cp)
+ THEN
+; immediate
+
+: (error) ( id ptr len -- )
+ dup 1 + TO debuglen
+ debugstr swap move \ copy into buffer
+ 0 debuglen debugstr + c! \ terminate '\0'
+ debugstr bootmsg-error
+;
+
+\ Usage: 42 error" error-txt"
+: error" ( id level [text<">] -- )
+ postpone s" state @
+ IF
+ ['] (error) compile,
+ ELSE
+ (error)
+ THEN
+; immediate
+
+bootmsg-nvupdate
diff --git a/slof/fs/claim.fs b/slof/fs/claim.fs
new file mode 100644
index 0000000..cba0312
--- /dev/null
+++ b/slof/fs/claim.fs
@@ -0,0 +1,403 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ \\\\\\\\\\\\\\ Constants
+500 CONSTANT AVAILABLE-SIZE
+10000000 CONSTANT MIN-RAM-SIZE \ assumed minimal memory size
+4000 CONSTANT MIN-RAM-RESERVE \ prevent from using first pages
+
+\ \\\\\\\\\\\\\\ Structures
+\ +
+\ The available element size depends strictly on the address/size
+\ value formats and will be different for various device types
+\ +
+STRUCT
+ cell field available>address
+ cell field available>size
+CONSTANT /available
+
+
+\ \\\\\\\\\\\\\\ Global Data
+CREATE available AVAILABLE-SIZE /available * allot available AVAILABLE-SIZE /available * erase
+VARIABLE mem-pre-released 0 mem-pre-released !
+
+\ \\\\\\\\\\\\\\ Structure/Implementation Dependent Methods
+: available>size@ available>size @ ;
+: available>address@ available>address @ ;
+: available>size! available>size ! ;
+: available>address! available>address ! ;
+
+: available! ( addr size available-ptr -- )
+ dup -rot available>size! available>address!
+;
+
+: available@ ( available-ptr -- addr size )
+ dup available>address@ swap available>size@
+;
+
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ +
+\ Warning: They are not yet really independent from available formatting
+\ +
+
+\ +
+\ Find position in the "available" where given range exists or can be inserted,
+\ return pointer and logical found/notfound value
+\ If error, return NULL pointer in addition to notfound code
+\ +
+: (?available-segment<) ( start1 end1 start2 end2 -- true/false ) drop < nip ;
+
+: (?available-segment>) ( start1 end1 start2 end2 -- true/false ) -rot 2drop > ;
+
+: (?available-segment-#) ( start1 end1 start2 end2 -- true/false )
+ 4dup ( s1 e1 s2 e2 s1 e1 s2 e2 )
+ 3 pick 3 pick between >r
+ -rot between r> and IF 4drop TRUE EXIT THEN
+ 2dup 5 roll -rot ( e1 s2 e2 s1 s2 e2 )
+ between >r between r> xor
+;
+
+: (find-available) ( addr addr+size-1 a-ptr a-size -- a-ptr' found )
+ ?dup 0= IF -rot 2drop false EXIT THEN \ Not Found
+
+ 2dup 2/ dup >r /available * +
+ ( addr addr+size-1 a-ptr a-size a-ptr' -- R: a-size' )
+ dup available>size@ 0= IF 2drop r> RECURSE EXIT THEN
+
+ dup >r available@ over + 1- 2>r 2swap
+ ( a-ptr a-size addr addr+size-1 )
+ ( R: a-size' a-ptr' addr' addr'+size'-1 )
+
+ 2dup 2r@ (?available-segment>) IF
+ 2swap 2r> 2drop r>
+ /available + -rot r> - 1- nip RECURSE EXIT \ Look Right
+ THEN
+ 2dup 2r@ (?available-segment<) IF
+ 2swap 2r> 2drop r>
+ 2drop r> RECURSE EXIT \ Look Left
+ THEN
+ 2dup 2r@ (?available-segment-#) IF \ Conflict - segments overlap
+ 2r> 2r> 3drop 3drop 2drop
+ 1212 throw
+ THEN
+ 2r> 3drop 3drop r> r> drop ( a-ptr' -- )
+ dup available>size@ 0<> ( a-ptr' found -- )
+;
+
+: (find-available) ( addr size -- seg-ptr found )
+ over + 1- available AVAILABLE-SIZE ['] (find-available) catch IF
+ 2drop 2drop 0 false
+ THEN
+;
+
+
+: dump-available ( available-ptr -- )
+ cr
+ dup available - /available / AVAILABLE-SIZE swap - 0 ?DO
+ dup available@ ?dup 0= IF
+ 2drop UNLOOP EXIT
+ THEN
+ swap . . cr
+ /available +
+ LOOP
+ dup
+;
+
+: .available available dump-available ;
+
+\ +
+\ release utils:
+\ +
+
+\ +
+\ (drop-available) just blindly compresses space of available map
+\ +
+: (drop-available) ( available-ptr -- )
+ dup available - /available / \ current element index
+ AVAILABLE-SIZE swap - \ # of remaining elements
+
+ ( first nelements ) 1- 0 ?DO
+ dup /available + dup available@
+
+ ( current next next>address next>size ) ?dup 0= IF
+ 2drop LEAVE \ NULL element - goto last copy
+ THEN
+ 3 roll available! ( next )
+ LOOP
+
+ \ Last element : just zero it out
+ 0 0 rot available!
+;
+
+\ +
+\ (stick-to-previous-available) merge the segment on stack
+\ with the previous one, if possible, and modified segment parameters if merged
+\ Return success code
+\ +
+: (stick-to-previous-available) ( addr size available-ptr -- naddr nsize nptr success )
+ dup available = IF
+ false EXIT \ This was the first available segment
+ THEN
+
+ dup /available - dup available@
+ + 4 pick = IF
+ nip \ Drop available-ptr since we are going to previous one
+ rot drop \ Drop start addr, we take the previous one
+
+ dup available@ 3 roll + rot true
+ ( prev-addr prev-size+size prev-ptr true )
+ ELSE
+ drop false
+ ( addr size available-ptr false )
+ THEN
+;
+
+\ +
+\ (insert-available) just blindly makes space for another element on given
+\ position
+\ +
+\ insert-available should also check adjacent elements and merge if new
+\ region is contiguos w. others
+\ +
+: (insert-available) ( available-ptr -- available-ptr )
+ dup \ current element
+ dup available - /available / \ current element index
+ AVAILABLE-SIZE swap - \ # of remaining elements
+
+ dup 0<= 3 pick available>size@ 0= or IF
+ \ End of "available" or came to an empty element - Exit
+ drop drop EXIT
+ THEN
+
+ over available@ rot
+
+ ( first first/=current/ first>address first>size nelements ) 1- 0 ?DO
+ 2>r
+ ( first current R: current>address current>size )
+
+ /available + dup available@
+ ( first current+1/=next/ next>address next>size )
+ ( R: current>address current>size )
+
+ 2r> 4 pick available! dup 0= IF
+ \ NULL element - last copy
+ rot /available + available!
+ UNLOOP EXIT
+ THEN
+ LOOP
+
+ ( first next/=last/ last[0]>address last[0]>size ) ?dup 0<> IF
+ cr ." release error: available map overflow"
+ cr ." Dumping available property"
+ .available
+ cr ." No space for one before last entry:" cr swap . .
+ cr ." Dying ..." cr 123 throw
+ THEN
+
+ 2drop
+;
+
+: insert-available ( addr size available-ptr -- addr size available-ptr )
+ dup available>address@ 0<> IF
+ \ Not empty :
+ dup available>address@ rot dup -rot -
+
+ ( addr available-ptr size available>address@-size )
+
+ 3 pick = IF \ if (available>address@ - size == addr)
+ \ Merge w. next segment - no insert needed
+
+ over available>size@ + swap
+ ( addr size+available>size@ available-ptr )
+
+ (stick-to-previous-available) IF
+ \ Merged w. prev & next one : discard extra seg
+ dup /available + (drop-available)
+ THEN
+ ELSE
+ \ shift the rest of "available" to make space
+
+ swap (stick-to-previous-available)
+ not IF (insert-available) THEN
+ THEN
+ ELSE
+ (stick-to-previous-available) drop
+ THEN
+;
+
+defer release
+
+\ +
+\ claim utils:
+\ +
+: drop-available ( addr size available-ptr -- addr )
+ dup >r available@
+ ( req_addr req_size segment_addr segment_size R: available-ptr )
+
+ over 4 pick swap - ?dup 0<> IF
+ \ Segment starts before requested address : free the head space
+ dup 3 roll swap r> available! -
+
+ ( req_addr req_size segment_size-segment_addr+req_addr )
+ over - ?dup 0= IF
+ \ That's it - remainder of segment is what we claim
+ drop
+ ELSE
+ \ Both head and tail of segment remain unclaimed :
+ \ need an extra available element
+ swap 2 pick + swap release
+ THEN
+ ELSE
+ nip ( req_addr req_size segment_size )
+ over - ?dup 0= IF
+ \ Exact match : drop the whole available segment
+ drop r> (drop-available)
+ ELSE
+ \ We claimed the head, need to leave the tail available
+ -rot over + rot r> available!
+ THEN
+ THEN
+ ( base R: -- )
+;
+
+: pwr2roundup ( value -- pwr2value )
+ dup CASE
+ 0 OF EXIT ENDOF
+ 1 OF EXIT ENDOF
+ ENDCASE
+ dup 1 DO drop i dup +LOOP
+ dup +
+;
+
+: (claim-best-fit) ( len align -- len base )
+ pwr2roundup 1- -1 -1
+ ( len align-1 best-fit-residue/=-1/ best-fit-base/=-1/ )
+
+ available AVAILABLE-SIZE /available * + available DO
+ i \ Must be saved now, before we use Return stack
+ -rot >r >r swap >r
+
+ ( len i R: best-fit-base best-fit-residue align-1 )
+
+ available@ ?dup 0= IF drop r> r> r> LEAVE THEN \ EOL
+
+ 2 pick - dup 0< IF
+ 2drop \ Can't Fit: Too Small
+ ELSE
+ dup 2 pick r@ and - 0< IF
+ 2drop \ Can't Fit When Aligned
+ ELSE
+ ( len i>address i>size-len )
+ ( R: best-fit-base best-fit-residue align-1 )
+ r> -rot dup r@ U< IF
+ \ Best Fit so far: drop the old one
+ 2r> 2drop
+
+ ( len align-1 nu-base nu-residue R: )
+ \ Now align new base and push to R:
+ swap 2 pick + 2 pick invert and >r >r >r
+ ELSE
+ 2drop >r
+ THEN
+ THEN
+ THEN
+ r> r> r>
+ /available +LOOP
+
+ -rot 2drop ( len best-fit-base/or -1 if none found/ )
+;
+
+: (adjust-release0) ( 0 size -- addr' size' )
+ \ segment 0 already pre-relased in early phase: adjust
+ 2dup MIN-RAM-SIZE dup 3 roll + -rot -
+ dup 0< IF 2drop ELSE
+ 2swap 2drop 0 mem-pre-released !
+ THEN
+;
+
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ +
+\ IEEE 1275 implementation:
+\ claim
+\ Claim the region with given start address and size (if align parameter is 0);
+\ alternatively claim any region of given alignment
+\ +
+\ Throw an exception if failed
+\ +
+: claim ( [ addr ] len align -- base )
+ ?dup 0<> IF
+ (claim-best-fit) dup -1 = IF
+ 2drop cr ." claim error : aligned allocation failed" cr
+ ." available:" cr .available
+ 321 throw EXIT
+ THEN
+ swap
+ THEN
+
+ 2dup (find-available) not IF
+ drop
+\ cr ." claim error : requested " . ." bytes of memory at " .
+\ ." not available" cr
+\ ." available:" cr .available
+ 2drop
+ 321 throw EXIT
+ THEN
+ ( req_addr req_size available-ptr ) drop-available
+
+ ( req_addr )
+;
+
+
+\ +
+\ IEEE 1275 implementation:
+\ release
+\ Free the region with given start address and size
+\ +
+: .release ( addr len -- )
+ over 0= mem-pre-released @ and IF (adjust-release0) THEN
+
+ 2dup (find-available) IF
+ drop swap
+ cr ." release error: region " . ." , " . ." already released" cr
+ ELSE
+ ?dup 0= IF
+ swap
+ cr ." release error: Bad/conflicting region " . ." , " .
+ ." or available list full " cr
+ ELSE
+ ( addr size available-ptr ) insert-available
+
+ \ NOTE: insert did not change the stack layout
+ \ but it may have changed any of the three values
+ \ in order to implement merge of free regions
+ \ We do not interpret these values any more
+ \ just blindly copy it in
+
+ ( addr size available-ptr ) available!
+ THEN
+ THEN
+;
+
+' .release to release
+
+
+\ pre-release minimal memory size
+0 MIN-RAM-SIZE release 1 mem-pre-released !
+
+\ claim first pages used for PPC exception vectors
+0 MIN-RAM-RESERVE 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop
+
+\ claim region used by firmware
+E000000 2000000 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop
+
diff --git a/slof/fs/client.fs b/slof/fs/client.fs
index 25715ba..01c4686 100644
--- a/slof/fs/client.fs
+++ b/slof/fs/client.fs
@@ -1,14 +1,14 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ Client interface.
@@ -17,6 +17,11 @@
VOCABULARY client-voc \ We store all client-interface callable words here.
+6789 CONSTANT sc-exit
+4711 CONSTANT sc-yield
+
+VARIABLE client-callback \ Address of client's callback function
+
: client-data ciregs >r3 @ ;
: nargs client-data la1+ l@ ;
: nrets client-data la1+ la1+ l@ ;
@@ -25,47 +30,100 @@ VOCABULARY client-voc \ We store all client-interface callable words here.
: stack-to-client-data
client-data nargs nrets + 2 + la+ nrets 0 ?DO tuck l! /l - LOOP drop ;
-: call-client ( p0 p1 client-entry -- )
+: call-client ( args len client-entry -- )
+ \ (args, len) describe the argument string, client-entry is the address of
+ \ the client's .entry symbol, i.e. where we eventually branch to.
+ \ ciregs is a variable that describes the register set of the host processor,
+ \ see slof/fs/exception.fs for details
+ \ client-entry-point maps to client_entry_point in slof/entry.S which is
+ \ the SLOF entry point when calling a SLOF client interface word from the
+ \ client.
+ \ We pass the arguments for the client in R6 and R7, the client interface
+ \ entry point address is passed in R5.
>r ciregs >r7 ! ciregs >r6 ! client-entry-point @ ciregs >r5 !
+ \ jump-client maps to call_client in slof/entry.S
+ \ When jump-client returns, R3 holds the address of a NUL-terminated string
+ \ that holds the client interface word the client wants to call, R4 holds
+ \ the return address.
r> jump-client drop
BEGIN
client-data-to-stack
+ \ Now create a Forth-style string, look it up in the client dictionary and
+ \ execute it, guarded by CATCH. Result of xt == 0 is stored on the return
+ \ stack
client-data l@ zcount
\ XXX: Should only look in client-voc...
- ALSO client-voc $find PREVIOUS dup 0= >r
- IF drop
- \ XXX: 6789 is magic...
- CATCH ?dup IF dup 6789 = IF drop r> drop EXIT THEN THROW THEN
- stack-to-client-data
- ELSE cr client-data l@ zcount type ." NOT FOUND" THEN
+ ALSO client-voc $find PREVIOUS
+ dup 0= >r IF
+ CATCH
+ \ If a client interface word needs some special treatment, like exit and
+ \ yield, then the implementation needs to use THROW to indicate its needs
+ ?dup IF
+ dup CASE
+ sc-exit OF drop r> drop EXIT ENDOF
+ sc-yield OF drop r> drop EXIT ENDOF
+ ENDCASE
+ \ Some special call was made but we don't know that to do with it...
+ THROW
+ THEN
+ stack-to-client-data
+ ELSE
+ cr type ." NOT FOUND"
+ THEN
+ \ Return to the client
r> ciregs >r3 ! ciregs >r4 @ jump-client
UNTIL ;
: flip-stack ( a1 ... an n -- an ... a1 ) ?dup IF 1 ?DO i roll LOOP THEN ;
+: (callback) ( "service-name<>" "arguments<cr>" -- )
+ client-callback @ \ client-callback points to the function prolog
+ dup 8 + @ ciregs >r2 ! \ Set up the TOC pointer (???)
+ @ call-client ; \ Resolve the function's address from the prolog
+' (callback) to callback
+
+: (continue-client)
+ s" " \ make call-client happy, client won't use the string anyways.
+ ciregs >r4 @ call-client ;
+' (continue-client) to continue-client
+\ Utility.
+: string-to-buffer ( str len buf len -- len' )
+ 2dup erase rot min dup >r move r> ;
\ Now come the actual client interface words.
ALSO client-voc DEFINITIONS
-: exit 6789 THROW ;
+: exit sc-exit THROW ;
+
+: yield sc-yield THROW ;
+
+: test ( zstr -- missing? )
+ \ XXX: Should only look in client-voc...
+ zcount
+ ALSO client-voc $find PREVIOUS IF nip FALSE ELSE nip nip TRUE THEN
+ ;
: finddevice ( zstr -- phandle )
- zcount find-package 0= IF -1 THEN ;
+ zcount find-node dup 0= IF drop -1 THEN ;
: getprop ( phandle zstr buf len -- len' )
- >r >r zcount rot get-property IF ( data dlen R: buf blen )
- r> swap dup r> min swap >r move r> ELSE r> r> 2drop -1 THEN ;
+ >r >r zcount rot get-property
+ 0= IF r> swap dup r> min swap >r move r>
+ ELSE r> r> 2drop -1 THEN ;
: getproplen ( phandle zstr -- len )
- zcount rot get-property IF nip ELSE -1 THEN ;
+ zcount rot get-property 0= IF nip ELSE -1 THEN ;
: setprop ( phandle zstr buf len -- size|-1 )
dup >r here dup >r swap dup allot move r> r>
- dup >r 2swap swap current-package @ >r set-package
- zcount property r> set-package r> ;
+ dup >r 2swap swap current-node @ >r set-node
+ zcount property r> set-node r> ;
+\ VERY HACKISH
+: canon ( zstr buf len -- len' )
+ over >r move r> zcount nip ;
: nextprop ( phandle zstr buf -- flag ) \ -1 invalid, 0 end, 1 ok
>r zcount rot next-property IF r> zplace 1 ELSE r> drop 0 THEN ;
@@ -73,51 +131,70 @@ ALSO client-voc DEFINITIONS
: open ( zstr -- ihandle ) zcount open-dev ;
: close ( ihandle -- ) close-dev ;
-\ XXX: should return -1 if no such method exists in that node
-: write ( ihandle str len -- len' ) rot s" write" rot $call-method ;
-: read ( ihandle str len -- len' ) rot s" read" rot $call-method ;
-: seek ( ihandle hi lo -- status ) swap rot s" seek" rot $call-method ;
-
-: claim ( virt size align -- addr )
- \ We don't do any assigned-addresses bookkeeping; furthermore, we're
- \ running with translations off, so just tell the client it can have it.
- \ XXX: doesn't work if client doesn't ask for a specific address.
- 2drop ;
-: release ( virt size -- )
- 2drop ;
+\ Now implemented: should return -1 if no such method exists in that node
+: write ( ihandle str len -- len' ) rot s" write" rot
+ ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
+: read ( ihandle str len -- len' ) rot s" read" rot
+ ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
+: seek ( ihandle hi lo -- status ) swap rot s" seek" rot
+ ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
+
+\ A real claim implementation: 3.2% memory fat :-)
+: claim ( addr len align -- base )
+ dup IF rot drop
+ ['] claim CATCH IF 2drop -1 THEN
+ ELSE
+ ['] claim CATCH IF 3drop -1 THEN
+ THEN
+;
+
+: release ( addr len -- ) release ;
: instance-to-package ( ihandle -- phandle )
ihandle>phandle ;
-: instance-to-path ( ihandle buf len -- len' )
- \ XXX: we do no buffer overflow checking!
- drop >r ihandle>phandle s" full_name" rot get-property drop
- r> swap dup >r move r> 1- ;
-
: package-to-path ( phandle buf len -- len' )
- \ XXX: we do no overflow checking!
- drop >r s" full_name" rot get-property IF r> swap dup >r move r> 1-
- ELSE true ABORT" No full_name property?!?" THEN ;
+ 2>r node>path 2r> string-to-buffer ;
+: instance-to-path ( ihandle buf len -- len' )
+ 2>r instance>path 2r> string-to-buffer ;
+: instance-to-interposed-path ( ihandle buf len -- len' )
+ 2>r instance>qpath 2r> string-to-buffer ;
: call-method ( str ihandle arg ... arg -- result return ... return )
- nargs flip-stack zcount rot ['] $call-method CATCH
- dup IF nrets 1 ?DO -444 LOOP THEN
- nrets flip-stack ;
+ nargs flip-stack zcount rot ['] $call-method CATCH
+ nrets 0= IF drop ELSE \ if called with 0 return args do not return the catch result
+ dup IF nrets 1 ?DO -444 LOOP THEN
+ nrets flip-stack
+ THEN ;
-: interpret ( ... zstr -- result ... )
- \ XXX: we just throw away the arguments.
- nargs 0 ?DO drop LOOP nrets 1 ?DO -555 LOOP -667 ;
+\ From the PAPR.
+: test-method ( phandle str -- missing? )
+ zcount rot find-method dup IF nip THEN 0= ;
-\ XXX: no real clock, but monotonically increasing, at least ;-)
-VARIABLE milliseconds
-: milliseconds milliseconds @ 1 milliseconds +! ;
+: milliseconds milliseconds ;
: start-cpu ( phandle addr r3 -- )
- \ phandle isn't actually used, but that's no problem on a 2-CPU system.
- 3fc0 l! 3f80 l! 3f40 l! ;
+ >r >r
+ s" reg" rot get-property 0= IF drop l@
+ ELSE true ABORT" start-cpu called with invalid phandle" THEN
+ r> r> of-start-cpu drop
+;
+
+\ Quiesce firmware and assert that all hardware is in a sane state
+\ (e.g. assert that no background DMA is running anymore)
+: quiesce ( -- )
+ \ The main quiesce call is defined in quiesce.fs
+ quiesce
+;
+
+\
+\ User Interface, defined in 6.3.2.6
+\
+: interpret ( ... zstr -- result ... )
+ zcount ['] evaluate CATCH ;
-\ Just to shut up warnings resulting from Linux calling this whether it
-\ exists or not. It isn't even standard, but hey.
-: quiesce ;
+\ Allow the client to register a callback
+: set-callback ( newfunc -- oldfunc )
+ client-callback @ swap client-callback ! ;
PREVIOUS DEFINITIONS
diff --git a/slof/fs/debug.fs b/slof/fs/debug.fs
new file mode 100644
index 0000000..b2593dc
--- /dev/null
+++ b/slof/fs/debug.fs
@@ -0,0 +1,346 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+false constant <debug-dummy>
+
+12 34 2constant (2constant) ' (2constant) cell+ @
+\ fake device node
+here 0
+dup , dup , dup , dup , dup ,
+over 7 cells + ,
+dup , dup , dup , dup , dup ,
+dup , drop
+current-node ! \ FAKE!
+12 instance value (instancevalue) ' (instancevalue) cell+ @
+instance variable (instancevariable) ' (instancevariable) cell+ @
+instance defer (instancedefer) ' (instancedefer) cell+ @
+0 current-node !
+
+forget <debug-dummy>
+
+constant <instancedefer>
+constant <instancevariable>
+constant <instancevalue>
+constant <2constant>
+
+
+\ Get the name of Forth command whose execution token is xt
+
+: xt>name ( xt -- str len )
+ BEGIN
+ cell - dup c@ 0 2 within IF
+ dup 2+ swap 1+ c@ exit
+ THEN
+ AGAIN
+;
+
+cell -1 * CONSTANT -cell
+: cell- ( n -- n-cell-size )
+ [ cell -1 * ] LITERAL +
+;
+
+\ Search for xt of given address
+: find-xt-addr ( addr -- xt )
+ BEGIN
+ dup @ <colon> = IF
+ EXIT
+ THEN
+ cell-
+ AGAIN
+;
+
+: (.immediate) ( xt -- )
+ \ is it immediate?
+ xt>name drop 2 - c@ \ skip len and flags
+ immediate? IF
+ ." IMMEDIATE"
+ THEN
+;
+
+: (.xt) ( xt -- )
+ xt>name type
+;
+
+\ Trace back on current return stack.
+\ Start at 1, since 0 is return of trace-back itself
+
+: trace-back ( )
+ 1
+ BEGIN
+ cr dup dup . ." : " rpick dup . ." : "
+ ['] tib here within IF
+ dup rpick find-xt-addr (.xt)
+ THEN
+ 1+ dup rdepth 5 - >= IF cr drop EXIT THEN
+ AGAIN
+;
+
+: (see-colon) ( xt -- )
+ ." : " dup (.xt) cr 3 spaces
+ BEGIN
+ cell + dup @
+ dup <semicolon> <>
+ WHILE
+ dup (.xt) ." "
+ CASE
+ <0branch> OF cell+ dup @ . ENDOF
+ <branch> OF cell+ dup @ . ENDOF
+ <do?do> OF cell+ dup @ . ENDOF
+ <lit> OF cell+ dup @ . ENDOF
+ <dotick> OF cell+ dup @ (.xt) ." " ENDOF
+ <doloop> OF cell+ dup @ . ENDOF
+ <do+loop> OF cell+ dup @ . ENDOF
+ <sliteral> OF cell+ dup count dup >r type ." "
+ r> -cell and + .s ENDOF
+ dup OF ." " ENDOF
+ ENDCASE
+ REPEAT
+ 2drop
+ cr ." ;"
+;
+
+\ Create words are a bit tricky. We find out where their code points.
+\ If this code is part of SLOF, it is not a user generated CREATE.
+
+: (see-create) ( xt -- )
+ dup cell+ @
+ CASE
+ <2constant> OF
+ dup cell+ cell+ dup @ swap cell+ @ . . ." 2CONSTANT "
+ ENDOF
+
+ <instancevalue> OF
+ dup cell+ cell+ @ . ." INSTANCE VALUE "
+ ENDOF
+
+ <instancevariable> OF
+ ." INSTANCE VARIABLE "
+ ENDOF
+
+ dup OF
+ ." CREATE "
+ ENDOF
+ ENDCASE
+ (.xt)
+;
+
+\ Decompile Forth command whose execution token is xt
+
+: (see) ( xt -- )
+ cr dup dup @
+ CASE
+ <variable> OF ." VARIABLE " (.xt) ENDOF
+ <value> OF dup execute . ." VALUE " (.xt) ENDOF
+ <constant> OF dup execute . ." CONSTANT " (.xt) ENDOF
+ <defer> OF dup cell+ @ swap ." DEFER " (.xt) ." is " (.xt) ENDOF
+ <alias> OF dup cell+ @ swap ." ALIAS " (.xt) ." " (.xt) ENDOF
+ <buffer:> OF ." BUFFER: " (.xt) ENDOF
+ <create> OF (see-create) ENDOF
+ <colon> OF (see-colon) ENDOF
+ dup OF ." ??? PRIM " (.xt) ENDOF
+ ENDCASE
+ (.immediate) cr
+ ;
+
+\ Decompile Forth command old-name
+
+: see ( "old-name<>" -- )
+ ' (see)
+;
+
+\ Work in progress...
+
+0 value forth-ip
+true value trace>stepping?
+true value trace>print?
+true value trace>up?
+0 value trace>depth
+0 value trace>rdepth
+: trace-depth+ ( -- ) trace>depth 1+ to trace>depth ;
+: trace-depth- ( -- ) trace>depth 1- to trace>depth ;
+
+: stepping ( -- )
+ true to trace>stepping?
+;
+
+: tracing ( -- )
+ false to trace>stepping?
+;
+
+: trace-print-on ( -- )
+ true to trace>print?
+;
+
+: trace-print-off ( -- )
+ false to trace>print?
+;
+
+
+\ Add n to ip
+
+: fip-add ( n -- )
+ forth-ip + to forth-ip
+;
+
+: trace-print ( -- )
+ forth-ip cr u. ." : "
+ forth-ip @ xt>name type ." "
+ ." ( " .s ." ) | "
+;
+
+: trace-interpret ( -- )
+ rdepth 1- to trace>rdepth
+ BEGIN
+ depth . [char] > dup emit emit space
+ source expect ( str len )
+ ['] interpret catch print-status
+ AGAIN
+;
+
+\ Save execution token address and content
+
+0 value debug-last-xt
+0 value debug-last-xt-content
+
+\ Main trace routine, trace a colon definition
+
+: trace-xt ( xt -- )
+ debug-last-xt ['] breakpoint @ swap ! \ Re-arm break point
+ r> drop \ Drop return of 'trace-xt call
+ cell + to forth-ip \ Step over ":"
+ true to trace>print?
+ BEGIN
+ trace>print? IF trace-print THEN
+
+ forth-ip ( ip )
+ trace>stepping? IF
+ BEGIN
+ key
+ CASE
+ [char] d OF dup @ @ <colon> = IF \ recurse only into colon definitions
+ trace-depth+ dup >r @ recurse
+ THEN true ENDOF
+ [char] u OF trace>depth IF tracing trace-print-off true ELSE false THEN ENDOF
+ [char] f OF drop cr trace-interpret ENDOF \ quit trace and start interpreter FIXME rstack
+ [char] c OF tracing true ENDOF
+ [char] t OF trace-back false ENDOF
+ [char] q OF drop cr quit ENDOF
+ 20 OF true ENDOF
+ dup OF cr ." Press d: Down into current word" cr
+ ." Press u: Up to caller" cr
+ ." Press f: Switch to forth interpreter, 'resume' will continue tracing" cr
+ ." Press c: Switch to tracing" cr
+ ." Press <space>: Execute current word" cr
+ ." Press q: Abort execution, switch to interpreter" cr
+ false ENDOF
+ ENDCASE
+ UNTIL
+ THEN ( ip' )
+ dup to forth-ip @ dup ( xt xt )
+
+ CASE
+ <sliteral> OF drop forth-ip cell+ dup dup c@ + -cell and to forth-ip ENDOF
+ <dotick> OF drop forth-ip cell+ @ cell fip-add ENDOF
+ <lit> OF drop forth-ip cell+ @ cell fip-add ENDOF
+ <doto> OF drop forth-ip cell+ @ cell+ ! cell fip-add ENDOF
+ <0branch> OF drop IF
+ cell fip-add
+ ELSE
+ forth-ip cell+ @ cell+ fip-add THEN
+ ENDOF
+ <do?do> OF drop 2dup <> IF
+ swap >r >r cell fip-add
+ ELSE
+ forth-ip cell+ @ cell+ fip-add 2drop THEN
+ ENDOF
+ <branch> OF drop forth-ip cell+ @ cell+ fip-add ENDOF
+ <doloop> OF drop r> 1+ r> 2dup = IF
+ 2drop cell fip-add
+ ELSE >r >r
+ forth-ip cell+ @ cell+ fip-add THEN
+ ENDOF
+ <do+loop> OF drop r> + r> 2dup = IF
+ 2drop cell fip-add
+ ELSE >r >r
+ forth-ip cell+ @ cell+ fip-add THEN
+ ENDOF
+
+ <semicolon> OF trace>depth 0> IF
+ trace-depth- stepping drop r> recurse
+ ELSE
+ drop exit THEN
+ ENDOF
+ <exit> OF trace>depth 0> IF
+ trace-depth- stepping drop r> recurse
+ ELSE
+ drop exit THEN
+ ENDOF
+ dup OF execute ENDOF
+ ENDCASE
+ forth-ip cell+ to forth-ip
+ AGAIN
+;
+
+\ Resume execution from tracer
+: resume ( -- )
+ trace>rdepth rdepth!
+ forth-ip cell - trace-xt
+;
+
+\ Turn debug off, by erasing breakpoint
+
+: debug-off ( -- )
+ debug-last-xt IF
+ debug-last-xt-content debug-last-xt ! \ Restore overwriten token
+ 0 to debug-last-xt
+ THEN
+;
+
+
+
+\ Entry point for debug
+
+: (break-entry) ( -- )
+ debug-last-xt-content debug-last-xt ! \ Restore overwriten token
+ r> drop \ Don't return to bp, but to caller
+ debug-last-xt-content <colon> <> IF \ Execute non colon definition
+ debug-last-xt cr u. ." : "
+ debug-last-xt xt>name type ." "
+ ." ( " .s ." ) | "
+ key drop
+ debug-last-xt execute
+ ELSE
+ debug-last-xt 0 to trace>depth trace-xt \ Trace colon definition
+ THEN
+;
+
+\ Put entry point bp defer
+' (break-entry) to BP
+
+\ Mark the command indicated by xt for debugging
+
+: (debug ( xt -- )
+ debug-off ( xt ) \ Remove active breakpoint
+ dup to debug-last-xt ( xt ) \ Save token for later debug
+ dup @ to debug-last-xt-content ( xt ) \ Save old value
+ ['] breakpoint @ swap !
+;
+
+\ Mark the command indicated by xt for debugging
+
+: debug ( "old-name<>" -- )
+ parse-word $find IF \ Get xt for old-name
+ (debug
+ ELSE
+ ." undefined word " type cr
+ THEN
+;
diff --git a/slof/fs/devices/pci-class_02.fs b/slof/fs/devices/pci-class_02.fs
new file mode 100644
index 0000000..7cf3493
--- /dev/null
+++ b/slof/fs/devices/pci-class_02.fs
@@ -0,0 +1,35 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+s" network [ " type my-space pci-class-name type s" ]" type
+
+my-space pci-device-generic-setup
+my-space pci-alias-net
+
+s" network" device-type
+
+cr
+
+INSTANCE VARIABLE obp-tftp-package
+: open ( -- okay? )
+ open IF \ enables PCI mem, io and Bus master and returns TRUE
+ my-args s" obp-tftp" $open-package obp-tftp-package ! true
+ ELSE
+ false
+ THEN ;
+: close ( -- )
+ s" close" obp-tftp-package @ $call-method
+ close ; \ disables PCI mem, io and Bus master
+: load ( addr -- len )
+ s" load" obp-tftp-package @ $call-method ;
+
+: ping ( -- ) s" ping" obp-tftp-package @ $call-method ;
diff --git a/slof/fs/devices/pci-class_0c.fs b/slof/fs/devices/pci-class_0c.fs
new file mode 100644
index 0000000..8c3d43c
--- /dev/null
+++ b/slof/fs/devices/pci-class_0c.fs
@@ -0,0 +1,39 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+s" serial bus [ " type my-space pci-class-name type s" ]" type cr
+
+my-space pci-device-generic-setup
+
+
+\ Handle USB OHCI controllers:
+: handle-usb-ohci-class ( -- )
+ \ set Memory Write and Invalidate Enable, SERR# Enable
+ \ (see PCI 3.0 Spec Chapter 6.2.2 device control):
+ 4 config-w@ 110 or 4 config-w!
+ pci-master-enable \ set PCI Bus master bit and
+ pci-mem-enable \ memory space enable for USB scan
+ 10 config-l@ \ get base address on stack for usb-ohci.fs
+ \ TODO: Use translate-address here
+ s" usb-ohci.fs" included
+;
+
+\ Check PCI sub-class and interface type of Serial Bus Controller
+\ to include the appropriate driver:
+: handle-sbc-subclass ( -- )
+ my-space pci-class@ ffff and CASE \ get PCI sub-class and interface
+ 0310 OF handle-usb-ohci-class ENDOF \ USB OHCI controller
+ ENDCASE
+;
+
+handle-sbc-subclass
+
diff --git a/slof/fs/devices/pci-device_10de_0141.fs b/slof/fs/devices/pci-device_10de_0141.fs
new file mode 100644
index 0000000..ab9f2a5
--- /dev/null
+++ b/slof/fs/devices/pci-device_10de_0141.fs
@@ -0,0 +1,49 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+my-space pci-class-name type
+
+my-space pci-device-generic-setup
+
+enable-io-access
+enable-mem-access
+
+30 config-l@ pci-find-fcode execute-rom-fcode
+
+: check-display ( nodepath len -- true|false ) \ true if display found and "screen" alias set
+\ check if display availabe, set screen alias
+2dup find-node \ ( path len phandle|0 ) find node
+?dup IF
+ \ node found, get "display-type" property
+ s" display-type" rot get-property ( path len true|propaddr proplen 0 )
+ 0= IF
+ ( path len propaddr proplen ) \ property found, check if the value is not "NONE"
+ s" NONE" 0 char-cat ( path len propaddr proplen str strlen ) \ null-terminated NONE string
+ str= 0= IF
+ ( path len ) \ "display-type" property is not "NONE" so we can set "screen" alias
+ s" screen" 2swap set-alias
+ true ( true ) \ return true
+ ELSE
+ 2drop false ( false ) \ return false
+ THEN
+ THEN
+THEN
+;
+
+get-node node>path s" /NVDA,DISPLAY-A" $cat check-display
+0= IF
+ \ no display found on DISPLAY-A ... check DISPLAY-B
+ get-node node>path s" /NVDA,DISPLAY-B" $cat check-display
+ drop \ drop result
+THEN
+
+s" name" get-my-property drop s" ( " type type s" ) " type cr
diff --git a/slof/fs/dictionary.fs b/slof/fs/dictionary.fs
new file mode 100644
index 0000000..15cc2cb
--- /dev/null
+++ b/slof/fs/dictionary.fs
@@ -0,0 +1,74 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: words
+ last @
+ begin ?dup while
+ dup cell+ char+ count type space @
+ repeat
+;
+
+: .calls ( xt -- )
+ current-node @ >r 0 set-node \ only search commands, according too IEEE1275
+
+ last begin @ ?dup while ( xt currxt )
+ dup cell+ char+ ( xt currxt name* )
+ dup dup c@ + 1+ aligned ( xt currxt name* CFA )
+ dup @ <colon> = IF ( xt currxt name* CFA )
+ begin
+ cell+ dup @ ['] semicolon <>
+ while ( xt currxt *name pos )
+ dup @ 4 pick = IF ( xt currxt *name pos )
+ over count type space
+ begin cell+ dup @ ['] semicolon = until cell - \ eat up other occurences
+ THEN
+ repeat
+ THEN
+ 2drop ( xt currxt )
+ repeat
+ drop
+
+ r> set-node \ restore node
+ ;
+
+0 value #sift-count
+false value sift-compl-only
+
+: $inner-sift ( text-addr text-len LFA -- ... word-addr word-len true | false )
+ dup cell+ char+ count \ get word name
+ 2dup 6 pick 6 pick find-isubstr \ is there a partly match?
+ \ in tab completion mode the substring has to be at the beginning
+ sift-compl-only IF 0= ELSE over < THEN
+ IF
+ #sift-count 1+ to #sift-count \ count completions
+ true
+ ELSE
+ 2drop false
+ THEN
+ ;
+
+: $sift ( text-addr text-len -- )
+ current-node @ >r 0 set-node \ only search commands, according too IEEE1275
+ sift-compl-only >r false to sift-compl-only \ all substrings, not only compl.
+ last begin @ ?dup while \ walk the whole dictionary
+ $inner-sift IF type space THEN
+ repeat
+ 2drop
+ 0 to #sift-count \ we don't need completions here.
+ r> to sift-compl-only \ restore previous sifting mode
+ r> set-node \ restore node
+ ;
+
+: sifting ( "text< >" -- )
+ parse-word $sift
+ ;
+
diff --git a/slof/fs/display.fs b/slof/fs/display.fs
new file mode 100644
index 0000000..f0ffae0
--- /dev/null
+++ b/slof/fs/display.fs
@@ -0,0 +1,124 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+0 VALUE char-height
+0 VALUE char-width
+0 VALUE fontbytes
+
+CREATE display-emit-buffer 20 allot
+
+\ \\\\\\\\\\\\\\ Global Data
+
+\ \\\\\\\\\\\\\\ Structure/Implementation Dependent Methods
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ *
+\ *
+defer dis-old-emit
+' emit behavior to dis-old-emit
+
+: display-write terminal-write ;
+: display-emit dup dis-old-emit display-emit-buffer tuck c! 1 terminal-write drop ;
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ Generic device methods:
+\ *
+
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ IEEE 1275 : display device driver initialization
+\ *
+: is-install ( 'open -- )
+ s" defer vendor-open to vendor-open" eval
+ s" : open deadbeef vendor-open dup deadbeef = IF drop true ELSE nip THEN ;" eval
+ s" defer write ' display-write to write" eval
+ s" : draw-logo ['] draw-logo CATCH IF 2drop 2drop THEN ;" eval
+ s" : reset-screen ['] reset-screen CATCH drop ;" eval
+;
+
+: is-remove ( 'close -- )
+ s" defer close to close" eval
+;
+
+: is-selftest ( 'selftest -- )
+ s" defer selftest to selftest" eval
+;
+
+
+STRUCT
+ cell FIELD font>addr
+ cell FIELD font>width
+ cell FIELD font>height
+ cell FIELD font>advance
+ cell FIELD font>min-char
+ cell FIELD font>#glyphs
+CONSTANT /font
+
+CREATE default-font-ctrblk /font allot default-font-ctrblk
+ dup font>addr 0 swap !
+ dup font>width 8 swap !
+ dup font>height -10 swap !
+ dup font>advance 1 swap !
+ dup font>min-char 20 swap !
+ font>#glyphs 7f swap !
+
+: display-default-font ( str len -- )
+ romfs-lookup dup 0= IF drop EXIT THEN
+ 600 <> IF ." Only support 60x8x16 fonts ! " drop EXIT THEN
+ default-font-ctrblk font>addr !
+;
+
+s" default-font.bin" display-default-font
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ *
+\ *
+
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ Generic device methods:
+\ *
+: .scan-lines ( height -- scanlines ) dup 0>= IF 1- ELSE negate THEN ;
+
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ *
+
+: set-font ( addr width height advance min-char #glyphs -- )
+ default-font-ctrblk /font + /font 0
+ DO
+ 1 cells - dup >r ! r> 1 cells
+ +LOOP drop
+ default-font-ctrblk dup font>height @ abs to char-height
+ dup font>width @ to char-width font>advance @ to fontbytes
+;
+
+: >font ( char -- addr )
+ dup default-font-ctrblk dup >r font>min-char @ dup r@ font>#glyphs + within
+ IF
+ r@ font>min-char @ -
+ r@ font>advance @ * r@ font>height @ .scan-lines *
+ r> font>addr @ +
+ ELSE
+ drop r> font>addr @
+ THEN
+;
+
+: default-font ( -- addr width height advance min-char #glyphs )
+ default-font-ctrblk /font 0 DO dup cell+ >r @ r> 1 cells +LOOP drop
+;
+
+
diff --git a/slof/fs/dump.fs b/slof/fs/dump.fs
index 1b9e883..a7c17fd 100644
--- a/slof/fs/dump.fs
+++ b/slof/fs/dump.fs
@@ -1,26 +1,42 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
-\ Hexdump thingy. A bit simplistic, always prints full lines.
+\ Hex dump facilities.
-hex
-
-DEFER dump-c@
-: .2 ( u -- ) 0 <# # # #> type space ;
-: .char ( c -- ) dup bl 7e between 0= IF drop [char] . THEN emit ;
-: dumpline ( addr -- )
- cr dup 8 u.r ." : " dup 10 bounds DO i dump-c@ .2 LOOP
- space space 10 bounds DO i dump-c@ .char LOOP ;
-: (dump) ( addr size -- ) bounds DO i dumpline 10 +LOOP ;
-: dump ['] c@ to dump-c@ (dump) ;
-: rdump ['] rb@ to dump-c@ (dump) ;
+1 VALUE /dump
+' c@ VALUE 'dump
+0 VALUE dump-first
+0 VALUE dump-last
+0 VALUE dump-cur
+: .char ( c -- ) dup bl 7f within 0= IF drop [char] . THEN emit ;
+: dump-line ( -- )
+ cr dump-cur dup 8 0.r [char] : emit 10 /dump / 0 DO
+ space dump-cur dump-first dump-last within IF
+ dump-cur 'dump execute /dump 2* 0.r ELSE
+ /dump 2* spaces THEN dump-cur /dump + to dump-cur LOOP
+ /dump 1 <> IF drop EXIT THEN
+ to dump-cur 2 spaces
+ 10 0 DO dump-cur dump-first dump-last within IF
+ dump-cur 'dump execute .char ELSE space THEN dump-cur 1+ to dump-cur LOOP ;
+: (dump) ( addr len reader size -- )
+ to /dump to 'dump bounds /dump negate and to dump-first to dump-last
+ dump-first f invert and to dump-cur
+ base @ hex BEGIN dump-line dump-cur dump-last >= UNTIL base ! ;
+: du ( -- ) dump-last 100 'dump /dump (dump) ;
+: dump ['] c@ 1 (dump) ;
+: wdump ['] w@ 2 (dump) ;
+: ldump ['] l@ 4 (dump) ;
+: xdump ['] x@ 8 (dump) ;
+: rdump ['] rb@ 1 (dump) ;
+\ : iodump ['] io-c@ 1 (dump) ;
+\ : siodump ['] siocfg@ 1 (dump) ;
diff --git a/slof/fs/elf.fs b/slof/fs/elf.fs
index 997774d..f7edf76 100644
--- a/slof/fs/elf.fs
+++ b/slof/fs/elf.fs
@@ -1,19 +1,14 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
-
-\ ELF loader.
-
-\ Author: Hartmut Penner <hpenner@de.ibm.com>
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ ELF 32 bit header
@@ -22,7 +17,7 @@ STRUCT
/c field ehdr>e_class
/c field ehdr>e_data
/c field ehdr>e_version
- /c field ehdr>e_pad
+ /c field ehdr>e_pad
/l field ehdr>e_ident_2
/l field ehdr>e_ident_3
/w field ehdr>e_type
@@ -61,7 +56,7 @@ STRUCT
/c field ehdr64>e_class
/c field ehdr64>e_data
/c field ehdr64>e_version
- /c field ehdr64>e_pad
+ /c field ehdr64>e_pad
/l field ehdr64>e_ident_2
/l field ehdr64>e_ident_3
/w field ehdr64>e_type
@@ -84,7 +79,7 @@ END-STRUCT
STRUCT
/l field phdr64>p_type
- /l field phdr64>p_flags
+ /l field phdr64>p_flags
cell field phdr64>p_offset
cell field phdr64>p_vaddr
cell field phdr64>p_paddr
@@ -93,117 +88,183 @@ STRUCT
cell field phdr64>p_align
END-STRUCT
-: load-segment ( file-addr program-header-addr -- )
- ( file-addr program-header-addr )
- dup >r phdr>p_vaddr l@ r@ phdr>p_memsz l@ erase
+\ Claim memory for segment
+\ Abort, if no memory available
- ( file-addr R: programm-header-addr )
- r@ phdr>p_vaddr l@ r@ phdr>p_memsz l@ dup 0= IF 2drop ELSE flushcache THEN
+false value elf-claim?
+0 value last-claim
- ( file-addr R: programm-header-addr )
- r@ phdr>p_offset l@ + r@ phdr>p_vaddr l@ r> phdr>p_filesz l@ move
+: claim-segment ( file-addr program-header-addr -- )
+ elf-claim? IF
+ >r
+ here last-claim , to last-claim \ Setup ptr to last claim
+ \ Put addr and size ain the data space
+ r@ phdr>p_vaddr l@ dup , r> phdr>p_memsz l@ dup , ( file-addr addr size )
+ 0 ['] claim CATCH IF ABORT" Memory for ELF file already in use " THEN
+ THEN
+ 2drop
;
+: load-segment ( file-addr program-header-addr -- )
+ >r
+ ( file-addr R: program-header-addr )
+ \ Copy into storage
+ r@ phdr>p_offset l@ + r@ phdr>p_vaddr l@ r@ phdr>p_filesz l@ move
+
+ ( R: programm-header-addr )
+ \ Clear BSS
+ r@ phdr>p_vaddr l@ r@ phdr>p_filesz l@ +
+ r@ phdr>p_memsz l@ r@ phdr>p_filesz l@ - erase
+
+ ( R: programm-header-addr )
+ \ Flush cache
+ r@ phdr>p_vaddr l@ r> phdr>p_memsz l@ dup 0= IF 2drop ELSE flushcache THEN
+;
: load-segments ( file-addr -- )
- ( file-addr )
+ ( file-addr )
dup dup ehdr>e_phoff l@ + \ Calculate program header address
( file-addr program-header-addr )
over ehdr>e_phnum w@ 0 ?DO \ loop e_phnum times
- ( file-addr program-header-addr )
+ ( file-addr program-header-addr )
dup phdr>p_type l@ 1 = IF \ PT_LOAD ?
-
+
+ ( file-addr program-header-addr )
+ 2dup claim-segment \ claim segment
+
( file-addr program-header-addr )
2dup load-segment THEN \ copy segment
( file-addr program-header-addr )
- over ehdr>e_phentsize w@ + LOOP \ step to next header
+ over ehdr>e_phentsize w@ + LOOP \ step to next header
( file-addr program-header-addr )
over ehdr>e_entry l@
( file-addr program-header-addr )
- nip nip \ cleanup
+ nip nip \ cleanup
;
-: load-segment64 ( file-addr program-header-addr -- )
+: load-segment64 ( file-addr program-header-addr -- )
+ >r
+ ( file-addr R: program-header-addr )
+ \ Copy into storage
+ r@ phdr64>p_offset @ + r@ phdr64>p_vaddr @ r@ phdr64>p_filesz @ move
- ( file-addr program-header-addr )
- dup >r phdr64>p_vaddr @ r@ phdr64>p_memsz @ erase
+ ( R: programm-header-addr )
+ \ Clear BSS
+ r@ phdr64>p_vaddr @ r@ phdr64>p_filesz @ +
+ r@ phdr64>p_memsz @ r@ phdr64>p_filesz @ - erase
- ( file-addr R: programm-header-addr )
- r@ phdr64>p_vaddr @ r@ phdr64>p_memsz @ dup 0= IF 2drop ELSE flushcache THEN
-
- ( file-addr R: programm-header-addr )
- r@ phdr64>p_offset @ + r@ phdr64>p_vaddr @ r> phdr64>p_filesz @ move
+ ( R: programm-header-addr )
+ \ Flush cache
+ r@ phdr64>p_vaddr @ r> phdr64>p_memsz @ dup 0= IF 2drop ELSE flushcache THEN
;
-
: load-segments64 ( file-addr -- entry )
- ( file-addr )
+ ( file-addr )
dup dup ehdr64>e_phoff @ + \ Calculate program header address
( file-addr program-header-addr )
over ehdr64>e_phnum w@ 0 ?DO \ loop e_phnum times
- ( file-addr program-header-addr )
+ ( file-addr program-header-addr )
dup phdr64>p_type l@ 1 = IF \ PT_LOAD ?
-
+
+ ( file-addr program-header-addr )
+ 2dup claim-segment \ claim segment
+
( file-addr program-header-addr )
2dup load-segment64 THEN \ copy segment
( file-addr program-header-addr )
- over ehdr64>e_phentsize w@ + LOOP \ step to next header
+ over ehdr64>e_phentsize w@ + LOOP \ step to next header
( file-addr program-header-addr )
over ehdr64>e_entry @
-
+
( file-addr program-header-addr entry )
- nip nip \ cleanup
+ nip nip \ cleanup
;
: elf-check-file ( file-addr -- 1 : 32, 2 : 64, else bad )
( file-addr )
- dup ehdr>e_ident l@ 7f454c46 <> ABORT" Not an ELF file"
-
+ dup ehdr>e_ident l@-be 7f454c46 <> IF
+ ABORT" Not an ELF executable"
+ THEN
+
( file-addr )
- dup ehdr>e_data c@ 2 <> ABORT" Not a Big Endian ELF file"
+ dup ehdr>e_data c@
+ ?bigendian IF
+ 2 <> ABORT" Not a Big Endian ELF file"
+ ELSE
+ 2 = ABORT" Not a Little Endian ELF file"
+ THEN
( file-addr )
- dup ehdr>e_type w@ 2 <> ABORT" Not an ELF executable"
+ dup ehdr>e_type w@ 2 <> ABORT" Not an ELF executable"
( file-addr )
dup ehdr>e_machine w@ dup 14 <> swap 15 <> and ABORT" Not a PPC ELF executable"
( file-addr)
ehdr>e_class c@
-;
+;
-: load-elf32 ( file-addr -- )
+: load-elf32 ( file-addr -- entry )
- ( file-addr)
+ ( file-addr)
load-segments
;
-: load-elf64 ( file-addr -- )
+: load-elf32-claim ( file-addr -- claim-list entry )
+ true to elf-claim?
+ 0 to last-claim
+ ['] load-elf32 CATCH IF false to elf-claim? ABORT THEN
+ last-claim swap
+ false to elf-claim?
+;
+
+
+: load-elf64 ( file-addr -- entry )
- ( file-addr)
+ ( file-addr)
load-segments64
;
-: load-elf-file ( file-addr -- entry )
+: load-elf64-claim ( file-addr -- claim-list entry )
+ true to elf-claim?
+ 0 to last-claim
+ ['] load-elf64 CATCH IF false to elf-claim? ABORT THEN
+ last-claim swap
+ false to elf-claim?
+;
+
+: load-elf-file ( file-addr -- entry 32-bit )
- ( file-addr )
- dup elf-check-file
+ ( file-addr )
+ dup elf-check-file
( file-addr 1|2|x )
CASE
- 1 OF load-elf32 ENDOF
- 2 OF load-elf64 ENDOF
+ 1 OF load-elf32 true ENDOF
+ 2 OF load-elf64 false ENDOF
dup OF true ABORT" Neither 32- nor 64-bit ELF file" ENDOF
ENDCASE
;
+
+\ Release memory claimed before
+
+: elf-release ( claim-list -- )
+ BEGIN
+ dup cell+ ( claim-list claim-list-addr )
+ dup @ swap cell+ @ ( claim-list claim-list-addr claim-list-sz )
+ release ( claim-list )
+ @ dup 0= ( Next-element )
+ UNTIL
+ drop
+;
diff --git a/slof/fs/envvar.fs b/slof/fs/envvar.fs
index 0cdb9f6..de96e43 100644
--- a/slof/fs/envvar.fs
+++ b/slof/fs/envvar.fs
@@ -1,93 +1,400 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
-\ Configuration variables. Not actually used yet, nor shown in /options.
+\ configuration variables
wordlist CONSTANT envvars
-: listenv get-current envvars set-current words set-current ;
+\ list the names in envvars
+: listenv get-current envvars set-current words set-current ;
+\ create a definition in envvars
: create-env ( "name" -- )
- get-current >r envvars set-current CREATE r> set-current ;
+ get-current envvars set-current CREATE set-current ;
+\ lay out the data for the separate envvar types
: env-int ( n -- ) 1 c, align , DOES> char+ aligned @ ;
: env-bytes ( a len -- ) 2 c, align dup , here swap dup allot move
- DOES> char+ aligned dup @ >r cell+ r> ;
-: env-string ( a len -- ) 3 c, string, DOES> char+ count ;
+ DOES> char+ aligned dup @ >r cell+ r> ;
+: env-string ( str len -- ) 3 c, string, DOES> char+ count ;
: env-flag ( f -- ) 4 c, c, DOES> char+ c@ 0<> ;
: env-secmode ( sm -- ) 5 c, c, DOES> char+ c@ ;
+\ create default envvars
: default-int ( n "name" -- ) create-env env-int ;
: default-bytes ( a len "name" -- ) create-env env-bytes ;
: default-string ( a len "name" -- ) create-env env-string ;
: default-flag ( f "name" -- ) create-env env-flag ;
: default-secmode ( sm "name" -- ) create-env env-secmode ;
-: findenv ( name len -- adr def-adr type )
- 2dup envvars voc-find dup 0= ABORT" not a configuration variable"
- link> >body char+ >r (find-order) link> >body dup char+ swap c@ r> swap ;
+: set-option ( option-name len option len -- )
+ 2swap encode-string
+ 2swap s" /options" find-node dup IF set-property ELSE drop 2drop 2drop THEN ;
+
+\ find an envvar's current and default value, and its type
+: findenv ( name len -- adr def-adr type | 0 )
+ 2dup envvars voc-find dup 0<> IF ( ABORT" not a configuration variable" )
+ link> >body char+ >r (find-order) link> >body dup char+ swap c@ r> swap
+ else nip nip THEN ;
+
+: test-flag ( param len -- true | false )
+ 2dup s" true" string=ci -rot s" false" string=ci or
+ ;
+
+: test-secmode ( param len -- true | false )
+ 2dup s" none" string=ci -rot 2dup s" command" string=ci -rot s" full"
+ string=ci or or
+ ;
+
+: isdigit ( char -- true | false )
+ 30 39 between ;
+
+: test-int ( param len -- true | false )
+ drop c@ isdigit if true else false then ;
+
+: test-string ( param len -- true | false )
+ 0 ?DO
+ dup i + c@ \ Get character / byte at current index
+ dup 20 < swap 7e > OR IF \ Is it out of range 32 to 126 (=ASCII)
+ drop FALSE UNLOOP EXIT \ FALSE means: No ASCII string
+ THEN
+ LOOP
+ drop TRUE \ Only ASCII found --> it is a string
+;
+
+: findtype ( param len name len -- param len name len type )
+ 2dup findenv dup 0= \ try to find type of envvar
+ IF \ no type found
+ drop 2swap
+ 2dup test-flag if 4 -rot else
+ 2dup test-secmode if 5 -rot else
+ 2dup test-int if 1 -rot else
+ 2dup test-string IF 3 ELSE 2 THEN \ 3 = string, 2 = default to bytes
+ -rot then then then
+ rot
+ >r 2swap r>
+ \ XXX: create env
+ else \ take type from default value
+ nip nip
+ THEN
+;
+
+\ set an envvar
: $setenv ( param len name len -- )
- 2dup findenv nip nip -rot $CREATE CASE
- 1 OF evaluate env-int ENDOF \ XXX: wants decimal and 0x...
- 2 OF env-bytes ENDOF
- 3 OF env-string ENDOF
- 4 OF evaluate env-flag ENDOF
- 5 OF evaluate env-secmode ENDOF \ XXX: recognize none, command, full
- ENDOF ENDCASE ;
-: setenv parse-word skipws 0 parse 2swap $setenv ;
+ 4dup set-option
+ findtype dup 0=
+ IF
+ true ABORT" not a configuration variable"
+ ELSE
+ -rot $CREATE CASE
+ 1 OF evaluate env-int ENDOF \ XXX: wants decimal and 0x...
+ \ Since we don't have 0x for hexnumbers, we need to find out the type ...
+ 2 OF
+ 2dup ( param len param len )
+ depth >r ( param len param len R: depth-before )
+ ['] evaluate CATCH IF \ Catch 'unknown Forth words'...
+ ( param len param' len' R: depth-before )
+ 2drop r> drop
+ env-string \ and encode 'unknown word' as string
+ ELSE
+ ( param len [...evaluated results...] R: depth-before )
+ \ If EVALUATE placed two items on the stack, use env-bytes,
+ \ for one item use env-int:
+ depth r> = IF env-bytes ELSE env-int THEN
+ 2drop
+ THEN
+ ENDOF
+ 3 OF env-string ENDOF
+ 4 OF evaluate env-flag ENDOF
+ 5 OF evaluate env-secmode ENDOF \ XXX: recognize none, command, full
+ ENDCASE
+ THEN
+;
+
+\ : setenv parse-word skipws 0 parse 2swap $setenv ;
+: setenv parse-word ( skipws ) 0d parse -leading 2swap $setenv ;
+\ print an envvar
: (printenv) ( adr type -- )
- CASE
- 1 OF aligned @ . ENDOF
- 2 OF aligned dup cell+ swap @ dump ENDOF
- 3 OF count type ENDOF
- 4 OF c@ IF ." true" ELSE ." false" THEN ENDOF
- 5 OF c@ . ENDOF \ XXX: print symbolically
- ENDCASE ;
-: printenv parse-word findenv rot over cr ." Current: " (printenv)
- cr ." Default: " (printenv) ;
+ CASE
+ 1 OF aligned @ . ENDOF
+ 2 OF aligned dup cell+ swap @ dup IF dump ELSE 2drop THEN ENDOF
+ 3 OF count type ENDOF
+ 4 OF c@ IF ." true" ELSE ." false" THEN ENDOF
+ 5 OF c@ . ENDOF \ XXX: print symbolically
+ ENDCASE ;
+
+: .printenv-header cr
+ s" ---environment variable--------current value-------------default value------"
+ type cr ;
+
+DEFER old-emit
+0 VALUE emit-counter
+
+: emit-and-count emit-counter 1 + to emit-counter old-emit ;
+
+: .enable-emit-counter
+ 0 to emit-counter
+ ['] emit behavior to old-emit
+ ['] emit-and-count to emit ;
+
+: .disable-emit-counter
+ ['] old-emit behavior to emit ;
+
+: .spaces dup 0 > IF spaces ELSE
+ drop space THEN ;
+
+: .print-one-env 3 .spaces
+ 2dup dup -rot type 1c swap - .spaces
+ findenv rot over
+ .enable-emit-counter
+ (printenv) .disable-emit-counter
+ 1a emit-counter - .spaces
+ (printenv) ;
+
+: .print-all-env .printenv-header
+ envvars cell+ BEGIN @ dup WHILE dup link> >name
+ name>string .print-one-env cr REPEAT drop ;
+
+: printenv parse-word dup 0= IF
+ 2drop .print-all-env ELSE findenv dup 0=
+ ABORT" not a configuration variable"
+ rot over cr ." Current: " (printenv)
+ cr ." Default: " (printenv) THEN ;
+
+\ set envvar(s) to default value
: (set-default) ( def-xt -- )
- dup >name name>string $CREATE dup >body c@ >r execute r> CASE
- 1 OF env-int ENDOF
- 2 OF env-bytes ENDOF
- 3 OF env-string ENDOF
- 4 OF env-flag ENDOF
- 5 OF env-secmode ENDOF ENDCASE ;
+ dup >name name>string $CREATE dup >body c@ >r execute r> CASE
+ 1 OF env-int ENDOF
+ 2 OF env-bytes ENDOF
+ 3 OF env-string ENDOF
+ 4 OF env-flag ENDOF
+ 5 OF env-secmode ENDOF ENDCASE ;
: set-default parse-word envvars voc-find
- dup 0= ABORT" not a configuration variable" link> (set-default) ;
+ dup 0= ABORT" not a configuration variable" link> (set-default) ;
: set-defaults envvars cell+ BEGIN @ dup WHILE dup link> (set-default) REPEAT
drop ;
+\ the defaults
+\ some of those are platform dependent, and should e.g. be
+\ created from VPD values
true default-flag auto-boot?
s" " default-string boot-device
s" " default-string boot-file
+s" boot" default-string boot-command
s" " default-string diag-device
s" " default-string diag-file
false default-flag diag-switch?
true default-flag fcode-debug?
s" " default-string input-device
-s" 1 2 3 * + ." default-string nvramrc
+s" " default-string nvramrc
s" " default-string oem-banner
false default-flag oem-banner?
0 0 default-bytes oem-logo
false default-flag oem-logo?
s" " default-string output-device
-50 default-int screen-#columns
-18 default-int screen-#rows
+200 default-int screen-#columns
+200 default-int screen-#rows
0 default-int security-#badlogins
-0 default-secmode security-mode
+0 default-secmode security-mode
s" " default-string security-password
0 default-int selftest-#megs
false default-flag use-nvramrc?
+false default-flag direct-serial?
+true default-flag real-mode?
+true default-flag use-axon-ddr?
+
set-defaults
+
+VARIABLE nvoff \ 70 get-header 2drop nvoff !
+
+: (nvupdate-one) ( adr type -- )
+ CASE
+ 1 OF aligned @ . ENDOF
+ 2 OF drop ." 0 0" ENDOF
+ 3 OF count type ENDOF
+ 4 OF c@ IF ." true" ELSE ." false" THEN ENDOF
+ 5 OF c@ . ENDOF \ XXX: print symbolically
+ ENDCASE ;
+: nvupdate-one ( def-xt -- )
+ >name name>string
+ ( ." setenv " 2dup type space ) \ Old Implementation
+ 2dup type s" =" type
+ findenv nip (nvupdate-one)
+ ( cr ) \ Old Implementation
+ 0 emit
+ ;
+
+: (nvupdate) envvars cell+ BEGIN @ dup WHILE dup link> nvupdate-one REPEAT
+ drop ;
+
+: nvemit nvoff @ rb! 1 nvoff +! 0 nvoff @ rb! ;
+: nvupdate
+ 70 get-header 2drop nvoff !
+ ['] emit behavior ['] nvemit to emit (nvupdate) to emit ;
+
+
+
+: get-nv ( -- )
+ 70 get-header ( addr offset not-found | not-found ) \ find partition header
+ IF
+ create-default-headers \ partition header not found: set default values
+ nvupdate
+ 70 get-header IF ." NVRAM seems to be broken." cr EXIT THEN
+ THEN
+ \ partition header found: read data from nvram
+ drop ( addr ) \ throw away offset
+ BEGIN
+ dup rzcount dup \ make string from offset and make condition
+ WHILE ( offset offset length )
+ 2dup [char] = split \ Split string at equal sign (=)
+ ( offset offset length name len param len )
+ 2swap ( offset offset length param len name len )
+ $setenv \ Set envvar
+ nip \ throw away old string begin
+ + 1+ \ calc new offset
+ REPEAT
+ 2drop drop \ cleanup
+;
+
+
+get-nv
+
+
+: check-for-nvramrc ( -- )
+ use-nvramrc? IF
+ s" Executing following code from nvramrc: "
+ s" nvramrc" evaluate $cat
+ nvramlog-write-string-cr
+ s" (!) Executing code specified in nvramrc" type
+ cr s" SLOF Setup = " type
+ \ to remove the string from the console if the nvramrc is broken
+ \ we need to know how many chars are printed
+ .enable-emit-counter
+ s" nvramrc" evaluate ['] evaluate CATCH IF
+ \ dropping the rest of the nvram string
+ 2drop
+ \ delete the chars we do not want to see
+ emit-counter 0 DO 8 emit LOOP
+ s" (!) Code in nvramrc triggered exception. "
+ 2dup nvramlog-write-string
+ type cr 12 spaces s" Aborting nvramrc execution" 2dup
+ nvramlog-write-string-cr type cr
+ s" SLOF Setup = " type
+ THEN
+ .disable-emit-counter
+ THEN
+;
+
+
+: (nv-findalias) ( alias-ptr alias-len -- pos )
+ \ create a temporary empty string
+ here 0
+ \ append "devalias " to the temporary string
+ s" devalias " string-cat
+ \ append "<name-str>" to the temporary string
+ 3 pick 3 pick string-cat
+ \ append a SPACE character to the temporary string
+ s" " string-cat
+ \ get nvramrc
+ s" nvramrc" evaluate
+ \ get position of the temporary string inside of nvramrc
+ 2swap find-substr
+ nip nip
+;
+
+: (nv-build-real-entry) ( name-ptr name-len dev-ptr dev-len -- str-ptr str-len )
+ \ create a temporary empty string
+ 2swap here 0
+ \ append "devalias " to the temporary string
+ s" devalias " string-cat
+ \ append "<name-ptr>" to the temporary string
+ 2swap string-cat
+ \ append a SPACE character to the temporary string
+ s" " string-cat
+ \ append "<dev-ptr> to the temporary string
+ 2swap string-cat
+ \ append a CR character to the temporary string
+ 0d char-cat
+ \ append a LF character to the temporary string
+ 0a char-cat
+;
+
+: (nv-build-null-entry) ( name-ptr name-len dev-ptr dev-len -- str-ptr str-len )
+ 4drop here 0
+;
+
+: (nv-build-nvramrc) ( name-str name-len dev-str dev-len xt-build-entry -- )
+ \ *** PART 1: check if there is still an alias definition available ***
+ ( alias-ptr alias-len path-ptr path-ptr call-build-entry alias-pos )
+ 4 pick 4 pick (nv-findalias)
+ \ if our alias definition is a new one
+ dup s" nvramrc" evaluate nip >= IF
+ \ call-build-entry
+ drop execute
+ \ append content of "nvramrc" to the temporary string
+ s" nvramrc" evaluate string-cat
+ \ Allocate the temporary string
+ dup allot
+ \ write the string into nvramrc
+ s" nvramrc" $setenv
+ ELSE \ if our alias is still defined in nvramrc
+ \ *** PART 2: calculate the memory size for the new content of nvramrc ***
+ \ add number of bytes needed for nvramrc-prefix to number of bytes needed
+ \ for the new entry
+ 5 pick 5 pick 5 pick 5 pick 5 pick execute nip over +
+ ( alias-ptr alias-len path-ptr path-ptr build-entry-xt alias-pos tmp-len )
+ \ add number of bytes needed for nvramrc-postfix
+ s" nvramrc" evaluate 3 pick string-at
+ 2dup find-nextline string-at nip +
+ \ *** PART 3: build the new content ***
+ \ allocate enough memory for new content
+ alloc-mem 0
+ ( alias-ptr alias-len path-ptr path-ptr build-entry-xt alias-pos mem len )
+ \ add nvramrc-prefix
+ s" nvramrc" evaluate drop 3 pick string-cat
+ \ add new entry
+ rot >r >r >r execute r> r> 2swap string-cat
+ ( mem, len ) ( R: alias-pos )
+ \ add nvramrc-postfix
+ s" nvramrc" evaluate r> string-at
+ 2dup find-nextline string-at string-cat
+ ( mem len )
+ \ write the temporary string into nvramrc and clean up memory
+ 2dup s" nvramrc" $setenv free-mem
+ THEN
+;
+
+: $nvalias ( name-str name-len dev-str dev-len -- )
+ 4dup ['] (nv-build-real-entry) (nv-build-nvramrc)
+ set-alias
+ s" true" s" use-nvramrc?" $setenv
+ nvupdate
+;
+
+: nvalias ( "alias-name< >device-specifier<eol>" -- )
+ parse-word parse-word $nvalias
+;
+
+: $nvunalias ( name-str name-len -- )
+ s" " ['] (nv-build-null-entry) (nv-build-nvramrc)
+ nvupdate
+;
+
+: nvunalias ( "alias-name< >" -- )
+ parse-word $nvunalias
+;
+
+: diagnostic-mode? diag-switch? ;
+
diff --git a/slof/fs/exception.fs b/slof/fs/exception.fs
new file mode 100644
index 0000000..d243eb9
--- /dev/null
+++ b/slof/fs/exception.fs
@@ -0,0 +1,154 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+STRUCT
+ cell FIELD >r0 cell FIELD >r1 cell FIELD >r2 cell FIELD >r3
+ cell FIELD >r4 cell FIELD >r5 cell FIELD >r6 cell FIELD >r7
+ cell FIELD >r8 cell FIELD >r9 cell FIELD >r10 cell FIELD >r11
+ cell FIELD >r12 cell FIELD >r13 cell FIELD >r14 cell FIELD >r15
+ cell FIELD >r16 cell FIELD >r17 cell FIELD >r18 cell FIELD >r19
+ cell FIELD >r20 cell FIELD >r21 cell FIELD >r22 cell FIELD >r23
+ cell FIELD >r24 cell FIELD >r25 cell FIELD >r26 cell FIELD >r27
+ cell FIELD >r28 cell FIELD >r29 cell FIELD >r30 cell FIELD >r31
+ cell FIELD >cr cell FIELD >xer cell FIELD >lr cell FIELD >ctr
+ cell FIELD >srr0 cell FIELD >srr1 cell FIELD >dar cell FIELD >dsisr
+CONSTANT ciregs-size
+
+
+
+: .16 10 0.r 3 spaces ;
+: .8 8 spaces 8 0.r 3 spaces ;
+: .4regs cr 4 0 DO dup @ .16 8 cells+ LOOP drop ;
+: .fixed-regs
+ cr ." R0 .. R7 R8 .. R15 R16 .. R23 R24 .. R31"
+ dup 8 0 DO dup .4regs cell+ LOOP drop
+;
+
+: .special-regs
+ cr ." CR / XER LR / CTR SRR0 / SRR1 DAR / DSISR"
+ cr dup >cr @ .8 dup >lr @ .16 dup >srr0 @ .16 dup >dar @ .16
+ cr dup >xer @ .16 dup >ctr @ .16 dup >srr1 @ .16 >dsisr @ .8
+;
+
+: .regs
+ cr .fixed-regs
+ cr .special-regs
+ cr cr
+;
+
+: .hw-exception ( reason-code exception-nr -- )
+ ." ( " dup . ." ) "
+ CASE
+ 200 OF ." Machine Check" ENDOF
+ 300 OF ." Data Storage" ENDOF
+ 380 OF ." Data Segment" ENDOF
+ 400 OF ." Intruction Storage" ENDOF
+ 480 OF ." Instruction Segment" ENDOF
+ 500 OF ." External" ENDOF
+ 600 OF ." Alignment" ENDOF
+ 700 OF ." Program" ENDOF
+ 800 OF ." Floating-point unavailable" ENDOF
+ 900 OF ." Decrementer" ENDOF
+ 980 OF ." Hypervisor Decrementer" ENDOF
+ C00 OF ." System Call" ENDOF
+ D00 OF ." Trace" ENDOF
+ F00 OF ." Performance Monitor" ENDOF
+ F20 OF ." VMX Unavailable" ENDOF
+ 1200 OF ." System Error" ENDOF
+ 1600 OF ." Maintenance" ENDOF
+ 1800 OF ." Thermal" ENDOF
+ dup OF ." Unknown" ENDOF
+ ENDCASE
+ ." Exception [ " . ." ]"
+;
+
+: .sw-exception ( exception-nr -- )
+ ." Exception [ " . ." ] triggered by boot firmware."
+;
+
+\ this word gets also called for non-hardware exceptions.
+: be-hw-exception ( [reason-code] exception-nr -- )
+ cr cr
+ dup 0> IF .hw-exception ELSE .sw-exception THEN
+ cr eregs .regs
+;
+' be-hw-exception to hw-exception-handler
+
+: (boot-exception-handler) ( x1...xn exception-nr -- x1...xn)
+ dup IF
+ dup 0 > IF
+ negate cp 9 emit ." : " type
+ ELSE
+ CASE
+ -6d OF cr ." W3411: Client application returned." cr ENDOF
+ -6c OF cr ." E3400: It was not possible to boot from any device "
+ ." specified in the VPD." cr
+ ENDOF
+ -6b OF cr ." E3410: Boot list successfully read from VPD "
+ ." but no useful information received." cr
+ ENDOF
+ -6a OF cr ." E3420: Boot list could not be read from VPD." cr
+ ENDOF
+ -69 OF
+ cr ." E3406: Client application returned an error"
+ abort"-str @ count dup IF
+ ." : " type cr
+ ELSE
+ ." ." cr
+ 2drop
+ THEN
+ ENDOF
+ -68 OF cr ." E3405: No such device" cr ENDOF
+ -67 OF cr ." E3404: Not a bootable device!" cr ENDOF
+ -66 OF cr ." E3408: Failed to claim memory for the executable" cr
+ ENDOF
+ -65 OF cr ." E3407: Load failed" cr ENDOF
+ -64 OF cr ." E3403: Bad executable: " abort"-str @ count type cr
+ ENDOF
+ -63 OF cr ." E3409: Unknown FORTH Word" cr ENDOF
+ -2 OF cr ." E3401: Aborting boot, " abort"-str @ count type cr
+ ENDOF
+ dup OF ." E3402: Aborting boot, internal error" cr ENDOF
+ ENDCASE
+ THEN
+ ELSE
+ drop
+ THEN
+;
+
+' (boot-exception-handler) to boot-exception-handler
+
+: throw-error ( error-code "error-string" -- )
+ skipws 0a parse rot throw
+;
+
+\ Enable external interrupt in msr
+
+: enable-ext-int ( -- )
+ msr@ 8000 or msr!
+;
+
+\ Disable external interrupt in msr
+
+: disable-ext-int ( -- )
+ msr@ 8000 not and msr!
+;
+
+\ Generate external interrupt thru Internal Interrupt Controller of BE
+
+: gen-ext-int ( -- )
+ 7fffffff dec! \ Reset decrementer
+ enable-ext-int \ Enable interrupt
+ FF 20000508418 rx! \ Interrupt priority mask
+ 10 20000508410 rx! \ Interrupt priority
+;
+
diff --git a/slof/fs/fbuffer.fs b/slof/fs/fbuffer.fs
new file mode 100644
index 0000000..3167ca5
--- /dev/null
+++ b/slof/fs/fbuffer.fs
@@ -0,0 +1,178 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+#include "terminal.fs"
+#include "display.fs"
+
+\ \\\\\\\\\\\\\\ Global Data
+
+0 VALUE frame-buffer-adr
+0 VALUE screen-height
+0 VALUE screen-width
+0 VALUE window-top
+0 VALUE window-left
+
+0 VALUE .sc
+: screen-#rows .sc IF 18 ELSE true to .sc s" screen-#rows" eval false to .sc THEN ;
+: screen-#columns .sc IF 50 ELSE true to .sc s" screen-#columns" eval false to .sc THEN ;
+
+\ \\\\\\\\\\\\\\ Structure/Implementation Dependent Methods
+
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ *
+\ *
+
+: fb8-background inverse-screen? ;
+: fb8-foreground inverse? invert ;
+
+: fb8-lines2bytes ( #lines -- #bytes ) char-height * screen-width * ;
+: fb8-columns2bytes ( #columns -- #bytes ) char-width * ;
+: fb8-line2addr ( line# -- addr )
+ char-height * window-top + screen-width *
+ frame-buffer-adr + window-left +
+;
+
+: fb8-erase-block ( addr len ) fb8-background rfill ;
+
+
+0 VALUE .ab
+CREATE bitmap-buffer 400 allot
+
+: active-bits ( -- new ) .ab dup 8 > IF 8 - to .ab 8 ELSE
+ char-width to .ab ?dup 0= IF recurse THEN
+ THEN ;
+
+: fb8-char2bitmap ( font-height font-addr -- bitmap-buffer )
+ bitmap-buffer >r
+ char-height rot 0> IF r> char-width 2dup fb8-erase-block + >r 1- THEN
+
+ r> -rot char-width to .ab
+ ( fb-addr font-addr font-height )
+ fontbytes * bounds ?DO
+ i c@ active-bits 0 ?DO
+ dup 80 and IF fb8-foreground ELSE fb8-background THEN
+ ( fb-addr fbyte colr ) 2 pick ! 1 lshift swap 1+ swap
+ LOOP drop
+ LOOP drop
+ bitmap-buffer
+;
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ * IEEE 1275: Frame buffer support routines
+\ *
+
+: fb8-draw-logo ( line# addr width height -- ) ." fb8-draw-logo ( " .s ." )" cr
+ 2drop 2drop
+;
+
+: fb8-toggle-cursor ( -- )
+ line# fb8-line2addr column# fb8-columns2bytes +
+ char-height 0 ?DO
+ char-width 0 ?DO dup dup rb@ -1 xor swap rb! 1+ LOOP
+ screen-width + char-width -
+ LOOP drop
+;
+
+: fb8-draw-character ( char -- )
+ >r default-font over + r@ -rot between IF
+ 2swap 3drop r> >font fb8-char2bitmap ( bitmap-buf )
+ line# fb8-line2addr column# fb8-columns2bytes + ( bitmap-buf fb-addr )
+ char-height 0 ?DO
+ 2dup char-width mrmove
+ screen-width + >r char-width + r>
+ LOOP 2drop
+ ELSE 2drop r> 3drop THEN
+;
+
+: fb8-insert-lines ( n -- )
+ fb8-lines2bytes >r line# fb8-line2addr dup dup r@ +
+ #lines line# - fb8-lines2bytes r@ - rmove
+ r> fb8-erase-block
+;
+
+: fb8-delete-lines ( n -- )
+ fb8-lines2bytes >r line# fb8-line2addr dup dup r@ + swap
+ #lines fb8-lines2bytes r@ - dup >r rmove
+ r> + r> fb8-erase-block
+;
+
+: fb8-insert-characters ( n -- )
+ line# fb8-line2addr column# fb8-columns2bytes + >r
+ #columns column# - 2dup >= IF
+ nip dup 0> IF fb8-columns2bytes r> ELSE r> 2drop EXIT THEN
+ ELSE
+ fb8-columns2bytes swap fb8-columns2bytes tuck -
+ over r@ tuck + rot char-height 0 ?DO
+ 3dup rmove
+ -rot screen-width tuck + -rot + swap rot
+ LOOP
+ 3drop r>
+ THEN
+ char-height 0 ?DO dup 2 pick fb8-erase-block screen-width + LOOP 2drop
+;
+
+: fb8-delete-characters ( n -- )
+ line# fb8-line2addr column# fb8-columns2bytes + >r
+ #columns column# - 2dup >= IF
+ nip dup 0> IF fb8-columns2bytes r> ELSE r> 2drop EXIT THEN
+ ELSE
+ fb8-columns2bytes swap fb8-columns2bytes tuck -
+ over r@ + 2dup + r> swap >r rot char-height 0 ?DO
+ 3dup rmove
+ -rot screen-width tuck + -rot + swap rot
+ LOOP
+ 3drop r> over -
+ THEN
+ char-height 0 ?DO dup 2 pick fb8-erase-block screen-width + LOOP 2drop
+;
+
+: fb8-reset-screen ( -- ) ( Left as no-op by design ) ;
+
+: fb8-erase-screen ( -- )
+ frame-buffer-adr screen-height screen-width * fb8-erase-block
+;
+
+: fb8-invert-screen ( -- )
+ frame-buffer-adr screen-height screen-width * 2dup /x / 0 ?DO
+ dup rx@ -1 xor over rx! xa1+
+ LOOP 3drop
+;
+
+: fb8-blink-screen ( -- ) fb8-invert-screen fb8-invert-screen ;
+
+: fb8-install ( width height #columns #lines -- )
+ screen-#rows min to #lines
+ screen-#columns min to #columns
+ dup to screen-height char-height #lines * - 2/ to window-top
+ dup to screen-width char-width #columns * - 2/ to window-left
+ ['] fb8-toggle-cursor to toggle-cursor
+ ['] fb8-draw-character to draw-character
+ ['] fb8-insert-lines to insert-lines
+ ['] fb8-delete-lines to delete-lines
+ ['] fb8-insert-characters to insert-characters
+ ['] fb8-delete-characters to delete-characters
+ ['] fb8-erase-screen to erase-screen
+ ['] fb8-blink-screen to blink-screen
+ ['] fb8-invert-screen to invert-screen
+ ['] fb8-reset-screen to reset-screen
+ ['] fb8-draw-logo to draw-logo
+;
+
+\ \\\\\\\\\\\\ Debug Stuff \\\\\\\\\\\\\\\\
+
+: fb8-dump-bitmap cr char-height 0 ?do char-width 0 ?do dup c@ if ." @" else ." ." then 1+ loop cr loop drop ;
+
+: fb8-dump-char >font -b swap fb8-char2bitmap fb8-dump-bitmap ;
+
+
diff --git a/slof/fs/fcode/1275.fs b/slof/fs/fcode/1275.fs
new file mode 100644
index 0000000..39ee3ed
--- /dev/null
+++ b/slof/fs/fcode/1275.fs
@@ -0,0 +1,353 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+0 value function-type ' function-type @ constant <value>
+ variable function-type ' function-type @ constant <variable>
+0 constant function-type ' function-type @ constant <constant>
+: function-type ; ' function-type @ constant <colon>
+create function-type ' function-type @ constant <create>
+defer function-type ' function-type @ constant <defer>
+
+\ variable tmp-buf-current
+\ variable orig-here
+\ create tmp-buf 10000 allot
+
+( ---------------------------------------------------- )
+
+: fcode-revision ( -- n )
+ 00030000 \ major * 65536 + minor
+ ;
+
+: b(lit) ( -- n )
+ next-ip read-fcode-num32
+ ?compile-mode IF literal, THEN
+ ;
+
+: b(")
+ next-ip read-fcode-string
+ ?compile-mode IF fc-string, align postpone count THEN
+ ;
+
+: b(')
+ next-ip read-fcode# get-token drop ?compile-mode IF literal, THEN
+ ;
+
+: ?jump-direction ( n -- )
+ dup 8000 >= IF FFFF swap - negate 2- THEN
+ ;
+
+: ?negative
+ 8000 and
+ ;
+
+: dest-on-top
+ 0 >r BEGIN dup @ 0= WHILE >r REPEAT
+ BEGIN r> dup WHILE swap REPEAT
+ drop
+ ;
+
+: ?branch
+ true =
+ ;
+
+: read-fcode-offset \ ELSE needs to be fixed!
+ ?offset16 IF next-ip read-fcode-num16 ELSE THEN
+ ;
+
+: b?branch ( flag -- )
+ ?compile-mode IF
+ read-fcode-offset ?negative IF dest-on-top postpone until
+ ELSE postpone if
+ THEN
+ ELSE
+ ?branch IF 2 jump-n-ip
+ ELSE read-fcode-offset
+ ?jump-direction 2- jump-n-ip
+ THEN
+ THEN
+ ; immediate
+
+: bbranch ( -- )
+ ?compile-mode IF
+ read-fcode-offset
+ ?negative IF dest-on-top postpone again
+ ELSE postpone else
+ get-ip next-ip fcode@ B2 = IF drop ELSE set-ip THEN
+ THEN
+ ELSE
+ read-fcode-offset ?jump-direction 2- jump-n-ip
+ THEN
+ ; immediate
+
+: b(<mark) ( -- )
+ ?compile-mode IF postpone begin THEN
+ ; immediate
+
+: b(>resolve) ( -- )
+ ?compile-mode IF postpone then THEN
+ ; immediate
+
+: ffwto; ( -- )
+ BEGIN fcode@ dup c2 <> WHILE
+." ffwto: skipping " dup . ." @ " get-ip . cr
+ CASE 10 OF ( lit ) read-fcode-num32 drop ENDOF
+ 11 OF ( ' ) read-fcode# drop ENDOF
+ 12 OF ( " ) read-fcode-string 2drop ENDOF
+ 13 OF ( bbranch ) read-fcode-offset drop ENDOF
+ 14 OF ( b?branch ) read-fcode-offset drop ENDOF
+ 15 OF ( loop ) read-fcode-offset drop ENDOF
+ 16 OF ( +loop ) read-fcode-offset drop ENDOF
+ 17 OF ( do ) read-fcode-offset drop ENDOF
+ 18 OF ( ?do ) read-fcode-offset drop ENDOF
+ 1C OF ( of ) read-fcode-offset drop ENDOF
+ C6 OF ( endof ) read-fcode-offset drop ENDOF
+ C3 OF ( to ) read-fcode# drop ENDOF
+ dup OF next-ip ENDOF
+ ENDCASE
+ REPEAT next-ip
+;
+
+: rpush ( rparm -- ) \ push the rparm to be on top of return stack after exit
+ r> swap >r >r
+;
+
+: rpop ( -- rparm ) \ pop the rparm that was on top of return stack before this
+ r> r> swap >r
+;
+
+: b1(;) ( -- )
+." b1(;)" cr
+ rpop set-ip
+;
+
+\ : b1(:) ( -- )
+\ ." b1(:)" cr
+\ <colon> compile, get-ip 1+ literal ] get-ip rpush set-ip [
+\ ffwto;
+\ ; immediate
+
+: b(;) ( -- )
+ postpone exit reveal postpone [
+ ; immediate
+
+: b(:) ( -- )
+ <colon> compile, ]
+ ; immediate
+
+: b(case) ( sel -- sel )
+ postpone case
+ ; immediate
+
+: b(endcase)
+ postpone endcase
+ ; immediate
+
+: b(of)
+ postpone of
+ read-fcode-offset drop \ read and discard offset
+ ; immediate
+
+: b(endof)
+ postpone endof
+ read-fcode-offset drop
+ ; immediate
+
+: b(do)
+ postpone do
+ read-fcode-offset drop
+ ; immediate
+
+: b(?do)
+ postpone ?do
+ read-fcode-offset drop
+ ; immediate
+
+: b(loop)
+ postpone loop
+ read-fcode-offset drop
+ ; immediate
+
+: b(+loop)
+ postpone +loop
+ read-fcode-offset drop
+ ; immediate
+
+: b(leave)
+ postpone leave
+ ; immediate
+
+: new-token \ unnamed local fcode function
+ align here next-ip read-fcode# 0 swap set-token
+ ;
+
+: external-token ( -- ) \ named local fcode function
+ next-ip read-fcode-string
+ header ( str len -- ) \ create a header in the current dictionary entry
+ new-token
+ ;
+
+: new-token
+ eva-debug? IF
+ s" x" get-ip >r next-ip read-fcode# r> set-ip (u.) $cat strdup
+ header
+ THEN new-token
+;
+
+: named-token \ decide wether or not to give a new token an own name in the dictionary
+ fcode-debug? IF new-token ELSE external-token THEN
+ ;
+
+: b(to) ( x -- )
+ next-ip read-fcode#
+ get-token drop
+ >body cell -
+ ?compile-mode IF literal, postpone ! ELSE ! THEN
+ ; immediate
+
+: b(value)
+ <value> , , reveal
+ ;
+
+: b(variable)
+ <variable> , 0 , reveal
+ ;
+
+: b(constant)
+ <constant> , , reveal
+ ;
+
+: undefined-defer
+ cr cr ." Unititialized defer word has been executed!" cr cr
+ true fcode-end !
+ ;
+
+: b(defer)
+ <defer> , reveal
+ postpone undefined-defer
+ ;
+
+: b(create)
+ <variable> ,
+ postpone noop reveal
+ ;
+
+: b(field) ( E: addr -- addr+offset ) ( F: offset size -- offset+size )
+ <colon> , over literal,
+ postpone + postpone exit
+ +
+ ;
+
+: b(buffer:) ( E: -- a-addr) ( F: size -- )
+ <variable> , allot
+ ;
+
+: suspend-fcode ( -- )
+ noop \ has to be implemented more efficiently ;-)
+ ;
+
+: offset16 ( -- )
+ 16 to fcode-offset
+ ;
+
+: version1 ( -- )
+ 1 to fcode-spread
+ 8 to fcode-offset
+ read-header
+ ;
+
+: start0 ( -- )
+ 0 to fcode-spread
+ offset16
+ read-header
+ ;
+
+: start1 ( -- )
+ 1 to fcode-spread
+ offset16
+ read-header
+ ;
+
+: start2 ( -- )
+ 2 to fcode-spread
+ offset16
+ read-header
+ ;
+
+: start4 ( -- )
+ 4 to fcode-spread
+ offset16
+ read-header
+ ;
+
+: end0 ( -- )
+ true fcode-end !
+ ;
+
+: end1 ( -- )
+ end0
+ ;
+
+: ferror ( -- )
+ clear end0
+ cr ." FCode# " fcode-num @ . ." not assigned!"
+ cr ." FCode evaluation aborted." cr
+ ." ( -- S:" depth . ." R:" rdepth . ." ) " .s cr
+ abort
+ ;
+
+: reset-local-fcodes
+ FFF 800 DO ['] ferror 0 i set-token LOOP
+ ;
+
+: byte-load ( addr xt -- )
+ >r >r
+ save-evaluator-state
+ r> r>
+ reset-fcode-end
+ 1 to fcode-spread
+ dup 1 = IF drop ['] rb@ THEN to fcode-rb@
+ set-ip
+ reset-local-fcodes
+ depth >r
+ evaluate-fcode
+ r> depth 1- <> IF clear end0
+ cr ." Ambiguous stack depth after byte-load!"
+ cr ." FCode evaluation aborted." cr cr
+ ELSE restore-evaluator-state
+ THEN
+ ['] c@ to fcode-rb@
+ ;
+
+create byte-load-test-fcode
+f1 c, 08 c, 18 c, 69 c, 00 c, 00 c, 00 c, 68 c,
+12 c, 16 c, 62 c, 79 c, 74 c, 65 c, 2d c, 6c c,
+6f c, 61 c, 64 c, 2d c, 74 c, 65 c, 73 c, 74 c,
+2d c, 66 c, 63 c, 6f c, 64 c, 65 c, 21 c, 21 c,
+90 c, 92 c, ( a6 c, a7 c, 2e c, ) 00 c,
+
+: byte-load-test
+ byte-load-test-fcode ['] w@
+ ; immediate
+
+: fcode-ms
+ s" ms" $find IF 0= IF compile, ELSE execute THEN THEN ; immediate
+
+: fcode-$find
+ $find
+ IF
+ drop true
+ ELSE
+ false
+ THEN
+ ;
+
+( ---------------------------------------------------- )
diff --git a/slof/fs/fcode/big.fs b/slof/fs/fcode/big.fs
new file mode 100644
index 0000000..c2cb8d9
--- /dev/null
+++ b/slof/fs/fcode/big.fs
@@ -0,0 +1,45 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ big-endian
+
+( ---------------------------------------------------- )
+
+: read-fcode-num16 ( -- n )
+ 0 fcode-num !
+ ?arch64 IF
+ read-byte fcode-num 6 + C!
+ next-ip read-byte fcode-num 7 + C!
+ ELSE
+ read-byte fcode-num 2 + C!
+ next-ip read-byte fcode-num 3 + C!
+ THEN
+ fcode-num @
+ ;
+
+: read-fcode-num32 ( -- n )
+ 0 fcode-num !
+ ?arch64 IF
+ read-byte fcode-num 4 + C!
+ next-ip read-byte fcode-num 5 + C!
+ next-ip read-byte fcode-num 6 + C!
+ next-ip read-byte fcode-num 7 + C!
+ ELSE
+ read-byte fcode-num 0 + C!
+ next-ip read-byte fcode-num 1 + C!
+ next-ip read-byte fcode-num 2 + C!
+ next-ip read-byte fcode-num 3 + C!
+ THEN
+ fcode-num @
+ ;
+
+( ---------------------------------------------------- )
diff --git a/slof/fs/fcode/core.fs b/slof/fs/fcode/core.fs
new file mode 100644
index 0000000..8cfadeb
--- /dev/null
+++ b/slof/fs/fcode/core.fs
@@ -0,0 +1,169 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: ?offset16 ( -- true|false )
+ fcode-offset 16 =
+ ;
+
+: ?arch64 ( -- true|false )
+ cell 8 =
+ ;
+
+: ?bigendian ( -- true|false )
+ deadbeef fcode-num !
+ fcode-num ?arch64 IF 4 + THEN
+ c@ de =
+ ;
+
+: reset-fcode-end ( -- )
+ false fcode-end !
+ ;
+
+: get-ip ( -- n )
+ ip @
+ ;
+
+: set-ip ( n -- )
+ ip !
+ ;
+
+: next-ip ( -- )
+ get-ip 1+ set-ip
+ ;
+
+: jump-n-ip ( n -- )
+ get-ip + set-ip
+ ;
+
+: read-byte ( -- n )
+ get-ip fcode-rb@
+ ;
+
+: ?compile-mode ( -- on|off )
+ state @
+ ;
+
+: save-evaluator-state
+ get-ip eva-debug? IF ." saved ip " dup . cr THEN
+ fcode-end @ eva-debug? IF ." saved fcode-end " dup . cr THEN
+ fcode-offset eva-debug? IF ." saved fcode-offset " dup . cr THEN
+\ local fcodes are currently NOT saved!
+ fcode-spread eva-debug? IF ." saved fcode-spread " dup . cr THEN
+ ['] fcode@ behavior eva-debug? IF ." saved fcode@ " dup . cr THEN
+ ;
+
+: restore-evaluator-state
+ eva-debug? IF ." restored fcode@ " dup . cr THEN to fcode@
+ eva-debug? IF ." restored fcode-spread " dup . cr THEN to fcode-spread
+\ local fcodes are currently NOT restored!
+ eva-debug? IF ." restored fcode-offset " dup . cr THEN to fcode-offset
+ eva-debug? IF ." restored fcode-end " dup . cr THEN fcode-end !
+ eva-debug? IF ." restored ip " dup . cr THEN set-ip
+ ;
+
+: token-table-index ( fcode# -- addr )
+ cells token-table +
+ ;
+
+: join-immediate ( xt immediate? addr -- xt+immediate? addr )
+ -rot + swap
+ ;
+
+: split-immediate ( xt+immediate? -- xt immediate? )
+ dup 1 and 2dup - rot drop swap
+ ;
+
+: literal, ( n -- )
+ postpone literal
+ ;
+
+: fc-string,
+ postpone sliteral
+ dup c, bounds ?do i c@ c, loop
+ ;
+
+: set-token ( xt immediate? fcode# -- )
+ token-table-index join-immediate !
+ ;
+
+: get-token ( fcode# -- xt immediate? )
+ token-table-index @ split-immediate
+ ;
+
+-1 VALUE break-fcode-addr
+
+: exec ( FCode# -- )
+
+ eva-debug? IF
+ dup
+ get-ip 8 u.r ." : "
+ ." [" 3 u.r ." ] "
+ THEN
+ get-ip break-fcode-addr = IF
+ TRUE fcode-end ! drop EXIT
+ THEN
+
+ get-token 0= IF \ imm == 0 == false
+ ?compile-mode IF
+ compile,
+ ELSE
+ eva-debug? IF dup xt>name type space THEN
+ execute
+ THEN
+ ELSE \ immediate
+ eva-debug? IF dup xt>name type space THEN
+ execute
+ THEN
+ eva-debug? IF .s cr THEN
+ ;
+
+( ---------------------------------------------------- )
+
+0 ?bigendian INCLUDE? big.fs
+0 ?bigendian NOT INCLUDE? little.fs
+
+( ---------------------------------------------------- )
+
+: read-fcode# ( -- FCode# )
+ read-byte
+ dup 01 0F between IF drop read-fcode-num16 THEN
+ ;
+
+: read-header ( adr -- )
+ next-ip read-byte drop
+ next-ip read-fcode-num16 drop
+ next-ip read-fcode-num32 drop
+ ;
+
+: read-fcode-string ( -- str len )
+ read-byte \ get string length ( -- len )
+ next-ip get-ip \ get string addr ( -- len str )
+ swap \ type needs the parameters swapped ( -- str len )
+ dup 1- jump-n-ip \ jump to the end of the string in FCode
+ ;
+
+: evaluate-fcode ( -- )
+ fcode@ exec \ read start code
+ BEGIN
+ next-ip fcode@ exec
+ fcode-end @
+ UNTIL
+ ;
+
+: step-fcode ( -- )
+ break-fcode-addr >r -1 to break-fcode-addr
+ fcode@ exec next-ip
+ r> to break-fcode-addr
+;
+
+
+( ---------------------------------------------------- )
diff --git a/slof/fs/fcode/evaluator.fs b/slof/fs/fcode/evaluator.fs
new file mode 100644
index 0000000..a0249ab
--- /dev/null
+++ b/slof/fs/fcode/evaluator.fs
@@ -0,0 +1,99 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+( eva - gordons fcode bytecode evaluator )
+
+hex
+
+-1 constant true
+ 0 constant false
+
+variable ip
+variable fcode-end
+variable fcode-num
+ 1 value fcode-spread
+16 value fcode-offset
+false value eva-debug?
+false value fcode-debug?
+defer fcode-rb@
+defer fcode@
+
+' c@ to fcode-rb@
+
+create token-table 2000 cells allot \ 1000h = 4096d
+
+include core.fs
+include 1275.fs
+include tokens.fs
+
+0 value buff
+0 value buff-size
+
+( ---------------------------------------------------- )
+
+' read-fcode# to fcode@
+
+: step next-ip fcode@ exec ; immediate
+( ---------------------------------------------------- )
+
+: rom-code-ignored ( image# name len -- )
+ diagnostic-mode? IF type ." code found in image " . ." , ignoring ..." cr
+ ELSE 3drop THEN
+;
+
+: pci-find-rom ( baseaddr -- addr )
+ -8 and dup IF
+ dup rw@ 55aa = IF
+ diagnostic-mode? IF ." Device ROM found at " dup . cr THEN
+ ELSE drop 0 THEN
+ THEN
+;
+
+: pci-find-fcode ( baseaddr -- addr len | false )
+ pci-find-rom ?dup IF
+ dup 18 + rw@ wbflip +
+ 0 swap BEGIN
+ dup rl@ 50434952 ( 'PCIR') <> IF
+ diagnostic-mode? IF
+ ." Invalid PCI Data structure, ignoring ROM contents" cr
+ THEN
+ 2drop false EXIT
+ THEN
+ dup 14 + rb@ CASE
+ 0 OF over . s" Intel x86 BIOS" rom-code-ignored ENDOF
+ 1 OF swap diagnostic-mode? IF
+ ." Open Firmware FCode found at image " . cr
+ ELSE drop THEN
+ dup a + rw@ wbflip over + \ This code start
+ swap 10 + rw@ wbflip 200 * \ This code length
+ EXIT
+ ENDOF
+ 2 OF over . s" HP PA RISC" rom-code-ignored ENDOF
+ 3 OF over . s" EFI" rom-code-ignored ENDOF
+ dup OF over . s" Unknown type" rom-code-ignored ENDOF
+ ENDCASE
+ dup 15 + rb@ 80 and IF 2drop EXIT THEN \ End of last image
+ dup 10 + rw@ wbflip 200 * + \ Next image start
+ swap 1+ swap \ Next image #
+ 0 UNTIL
+ THEN false
+;
+
+: execute-rom-fcode ( addr len | false -- )
+ ?dup IF
+ diagnostic-mode? IF ." , executing ..." cr THEN
+ dup >r r@ alloc-mem dup >r swap rmove
+ r@ set-ip evaluate-fcode
+ diagnostic-mode? IF ." Done." cr THEN
+ r> r> free-mem
+ THEN
+;
diff --git a/slof/fs/fcode/tokens.fs b/slof/fs/fcode/tokens.fs
new file mode 100644
index 0000000..bf76b8b
--- /dev/null
+++ b/slof/fs/fcode/tokens.fs
@@ -0,0 +1,411 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: fc-abort ." FCode called abort: IP " get-ip . ( ." STACK: " .s ) depth dup 0< IF abort THEN . rdepth . cr abort ;
+: fc-0 ." 0(lit): STACK ( S: " depth . ." R: " rdepth . ." ): " depth 0> IF .s THEN 0 ;
+: fc-1 ." 1(lit): STACK ( S: " depth . ." R: " rdepth . ." ): " depth 0> IF .s THEN 1 ;
+
+: parse-1hex 1 hex-decode-unit ;
+
+
+: reset-token-table
+ FFF 0 DO ['] ferror 0 i set-token LOOP
+ ;
+
+reset-token-table
+
+' end0 0 00 set-token
+
+\ 01...0F beginning code of 2-byte FCode sequences
+
+\ ' ferror 1 08 set-token
+\ ' ferror 1 09 set-token
+\ ' ferror 1 0a set-token
+\ ' ferror 1 0b set-token
+\ ' ferror 1 0c set-token
+\ ' ferror 1 0d set-token
+\ ' ferror 1 0e set-token
+\ ' ferror 1 0f set-token
+
+' b(lit) 1 10 set-token
+
+' b(') 1 11 set-token
+' b(") 1 12 set-token
+' bbranch 1 13 set-token
+' b?branch 1 14 set-token
+' b(loop) 1 15 set-token
+' b(+loop) 1 16 set-token
+' b(do) 1 17 set-token
+' b(?do) 1 18 set-token
+' i 0 19 set-token
+' j 0 1A set-token
+' b(leave) 1 1B set-token
+' b(of) 1 1C set-token
+' execute 0 1D set-token
+' + 0 1E set-token
+' - 0 1F set-token
+' * 0 20 set-token
+' / 0 21 set-token
+' mod 0 22 set-token
+' and 0 23 set-token
+' or 0 24 set-token
+' xor 0 25 set-token
+' invert 0 26 set-token
+' lshift 0 27 set-token
+' rshift 0 28 set-token
+' >>a 0 29 set-token
+' /mod 0 2A set-token
+' u/mod 0 2B set-token
+' negate 0 2C set-token
+' abs 0 2D set-token
+' min 0 2E set-token
+' max 0 2F set-token
+' >r 0 30 set-token
+' r> 0 31 set-token
+' r@ 0 32 set-token
+' exit 0 33 set-token
+' 0= 0 34 set-token
+' 0<> 0 35 set-token
+' 0< 0 36 set-token
+' 0<= 0 37 set-token
+' 0> 0 38 set-token
+' 0>= 0 39 set-token
+' < 0 3A set-token
+' > 0 3B set-token
+' = 0 3C set-token
+' <> 0 3D set-token
+' u> 0 3E set-token
+' u<= 0 3F set-token
+' u< 0 40 set-token
+' u>= 0 41 set-token
+' >= 0 42 set-token
+' <= 0 43 set-token
+' between 0 44 set-token
+' within 0 45 set-token
+' DROP 0 46 set-token
+' DUP 0 47 set-token
+' OVER 0 48 set-token
+' SWAP 0 49 set-token
+' ROT 0 4A set-token
+' -ROT 0 4B set-token
+' TUCK 0 4C set-token
+' nip 0 4D set-token
+' pick 0 4E set-token
+' roll 0 4F set-token
+' ?dup 0 50 set-token
+' depth 0 51 set-token
+' 2drop 0 52 set-token
+' 2dup 0 53 set-token
+' 2over 0 54 set-token
+' 2swap 0 55 set-token
+' 2rot 0 56 set-token
+' 2/ 0 57 set-token
+' u2/ 0 58 set-token
+' 2* 0 59 set-token
+' /c 0 5A set-token
+' /w 0 5B set-token
+' /l 0 5C set-token
+' /n 0 5D set-token
+' ca+ 0 5E set-token
+' wa+ 0 5F set-token
+' la+ 0 60 set-token
+' na+ 0 61 set-token
+' char+ 0 62 set-token
+' wa1+ 0 63 set-token
+' la1+ 0 64 set-token
+' cell+ 0 65 set-token
+' chars 0 66 set-token
+' /w* 0 67 set-token
+' /l* 0 68 set-token
+' cells 0 69 set-token
+' on 0 6A set-token
+' off 0 6B set-token
+' +! 0 6C set-token
+' @ 0 6D set-token
+' l@ 0 6E set-token
+' w@ 0 6F set-token
+' <w@ 0 70 set-token
+' c@ 0 71 set-token
+' ! 0 72 set-token
+' l! 0 73 set-token
+' w! 0 74 set-token
+' c! 0 75 set-token
+' 2@ 0 76 set-token
+' 2! 0 77 set-token
+' move 0 78 set-token
+' fill 0 79 set-token
+' comp 0 7A set-token
+' noop 0 7B set-token
+' lwsplit 0 7C set-token
+' wljoin 0 7D set-token
+' lbsplit 0 7E set-token
+' bljoin 0 7F set-token
+' wbflip 0 80 set-token
+' upc 0 81 set-token
+' lcc 0 82 set-token
+' pack 0 83 set-token
+' count 0 84 set-token
+' body> 0 85 set-token
+' >body 0 86 set-token
+' fcode-revision 0 87 set-token
+' span 0 88 set-token
+' unloop 0 89 set-token
+' expect 0 8A set-token
+' alloc-mem 0 8B set-token \ alloc-mem
+' free-mem 0 8C set-token \ free-mem
+' key? 0 8D set-token
+' key 0 8E set-token
+' emit 0 8F set-token
+' type 0 90 set-token
+' cr 0 91 set-token \ should be (cr but terminal support is not
+ \ available
+' cr 0 92 set-token
+\ ' #out 0 93 set-token
+\ ' #line 0 94 set-token
+' hold 0 95 set-token
+' <# 0 96 set-token
+' u#> 0 97 set-token
+' sign 0 98 set-token
+' u# 0 99 set-token
+' u#s 0 9A set-token
+' u. 0 9B set-token
+' u.r 0 9C set-token
+' . 0 9D set-token
+' .r 0 9E set-token
+' .s 0 9F set-token
+' base 0 A0 set-token
+\ ' convert 0 A1 set-token
+' $number 0 A2 set-token
+' digit 0 A3 set-token
+' -1 0 A4 set-token
+' 0 0 A5 set-token
+' 1 0 A6 set-token
+' 2 0 A7 set-token
+' 3 0 A8 set-token
+' bl 0 A9 set-token
+' bs 0 AA set-token
+' bell 0 AB set-token
+' bounds 0 AC set-token
+' here 0 AD set-token
+' aligned 0 AE set-token
+' wbsplit 0 AF set-token
+' bwjoin 0 B0 set-token
+' b(<mark) 1 B1 set-token
+' b(>resolve) 1 B2 set-token
+\ ' ferror 0 B3 set-token
+\ ' ferror 0 B4 set-token
+' new-token 0 B5 set-token
+' named-token 0 B6 set-token
+\ fcode-debug? IF
+' b(:) 1 B7 set-token
+\ ELSE
+\ ' b(:) 1 B7 set-token
+\ THEN
+' b(value) 1 B8 set-token
+' b(variable) 1 B9 set-token
+' b(constant) 1 BA set-token
+' b(create) 1 BB set-token
+' b(defer) 1 BC set-token
+' b(buffer:) 1 BD set-token
+' b(field) 1 BE set-token
+\ ' ferror 0 BF set-token
+' INSTANCE 0 C0 set-token
+\ ' noop 1 C0 set-token
+\ ' ferror 0 C1 set-token
+\ fcode-debug? IF
+' b(;) 1 C2 set-token
+\ ELSE
+\ ' b(;) 1 C2 set-token
+\ THEN
+' b(to) 1 C3 set-token
+' b(case) 1 C4 set-token
+' b(endcase) 1 C5 set-token
+' b(endof) 1 C6 set-token
+' # 0 C7 set-token
+' #s 0 C8 set-token
+' #> 0 C9 set-token
+' external-token 0 CA set-token
+' $find 0 CB set-token
+' offset16 0 CC set-token
+' evaluate 0 CD set-token
+\ 0 CE reserved
+\ 0 CF reserved
+' c, 0 D0 set-token
+' w, 0 D1 set-token
+' l, 0 D2 set-token
+' , 0 D3 set-token
+' um* 0 D4 set-token
+' um/mod 0 D5 set-token
+\ 0 D6 reserved
+\ 0 D7 reserved
+' d+ 0 D8 set-token
+' d- 0 D9 set-token
+' get-token 0 DA set-token
+' set-token 0 DB set-token
+' state 0 DC set-token \ possibly broken
+' compile, 0 DD set-token
+' behavior 0 DE set-token
+
+' start0 0 F0 set-token
+' start1 0 F1 set-token
+' start2 0 F2 set-token
+' start4 0 F3 set-token
+
+' ferror 0 FC set-token
+' version1 0 FD set-token
+
+\ ' 4-byte-id 0 FE set-token \ Historical
+' end1 0 FF set-token
+
+\ ' dma-alloc 0 101 set-token
+' my-address 0 102 set-token
+' my-space 0 103 set-token
+' property 0 110 set-token
+' encode-int 0 111 set-token
+' encode+ 0 112 set-token
+' encode-phys 0 113 set-token
+' encode-string 0 114 set-token
+' encode-bytes 0 115 set-token
+' reg 0 116 set-token
+' model 0 119 set-token
+' device-type 0 11A set-token
+' parse-2int 0 11B set-token
+' is-install 0 11C set-token
+' is-remove 0 11D set-token
+' is-selftest 0 11E set-token
+' new-device 0 11F set-token
+' diagnostic-mode? 0 120 set-token
+' memory-test-suite 0 122 set-token
+' mask 0 124 set-token
+' get-msecs 0 125 set-token
+' ms 0 126 set-token
+' finish-device 0 127 set-token
+' decode-phys 0 128 set-token
+' #lines 0 150 set-token
+' #columns 0 151 set-token
+' line# 0 152 set-token
+' column# 0 153 set-token
+' inverse? 0 154 set-token
+' inverse-screen? 0 155 set-token
+
+' draw-character 0 157 set-token
+' reset-screen 0 158 set-token
+' toggle-cursor 0 159 set-token
+' erase-screen 0 15A set-token
+' blink-screen 0 15B set-token
+' invert-screen 0 15C set-token
+' insert-characters 0 15D set-token
+' delete-characters 0 15E set-token
+' insert-lines 0 15F set-token
+' delete-lines 0 160 set-token
+' draw-logo 0 161 set-token
+' frame-buffer-adr 0 162 set-token
+' screen-height 0 163 set-token
+' screen-width 0 164 set-token
+' window-top 0 165 set-token
+' window-left 0 166 set-token
+
+' default-font 0 16A set-token
+' set-font 0 16B set-token
+' char-height 0 16C set-token
+' char-width 0 16D set-token
+' >font 0 16E set-token
+' fontbytes 0 16F set-token
+
+' fb8-install 0 18B set-token
+
+' device-name 0 201 set-token
+' my-args 0 202 set-token
+' my-self 0 203 set-token
+' find-package 0 204 set-token
+' open-package 0 205 set-token
+' close-package 0 206 set-token
+' find-method 0 207 set-token
+' call-package 0 208 set-token
+' $call-parent 0 209 set-token
+' my-parent 0 20A set-token
+' ihandle>phandle 0 20B set-token
+' my-unit 0 20D set-token
+' $call-method 0 20E set-token
+' $open-package 0 20F set-token
+' (is-user-word) 0 214 set-token
+' suspend-fcode 0 215 set-token
+\ ' abort 0 216 set-token
+' fc-abort 0 216 set-token
+' catch 0 217 set-token
+' throw 0 218 set-token
+' get-my-property 0 21A set-token
+' decode-int 0 21B set-token
+' decode-string 0 21C set-token
+' get-inherited-property 0 21D set-token
+' delete-property 0 21E set-token
+' get-package-property 0 21F set-token
+' cpeek 0 220 set-token
+' wpeek 0 221 set-token
+' lpeek 0 222 set-token
+' cpoke 0 223 set-token
+' wpoke 0 224 set-token
+' lpoke 0 225 set-token
+' lwflip 0 226 set-token
+' lbflip 0 227 set-token
+' lbflips 0 228 set-token
+' rx@ 0 22E set-token
+' rx! 0 22F set-token
+' rb@ 0 230 set-token
+' rb! 0 231 set-token
+' rw@ 0 232 set-token
+' rw! 0 233 set-token
+' rl@ 0 234 set-token
+' rl! 0 235 set-token
+' wbflips 0 236 set-token
+' lwflips 0 237 set-token
+\ ' probe 0 238 set-token
+\ ' probe-virtual 0 239 set-token
+\ 0 23A reserved
+' child 0 23B set-token
+' peer 0 23C set-token
+' next-property 0 23D set-token
+' byte-load 0 23E set-token
+' set-args 0 23F set-token
+' left-parse-string 0 240 set-token
+' bxjoin 0 241 set-token
+' <l@ 0 242 set-token
+' lxjoin 0 243 set-token
+' wxjoin 0 244 set-token
+' x, 0 245 set-token
+' x@ 0 246 set-token
+' x! 0 247 set-token
+' /x 0 248 set-token
+' /x* 0 249 set-token
+' xa+ 0 24A set-token
+' xa1+ 0 24B set-token
+' xbflip 0 24C set-token
+' xbflips 0 24D set-token
+' xbsplit 0 24E set-token
+' xlflip 0 24F set-token
+' xlflips 0 250 set-token
+' xlsplit 0 251 set-token
+' xwflip 0 252 set-token
+' xwflips 0 253 set-token
+' xwsplit 0 254 set-token
+\ 0 254 RESERVED FCODES
+\ ...
+\ 0 5FF RESERVED FCODES
+
+\ 0 600 VENDOR FCODES
+\ ...
+\ 0 7FF VENDOR FCODES
+
+\ 0 800 LOCAL FCODES
+\ ...
+\ 0 FFF LOCAL FCODES
+
diff --git a/slof/fs/find-hash.fs b/slof/fs/find-hash.fs
index 31ee66f..2d6facf 100644
--- a/slof/fs/find-hash.fs
+++ b/slof/fs/find-hash.fs
@@ -1,30 +1,33 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
-\ A simple little hash table, to speed up compiling. Quite important if
-\ running on a CPU emulator; on real hardware, not so.
-
-CREATE name-hash 20 cells allot
-: clean-hash name-hash 20 cells erase ;
+CREATE name-hash 200 cells allot
+: clean-hash name-hash 200 cells erase ;
clean-hash
-: hash ( str len -- hash ) swap c@ xor 1f and cells name-hash + ;
+\ The hash algorithm (AND with 1f is necessary because of case insensitivity)
+: hash ( str len -- hash )
+ f and 5 lshift swap c@ 1f and xor cells name-hash +
+;
+
: hash-find ( str len head -- 0 | link )
>r 2dup 2dup hash
dup >r @ dup IF link>name name>string string=ci ELSE nip nip THEN
IF 2drop r> @ r> drop exit THEN
r> r> swap >r ((find))
dup IF dup r> ! ELSE r> drop THEN ;
+
: hash-reveal hash off ;
+
' hash-reveal to (reveal)
' hash-find to (find)
diff --git a/slof/fs/generic-disk.fs b/slof/fs/generic-disk.fs
new file mode 100644
index 0000000..bfbcb15
--- /dev/null
+++ b/slof/fs/generic-disk.fs
@@ -0,0 +1,68 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Generic disk support
+
+\ Input:
+\ name of device ( e.g. "disk", "cdrom", ... )
+\ dev#
+
+\ Needs from parent in device tree:
+\ dev-read-blocks ( addr block# #blocks phys.lo ... phys.hi -- #read )
+\ block-size
+\ max-transfer
+
+\ Provides:
+\ open ( -- okay? )
+\ close ( -- )
+\ read ( addr len -- actual )
+\ seek ( pos.lo pos.hi -- status )
+\ read-blocks ( addr block# #blocks -- #read )
+\ Uses:
+\ disk-label package interpose for partition and file systems support
+\ deblocker package for byte read support
+
+( str len phys.lo ... phys.hi -- )
+new-device set-unit ( str len )
+ 2dup device-name
+ s" 0 pci-alias-" 2swap $cat evaluate
+ s" block" device-type
+
+\ Requiered interface for deblocker
+
+ s" block-size" $call-parent CONSTANT block-size
+ s" max-transfer" $call-parent CONSTANT max-transfer
+
+: read-blocks ( addr block# #blocks -- #read )
+ my-unit s" dev-read-blocks" $call-parent
+;
+
+INSTANCE VARIABLE deblocker
+
+: open ( -- okay? )
+ 0 0 s" deblocker" $open-package dup deblocker ! dup IF
+ s" disk-label" find-package IF
+ my-args rot interpose
+ THEN
+ THEN 0<> ;
+
+: close ( -- )
+ deblocker @ close-package ;
+
+: seek ( pos.lo pos.hi -- status )
+ s" seek" deblocker @ $call-method ;
+
+: read ( addr len -- actual )
+ s" read" deblocker @ $call-method ;
+
+finish-device
diff --git a/slof/fs/ide.fs b/slof/fs/ide.fs
index addb885..59c8438 100644
--- a/slof/fs/ide.fs
+++ b/slof/fs/ide.fs
@@ -1,78 +1,625 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+\ 26.06.2007 added: two devices (Master/Slave) per channel
+
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+: decode-unit 1 hex-decode-unit ;
+: encode-unit 1 hex-encode-unit ;
-\ ATA disk.
+0 VALUE >ata \ base address for command-block
+0 VALUE >ata1 \ base address for control block
-\ We run it at PIO mode 0; this is a) not too slow for the sizes we have to
-\ handle, and b) works with all disks.
-\ We assume there is a disk drive connected; however, if not, nothing will
-\ crash.
+true VALUE no-timeout \ flag that no timeout occured
-new-device s" /ht/ata@4,1/disk" full-name
+0c CONSTANT #cdb-bytes \ command descriptor block (12 bytes)
-s" disk" device-name s" block" device-type
+\ *****************************
+\ Some register access helpers.
+\ *****************************
+: ata-ctrl! 2 >ata1 + io-c! ; \ device control reg
+: ata-astat@ 2 >ata1 + io-c@ ; \ read alternate status
+
+: ata-data@ 0 >ata + io-w@ ; \ data reg
+: ata-data! 0 >ata + io-w! ; \ data reg
+: ata-err@ 1 >ata + io-c@ ; \ error reg
+: ata-feat! 1 >ata + io-c! ; \ feature reg
+: ata-cnt@ 2 >ata + io-c@ ; \ sector count reg
+: ata-cnt! 2 >ata + io-c! ; \ sector count reg
+: ata-lbal! 3 >ata + io-c! ; \ lba low reg
+: ata-lbal@ 3 >ata + io-c@ ; \ lba low reg
+: ata-lbam! 4 >ata + io-c! ; \ lba mid reg
+: ata-lbam@ 4 >ata + io-c@ ; \ lba mid reg
+: ata-lbah! 5 >ata + io-c! ; \ lba high reg
+: ata-lbah@ 5 >ata + io-c@ ; \ lba high reg
+: ata-dev! 6 >ata + io-c! ; \ device reg
+: ata-dev@ 6 >ata + io-c@ ; \ device reg
+: ata-cmd! 7 >ata + io-c! ; \ command reg
+: ata-stat@ 7 >ata + io-c@ ; \ status reg
-: open true ;
-: close ;
+\ **********************************************************************
+\ ATA / ATAPI Commands specifications:
+\ - AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
+\ - ATA Packet Interface for CD-ROMs SFF-8020i
+\ - ATA/ATAPI Host Adapters Standard (T13/1510D)
+\ **********************************************************************
+00 CONSTANT cmd#nop \ ATA and ATAPI
+08 CONSTANT cmd#device-reset \ ATAPI only (mandatory)
+20 CONSTANT cmd#read-sector \ ATA and ATAPI
+90 CONSTANT cmd#execute-device-diagnostic \ ATA and ATAPI
+a0 CONSTANT cmd#packet \ ATAPI only (mandatory)
+a1 CONSTANT cmd#identify-packet-device \ ATAPI only (mandatory)
+ec CONSTANT cmd#identify-device \ ATA and ATAPI
-\ Some register access helpers.
-: ata-ctrl! 3f6 io-c! ; \ device control reg
-: ata-data@ 1f0 io-w@ ; \ data reg
-: ata-cnt! 1f2 io-c! ; \ sector count reg
-: ata-lbal! 1f3 io-c! ; \ lba low reg
-: ata-lbam! 1f4 io-c! ; \ lba mid reg
-: ata-lbah! 1f5 io-c! ; \ lba high reg
-: ata-dev! 1f6 io-c! ; \ device reg
-: ata-cmd! 1f7 io-c! ; \ command reg
-: ata-stat@ 1f7 io-c@ ; \ status reg
-
-\ Init controller; we use the master device only.
-02 ata-ctrl!
-00 ata-dev!
-
-CREATE sector 200 allot
-
-: wait-for-ready BEGIN ata-stat@ 80 and WHILE REPEAT ;
-: pio-sector ( addr -- ) 100 0 DO ata-data@ over w! wa1+ LOOP drop ;
-: pio-sector ( addr -- ) wait-for-ready pio-sector ;
+\ *****************************
+\ Setup Regs for ATA:
+\ BAR 0 & 1 : Device 0
+\ BAR 2 & 3 : Device 1
+\ *****************************
+: set-regs ( n -- )
+\ dup ." < Set #" . \ *** DEBUG LINE ****
+ dup
+ 01 and \ only Chan 0 or Chan 1 allowed
+ 3 lshift dup 10 + config-l@ -4 and to >ata
+ 14 + config-l@ -4 and to >ata1
+ 02 and
+ IF
+ 10
+ ELSE
+ 00
+ THEN
+ ata-dev!
+\ >ata ." /" . ata-astat@ ." /" . ." > " \ *** DEBUG LINE ***
+;
+
+ 200 VALUE block-size
+80000 VALUE max-transfer \ Arbitrary, really
+
+CREATE sector d# 512 allot
+CREATE packet-cb #cdb-bytes allot
+CREATE packet-buffer 800 allot
+
+\ ********************************
+\ show all ATAPI-registers
+\ data-register not read in order
+\ to not influence PIO mode
+\ ********************************
+: show-regs
+ cr
+ cr ." alt. Status: " ata-astat@ .
+ cr ." Status : " ata-stat@ .
+ cr ." Device : " ata-dev@ .
+ cr ." Error-Reg : " ata-err@ .
+ cr ." Sect-Count : " ata-cnt@ .
+ cr ." LBA-Low : " ata-lbal@ .
+ cr ." LBA-Med : " ata-lbam@ .
+ cr ." LBA-High : " ata-lbah@ .
+;
+
+\ ***************************************************
+\ reads ATAPI-Status and displays it if check-bit set
+\ ***************************************************
+: status-check ( -- )
+ ata-stat@
+ dup
+ 01 and \ is 'check' flag set ?
+ IF
+ cr
+ ." - ATAPI-Status: " .
+ ata-err@ \ retrieve sense code
+ dup
+ 60 = \ sense code = 6 ?
+ IF
+ ." ( media changed or reset )" \ 'unit attention'
+ drop \ drop err-reg content
+ ELSE
+ ." (Err : " . ." )" \ show err-reg content
+ THEN
+ cr
+ ELSE
+ drop \ remove unused status
+ THEN
+;
+
+\ *************************************
+\ Wait for interface ready condition
+\ Bit 7 of Status-Register is busy flag
+\ new version with abort after 5 sec.
+\ *************************************
+: wait-for-ready
+ get-msecs \ start timer
+ BEGIN
+ ata-stat@ 80 and 0<> \ busy flag still set ?
+ no-timeout and
+ WHILE \ yes
+ dup get-msecs swap
+ - \ calculate timer difference
+ FFFF AND \ reduce to 65.5 seconds
+ d# 5000 > \ difference > 5 seconds ?
+ IF
+ false to no-timeout
+ THEN
+ REPEAT
+ drop
+;
+
+\ *************************************
+\ wait for specific status bits
+\ new version with abort after 5 sec.
+\ *************************************
+: wait-for-status ( val mask -- )
+ get-msecs \ initial timer value (start)
+ >r
+ BEGIN
+ 2dup \ val mask
+ ata-stat@ and <> \ expected status ?
+ no-timeout and \ and no timeout ?
+ WHILE
+ get-msecs r@ - \ calculate timer difference
+ FFFF AND \ mask-off overflow bits
+ d# 5000 > \ 5 seconds exceeded ?
+ IF
+ false to no-timeout \ set global flag
+ THEN
+ REPEAT
+ r> \ clean return stack
+ 3drop
+;
+
+\ *********************************
+\ remove extra spaces from string end
+\ *********************************
+: cut-string ( saddr nul -- )
+ swap
+ over +
+ swap
+ 1 rshift \ bytecount -> wordcount
+ 0 do
+ /w -
+ dup ( addr -- addr addr )
+ w@ ( addr addr -- addr nuw )
+ dup ( addr nuw -- addr nuw nuw )
+ 2020 =
+ IF
+ drop
+ 0
+ ELSE
+ LEAVE
+ THEN
+ over
+ w!
+ LOOP
+ drop
+ drop
+;
+
+\ ****************************************************
+\ prints model-string received by identify device
+\ ****************************************************
+: show-model ( dev# chan# -- )
+ 2dup
+ ." CH " . \ channel 0 / 1
+ 0= IF ." / MA" \ Master / Slave
+ ELSE ." / SL"
+ THEN
+ swap
+ 2 * + ." (@" . ." ) : " \ device number
+ sector 1 +
+ c@
+ 80 AND 0=
+ IF
+ ." ATA-Drive "
+ ELSE
+ ." ATAPI-Drive "
+ THEN
+
+ 22 emit \ start string display with "
+ sector d# 54 + \ string starts 54 bytes from buffer start
+ dup
+ d# 40 \ and is 40 chars long
+ cut-string \ remove all trailing spaces
+
+ BEGIN
+ dup
+ w@
+ wbflip
+ wbsplit
+ dup 0<> \ first char
+ IF
+ emit
+ dup 0<> \ second char
+ IF
+ emit
+ wa1+ \ increment address for next
+ false
+ ELSE \ second char = EndOfString
+ drop
+ true
+ THEN
+ ELSE \ first char = EndOfString
+ drop
+ drop
+ true
+ THEN
+ UNTIL \ end of string detected
+ drop
+ 22 emit \ end string display
+
+ sector c@ \ get lower byte of first doublet
+ 80 AND \ check bit 7
+ IF
+ ." (removable media)"
+ THEN
+
+ sector 1 +
+ c@
+ 80 AND 0= IF \ is this an ATA drive ?
+ sector d# 120 + \ get word 60 + 61
+ rl@-le \ read 32-bit as little endian value
+ d# 1000 / \ bytes -> kbytes (avoid 32-bit overflow)
+ d# 512 * \ LBA = 512 Bytes
+ d# 500 + \ round +- 0.5
+ d# 1000 / \ kB -> MB
+ dup
+ d# 1000 >
+ IF
+ d# 500 +
+ d# 1000 /
+ ." (" .d ." GB)"
+ ELSE
+ ." (" .d ." MB)"
+ THEN
+ THEN
+
+ sector d# 98 + \ goto word 49
+ w@
+ wbflip
+ 200 and 0= IF cr ." ** LBA is not supported " THEN
+
+ sector c@ \ get lower byte of first doublet
+ 03 AND 01 = \ we use 12-byte packet commands (=00b)
+ IF
+ cr ." packet size = 16 ** not supported ! **"
+ THEN
+ no-timeout not \ any timeout occured so far ?
+ IF
+ cr ." ** timeout **"
+ THEN
+;
+
+\ ****************************
+\ ATA functions
+\ ****************************
+: pio-sector ( addr -- ) 100 0 DO ata-data@
+ over w! wa1+ LOOP drop ;
+: pio-sector ( addr -- )
+ wait-for-ready pio-sector ;
: pio-sectors ( n addr -- ) swap 0 ?DO dup pio-sector 200 + LOOP drop ;
-: read-ident ec ata-cmd! 1 sector pio-sectors ;
-read-ident sector d# 54 + d# 40 wbflips
-cr .( Disk drive identifies as: ) sector d# 54 + d# 40 type
+: lba! lbsplit
+ 0f and 40 or \ always set LBA-mode + LBA (27..24)
+ ata-dev@ 10 and or \ add current device-bit (DEV)
+ ata-dev! \ set LBA (27..24)
+ ata-lbah! \ set LBA (23..16)
+ ata-lbam! \ set LBA (15..8)
+ ata-lbal! \ set LBA (7..0)
+;
-: lba! lbsplit f and 40 or ata-dev! ata-lbah! ata-lbam! ata-lbal! ;
-: read-sectors ( lba count addr -- )
+: read-sectors ( lba count addr -- )
>r dup >r ata-cnt! lba! 20 ata-cmd! r> r> pio-sectors ;
-: read-sectors ( lba count addr -- )
- BEGIN >r dup 100 > WHILE
- over 100 R@ read-sectors
- >r 100 + r> 100 - r> 20000 + REPEAT
- r> read-sectors ;
-' read-sectors to disk-read
-200 CONSTANT block-size
-0 VALUE disk-offset
-CREATE deblock 20000 allot
+: read-sectors ( lba count addr dev-nr -- )
+ set-regs ( lba count addr ) \ Set ata regs
+ BEGIN >r dup 100 > WHILE
+ over 100 r@ read-sectors
+ >r 100 + r> 100 - r> 20000 + REPEAT
+ r> read-sectors
+;
+
+: ata-read-blocks ( addr block# #blocks dev# -- #read )
+ swap dup >r swap >r rot r> ( addr block# #blocks dev # R: #blocks )
+ read-sectors r> ( R: #read )
+;
+
+\ *******************************
+\ ATAPI functions
+\ preset LBA register with maximum
+\ allowed block-size (16-bits)
+\ *******************************
+: set-lba ( block-length -- )
+ lbsplit ( quad -- b1.lo b2 b3 b4.hi )
+ drop \ skip upper two bytes
+ drop
+ ata-lbah!
+ ata-lbam!
+;
+
+\ *******************************************
+\ gets byte-count and reads a block of words
+\ from data-register to a buffer
+\ *******************************************
+: read-pio-block ( buff-addr -- buff-addr-new)
+ ata-lbah@ 8 lshift \ get block length High
+ ata-lbam@ or \ get block length Low
+ 1 rshift \ bcount -> wcount
+ dup
+ 0> IF \ any data to transfer?
+ 0 DO \ words to read
+ dup \ buffer-address
+ ata-data@ swap w! \ write 16-bits
+ wa1+ \ address of next entry
+ LOOP
+ ELSE
+ drop ( buff-addr wcount -- buff-addr )
+ THEN
+ wait-for-ready
+;
+
+\ ********************************************
+\ ATAPI support
+\ Send a command block (12 bytes) in PIO mode
+\ read data if requested
+\ ********************************************
+: send-atapi-packet ( req-buffer req-len -- )
+ >r ( req-len R: req-buffer )
+ 800 set-lba \ set regs to length limit
+ 00 ata-feat!
+ cmd#packet ata-cmd! \ A0 = ATAPI packet command
+ 48 C8 wait-for-status ( val mask -- ) \ BSY:0 DRDY:1 DRQ:1
+ 6 0 do
+ packet-cb i 2 * + \ transfer command block (12 bytes)
+ w@
+ ata-data! \ 6 doublets PIO transfer to device
+ loop \ copy packet to data-reg
+ status-check \ status err bit set ? -> display
+ wait-for-ready \ busy released ?
+ BEGIN
+ ata-stat@ 08 and 08 = WHILE \ Data-Request-Bit set ?
+ r> \ get target buffer address
+ read-pio-block \ only if from device requested
+ >r \ start of next block
+ REPEAT
+ r>
+ drop
+;
+
+\ ********************************
+\ ATAPI packet commands
+\ ********************************
+03 CONSTANT scsi-cmd#request-sense
+12 CONSTANT scsi-cmd#inquiry
+28 CONSTANT scsi-cmd#read10
+A8 CONSTANT scsi-cmd#read12
+25 CONSTANT scsi-cmd#read-capacity
+2B CONSTANT scsi-cmd#seek
+
+\ Methods to access atapi disk
+
+: atapi-test ( -- true|false )
+ packet-cb #cdb-bytes erase \ command-code 0
+ packet-buffer send-atapi-packet
+ ata-stat@ 1 and IF false ELSE true THEN
+;
+
+: atapi-sense ( -- ASC sense-key )
+ packet-cb #cdb-bytes erase
+ scsi-cmd#request-sense packet-cb c! \ set command-code 03h
+ 12 packet-cb 4 + c! \ allocation length = 18
+ packet-buffer send-atapi-packet
+ packet-buffer d# 12 + c@ \ additional sense code (ASC)
+ packet-buffer 2 + c@ f and \ sense key
+;
+
+: atapi-inquiry ( -- )
+ packet-cb #cdb-bytes erase \ set command-code 12h
+ scsi-cmd#inquiry packet-cb c!
+ 24 packet-cb 4 + c!
+ packet-buffer send-atapi-packet
+;
+
+: atapi-capacity ( -- )
+ packet-cb #cdb-bytes erase
+ scsi-cmd#read-capacity packet-cb c! \ set command-code 25h
+ packet-buffer send-atapi-packet
+;
+
+: atapi-seek ( offset -- )
+ packet-cb #cdb-bytes erase
+ scsi-cmd#seek packet-cb c! \ set command code 2bh
+ packet-cb 4 + l!
+ packet-buffer send-atapi-packet
+;
+
+: atapi-start ( cmd -- )
+ packet-cb #cdb-bytes erase
+ 1b packet-cb c!
+ packet-cb 4 + c!
+ packet-buffer send-atapi-packet
+;
+
+: atapi-toc ( -- )
+ packet-cb #cdb-bytes erase
+ 43 packet-cb c!
+ 200 packet-cb 7 + w!
+ packet-buffer send-atapi-packet
+;
+
+: atapi-read ( offset cnt -- )
+ packet-cb #cdb-bytes erase
+ scsi-cmd#read10 packet-cb c! \ set command code 28h
+ packet-cb 7 + w! \ 2 bytes: Transfer Length
+ packet-cb 2 + l! \ 4 bytes: Block-Address
+ packet-buffer send-atapi-packet
+;
+
+: atapi-read-blocks ( address block# #blocks dev# -- #read-blocks )
+ set-regs ( dev# -- )
+ dup >r
+ packet-cb #cdb-bytes erase
+ scsi-cmd#read10 packet-cb c! \ set command code 28h
+ packet-cb 7 + w! \ 2 bytes: Transfer Length
+ packet-cb 2 + l! \ 4 bytes: Block-Address
+ send-atapi-packet
+ r>
+;
+
+\ ***********************************************
+\ wait until media in drive is ready ( max 5 sec)
+\ ***********************************************
+: wait-for-media-ready ( -- true|false )
+ get-msecs \ initial timer value (start)
+ >r
+ BEGIN
+ atapi-test \ unit ready? false if not
+ not
+ no-timeout and
+ WHILE
+ atapi-sense ( -- asc sensekey )
+ 02 = \ sense key 2 = media error
+ IF \ check add. sense code
+ 3A = IF false to no-timeout ." empty" THEN \ medium not present, abort waiting
+ ELSE
+ drop \ discard add. sense code
+ THEN
+ get-msecs r@ - \ calculate timer difference
+ FFFF AND \ mask-off overflow bits
+ d# 5000 > \ 5 seconds exceeded ?
+ IF
+ false to no-timeout \ set global flag
+ THEN
+ REPEAT
+ r>
+ drop
+ no-timeout
+;
+
+\ ******************************************************
+\ Method pointer for read-blocks methods
+\ controller implements 2 channels (primary / secondary)
+\ for 2 devices each (master / slasve)
+\ ******************************************************
+\ 2 channels (primary/secondary) per controller
+2 CONSTANT #chan
+
+\ 2 devices (master/slacve) per channel
+2 CONSTANT #dev
+
+\ results in a total of devices
+\ connected to a controller with
+\ two separate channels (4)
+: #totaldev #dev #chan * ;
+
+CREATE read-blocks-xt #totaldev cells allot read-blocks-xt #totaldev cells erase
+
+\ Execute read-blocks of device
+: dev-read-blocks ( address block# #blocks dev# -- #read-blocks )
+ dup cells read-blocks-xt + @ execute
+;
+
+\ **********************************************************
+\ Read device type
+\ Signature ATAPI ATA
+\ ---------------------------------------------
+\ Sector Count 01h 01h
+\ Sector Number 01h 01h
+\ Cylinder Low 14h 00h
+\ Cylinder High EBh 00h
+\ Device/Head 00h or 10h 00h or 01h
+\ see also ATA/ATAPI errata at:
+\ http://suif.stanford.edu/~csapuntz/blackmagic.html
+\ **********************************************************
+: read-ident ( -- true|false )
+ false
+ 00 ata-lbal! \ clear previous signature
+ 00 ata-lbam!
+ 00 ata-lbah!
+ cmd#identify-device ata-cmd! wait-for-ready \ first try ATA, ATAPI aborts command
+ ata-stat@ CF and 48 =
+ IF
+ drop true \ cmd accepted, this is a ATA
+ d# 512 set-lba \ set LBA to sector-length
+ ELSE \ ATAPI sends signature instead
+ ata-lbam@ 14 = IF \ cylinder low = 14 ?
+ ata-lbah@ EB = IF \ cylinder high = EB ?
+ cmd#device-reset ata-cmd! wait-for-ready \ only supported by ATAPI
+ cmd#identify-packet-device ata-cmd! wait-for-ready \ first try ata
+ ata-stat@ CF and 48 = IF
+ drop true \ replace flag
+ THEN
+ THEN
+ THEN
+ THEN
+ dup IF
+ ata-stat@ 8 AND IF \ data requested (as expected) ?
+ sector read-pio-block
+ drop \ discard address end
+ ELSE
+ drop false
+ THEN
+ THEN
+
+ no-timeout not IF \ check without any timeout ?
+ drop
+ false \ no, detection discarded
+ THEN
+;
-: seek ( lo hi -- status ) 20 lshift or to disk-offset 1 ;
+\ *************************************************
+\ Init controller ( chan 0 and 1 )
+\ device 0 (= master) and device 1 ( = slave)
+\ #dev #chan Dev-ID
+\ ----------------------
+\ 0 0 0 Master of Channel 0
+\ 0 1 1 Master of Channel 1
+\ 1 0 2 Slave of Channel 0
+\ 1 1 3 Slave of Channel 1
+\ *************************************************
-: read ( str len -- len' ) \ max 20000 bytes
- disk-offset 200 / over disk-offset + 1ff + 200 / over - deblock disk-read
- >r deblock disk-offset 1ff and + swap r@ move r>
- disk-offset over + to disk-offset ;
+: find-disks ( -- )
+ #chan 0 DO \ check 2 channels (primary & secondary)
+ #dev 0 DO \ check 2 devices per channel (master / slave)
+ i 2 * j + set-regs \ set base address and dev-register for register access
+ 02 ata-ctrl! \ disable interrupts
+ ata-stat@ 7f and 7f <> \ Check, if device is connected
+ IF
+ true to no-timeout \ preset timeout-flag
+ read-ident ( -- true|false )
+ IF
+ i j show-model \ print manufacturer + device string
+ sector 1+ c@ C0 and 80 = \ Check for ata or atapi
+ IF
+ wait-for-media-ready \ wait up to 5 sec if not ready
+ no-timeout and
+ IF
+ 800 to block-size \ ATAPI: 2048 bytes
+ 80000 to max-transfer
+ ['] atapi-read-blocks i 2 * j + cells read-blocks-xt + !
+ s" cdrom" strdup i 2 * j + s" generic-disk.fs" included
+ ELSE
+ ." -" \ show hint for not registered
+ THEN
+ ELSE
+ 200 to block-size \ ATA: 512 bytes
+ 80000 to max-transfer
+ ['] ata-read-blocks i 2 * j + cells read-blocks-xt + !
+ s" disk" strdup i 2 * j + s" generic-disk.fs" included
+ THEN
+ cr
+ THEN
+ THEN
+ LOOP
+ LOOP
+;
-: read ( str len -- len' )
- dup >r BEGIN dup WHILE 2dup 20000 min read tuck - >r + r> REPEAT 2drop r> ;
+find-disks
-finish-device
diff --git a/slof/fs/instance.fs b/slof/fs/instance.fs
index f5b480b..22be971 100644
--- a/slof/fs/instance.fs
+++ b/slof/fs/instance.fs
@@ -1,36 +1,36 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
\ Support for device node instances.
0 VALUE my-self
-\ Instance-init is a linked list, before finish-package.
-\ entry format: offset in instance, link, initial value.
-\ after finish-package it's a pointer to a memory block
-\ that is copied verbatim for every instance.
-\ This will have to be revisited, as it is not quite right:
-\ an instance variable can be used before the package is
-\ completed.
+: >instance
+ my-self 0= ABORT" No instance!"
+ my-self +
+;
-: (create-instance-var) ( "name" initial-value link-addr size-addr -- )
- CREATE dup @ , 1 cells swap +! linked , ;
+: (create-instance-var) ( initial-value -- )
+ get-node ?dup 0= ABORT" Instance word outside device context!"
+ dup node>instance @ ( iv phandle tmp-ihandle )
+ swap node>instance-size dup @ ( iv tmp-ih *instance-size instance-size )
+ dup , \ compile current instance ptr
+ swap 1 cells swap +! ( iv tmp-ih instance-size )
+ + !
+;
: create-instance-var ( "name" initial-value -- )
- current-package @ dup pkg>instance-init swap pkg>instance-size
- (create-instance-var) PREVIOUS DEFINITIONS ;
-
-: >instance my-self + ;
+ CREATE (create-instance-var) PREVIOUS ;
VOCABULARY instance-words ALSO instance-words DEFINITIONS
@@ -41,54 +41,90 @@ VOCABULARY instance-words ALSO instance-words DEFINITIONS
PREVIOUS DEFINITIONS
-: INSTANCE current-package @ 0= ABORT" No current package"
- ALSO instance-words ;
-
-VARIABLE shared-instance-link
-VARIABLE shared-instance-size
-
-: SIVARIABLE 0 shared-instance-link shared-instance-size (create-instance-var)
- DOES> @ >instance ;
-
-VOCABULARY shared-instance-vars ALSO shared-instance-vars DEFINITIONS
-
-SIVARIABLE the-package \ needs to be first!
-SIVARIABLE the-parent
-SIVARIABLE the-addr
-SIVARIABLE the-addr1
-SIVARIABLE the-addr2
-SIVARIABLE the-args
-SIVARIABLE the-args-len
-
-PREVIOUS DEFINITIONS
-: shared-instance-words ['] shared-instance-vars >body cell+ @ ;
-
-
-ALSO shared-instance-vars
-
-: my-parent the-parent @ ;
-: my-args the-args 2@ ;
-: set-my-args dup alloc-mem swap 2dup the-args 2! move ;
-
-\ Current package has already been set, when this is called.
+\ check whether a value or a defer word is an
+\ instance word: It must be a CREATE word and
+\ the DOES> part must do >instance as first thing
+
+: (instance?) ( xt -- xt true|false )
+ dup @ <create> = IF
+ dup cell+ @ cell+ @ ['] >instance =
+ ELSE
+ false
+ THEN
+;
+
+\ This word does instance values in compile mode.
+\ It corresponds to DOTO from engine.in
+: (doito) ( value R:*CFA -- )
+ r> cell+ dup >r
+ @ cell+ cell+ @ >instance !
+;
+
+: to ( value wordname<> -- )
+ ' (instance?)
+ state @ IF
+ \ compile mode handling normal or instance value
+ IF ['] (doito) ELSE ['] DOTO THEN
+ , , EXIT
+ THEN
+ IF
+ cell+ cell+ @ >instance ! \ interp mode instance value
+ ELSE
+ cell+ ! \ interp mode normal value
+ THEN
+; IMMEDIATE
+
+: INSTANCE ALSO instance-words ;
+
+
+STRUCT
+/n FIELD instance>node
+/n FIELD instance>parent
+/n FIELD instance>args
+/n FIELD instance>args-len
+CONSTANT /instance-header
+
+: my-parent my-self instance>parent @ ;
+: my-args my-self instance>args 2@ ;
+
+\ copy args from original instance to new created
+: set-my-args ( old-addr len -- )
+ dup IF \ IF len > 0 ( old-addr len )
+ dup alloc-mem \ | allocate space for new args ( old-addr len new-addr )
+ swap 2dup \ | write the new address ( old-addr new-addr len new-addr len )
+ my-self instance>args 2! \ | into the instance table ( old-addr new-addr len )
+ move \ | and copy the args ( -- )
+ ELSE \ ELSE ( old-addr len )
+ my-self instance>args 2! \ | set new args to zero, too ( )
+ THEN \ FI
+;
+
+\ Current node has already been set, when this is called.
: create-instance-data ( -- instance )
- current-package @ dup pkg>instance-init @ swap pkg>instance-size @
- dup alloc-mem dup >r swap move r> ;
-: create-instance my-self create-instance-data to my-self the-parent !
- current-package @ the-package ! ;
-: destroy-instance ( instance -- )
- dup @ pkg>instance-size @ free-mem ;
-
-PREVIOUS
+ get-node dup node>instance @ swap node>instance-size @ ( instance instance-size )
+ dup alloc-mem dup >r swap move r>
+;
+: create-instance ( -- )
+ my-self create-instance-data
+ dup to my-self instance>parent !
+ get-node my-self instance>node !
+;
+: destroy-instance ( instance -- )
+ dup @ node>instance-size @ free-mem
+;
-: ihandle>phandle @ ;
+: ihandle>phandle ( ihandle -- phandle )
+ dup 0= ABORT" no current instance" instance>node @
+;
: push-my-self ( ihandle -- ) r> my-self >r >r to my-self ;
: pop-my-self ( -- ) r> r> to my-self >r ;
: call-package push-my-self execute pop-my-self ;
-: $call-my-method ( str len -- ) my-self ihandle>phandle find-method
- 0= ABORT" no such method" execute ;
+: $call-static ( ... str len node -- ??? )
+\ cr ." call for " 3dup -rot type ." on node " .
+ find-method IF execute ELSE -1 throw THEN
+;
+: $call-my-method ( str len -- ) my-self ihandle>phandle $call-static ;
: $call-method push-my-self $call-my-method pop-my-self ;
: $call-parent my-parent $call-method ;
-
diff --git a/slof/fs/little-endian.fs b/slof/fs/little-endian.fs
new file mode 100644
index 0000000..76ce370
--- /dev/null
+++ b/slof/fs/little-endian.fs
@@ -0,0 +1,72 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+deadbeef here l!
+here c@ de = CONSTANT ?bigendian
+here c@ ef = CONSTANT ?littleendian
+
+
+?bigendian [IF]
+
+: l!-le >r lbflip r> l! ;
+: l@-le l@ lbflip ;
+
+: w!-le >r wbflip r> w! ;
+: w@-le w@ wbflip ;
+
+: rl!-le >r lbflip r> rl! ;
+: rl@-le rl@ lbflip ;
+
+: rw!-le >r wbflip r> rw! ;
+: rw@-le rw@ wbflip ;
+
+: l!-be l! ;
+: l@-be l@ ;
+
+: w!-be w! ;
+: w@-be w@ ;
+
+: rl!-be rl! ;
+: rl@-be rl@ ;
+
+: rw!-be rw! ;
+: rw@-be rw@ ;
+
+
+[ELSE]
+
+: l!-le l! ;
+: l@-le l@ ;
+
+: w!-le w! ;
+: w@-le w@ ;
+
+: rl!-le rl! ;
+: rl@-le rl@ ;
+
+: rw!-le rw! ;
+: rw@-le rw@ ;
+
+: l!-be >r lbflip r> l! ;
+: l@-be l@ lbflip ;
+
+: w!-be >r wbflip r> w! ;
+: w@-be w@ wbflip ;
+
+: rl!-be >r lbflip r> rl! ;
+: rl@-be rl@ lbflip ;
+
+: rw!-be >r wbflip r> rw! ;
+: rw@-be rw@ wbflip ;
+
+[THEN]
+
diff --git a/slof/fs/loaders.fs b/slof/fs/loaders.fs
new file mode 100644
index 0000000..b799692
--- /dev/null
+++ b/slof/fs/loaders.fs
@@ -0,0 +1,71 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+: start-elf ( arg len entry -- )
+ msr@ 7fffffffffffffff and 2000 or ciregs >srr1 ! call-client ;
+
+: start-elf64 ( arg len entry -- )
+ msr@ 2000 or ciregs >srr1 !
+ dup 8 + @ ciregs >r2 ! @ call-client ; \ entry point is pointer to .opd
+
+10000000 VALUE LOAD-BASE
+2000000 VALUE FLASH-LOAD-BASE
+
+: set-bootpath s" disk" find-alias
+ dup IF ELSE drop s" boot-device" evaluate find-alias THEN
+ dup IF strdup ELSE 0 THEN
+ encode-string s" bootpath" set-chosen ;
+
+: set-netbootpath s" net" find-alias
+ ?dup IF strdup encode-string s" bootpath" set-chosen THEN ;
+
+: set-bootargs skipws 0 parse dup 0= IF 2drop s" boot-file"
+ evaluate THEN encode-string s" bootargs" set-chosen ;
+
+: .(client-exec) ( arg len -- rc )
+ s" snk" romfs-lookup 0<> IF load-elf-file drop start-elf64 client-data
+ ELSE 2drop false THEN ;
+' .(client-exec) to (client-exec)
+
+: .client-exec ( arg len -- rc ) set-bootargs (client-exec) ;
+' .client-exec to client-exec
+
+: netflash ( -- rc ) s" netflash 2000000 " (parse-line) $cat set-netbootpath
+ client-exec ;
+
+: netsave ( "addr len {filename}[,params]" -- rc )
+ (parse-line) dup 0> IF
+ s" netsave " 2swap $cat set-netbootpath client-exec
+ ELSE
+ cr
+ ." Usage: netsave addr len [bootp|dhcp,]filename[,siaddr][,ciaddr][,giaddr][,bootp-retries][,tftp-retries][,use_ci]"
+ cr 2drop
+ THEN
+;
+
+: ping ( "{device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout]}" -- )
+ my-self >r current-node @ >r \ Save my-self
+ (parse-line) open-dev dup IF
+ dup to my-self dup ihandle>phandle set-node
+ s" ping" rot ['] $call-method CATCH IF
+ cr
+ ." Not a pingable device"
+ cr 3drop
+ THEN
+ ELSE
+ cr
+ ." Usage: ping device-path:[device-args,]server-ip,[client-ip],[gateway-ip][,timeout]"
+ cr drop
+ THEN
+ r> set-node r> to my-self \ Restore my-self
+;
diff --git a/slof/fs/logging.fs b/slof/fs/logging.fs
new file mode 100644
index 0000000..293a013
--- /dev/null
+++ b/slof/fs/logging.fs
@@ -0,0 +1,41 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ Words to write to nvram log
+
+defer nvramlog-write-byte
+
+: .nvramlog-write-byte ( byte -- )
+#ifndef DISABLE_NVRAM
+ 0 1 asm-cout
+#else
+ drop
+#endif
+;
+
+' .nvramlog-write-byte to nvramlog-write-byte
+
+: nvramlog-write-string ( str len -- )
+ 0 DO dup c@
+ nvramlog-write-byte char+ LOOP drop ;
+
+: nvramlog-write-number ( number format -- )
+ 0 swap <# 0 ?DO # LOOP #>
+ nvramlog-write-string ;
+
+: nvramlog-write-string-cr ( str len -- )
+ nvramlog-write-string
+ a nvramlog-write-byte d nvramlog-write-byte ;
+
+\ as long as dual-emit is enabled
+\ the string is written into NVRAM as well!!
+: log-string ( str len -- ) type ;
diff --git a/slof/fs/node.fs b/slof/fs/node.fs
new file mode 100644
index 0000000..4ae52b0
--- /dev/null
+++ b/slof/fs/node.fs
@@ -0,0 +1,663 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Device nodes.
+
+VARIABLE device-tree
+VARIABLE current-node
+: get-node current-node @ dup 0= ABORT" No active device tree node" ;
+
+STRUCT
+ cell FIELD node>peer
+ cell FIELD node>parent
+ cell FIELD node>child
+ cell FIELD node>properties
+ cell FIELD node>words
+ cell FIELD node>instance
+ cell FIELD node>instance-size
+ cell FIELD node>space?
+ cell FIELD node>space
+ cell FIELD node>addr1
+ cell FIELD node>addr2
+ cell FIELD node>addr3
+END-STRUCT
+
+: find-method ( str len phandle -- false | xt true )
+ node>words @ voc-find dup IF link> true THEN ;
+
+\ Instances.
+#include "instance.fs"
+
+1000 CONSTANT max-instance-size
+3000000 CONSTANT space-code-mask
+
+: create-node ( parent -- new )
+ max-instance-size alloc-mem dup max-instance-size erase >r
+ align wordlist >r wordlist >r
+ here 0 , swap , 0 , r> , r> , r> , /instance-header , 0 , 0 , 0 , 0 , ;
+
+: peer node>peer @ ;
+: parent node>parent @ ;
+: child node>child @ ;
+: peer dup IF peer ELSE drop device-tree @ THEN ;
+
+
+: link ( new head -- ) \ link a new node at the end of a linked list
+ BEGIN dup @ WHILE @ REPEAT ! ;
+: link-node ( parent child -- )
+ swap dup IF node>child link ELSE drop device-tree ! THEN ;
+
+\ Set a node as active node.
+: set-node ( phandle -- )
+ current-node @ IF previous THEN
+ dup current-node !
+ ?dup IF node>words @ also context ! THEN
+ definitions ;
+: get-parent get-node parent ;
+
+
+: new-node ( -- phandle ) \ active node becomes new node's parent;
+ \ new node becomes active node
+\ XXX: change to get-node, handle root node creation specially
+ current-node @ dup create-node
+ tuck link-node dup set-node ;
+
+: finish-node ( -- )
+\ we should resize the instance template buffer, but that doesn't help with our
+\ current implementation of alloc-mem anyway, so never mind. XXX
+ get-node parent set-node ;
+
+: device-end ( -- ) 0 set-node ;
+
+\ Properties.
+CREATE $indent 100 allot VARIABLE indent 0 indent !
+#include "property.fs"
+
+\ Unit address.
+: #address-cells s" #address-cells" rot parent get-property
+ ABORT" parent doesn't have a #address-cells property!"
+ decode-int nip nip ;
+: my-#address-cells get-node #address-cells ; \ bit of a misnomer... "my-"
+
+: encode-phys ( phys.hi ... phys.low -- str len )
+ encode-first? IF encode-start ELSE here 0 THEN
+ my-#address-cells 0 ?DO rot encode-int+ LOOP ;
+
+: decode-phys
+ my-#address-cells BEGIN dup WHILE 1- >r decode-int r> swap >r REPEAT drop
+ my-#address-cells BEGIN dup WHILE 1- r> swap REPEAT drop ;
+: decode-phys-and-drop
+ my-#address-cells BEGIN dup WHILE 1- >r decode-int r> swap >r REPEAT 3drop
+ my-#address-cells BEGIN dup WHILE 1- r> swap REPEAT drop ;
+: reg >r encode-phys r> encode-int+ s" reg" property ;
+
+
+: >space node>space @ ;
+: >space? node>space? @ ;
+: >address dup >r #address-cells dup 3 > IF r@ node>addr3 @ swap THEN
+ dup 2 > IF r@ node>addr2 @ swap THEN
+ 1 > IF r@ node>addr1 @ THEN r> drop ;
+: >unit dup >r >address r> >space ;
+
+: my-space ( -- phys.hi )
+ my-self ihandle>phandle >space ;
+: my-address my-self ihandle>phandle >address ;
+: my-unit my-self ihandle>phandle >unit ;
+
+\ Return lower 64 bit of address
+: my-unit-64 ( -- phys.lo+1|phys.lo )
+ my-unit ( phys.lo ... phys.hi )
+ my-self ihandle>phandle #address-cells ( phys.lo ... phys.hi #ad-cells )
+ CASE
+ 1 OF EXIT ENDOF
+ 2 OF lxjoin EXIT ENDOF
+ 3 OF drop lxjoin EXIT ENDOF
+ dup OF 2drop lxjoin EXIT ENDOF
+ ENDCASE
+;
+
+: set-space get-node dup >r node>space ! true r> node>space? ! ;
+: set-address my-#address-cells 1 ?DO
+ get-node node>space i cells + ! LOOP ;
+: set-unit set-space set-address ;
+: set-unit-64 ( phys.lo|phys.hi -- )
+ my-#address-cells 2 <> IF
+ ." set-unit-64: #address-cells <> 2 " abort
+ THEN
+ xlsplit set-unit
+;
+
+\ Never ever use this in actual code, only when debugging interactively.
+\ Thank you.
+: set-args ( arg-str len unit-str len -- )
+ s" decode-unit" get-parent $call-static set-unit set-my-args ;
+
+: $cat-unit dup parent 0= IF drop EXIT THEN
+ dup >space? not IF drop EXIT THEN
+ dup >r >unit s" encode-unit" r> parent $call-static dup IF
+ dup >r here swap move s" @" $cat here r> $cat
+ ELSE 2drop THEN ;
+
+\ Getting basic info about a node.
+: node>name dup >r s" name" rot get-property IF r> (u.) ELSE 1- r> drop THEN ;
+: node>qname dup node>name rot ['] $cat-unit CATCH IF drop THEN ;
+: node>path here 0 rot BEGIN dup WHILE dup parent REPEAT 2drop
+ dup 0= IF [char] / c, THEN
+ BEGIN dup WHILE [char] / c, node>qname here over allot swap move
+ REPEAT drop here 2dup - allot over - ;
+
+: interposed? ( ihandle -- flag )
+ \ We cannot actually detect if an instance is interposed; instead, we look
+ \ if an instance is part of the "normal" chain that would be opened by
+ \ open-dev and friends, if there were no interposition.
+ dup instance>parent @ dup 0= IF 2drop false EXIT THEN
+ ihandle>phandle swap ihandle>phandle parent <> ;
+: instance>qname dup >r interposed? IF s" %" ELSE 0 0 THEN
+ r@ ihandle>phandle node>qname $cat r> instance>args 2@
+ dup IF 2>r s" :" $cat 2r> $cat ELSE 2drop THEN ;
+: instance>qpath \ With interposed nodes.
+ here 0 rot BEGIN dup WHILE dup instance>parent @ REPEAT 2drop
+ dup 0= IF [char] / c, THEN
+ BEGIN dup WHILE [char] / c, instance>qname here over allot swap move
+ REPEAT drop here 2dup - allot over - ;
+: instance>path \ Without interposed nodes.
+ here 0 rot BEGIN dup WHILE
+ dup interposed? 0= IF dup THEN instance>parent @ REPEAT 2drop
+ dup 0= IF [char] / c, THEN
+ BEGIN dup WHILE [char] / c, instance>qname here over allot swap move
+ REPEAT drop here 2dup - allot over - ;
+
+: .node node>path type ;
+: pwd get-node .node ;
+
+: .instance instance>qpath type ;
+: .chain dup instance>parent @ ?dup IF recurse THEN
+ cr dup . instance>qname type ;
+
+
+\ Alias helper
+defer find-node
+: set-alias ( alias-name len device-name len -- )
+ encode-string
+ 2swap s" /aliases" find-node dup IF set-property ELSE drop THEN ;
+
+: find-alias ( alias-name len -- false | dev-path len )
+ s" /aliases" find-node dup IF
+ get-property 0= IF 1- dup 0= IF nip THEN ELSE false THEN
+ THEN ;
+
+: .alias ( alias-name len -- )
+ find-alias dup IF type ELSE ." no alias available" THEN ;
+
+: (.print-alias) ( lfa -- )
+ link> dup >name name>string
+ \ Don't print name property
+ 2dup s" name" string=ci IF 2drop drop
+ ELSE cr type space ." : " execute type
+ THEN ;
+
+: (.list-alias) ( phandle -- )
+ node>properties @ cell+ @ BEGIN dup WHILE dup (.print-alias) @ REPEAT drop ;
+
+: list-alias ( -- )
+ s" /aliases" find-node dup IF (.list-alias) THEN ;
+
+: devalias ( "{alias-name}<>{device-specifier}<cr>" -- )
+ parse-word parse-word dup IF set-alias
+ ELSE 2drop dup IF .alias
+ ELSE 2drop list-alias THEN THEN ;
+
+\ sub-alias does a single iteration of an alias at the begining od dev path
+\ expression. de-alias will repeat this until all indirect alising is resolved
+: sub-alias ( arg-str arg-len -- arg' len' | false )
+ 2dup
+ 2dup [char] / findchar ?dup IF ELSE 2dup [char] : findchar THEN
+ ( a l a l [p] -1|0 ) IF nip dup ELSE 2drop 0 THEN >r
+ ( a l l p -- R:p | a l -- R:0 )
+ find-alias ?dup IF ( a l a' p' -- R:p | a' l' -- R:0 )
+ r@ IF 2swap r@ - swap r> + swap $cat strdup ( a" l-p+p' -- )
+ ELSE ( a' l' -- R:0 ) r> drop ( a' l' -- ) THEN
+ ELSE ( a l -- R:p | -- R:0 ) r> IF 2drop THEN false ( 0 -- ) THEN
+;
+
+: de-alias ( arg-str arg-len -- arg' len' )
+ BEGIN over c@ [char] / <> dup IF drop 2dup sub-alias ?dup THEN
+ WHILE 2swap 2drop REPEAT
+;
+
+
+\ Display the device tree.
+: +indent ( not-last? -- )
+ IF s" | " ELSE s" " THEN $indent indent @ + swap move 4 indent +! ;
+: -indent ( -- ) -4 indent +! ;
+: ls-node ( node -- )
+ cr $indent indent @ type
+ dup peer IF ." |-- " ELSE ." +-- " THEN node>qname type ;
+: (ls) ( node -- )
+ child BEGIN dup WHILE dup ls-node dup child IF
+ dup peer +indent dup recurse -indent THEN peer REPEAT drop ;
+: ls ( -- ) get-node dup cr node>path type (ls) 0 indent ! ;
+
+: show-devs ( {device-specifier}<eol> -- )
+ skipws 0 parse dup IF de-alias ELSE 2drop s" /" THEN ( str len )
+ find-node dup 0= ABORT" No such device path" (ls)
+;
+
+
+VARIABLE interpose-node
+2VARIABLE interpose-args
+: interpose ( arg len phandle -- ) interpose-node ! interpose-args 2! ;
+: open-node ( arg len phandle -- ihandle | 0 )
+ current-node @ >r set-node create-instance set-my-args
+ ( and set unit-addr )
+\ XXX: assume default of success for nodes without open method
+ s" open" ['] $call-my-method CATCH IF 2drop true THEN
+ 0= IF my-self destroy-instance 0 to my-self THEN
+ my-self my-parent to my-self r> set-node
+ \ Handle interposition.
+ interpose-node @ IF my-self >r to my-self
+ interpose-args 2@ interpose-node @
+ interpose-node off recurse r> to my-self THEN ;
+: close-node ( ihandle -- )
+ my-self >r to my-self
+ s" close" ['] $call-my-method CATCH IF 2drop THEN
+ my-self destroy-instance r> to my-self ;
+
+: close-dev ( ihandle -- )
+ my-self >r to my-self
+ BEGIN my-self WHILE my-parent my-self close-node to my-self REPEAT
+ r> to my-self ;
+
+: new-device ( -- )
+ my-self new-node node>instance @ dup to my-self instance>parent !
+ get-node my-self instance>node ! ;
+: finish-device ( -- )
+ ( check for "name" property here, delete this node if not there )
+ finish-node my-parent my-self max-instance-size free-mem to my-self ;
+
+: split ( str len char -- left len right len )
+ >r 2dup r> findchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ;
+: generic-decode-unit ( str len ncells -- addr.lo ... addr.hi )
+ dup >r -rot BEGIN r@ WHILE r> 1- >r [char] , split 2swap
+ $number IF 0 THEN r> swap >r >r REPEAT r> 3drop
+ BEGIN dup WHILE 1- r> swap REPEAT drop ;
+: generic-encode-unit ( addr.lo ... addr.hi ncells -- str len )
+ 0 0 rot ?dup IF 0 ?DO rot (u.) $cat s" ," $cat LOOP 1- THEN ;
+: hex-decode-unit ( str len ncells -- addr.lo ... addr.hi )
+ base @ >r hex generic-decode-unit r> base ! ;
+: hex-encode-unit ( addr.lo ... addr.hi ncells -- str len )
+ base @ >r hex generic-encode-unit r> base ! ;
+
+: handle-leading-/ ( path len -- path' len' )
+ dup IF over c@ [char] / = IF 1 /string device-tree @ set-node THEN THEN ;
+: match-name ( name len node -- match? )
+ over 0= IF 3drop true EXIT THEN
+ s" name" rot get-property IF 2drop false EXIT THEN
+ 1- string=ci ; \ XXX should use decode-string
+0 VALUE #search-unit CREATE search-unit 4 cells allot
+: match-unit ( node -- match? )
+ node>space search-unit #search-unit 0 ?DO 2dup @ swap @ <> IF
+ 2drop false UNLOOP EXIT THEN cell+ swap cell+ swap LOOP 2drop true ;
+: match-node ( name len node -- match? )
+ dup >r match-name r> match-unit and ; \ XXX e3d
+: find-kid ( name len -- node|0 )
+ dup -1 = IF \ are we supposed to stay in the same node? -> resolve-relatives
+ 2drop get-node
+ ELSE
+ get-node child >r BEGIN r@ WHILE 2dup r@ match-node
+ IF 2drop r> EXIT THEN r> peer >r REPEAT
+ r> 3drop false
+ THEN ;
+: set-search-unit ( unit len -- )
+ dup 0= IF to #search-unit drop EXIT THEN
+ s" #address-cells" get-node get-property THROW
+ decode-int to #search-unit 2drop
+ s" decode-unit" get-node $call-static
+ #search-unit 0 ?DO search-unit i cells + ! LOOP ;
+: resolve-relatives ( path len -- path' len' )
+ \ handle ..
+ 2dup 2 = swap s" .." comp 0= and IF
+ get-node parent ?dup IF
+ set-node drop -1
+ ELSE
+ s" Already in root node." type
+ THEN
+ THEN
+ \ handle .
+ 2dup 1 = swap c@ [CHAR] . = and IF
+ drop -1
+ THEN
+ ;
+: find-component ( path len -- path' len' args len node|0 )
+ [char] / split 2swap ( path'. component. )
+ [char] : split 2swap ( path'. args. node-addr. )
+ [char] @ split ['] set-search-unit CATCH IF 2drop 2drop 0 EXIT THEN
+ resolve-relatives find-kid ;
+
+: .find-node ( path len -- phandle|0 )
+ current-node @ >r
+ handle-leading-/ current-node @ 0= IF 2drop r> set-node 0 EXIT THEN
+ BEGIN dup WHILE \ handle one component:
+ find-component ( path len args len node ) dup 0= IF
+ 3drop 2drop r> set-node 0 EXIT THEN
+ set-node 2drop REPEAT 2drop
+ get-node r> set-node ;
+' .find-node to find-node
+: find-node ( path len -- phandle|0 ) de-alias find-node ;
+
+: delete-node ( phandle -- )
+ dup node>parent @ node>child @ ( phandle 1st peer )
+ 2dup = IF
+ node>peer @ swap node>parent @ node>child !
+ EXIT
+ THEN
+ dup node>peer @
+ BEGIN 2 pick 2dup <> WHILE
+ drop
+ nip dup node>peer @
+ dup 0= IF 2drop drop unloop EXIT THEN
+ REPEAT
+ drop
+ node>peer @ swap node>peer !
+ drop
+;
+
+
+: open-dev ( path len -- ihandle|0 )
+ de-alias current-node @ >r
+ handle-leading-/ current-node @ 0= IF 2drop r> set-node 0 EXIT THEN
+ my-self >r 0 to my-self
+ 0 0 >r >r BEGIN dup WHILE \ handle one component:
+ ( arg len ) r> r> get-node open-node to my-self
+ find-component ( path len args len node ) dup 0= IF
+ 3drop 2drop my-self close-dev r> to my-self r> set-node 0 EXIT THEN
+ set-node >r >r REPEAT 2drop
+ \ open final node
+ r> r> get-node open-node to my-self
+ my-self r> to my-self r> set-node ;
+: select-dev open-dev dup to my-self ihandle>phandle set-node ;
+
+: find-device ( str len -- ) \ set as active node
+ find-node dup 0= ABORT" No such device path" set-node ;
+: dev skipws 0 parse find-device ;
+
+: (lsprop) ( node --)
+ dup cr $indent indent @ type ." node: " node>qname type
+ false +indent (.properties) cr -indent ;
+: (show-children) ( node -- )
+ child BEGIN dup WHILE
+ dup (lsprop) dup child IF false +indent dup recurse -indent THEN peer
+ REPEAT drop
+;
+: lsprop ( {device-specifier}<eol> -- )
+ skipws 0 parse dup IF de-alias ELSE 2drop s" /" THEN
+ find-device get-node dup dup
+ cr ." node: " node>path type (.properties) cr (show-children) 0 indent ! ;
+
+
+\ node>path does not allot the memory, since it is internally only used
+\ for typing.
+\ The external variant needs to allot memory !
+
+: (node>path) node>path ;
+
+: node>path ( phandle -- str len )
+ node>path dup allot
+;
+
+\ Support for support packages.
+
+\ The /packages node.
+0 VALUE packages
+
+\ We can't use the standard find-node stuff, as we are required to find the
+\ newest (i.e., last in our tree) matching package, not just any.
+: find-package ( name len -- false | phandle true )
+ 0 >r packages child BEGIN dup WHILE dup >r node>name 2over string=ci r> swap
+ IF r> drop dup >r THEN peer REPEAT 3drop r> dup IF true THEN ;
+
+: open-package ( arg len phandle -- ihandle | 0 ) open-node ;
+: close-package ( ihandle -- ) close-node ;
+: $open-package ( arg len name len -- ihandle | 0 )
+ find-package IF open-package ELSE 2drop false THEN ;
+
+
+\ Pseudocode in C Syntax
+\ if((addr>=child)&&(addr<=child+size)
+\ return (addr - child) + parent
+\ else return false
+\
+: translate-range ( child parent size addr -- taddr true | addr false )
+ swap 3 pick + over \ calculate child+size address
+ ( child parent size addr child+size )
+ > IF \ verify if addr is below child+size address
+ ( child parent addr )
+ 2 pick over \ fetch child and addr for compare
+ ( child parend addr child addr )
+ <= IF \ verify if addr is above child address
+ ( child parent addr )
+ 2 pick - + nip true \ pick child, calculate addr-child + parent, drop child and return true
+ ( taddr true )
+ ELSE
+ 2drop false \ drop child parent size and return false
+ ( addr false )
+ THEN
+ ELSE
+ ( child parent addr )
+ nip nip false \ drop child parent size and return false
+ ( addr false )
+ THEN
+;
+
+\ helper function based on decode-int to decode an integer property
+\ from a prop-encoded-array
+\ my-property cannot be used since this depends on a current instance
+: get-property-decoded ( addr len -- n )
+ get-node get-property
+ IF cr cr cr ." get-property-decoded: no such property" EXIT THEN decode-int nip nip
+;
+
+0 VALUE pci-phys-hi
+1C000000 CONSTANT pci-stop-mapping-code
+\ Explanation to pci-stop-mapping-code:
+\ Bits 26..28 are unsused in phys.hi in the IEEE 1275 PCI binding
+\ and set to 0. Use value where these bits are set in pci-phys-hi to communicate that
+\ translation sould stop.
+
+\ Helper function to extract one element of the child parent size tuple coded
+\ into the ranges properties array, element being exactly one of child, parent
+\ and size
+: extract-range-element ( ranges-addr ranges-len #cells -- element ranges-addr' ranges-len' )
+ \ -rot decode-int 3 roll 1 > IF 20 lshift -rot decode-int 3 roll + THEN -rot
+ CASE
+ 1 OF decode-int -rot ENDOF
+ 2 OF decode-int 20 lshift -rot decode-int 3 roll + -rot ENDOF
+ 3 OF
+ BEGIN
+ dup 0= IF
+ false ( ranges-addr ranges-len false )
+ ELSE
+ decode-int
+ pci-phys-hi \ for PCI phys.hi lies on the stack below addr
+ space-code-mask and
+ <> \ compare phys.hi
+ THEN
+ WHILE
+ \ discard phys.mid, phys.lo, parent, and size values. Then go to next PCI ranges tuple
+ 18 dup -rot - -rot + swap
+ REPEAT
+
+ dup 0= IF ( ranges-addr ranges-len )
+ pci-stop-mapping-code to pci-phys-hi ( ranges-addr ranges-len )
+ ELSE
+ \ ranges size >= 8, since phys.hi
+ \ was read in ELSE of WHILE condition
+ decode-int 20 lshift -rot decode-int 3 roll + -rot
+ THEN
+ ENDOF
+ ENDCASE
+;
+
+\ Function to convert a whole child parent size sequence into decoded-int format
+: extract-range ( ranges-addr ranges-len -- child parent size ranges-addr' ranges-len' )
+ \ child
+ s" #address-cells" get-property-decoded
+ extract-range-element
+ \ exit criterium for PCI: ranges-len is 0 and false on top of stack
+ pci-phys-hi pci-stop-mapping-code = IF EXIT THEN ( ranges-addr ranges-len )
+
+ \ parent ( child ranges-addr' ranges-len' )
+ decode-phys ( child ranges-addr" ranges-len" phys.lo .. phys.hi )
+ my-#address-cells 1 > IF 20 lshift + THEN ( child ranges-addr''' ranges-len''' parent )
+ -rot ( child parent ranges-addr''' ranges-len''' )
+
+ \ size
+ s" #size-cells" get-property-decoded ( child parent ranges-addr''' ranges-len''' #size-cells )
+ extract-range-element ( child parent size ranges-addr"" ranges-len"" )
+;
+
+\ Function to process a whole array one or more of child parent size sequences
+\ Prerequisite: Empty ranges handing is assumed to already exist.
+: translate-ranges-node ( addr ranges-addr ranges-len -- taddr true|false )
+ BEGIN
+ dup 0 > \ ranges-len > 0
+ WHILE
+ extract-range
+ pci-phys-hi pci-stop-mapping-code =
+ IF ( addr ranges-addr ranges-len )
+ nip nip EXIT ( false )
+ THEN
+ ( addr child parent size ranges-addr' ranges-len' )
+ 2rot ( parent size ranges-addr' ranges-len' addr child )
+ 5 roll ( size ranges-addr' ranges-len' addr child parent )
+ 5 roll ( ranges-addr' ranges-len' addr child parent size )
+ 3 roll ( ranges-addr' ranges-len' child parent size addr )
+ translate-range ( ranges-addr' ranges-len' taddr true | ranges-addr' ranges-len' addr false )
+ IF nip nip true EXIT
+ ELSE ( ranges-addr' ranges-len' addr )
+ -rot
+ ( addr ranges-addr' ranges-len' )
+ THEN
+ REPEAT
+ ( ranges-addr' ranges-len' taddr true | ranges-addr' ranges-len' false )
+ \ remove addr ranges-addr' ranges-len' from stack
+ nip nip \ leaving the 0 ranges-len' as false
+ ( false )
+;
+
+\ Helper function to search the first ranges in current node or one of its parents
+\ and make that node the 'current node'
+\ Prerequisite: root node must have a ranges property
+\ Returns address, length, true if ranges property was found, otherwise false.
+: translate-set-to-next-ranges-node ( -- addr-ranges len-ranges true|false )
+ s" ranges" 2dup get-node get-property
+ IF
+ ( addr len true )
+ get-parent dup set-node get-property
+ IF
+ cr cr cr
+ s" no translatable address space due to missing ranges property" type
+ cr cr cr
+ false
+ ELSE
+ true
+ THEN
+ ELSE
+ ( addr len addr-ranges len-ranges )
+ rot drop rot drop true
+ THEN
+ ( ranges-addr ranges-len true|false )
+;
+
+: translate-address-end ( phandle-start taddr true|phandle-start false )
+ \ get back to the node where translation was started
+ dup IF
+ rot ( taddr true phandle-start )
+ set-node ( taddr true )
+ ELSE
+ swap ( phandle-start false )
+ set-node ( false )
+ THEN
+;
+
+\ Function to step up the device tree up to the root node.
+\ Contains empty ranges handling.
+\ Returns the translated address and true, when the address is translatable, otherwise false.
+: translate-ranges ( addr -- taddr true|false )
+ BEGIN
+ \ set-node semantic required here to continue from nodes found below.
+ translate-set-to-next-ranges-node
+ not IF false EXIT THEN ( false ) \ address is not translatable
+ \ due to missing ranges property in the hierarchy.
+ ( phandle-start addr ranges-addr ranges-len )
+ dup 0=
+ IF
+ \ empty ranges property detected, assume 1 : 1 translation
+ 2drop true
+ ( phandle-start addr true )
+ ELSE
+ ( phandle-start addr ranges-addr ranges-len )
+ translate-ranges-node
+ ( phandle-start taddr true|phandle-start false )
+ THEN
+ dup IF
+ ( phandle-start taddr true ) \ found a translation
+ drop
+ get-parent
+ dup 0=
+ IF \ arrived at root node, stop translation
+ drop true dup
+ ( phandle-start taddr true true )
+ ELSE
+ \ go to parent and continue
+ set-node false
+ ( phandle-start taddr true phandle-parent false )
+ THEN
+ ELSE
+ true \ address translation failed, exit loop
+ ( phandle-start false true )
+ THEN
+ UNTIL
+ ( phandle-start taddr true|phandle-start false )
+;
+
+
+: translate-address-back-to-start-node ( phandle-start taddr true|phandle-start false )
+ \ get back to the node where translation was started
+ dup IF
+ rot ( taddr true phandle-start )
+ set-node ( taddr true )
+ ELSE
+ swap ( phandle-start false )
+ set-node ( false )
+ THEN
+;
+
+: translate-address ( addr -- taddr true|false )
+ get-node swap \ save current node ( phandle-start addr )
+ translate-ranges ( phandle-start taddr true|phandle-start false )
+ translate-address-back-to-start-node ( taddr true|false )
+;
+
+
+: translate-address-pci ( phys.lo phys.mid phys.hi -- taddr true|false )
+ to pci-phys-hi ( phys.lo phys.mid )
+ lxjoin ( phys.addr )
+ get-node \ save current node ( phys.addr phandle-start )
+ swap ( phandle-start phys.addr )
+ translate-ranges \ fetches phys.hi for PCI ( phandle-start taddr true|phandle-start false )
+ translate-address-back-to-start-node ( taddr true|false )
+;
+
+\ device tree translate-address
+#include <translate.fs>
diff --git a/slof/fs/nvram.fs b/slof/fs/nvram.fs
new file mode 100644
index 0000000..5d8344b
--- /dev/null
+++ b/slof/fs/nvram.fs
@@ -0,0 +1,259 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: rztype ( str len -- ) \ stop at zero byte, read with rb@
+ BEGIN dup WHILE swap dup rb@ dup WHILE
+ emit char+ swap 1- REPEAT drop THEN 2drop ;
+
+: rtype ( str len -- )
+ 0 DO dup rb@ emit char+ LOOP drop ;
+
+: mrzplace ( str len buf -- ) 2dup + 0 swap rb! swap mrmove ;
+
+create tmpStr 500 allot
+: rzcount ( zstr -- str len )
+ dup tmpStr >r BEGIN dup rb@ dup r> dup 1+ >r c! WHILE char+ REPEAT
+ r> drop over - swap drop tmpStr swap ;
+
+: >nvram nvram-base + ;
+
+: calc-header-cksum ( offset -- cksum )
+ >nvram dup rb@
+ 10 2 DO
+ over i + rb@ +
+ LOOP
+ wbsplit + nip
+;
+
+: bad-header? ( offset -- flag )
+ dup >nvram 2+ rw@ ( offset length )
+ 0= IF ( offset )
+ drop true EXIT ( )
+ THEN
+ dup calc-header-cksum ( offset checksum' )
+ swap >nvram 1+ rb@ ( checksum ' checksum )
+ <> ( flag )
+;
+
+: .header ( offset -- )
+ cr ( offset )
+ dup bad-header? IF ( offset )
+ ." BAD HEADER -- trying to print it anyway" cr
+ THEN
+ space >nvram ( adr )
+ \ print type
+ dup rb@ 2 0.r ( adr )
+ space space ( adr )
+ \ print length
+ dup 2+ rw@ 10 * 5 .r ( adr )
+ space space ( adr )
+ \ print name
+ 4 + 0c rztype ( )
+;
+
+: .headers ( -- )
+ cr cr ." Type Size Name"
+ cr ." ========================"
+ 0 BEGIN ( offset )
+ dup >nvram ( offset adr )
+ rb@ ( offset type )
+ WHILE
+ dup .header ( offset )
+ dup >nvram 2+ rw@ 10 * + ( offset offset' )
+ dup nvram-size < IF ( offset )
+ ELSE
+ drop EXIT ( )
+ THEN
+ REPEAT
+ drop ( )
+ cr cr
+;
+
+: find-header ( type -- offset false | true )
+ 0 >r ( type R: offset )
+ BEGIN
+ r@ >nvram ( type adr ) ( R: offset )
+ rb@ 2dup ( type sig type sig ) ( R: offset )
+ = IF ( type sig ) ( R: offset )
+ 2drop r> false EXIT ( offset false )
+ THEN
+ WHILE
+ r> dup ( type offset offset )
+ bad-header? IF ( type offset )
+ 2drop true EXIT ( true )
+ THEN
+ dup >nvram 2+ rw@ 10 * ( tyoe offset length )
+ + >r ( type ) ( R: offset' )
+ REPEAT
+ r> 2drop true ( true )
+;
+
+: get-header ( type -- data len false | true )
+ find-header ?dup IF ( offset false | true )
+ EXIT ( true )
+ THEN
+ dup ( offset offset )
+ bad-header? ?dup IF ( offset true | offset )
+ nip EXIT ( true )
+ THEN
+ >nvram ( adr )
+ dup 10 + swap ( adr' adr )
+ 2+ rw@ 1- 10 * ( adr length )
+ false ( adr length true )
+;
+
+\ FIXME: This function should return if it succeeded!
+: add-header ( type size name len -- )
+ rot dup >r 10 / ( type name len size/10 R:size )
+ 7f get-header IF ( type name len size/10 R:size )
+ r> drop 4drop
+ ." couldn't find free partition" \ FIXME this should be a warning!!!
+ EXIT
+ THEN
+ r> 2dup <= IF
+ 2drop 2drop 3drop
+ ." couldn't find space in free partition"
+ EXIT
+ THEN
+ - 10 + 10 / >r dup e - r> swap rw! \ write new free size
+ 10 - dup dup nvram-base - calc-header-cksum swap 1+ rb!
+ dup 2+ rw@ 10 * + \ now we are on next header offset
+ dup >r 2+ rw! \ write new size
+ rot r@ rb! \ write type
+ r@ 4 + mrzplace \ write name
+ r@ nvram-base - calc-header-cksum r> 1+ rb!
+;
+
+: create-header ( type size name len -- )
+ 0 find-header ABORT" couldn't find space for new NVRAM partition"
+ \ write name
+ dup >r >nvram 4 + mrzplace ( type size ) ( R: offset )
+ \ adr of first byte behind partition
+ r@ >nvram over + ( type size adr' ) ( R: offset )
+ \ clear first byte behind new partition
+ dup nvram-size >nvram < IF ( type size adr' ) ( R: offset )
+ 0 swap rb! ( type size ) ( R: offset )
+ ELSE
+ drop ( type size ) ( R: offset )
+ THEN
+ \ write size
+ 10 / r@ >nvram 2+ rw! ( type ) ( R: offset )
+ \ write type
+ dup r@ >nvram rb! ( type ) ( R: offset )
+ \ write checksum
+ r@ calc-header-cksum ( type cksum ) ( R: offset)
+ r> >nvram 1+ rb! ( type )
+ \ zero out partition
+ get-header drop 0 rfill ( )
+;
+
+: calc-used-nvram-space ( -- used )
+ 0 dup >r BEGIN ( offset ) ( R: used )
+ dup >nvram rb@ ( offset sig ) ( R: used )
+ WHILE
+ dup >nvram 2+ rw@ 10 * ( offset length ) ( R: used )
+ r> + >r ( offset ) ( R: used )
+ dup >nvram 2+ rw@ 10 * ( offset length ) ( R: used )
+ + ( offset' ) ( R: used )
+ REPEAT
+ drop r> ( used )
+;
+
+: create-default-headers
+ s" Creating common NVRAM partition" nvramlog-write-string-cr
+ 70 1000 s" common" create-header ( )
+ \ calculate free partition
+ nvram-size calc-used-nvram-space - ( free )
+ dup 1 < IF ( free )
+ drop ( )
+ ELSE
+ s" Creating free space NVRAM partition with 0x" nvramlog-write-string
+ dup 6 nvramlog-write-number ( free )
+ s" bytes" nvramlog-write-string-cr
+ 7f swap ( 7f type )
+ here 10 allot ( 7f type adr )
+ 10 0 DO
+ dup i + FF swap c! ( 7f type adr )
+ LOOP
+ e create-header ( )
+ THEN
+;
+
+: reset-nvram ( -- )
+ nvram-base nvram-size 0 rfill ( )
+ 51 20000 s" ibm,BE0log" create-header ( )
+ 51 5000 s" ibm,BE1log" create-header ( )
+ nvram-base 10 + dup ( adr adr )
+ 1 swap x! ( adr )
+ 40 swap w! ( )
+ 20000 nvram-base + 10 + dup ( adr adr )
+ 1 swap x! ( adr )
+ 40 swap w! ( )
+ create-default-headers ( )
+;
+
+: type-no-zero ( addr len -- )
+ 0 do dup i + dup rb@ 0= IF drop ELSE 1 rtype THEN loop drop ;
+
+: .dmesg ( base-addr -- ) dup 14 + rl@ dup >r
+ ( base-addr act-off ) ( R: act-off )
+ over over over + swap 10 + rw@ + >r
+ ( base-addr act-off ) ( R: act-off nvram-act-addr )
+ over 2 + rw@ 10 * swap - over swap
+ ( base-addr base-addr start-size ) ( R: act-off nvram-act-addr )
+ r> swap rot 10 + rw@ - cr type-no-zero
+ ( base-addr ) ( R: act-off )
+ dup 10 + rw@ + r> type-no-zero ;
+
+
+: type-no-zero-part ( from-str cnt-str addr len )
+ 0 do
+ dup i + dup c@ 0= IF
+ drop
+ ELSE
+ ( from-str cnt-str addr addr+i )
+ ( from-str==0 AND cnt-str > 0 )
+ 3 pick 0= 3 pick 0 > AND IF
+ dup 1 type
+ THEN
+
+ c@ a = IF
+ 2 pick 0= IF
+ over 1- 0 max
+ rot drop swap
+ THEN
+ 2 pick 1- 0 max
+ 3 roll drop rot rot
+ ( from-str-- cnt-str-- addr addr+i )
+ THEN
+ THEN
+ loop drop ;
+
+: .dmesg-part ( from-str cnt-str base-addr -- ) dup 14 + l@ dup >r
+ ( base-addr act-off ) ( R: act-off )
+ over over over + swap 10 + w@ + >r
+ ( base-addr act-off ) ( R: act-off nvram-act-addr )
+ over 2 + w@ 10 * swap - over swap
+ ( base-addr base-addr start-size ) ( R: act-off nvram-act-addr )
+ r> swap rot 10 + w@ - cr
+ rot 4 roll 4 roll 4 roll 4 roll
+ ( base-addr from-str cnt-str addr len )
+ type-no-zero-part rot
+ ( base-addr ) ( R: act-off )
+ dup 10 + w@ + r> type-no-zero-part ;
+
+: dmesg-part ( from-str cnt-str -- from-str cnt-str )
+ 2dup nvram-base .dmesg-part nip nip ;
+
+: dmesg ( -- ) nvram-base .dmesg ;
+
+: dmesg2 ( -- ) nvram-log-be1-base .dmesg ;
diff --git a/slof/fs/packages.fs b/slof/fs/packages.fs
new file mode 100644
index 0000000..3b222be
--- /dev/null
+++ b/slof/fs/packages.fs
@@ -0,0 +1,62 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ =============================================================================
+\ SUPPORT PACKAGES
+\ =============================================================================
+
+
+s" packages" device-name
+get-node to packages
+
+\ new-device
+\ #include "packages/filler.fs"
+\ finish-device
+
+new-device
+#include "packages/deblocker.fs"
+finish-device
+
+new-device
+#include "packages/disk-label.fs"
+finish-device
+
+new-device
+#include "packages/fat-files.fs"
+finish-device
+
+new-device
+#include "packages/rom-files.fs"
+finish-device
+
+new-device
+#include "packages/ext2-files.fs"
+finish-device
+
+new-device
+#include "packages/obp-tftp.fs"
+finish-device
+
+new-device
+#include "packages/iso-9660.fs"
+finish-device
+
+new-device
+#include "packages/scsi.fs"
+finish-device
+
+new-device
+#include "packages/bulk.fs"
+finish-device
+
+
diff --git a/slof/fs/packages/bulk.fs b/slof/fs/packages/bulk.fs
new file mode 100644
index 0000000..3ee48a0
--- /dev/null
+++ b/slof/fs/packages/bulk.fs
@@ -0,0 +1,87 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" bulk" device-name
+
+
+\ standard open firmare method
+
+
+: open true ;
+
+\ standard open firmare method
+
+
+: close ;
+
+
+\ -------------------------------------------------
+\ Locals
+\ ------------------------------------------------
+
+
+8 chars alloc-mem VALUE setup-packet
+
+
+\ --------------------------------------------------
+\ signature --->4bytes offset --->0
+\ tag --->4bytes offset --->4
+\ trans-len --->4bytes offset --->8
+\ dir-flag --->1byte offset --->c
+\ lun --->1byte offset --->d
+\ comm-len --->1byte offset --->e
+\ --------------------------------------------------
+
+
+0 VALUE cbw-addr
+: build-cbw ( address tag transfer-len direction lun command-len -- )
+ 5 pick TO cbw-addr ( address tag transfer-len direction lun command-len )
+ cbw-addr 0f erase ( address tag transfer-len direction lun command-len )
+ cbw-addr e + c! ( address tag transfer-len direction lun )
+ cbw-addr d + c! ( address tag transfer-len direction )
+ cbw-addr c + c! ( address tag transfer-len )
+ cbw-addr 8 + l!-le ( address tag )
+ cbw-addr 4 + l!-le ( address )
+ 43425355 cbw-addr l!-le ( address )
+ drop ;
+
+
+\ ---------------------------------------------------
+\ signature --->4bytes offset --->0
+\ tag --->4bytes offset --->4
+\ residue --->4bytes offset --->8
+\ status --->1byte offset --->c
+\ ---------------------------------------------------
+
+
+0 VALUE csw-addr
+: analyze-csw ( address -- residue tag true|reason false )
+ TO csw-addr
+ csw-addr l@-le 53425355 = IF
+ csw-addr c + c@ dup 0= IF ( reason )
+ drop
+ csw-addr 8 + l@-le ( residue )
+ csw-addr 4 + l@-le ( residue tag ) \ command block tag
+ TRUE ( residue tag TRUE )
+ ELSE
+ FALSE ( reason FALSE )
+ THEN
+ ELSE
+ FALSE ( FALSE )
+ THEN
+ csw-addr 0c erase
+;
+
+: bulk-reset-recovery-procedure ( bulk-out-endp bulk-in-endp usb-addr -- )
+ s" bulk-reset-recovery-procedure" $call-parent
+;
diff --git a/slof/fs/packages/deblocker.fs b/slof/fs/packages/deblocker.fs
new file mode 100644
index 0000000..92b4862
--- /dev/null
+++ b/slof/fs/packages/deblocker.fs
@@ -0,0 +1,61 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ =============================================================================
+\ =============================================================================
+
+
+\ The deblocker. Allows block devices to be used as a (seekable) byte device.
+
+s" deblocker" device-name
+
+INSTANCE VARIABLE offset
+INSTANCE VARIABLE block-size
+INSTANCE VARIABLE max-transfer
+INSTANCE VARIABLE my-block
+INSTANCE VARIABLE adr
+INSTANCE VARIABLE len
+
+: open
+ s" block-size" ['] $call-parent CATCH IF 2drop false EXIT THEN
+ block-size !
+ s" max-transfer" ['] $call-parent CATCH IF 2drop false EXIT THEN
+ max-transfer !
+ block-size @ alloc-mem my-block !
+ 0 offset !
+ true ;
+: close my-block @ block-size @ free-mem ;
+
+: seek ( lo hi -- status ) \ XXX: perhaps we should fail if the underlying
+ \ device would fail at this offset
+ lxjoin offset ! 0 ;
+: block+remainder ( -- block# remainder ) offset @ block-size @ u/mod swap ;
+: read-blocks ( addr block# #blocks -- actual ) s" read-blocks" $call-parent ;
+: read ( addr len -- actual )
+ dup >r len ! adr !
+ \ First, handle a partial block at the start.
+ block+remainder dup IF ( block# offset-in-block )
+ >r my-block @ swap 1 read-blocks drop
+ my-block @ r@ + adr @ block-size @ r> - len @ min dup >r move
+ r> dup negate len +! dup adr +! offset +! ELSE 2drop THEN
+
+ \ Now, in a loop read max. max-transfer sized runs of whole blocks.
+ BEGIN len @ block-size @ >= WHILE
+ adr @ block+remainder drop len @ max-transfer @ min block-size @ / read-blocks
+ block-size @ * dup negate len +! dup adr +! offset +! REPEAT
+
+ \ And lastly, handle a partial block at the end.
+ len @ IF my-block @ block+remainder drop 1 read-blocks drop
+ my-block @ adr @ len @ move THEN
+
+ r> ;
diff --git a/slof/fs/packages/disk-label.fs b/slof/fs/packages/disk-label.fs
new file mode 100644
index 0000000..08761fd
--- /dev/null
+++ b/slof/fs/packages/disk-label.fs
@@ -0,0 +1,265 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" disk-label" device-name
+
+INSTANCE VARIABLE partition
+INSTANCE VARIABLE part-offset
+INSTANCE VARIABLE block-size
+INSTANCE VARIABLE block
+INSTANCE VARIABLE args
+INSTANCE VARIABLE args-len
+
+INSTANCE VARIABLE block# \ variable to store logical sector#
+INSTANCE VARIABLE hit# \ partition counter
+INSTANCE VARIABLE success-flag
+0ff constant END-OF-DESC
+3 constant PARTITION-ID
+48 constant VOL-PART-LOC
+
+: seek lxjoin part-offset @ + xlsplit s" seek" $call-parent ;
+: read s" read" $call-parent ;
+
+: init-block ( -- )
+ s" block-size" ['] $call-parent CATCH IF ABORT" no block-size" THEN
+ block-size !
+ block-size @ alloc-mem dup block-size @ erase block ! ;
+
+: parse-partition ( -- okay? )
+ 0 part-offset ! 0 partition ! my-args args-len ! args !
+
+ \ Fix up the "0" thing yaboot does.
+ args-len @ 1 = IF args @ c@ [char] 0 = IF 0 args-len ! THEN THEN
+
+ \ Check for "full disk" arguments.
+ my-args [char] , findchar 0= IF true EXIT THEN drop \ no comma
+ my-args [char] , split args-len ! args !
+ dup 0= IF 2drop true EXIT THEN \ no first argument
+
+ \ Check partition #.
+ base @ >r decimal $number r> base !
+ IF cr ." Not a partition #" false EXIT THEN
+
+ \ Store part #, done.
+ partition ! true ;
+
+: try-dos-partition ( -- okay? )
+ partition @ 1 5 within 0= IF cr ." Partition # not 1-4" false EXIT THEN
+
+ \ Read partition table.
+ 0 0 seek drop block @ block-size @ read drop
+ block @ 1fe + 2c@ bwjoin aa55 <> IF cr ." No partitions" false EXIT THEN
+
+ \ Could/should check for valid partition here... aa55 is not enough really.
+
+ \ Get the partition offset.
+ partition @ 10 * 1b6 + block @ + 4c@ bljoin block-size @ * part-offset !
+ true ;
+
+\ Check for an ISO-9660 filesystem on the disk
+\ : try-iso9660-partition ( -- true|false )
+\ implement me if you can ;-)
+\ ;
+
+
+\ Check for an ISO-9660 filesystem on the disk
+\ (cf. CHRP IEEE 1275 spec., chapter 11.1.2.3)
+: has-iso9660-filesystem ( -- TRUE|FALSE )
+ \ Seek and read starting from 16th sector:
+ 10 800 * 0 seek drop
+ block @ block-size @ read drop
+ \ Check for CD-ROM volume magic:
+ block @ c@ 1 =
+ block @ 1+ 5 s" CD001" str=
+ and
+;
+
+
+: try-dos-files ( -- found? )
+ block @ 1fe + 2c@ bwjoin aa55 <> IF false EXIT THEN
+ block @ c@ e9 <> IF
+ block @ c@ eb <> block @ 2+ c@ 90 <> or IF false EXIT THEN THEN
+ s" fat-files" find-package IF args @ args-len @ rot interpose THEN true
+;
+
+CREATE ext2-magic 2 allot
+: try-ext2-files ( -- found? )
+ 438 0 seek drop ext2-magic 2 read drop
+ ext2-magic w@-le ef53 <> IF false EXIT THEN
+ s" ext2-files" find-package IF args @ args-len @ rot interpose THEN true
+;
+
+: try-iso9660-files
+ \ seek and read starting from 16th sector for volume descriptors
+ block @ 1+ 5 s" CD001" str=
+ IF \ found ISO9660 signature
+ s" iso-9660" find-package IF args @ args-len @ rot interpose THEN
+ TRUE
+ ELSE
+ FALSE
+ THEN
+;
+
+
+: try-files ( -- found? )
+ \ If no path, then full disk.
+ args-len @ 0= IF true EXIT THEN
+
+ 0 0 seek drop
+ block @ block-size @ read drop
+ try-dos-files IF true EXIT THEN
+ try-ext2-files IF true EXIT THEN
+
+ \ Seek to the begining of logical 2048-byte sector 16
+ \ refer to Chapter C.11.1 in PAPR 2.0 Spec
+ 10 800 * 0 seek drop
+ block @ block-size @ read drop
+ try-iso9660-files IF true EXIT THEN
+
+ \ ... more filesystem types here ...
+
+ false
+;
+
+: try-partitions ( -- found? )
+ try-dos-partition IF try-files EXIT THEN
+ \ try-iso9660-partition IF try-files EXIT THEN
+ \ ... more partition types here...
+ false ;
+
+: open
+ init-block
+ parse-partition 0= IF
+ false EXIT
+ THEN
+ partition @ 0= IF
+ try-files EXIT
+ THEN
+ try-partitions
+;
+
+: close
+ block @ block-size @ free-mem ;
+
+\ Workaround for not having "value" variables yet.
+: block-size block-size @ ;
+
+STRUCT
+ /c field part-entry>active
+ /c field part-entry>start-head
+ /c field part-entry>start-sect
+ /c field part-entry>start-cyl
+ /c field part-entry>id
+ /c field part-entry>end-head
+ /c field part-entry>end-sect
+ /c field part-entry>end-cyl
+ /l field part-entry>sector-offset
+ /l field part-entry>sector-count
+
+CONSTANT /partition-entry
+
+
+\ Load from first active DOS boot partition.
+\ Note: sector block size is always 512 bytes for DOS partition tables.
+
+: load-from-dos-boot-partition ( addr -- size )
+ 0 0 seek drop
+ block @ 200 read drop
+ \ Check for DOS partition table magic:
+ block @ 1fe + 2c@ bwjoin aa55 <> IF FALSE EXIT THEN
+ \ Now step through the partition table:
+ block @ 1be + ( addr part-off )
+ 4 0 DO
+ dup part-entry>active c@ 80 = ( addr part-off active? )
+ over part-entry>id c@ 41 = and IF ( addr part-off )
+ dup part-entry>sector-offset 4c@ bljoin ( addr part-off sect-off )
+ \ seek to the boot partition
+ 200 * 0 seek drop ( addr part-off )
+ part-entry>sector-count 4c@ bljoin ( addr sect-count )
+ 200 * read ( size )
+ UNLOOP EXIT
+ THEN
+ /partition-entry + ( addr part-off )
+ LOOP
+ 2drop 0
+;
+
+: load-from-boot-partition ( addr -- size )
+ load-from-dos-boot-partition
+ \ More boot partition formats ...
+;
+
+
+\ Extract the boot loader path from a bootinfo.txt file
+\ In: address and length of buffer where the bootinfo.txt has been loaded to.
+\ Out: string address and length of the boot loader (within the input buffer)
+\ or a string with length = 0 when parsing failed.
+
+: parse-bootinfo-txt ( addr len -- str len )
+ 2dup s" <boot-script>" find-substr ( addr len pos1 )
+ 2dup = IF
+ \ String not found
+ 3drop 0 0 EXIT
+ THEN
+ dup >r - swap r> + swap ( addr1 len1 )
+ 2dup [char] \ findchar drop ( addr1 len1 pos2 )
+ dup >r - swap r> + swap ( addr2 len2 )
+ 2dup s" </boot-script>" find-substr nip ( addr2 len3 )
+;
+
+\ Try to load \ppc\bootinfo.txt from the disk (used mainly on CD-ROMs), and if
+\ available, get the boot loader path from this file and load it.
+\ See the "CHRP system binding to IEEE 1275" specification for more information
+\ about bootinfo.txt.
+
+: load-chrp-boot-file ( addr -- size )
+ \ Create bootinfo.txt path name and load that file:
+ my-self parent ihandle>phandle node>path
+ s" :\ppc\bootinfo.txt" $cat strdup ( addr str len )
+ open-dev dup 0= IF 2drop 0 EXIT THEN
+ >r dup ( addr addr R:ihandle )
+ dup s" load" r@ $call-method ( addr addr size R:ihandle )
+ r> close-dev ( addr addr size )
+ \ Now parse the information from bootinfo.txt:
+ parse-bootinfo-txt ( addr fnstr fnlen )
+ dup 0= IF 3drop 0 EXIT THEN
+ \ Create the full path to the boot loader:
+ my-self parent ihandle>phandle node>path ( addr fnstr fnlen nstr nlen )
+ s" :" $cat 2swap $cat strdup ( addr str len )
+ \ Update the bootpath:
+ 2dup encode-string s" bootpath" set-chosen
+ \ And finally load the boot loader itself:
+ open-dev dup 0= IF ." failed to load CHRP boot loader." 2drop 0 EXIT THEN
+ >r s" load" r@ $call-method ( size R:ihandle )
+ r> close-dev ( size )
+;
+
+
+\ Boot & Load w/o arguments is assumed to be boot from boot partition
+
+: load ( addr -- size )
+ args-len @ IF
+ TRUE ABORT" Load done w/o filesystem"
+ ELSE
+ partition @ IF
+ 0 0 seek drop
+ 200000 read
+ ELSE
+ has-iso9660-filesystem IF
+ dup load-chrp-boot-file ?dup 0 > IF nip EXIT THEN
+ THEN
+ load-from-boot-partition
+ dup 0= ABORT" No boot partition found"
+ THEN
+ THEN
+;
diff --git a/slof/fs/packages/ext2-files.fs b/slof/fs/packages/ext2-files.fs
new file mode 100644
index 0000000..d33f0e6
--- /dev/null
+++ b/slof/fs/packages/ext2-files.fs
@@ -0,0 +1,140 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+s" ext2-files" device-name
+
+INSTANCE VARIABLE first-block
+INSTANCE VARIABLE block-size
+INSTANCE VARIABLE inodes/group
+
+INSTANCE VARIABLE group-descriptors
+
+: seek s" seek" $call-parent ;
+: read s" read" $call-parent ;
+
+INSTANCE VARIABLE data
+INSTANCE VARIABLE #data
+
+: free-data
+ data @ ?dup IF #data @ free-mem 0 data ! THEN ;
+: read-data ( offset size -- )
+ free-data dup #data ! alloc-mem data !
+ xlsplit seek -2 and ABORT" ext2-files read-data: seek failed"
+ data @ #data @ read #data @ <> ABORT" ext2-files read-data: read failed" ;
+
+: read-block ( block# -- )
+ block-size @ * block-size @ read-data ;
+
+INSTANCE VARIABLE inode
+INSTANCE VARIABLE file-len
+INSTANCE VARIABLE blocks
+INSTANCE VARIABLE #blocks
+INSTANCE VARIABLE ^blocks
+INSTANCE VARIABLE #blocks-left
+: blocks-read ( n -- ) dup negate #blocks-left +! 4 * ^blocks +! ;
+: read-indirect-blocks ( indirect-block# -- )
+ read-block data @ data off
+ dup #blocks-left @ 4 * block-size @ min dup >r ^blocks @ swap move
+ r> 2 rshift blocks-read block-size @ free-mem ;
+: read-double-indirect-blocks ( double-indirect-block# -- )
+\ TBD
+;
+: read-triple-indirect-blocks ( triple-indirect-block# -- )
+\ TBD
+;
+: read-block#s ( -- )
+ blocks @ ?dup IF #blocks @ 4 * free-mem THEN
+ inode @ 4 + l@-le file-len !
+ file-len @ block-size @ // #blocks !
+ #blocks @ 4 * alloc-mem blocks !
+ blocks @ ^blocks ! #blocks @ #blocks-left !
+ #blocks-left @ c min \ # direct blocks
+ inode @ 28 + over 4 * ^blocks @ swap move blocks-read
+ #blocks-left @ IF inode @ 58 + l@-le read-indirect-blocks THEN
+ #blocks-left @ IF inode @ 5c + l@-le read-double-indirect-blocks THEN
+ #blocks-left @ IF inode @ 60 + l@-le read-triple-indirect-blocks THEN ;
+: read-inode ( inode# -- )
+ 1- inodes/group @ u/mod \ # in group, group #
+ 20 * group-descriptors @ + 8 + l@-le block-size @ * \ # in group, inode table
+ swap 80 * + xlsplit seek drop inode @ 80 read drop ;
+
+: .rwx ( bits last-char-if-special special? -- )
+ rot dup 4 and IF ." r" ELSE ." -" THEN
+ dup 2 and IF ." w" ELSE ." -" THEN
+ swap IF 1 and 0= IF upc THEN emit ELSE
+ 1 and IF ." x" ELSE ." -" THEN drop THEN ;
+CREATE mode-chars 10 allot s" ?pc?d?b?-?l?s???" mode-chars swap move
+: .mode ( mode -- )
+ dup c rshift f and mode-chars + c@ emit
+ dup 6 rshift 7 and over 800 and 73 swap .rwx
+ dup 3 rshift 7 and over 400 and 73 swap .rwx
+ dup 7 and swap 200 and 74 swap .rwx ;
+: .inode ( -- )
+ base @ >r decimal
+ inode @ w@-le .mode \ file mode
+ inode @ 1a + w@-le 5 .r \ link count
+ inode @ 02 + w@-le 9 .r \ uid
+ inode @ 18 + w@-le 9 .r \ gid
+ inode @ 04 + l@-le 9 .r \ size
+ r> base ! ;
+
+: do-super ( -- )
+ 400 400 read-data
+ data @ 14 + l@-le first-block !
+ 400 data @ 18 + l@-le lshift block-size !
+ data @ 28 + l@-le inodes/group !
+ first-block @ 1+ read-block data @ group-descriptors ! data off ;
+
+INSTANCE VARIABLE current-pos
+
+: read ( adr len -- actual )
+ file-len @ current-pos @ - min \ can't go past end of file
+ current-pos @ block-size @ u/mod 4 * blocks @ + l@-le read-block
+ block-size @ over - rot min >r ( adr off r: len )
+ data @ + swap r@ move r> dup current-pos +! ;
+: read ( adr len -- actual )
+ ( check if a file is selected, first )
+ dup >r BEGIN dup WHILE 2dup read dup 0= ABORT" ext2-files: read failed"
+ /string REPEAT 2drop r> ;
+: seek ( lo hi -- status )
+ lxjoin dup file-len @ > IF drop true EXIT THEN current-pos ! false ;
+: load ( adr -- len )
+ file-len @ read dup file-len @ <> ABORT" ext2-files: failed loading file" ;
+
+: .name ( adr -- ) dup 8 + swap 6 + c@ type ;
+: read-dir ( inode# -- adr )
+ read-inode read-block#s file-len @ alloc-mem
+ 0 0 seek ABORT" ext2-files read-dir: seek failed"
+ dup file-len @ read file-len @ <> ABORT" ext2-files read-dir: read failed" ;
+: .dir ( inode# -- )
+ read-dir dup BEGIN 2dup file-len @ - > over l@-le tuck and WHILE
+ cr dup 8 0.r space read-inode .inode space space dup .name
+ dup 4 + w@-le + REPEAT 2drop file-len @ free-mem ;
+: (find-file) ( adr name len -- inode#|0 )
+ 2>r dup BEGIN 2dup file-len @ - > over l@-le and WHILE
+ dup 8 + over 6 + c@ 2r@ str= IF 2r> 2drop nip l@-le EXIT THEN
+ dup 4 + w@-le + REPEAT 2drop 2r> 2drop 0 ;
+: find-file ( inode# name len -- inode#|0 )
+ 2>r read-dir dup 2r> (find-file) swap file-len @ free-mem ;
+: find-path ( inode# name len -- inode#|0 )
+ dup 0= IF 3drop 0 ." empty name " EXIT THEN
+ over c@ [char] \ = IF 1 /string ." slash " RECURSE EXIT THEN
+ [char] \ split 2>r find-file ?dup 0= IF
+ 2r> 2drop false ." not found " EXIT THEN
+ r@ 0<> IF 2r> ." more... " RECURSE EXIT THEN
+ 2r> 2drop ." got it " ;
+: close ;
+: open
+ do-super
+ 80 alloc-mem inode !
+ my-args nip 0= IF 0 0 ELSE
+ 2 my-args find-path ?dup 0= IF close false EXIT THEN THEN
+ read-inode read-block#s 0 0 seek 0= ;
diff --git a/slof/fs/packages/fat-files.fs b/slof/fs/packages/fat-files.fs
new file mode 100644
index 0000000..07c0f7e
--- /dev/null
+++ b/slof/fs/packages/fat-files.fs
@@ -0,0 +1,187 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" fat-files" device-name
+
+INSTANCE VARIABLE bytes/sector
+INSTANCE VARIABLE sectors/cluster
+INSTANCE VARIABLE #reserved-sectors
+INSTANCE VARIABLE #fats
+INSTANCE VARIABLE #root-entries
+INSTANCE VARIABLE total-#sectors
+INSTANCE VARIABLE media-descriptor
+INSTANCE VARIABLE sectors/fat
+INSTANCE VARIABLE sectors/track
+INSTANCE VARIABLE #heads
+INSTANCE VARIABLE #hidden-sectors
+
+INSTANCE VARIABLE fat-type
+INSTANCE VARIABLE bytes/cluster
+INSTANCE VARIABLE fat-offset
+INSTANCE VARIABLE root-offset
+INSTANCE VARIABLE cluster-offset
+INSTANCE VARIABLE #clusters
+
+: seek s" seek" $call-parent ;
+: read s" read" $call-parent ;
+
+INSTANCE VARIABLE data
+INSTANCE VARIABLE #data
+
+: free-data
+ data @ ?dup IF #data @ free-mem 0 data ! THEN ;
+: read-data ( offset size -- )
+ free-data dup #data ! alloc-mem data !
+ xlsplit seek -2 and ABORT" fat-files read-data: seek failed"
+ data @ #data @ read #data @ <> ABORT" fat-files read-data: read failed" ;
+
+CREATE fat-buf 8 allot
+: read-fat ( cluster# -- data )
+ fat-buf 8 erase
+ 1 #split fat-type @ * 2/ 2/ fat-offset @ +
+ xlsplit seek -2 and ABORT" fat-files read-fat: seek failed"
+ fat-buf 8 read 8 <> ABORT" fat-files read-fat: read failed"
+ fat-buf 8c@ bxjoin fat-type @ dup >r 2* #split drop r> #split
+ rot IF swap THEN drop ;
+
+INSTANCE VARIABLE next-cluster
+
+: read-cluster ( cluster# -- )
+ dup bytes/cluster @ * cluster-offset @ + bytes/cluster @ read-data
+ read-fat dup #clusters @ >= IF drop 0 THEN next-cluster ! ;
+: read-dir ( cluster# -- )
+ ?dup 0= IF root-offset @ #root-entries @ 20 * read-data 0 next-cluster !
+ ELSE read-cluster THEN ;
+
+: .time ( x -- )
+ base @ >r decimal
+ b #split 2 0.r [char] : emit 5 #split 2 0.r [char] : emit 2* 2 0.r
+ r> base ! ;
+: .date ( x -- )
+ base @ >r decimal
+ 9 #split 7bc + 4 0.r [char] - emit 5 #split 2 0.r [char] - emit 2 0.r
+ r> base ! ;
+: .attr ( attr -- )
+ 6 0 DO dup 1 and IF s" RHSLDA" drop i + c@ ELSE bl THEN emit u2/ LOOP drop ;
+: .dir-entry ( adr -- )
+ dup 0b + c@ 8 and IF drop EXIT THEN \ volume label, not a file
+ dup c@ e5 = IF drop EXIT THEN \ deleted file
+ cr
+ dup 1a + 2c@ bwjoin [char] # emit 4 0.r space \ starting cluster
+ dup 18 + 2c@ bwjoin .date space
+ dup 16 + 2c@ bwjoin .time space
+ dup 1c + 4c@ bljoin base @ decimal swap a .r base ! space \ size in bytes
+ dup 0b + c@ .attr space
+ dup 8 BEGIN 2dup 1- + c@ 20 = over and WHILE 1- REPEAT type
+ dup 8 + 3 BEGIN 2dup 1- + c@ 20 = over and WHILE 1- REPEAT dup IF
+ [char] . emit type ELSE 2drop THEN
+ drop ;
+: .dir-entries ( adr n -- )
+ 0 ?DO dup i 20 * + dup c@ 0= IF drop LEAVE THEN .dir-entry LOOP drop ;
+: .dir ( cluster# -- )
+ read-dir BEGIN data @ #data @ 20 / .dir-entries next-cluster @ WHILE
+ next-cluster @ read-cluster REPEAT ;
+
+: str-upper ( str len adr -- ) \ Copy string to adr, uppercase
+ -rot bounds ?DO i c@ upc over c! char+ LOOP drop ;
+CREATE dos-name b allot
+: make-dos-name ( str len -- )
+ dos-name b bl fill
+ 2dup [char] . findchar IF
+ 3dup 1+ /string 3 min dos-name 8 + str-upper nip THEN
+ 8 min dos-name str-upper ;
+
+: (find-file) ( -- cluster file-len is-dir? true | false )
+ data @ BEGIN dup data @ #data @ + < WHILE
+ dup dos-name b comp WHILE 20 + REPEAT
+ dup 1a + 2c@ bwjoin swap dup 1c + 4c@ bljoin swap 0b + c@ 10 and 0<> true
+ ELSE drop false THEN ;
+: find-file ( dir-cluster name len -- cluster file-len is-dir? true | false )
+ make-dos-name read-dir BEGIN (find-file) 0= WHILE next-cluster @ WHILE
+ next-cluster @ read-cluster REPEAT false ELSE true THEN ;
+: find-path ( dir-cluster name len -- cluster file-len true | false )
+ dup 0= IF 3drop false ." empty name " EXIT THEN
+ over c@ [char] \ = IF 1 /string ." slash " RECURSE EXIT THEN
+ [char] \ split 2>r find-file 0= IF 2r> 2drop false ." not found " EXIT THEN
+ r@ 0<> <> IF 2drop 2r> 2drop false ." no dir<->file match " EXIT THEN
+ r@ 0<> IF drop 2r> ." more... " RECURSE EXIT THEN
+ 2r> 2drop true ." got it " ;
+
+: do-super ( -- )
+ 0 200 read-data
+ data @ 0b + 2c@ bwjoin bytes/sector !
+ data @ 0d + c@ sectors/cluster !
+ bytes/sector @ sectors/cluster @ * bytes/cluster !
+ data @ 0e + 2c@ bwjoin #reserved-sectors !
+ data @ 10 + c@ #fats !
+ data @ 11 + 2c@ bwjoin #root-entries !
+ data @ 13 + 2c@ bwjoin total-#sectors !
+ data @ 15 + c@ media-descriptor !
+ data @ 16 + 2c@ bwjoin sectors/fat !
+ data @ 18 + 2c@ bwjoin sectors/track !
+ data @ 1a + 2c@ bwjoin #heads !
+ data @ 1c + 2c@ bwjoin #hidden-sectors !
+
+ \ For FAT16 and FAT32:
+ total-#sectors @ 0= IF data @ 20 + 4c@ bljoin total-#sectors ! THEN
+
+ \ For FAT32:
+ sectors/fat @ 0= IF data @ 24 + 4c@ bljoin sectors/fat ! THEN
+
+ \ XXX add other FAT32 stuff (offsets 28, 2c, 30)
+
+ \ Compute the number of data clusters, decide what FAT type we are.
+ total-#sectors @ #reserved-sectors @ - sectors/fat @ #fats @ * -
+ #root-entries @ 20 * bytes/sector @ // - sectors/cluster @ /
+ dup #clusters !
+ dup ff5 < IF drop c ELSE fff5 < IF 10 ELSE 20 THEN THEN fat-type !
+cr ." FAT" base @ decimal fat-type @ . base !
+
+ \ Starting offset of first fat.
+ #reserved-sectors @ bytes/sector @ * fat-offset !
+
+ \ Starting offset of root dir.
+ #fats @ sectors/fat @ * bytes/sector @ * fat-offset @ + root-offset !
+
+ \ Starting offset of "cluster 0".
+ #root-entries @ 20 * bytes/sector @ tuck // * root-offset @ +
+ bytes/cluster @ 2* - cluster-offset ! ;
+
+
+INSTANCE VARIABLE file-cluster
+INSTANCE VARIABLE file-len
+INSTANCE VARIABLE current-pos
+INSTANCE VARIABLE pos-in-data
+
+: seek ( lo hi -- status )
+ lxjoin dup current-pos ! file-cluster @ read-cluster
+ \ Read and skip blocks until we are where we want to be.
+ BEGIN dup #data @ >= WHILE #data @ - next-cluster @ dup 0= IF
+ 2drop true EXIT THEN read-cluster REPEAT pos-in-data ! false ;
+: read ( adr len -- actual )
+ file-len @ current-pos @ - min \ can't go past end of file
+ #data @ pos-in-data @ - min >r \ length for this transfer
+ data @ pos-in-data @ + swap r@ move \ move the data
+ r@ pos-in-data +! r@ current-pos +! pos-in-data @ #data @ = IF
+ next-cluster @ ?dup IF read-cluster 0 pos-in-data ! THEN THEN r> ;
+: read ( adr len -- actual )
+ dup >r BEGIN dup WHILE 2dup read dup 0= ABORT" fat-files: read failed"
+ /string ( tuck - >r + r> ) REPEAT 2drop r> ;
+: load ( adr -- len )
+ file-len @ read dup file-len @ <> ABORT" fat-files: failed loading file" ;
+
+: close free-data ;
+: open
+ do-super
+ 0 my-args find-path 0= IF close false EXIT THEN
+ file-len ! file-cluster ! 0 0 seek 0= ;
diff --git a/slof/fs/packages/filler.fs b/slof/fs/packages/filler.fs
new file mode 100644
index 0000000..c32c84c
--- /dev/null
+++ b/slof/fs/packages/filler.fs
@@ -0,0 +1,21 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" filler" device-name
+
+: block-size s" block-size" $call-parent ;
+: seek s" seek" $call-parent ;
+: read s" read" $call-parent ;
+
+: open true ;
+: close ;
diff --git a/slof/fs/packages/iso-9660.fs b/slof/fs/packages/iso-9660.fs
new file mode 100644
index 0000000..7927381
--- /dev/null
+++ b/slof/fs/packages/iso-9660.fs
@@ -0,0 +1,307 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" iso-9660" device-name
+
+
+0 VALUE iso-debug-flag
+
+\ Method for code clean up - For release version of code iso-debug-flag is
+\ cleared and for debugging it is set
+
+: iso-debug-print ( str len -- ) iso-debug-flag IF type cr ELSE 2drop THEN ;
+
+
+\ --------------------------------------------------------
+\ GLOBAL VARIABLES
+\ --------------------------------------------------------
+
+
+0 VALUE path-tbl-size
+0 VALUE path-tbl-addr
+0 VALUE root-dir-size
+0 VALUE vol-size
+0 VALUE logical-blk-size
+0 VALUE path-table
+0 VALUE count
+
+
+\ INSTANCE VARIABLES
+
+
+INSTANCE VARIABLE dir-addr
+INSTANCE VARIABLE data-buff
+INSTANCE VARIABLE #data
+INSTANCE VARIABLE ptable
+INSTANCE VARIABLE file-loc
+INSTANCE VARIABLE file-size
+INSTANCE VARIABLE cur-file-offset
+INSTANCE VARIABLE self
+INSTANCE VARIABLE index
+
+
+\ --------------------------------------------------------
+\ COLON DEFINITIONS
+\ --------------------------------------------------------
+
+
+\ This method is used to seek to the required position
+\ Which calls seek of disk-label
+
+: seek ( pos.lo pos.hi -- status ) s" seek" $call-parent ;
+
+
+\ This method is used to read the contents of disk
+\ it calls read of disk-label
+
+
+ : read ( addr len -- actual ) s" read" $call-parent ;
+
+
+\ This method releases the memory used as scratch pad buffer.
+
+: free-data ( -- )
+ data-buff @ ( data-buff )
+ ?DUP IF #data @ free-mem 0 data-buff ! THEN
+;
+
+
+\ This method will release the previous allocated scratch pad buffer and
+\ allocates a fresh buffer and copies the required number of bytes from the
+\ media in to it.
+
+: read-data ( offset size -- )
+ free-data DUP ( offset size size )
+ #data ! alloc-mem data-buff ! ( offset )
+ xlsplit ( pos.lo pos.hi )
+ seek -2 and ABORT" seek failed."
+ data-buff @ #data @ read ( actual )
+ #data @ <> ABORT" read failed."
+;
+
+
+\ This method extracts the information required from primary volume
+\ descriptor and stores the required information in the global variables
+
+: extract-vol-info ( -- )
+ 10 800 * 800 read-data
+ data-buff @ 88 + l@-be to path-tbl-size \ read path table size
+ data-buff @ 94 + l@-be to path-tbl-addr \ read big-endian path table
+ data-buff @ a2 + l@-be dir-addr ! \ gather of root directory info
+ data-buff @ 0aa + l@-be to root-dir-size \ get volume info
+ data-buff @ 54 + l@-be to vol-size \ size in blocks
+ data-buff @ 82 + l@-be to logical-blk-size
+ path-tbl-size alloc-mem dup TO path-table path-tbl-size erase
+ path-tbl-addr 800 * xlsplit seek drop
+ path-table path-tbl-size read drop \ pathtable in-system-memory copy
+;
+
+
+\ This method coverts the iso file name to user readble form
+
+: file-name ( str len -- str' len' )
+ 2dup [char] ; findchar IF ( str len )
+ dup -rot - >r + r> erase ( str' len' )
+ THEN
+;
+
+
+\ triplicates top stack element
+
+: dup3 ( num -- num num num ) dup dup dup ;
+
+
+\ This method is used for traversing records of path table. If the
+\ file identifier length is odd 1 byte padding is done else not.
+
+: get-next-record ( rec-addr -- next-rec-offset )
+ dup3 ( rec-addr rec-addr rec-addr rec-addr )
+ self @ 1 + self ! ( rec-addr rec-addr rec-addr rec-addr )
+ c@ 1 AND IF ( rec-addr rec-addr rec-addr )
+ c@ + 9 ( rec-addr rec-addr' rec-len )
+ ELSE
+ c@ + 8 ( rec-addr rec-addr' rec-len )
+ THEN
+ + swap - ( next-rec-offset )
+;
+
+
+\ This method does search of given directory name in the path table
+\ and returns true if finds a match else false.
+
+: path-table-search ( str len -- TRUE | FALSE )
+ path-table path-tbl-size + path-table ptable @ + DO ( str len )
+ 2dup I 6 + w@-be index @ = ( str len str len )
+ -rot I 8 + I c@ str= and IF ( str len )
+ s" Directory Matched!! " iso-debug-print ( str len )
+ self @ index ! ( str len )
+ I 2 + l@-be dir-addr ! I dup ( str len rec-addr )
+ get-next-record + path-table - ptable ! ( str len )
+ 2drop TRUE UNLOOP EXIT ( TRUE )
+ THEN
+ I get-next-record ( str len next-rec-offset )
+ +LOOP
+ 2drop
+ FALSE ( FALSE )
+ s" Invalid path / directory " iso-debug-print
+;
+
+
+\ METHOD for searching for a file with in a direcotory
+
+: search-file-dir ( str len -- TRUE | FALSE )
+ dir-addr @ 800 * dir-addr ! ( str len )
+ dir-addr @ 100 read-data ( str len )
+ data-buff @ 0e + l@-be dup >r ( str len rec-len )
+ 100 > IF ( str len )
+ s" size dir record" iso-debug-print ( str len )
+ dir-addr @ r@ read-data ( str len )
+ THEN
+ r> data-buff @ + data-buff @ DO ( str len )
+ I 19 + c@ 2 and invert IF ( str len )
+ 2dup ( str len str len )
+ I 21 + I 20 + c@ ( str len str len str' len' )
+ file-name str= IF ( str len )
+ s" File found!" iso-debug-print ( str len )
+ I 6 + l@-be 800 * ( str len file-loc )
+ file-loc ! ( str len )
+ I 0e + l@-be file-size ! ( str len )
+ 2drop
+ TRUE ( TRUE )
+ UNLOOP
+ EXIT
+ THEN
+ THEN
+ I c@ dup 0= IF ( str len len )
+ s" file not found" iso-debug-print
+ drop 2drop FALSE ( FALSE )
+ UNLOOP
+ EXIT
+ THEN
+ +LOOP
+ 2drop
+ FALSE ( FALSE )
+ s" file not found" iso-debug-print
+;
+
+
+\ This method splits the given absolute path in to directories from root and
+\ calls search-path-table. when string reaches to state when it can not be
+\ split i.e., end of the path, calls search-file-dir is made to search for
+\ file .
+
+: search-path ( str len -- FALSE|TRUE )
+ 0 ptable !
+ 1 self !
+ 1 index !
+ dup ( str len len )
+ 0= IF
+ 3drop FALSE ( FALSE )
+ s" Empty path name " iso-debug-print EXIT ( FALSE )
+ THEN
+ OVER c@ ( str len char )
+ [char] \ = IF ( str len )
+ swap 1 + swap 1 - BEGIN ( str len )
+ [char] \ split ( str len str' len ' )
+ dup 0 = IF ( str len str' len ' )
+ 2drop search-file-dir EXIT ( TRUE | FALSE )
+ ELSE
+ 2swap path-table-search invert IF ( str' len ' )
+ 2drop FALSE EXIT ( FALSE )
+ THEN
+ THEN
+ AGAIN
+ ELSE BEGIN
+ [char] \ split dup 0 = IF ( str len str' len' )
+ 2drop search-file-dir EXIT ( TRUE | FALSE )
+ ELSE
+ 2swap path-table-search invert IF ( str' len ' )
+ 2drop FALSE EXIT ( FALSE )
+ THEN
+ THEN
+ AGAIN
+ THEN
+;
+
+
+\ this method will seek and read the file in to the given memory location
+
+0 VALUE loc
+: load ( addr -- len )
+ dup to loc ( addr )
+ file-loc @ xlsplit seek drop
+ file-size @ read ( file-size )
+ iso-debug-flag IF s" Bytes returned from read:" type dup . cr THEN
+ dup file-size @ <> ABORT" read failed!"
+;
+
+
+
+\ memory used by the file system will be freed
+
+: close ( -- )
+ free-data count 1 - dup to count 0 = IF
+ path-table path-tbl-size free-mem
+ 0 TO path-table
+ THEN
+;
+
+
+\ open method of the file system
+
+: open ( -- TRUE | FALSE )
+ 0 data-buff !
+ 0 #data !
+ 0 ptable !
+ 0 file-loc !
+ 0 file-size !
+ 0 cur-file-offset !
+ 1 self !
+ 1 index !
+ count 0 = IF
+ s" extract-vol-info called " iso-debug-print
+ extract-vol-info
+ THEN
+ count 1 + to count
+ my-args search-path IF
+ file-loc @ xlsplit seek drop
+ TRUE ( TRUE )
+ ELSE
+ close
+ FALSE ( FALSE )
+ THEN
+ 0 cur-file-offset !
+ s" opened ISO9660 package" iso-debug-print
+;
+
+
+\ public seek method
+
+: seek ( pos.lo pos.hi -- status )
+ lxjoin dup cur-file-offset ! ( offset )
+ file-loc @ + xlsplit ( pos.lo pos.hi )
+ s" seek" $call-parent ( status )
+;
+
+
+\ public read method
+
+ : read ( addr len -- actual )
+ file-size @ cur-file-offset @ - ( addr len remainder-of-file )
+ min ( addr len|remainder-of-file )
+ s" read" $call-parent ( actual )
+ dup cur-file-offset @ + cur-file-offset ! ( actual )
+ cur-file-offset @ ( offset actual )
+ xlsplit seek drop ( actual )
+;
+
diff --git a/slof/fs/packages/obp-tftp.fs b/slof/fs/packages/obp-tftp.fs
new file mode 100644
index 0000000..0e3b35d
--- /dev/null
+++ b/slof/fs/packages/obp-tftp.fs
@@ -0,0 +1,55 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+s" obp-tftp" device-name
+
+INSTANCE VARIABLE ciregs-buffer
+
+: open ( -- okay? )
+ ciregs-size alloc-mem ciregs-buffer !
+ true
+;
+
+: load ( addr -- size )
+
+ \ Save old client interface register
+ ciregs ciregs-buffer @ ciregs-size move
+
+ s" bootargs" get-chosen 0= IF 0 0 THEN >r >r
+ s" bootpath" get-chosen 0= IF 0 0 THEN >r >r
+
+ \ Set bootpath to current device
+ my-parent ihandle>phandle node>path encode-string
+ s" bootpath" set-chosen
+
+ \ Generate arg string for snk like
+ \ "netboot load-addr length filename"
+ (u.) s" netboot " 2swap $cat s" 60000000 " $cat
+ my-args $cat
+
+ \ Call SNK netboot loadr
+ (client-exec) dup 0< IF drop 0 THEN
+
+ \ Restore to old client interface register
+ ciregs-buffer @ ciregs ciregs-size move
+
+ r> r> over IF s" bootpath" set-chosen ELSE 2drop THEN
+ r> r> over IF s" bootargs" set-chosen ELSE 2drop THEN
+;
+
+: close ( -- )
+ ciregs-buffer @ ciregs-size free-mem
+;
+
+: ping ( -- )
+ s" ping " my-args $cat (client-exec)
+;
diff --git a/slof/fs/packages/rom-files.fs b/slof/fs/packages/rom-files.fs
new file mode 100644
index 0000000..2a93e0a
--- /dev/null
+++ b/slof/fs/packages/rom-files.fs
@@ -0,0 +1,85 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ package which adds support to read the romfs
+\ this package is somehow limited as the maximum supported length
+\ for a file name is hardcoded to 0x100
+
+s" rom-files" device-name
+
+INSTANCE VARIABLE length
+INSTANCE VARIABLE next-file
+INSTANCE VARIABLE buffer
+INSTANCE VARIABLE buffer-size
+INSTANCE VARIABLE file
+INSTANCE VARIABLE file-size
+INSTANCE VARIABLE found
+
+: open true
+ 100 dup buffer-size ! alloc-mem buffer ! false found ! ;
+: close buffer @ buffer-size @ free-mem ;
+
+: read ( addr len -- actual ) s" read" $call-parent ;
+
+: seek ( lo hi -- status ) s" seek" $call-parent ;
+
+: .read-file-name ( offset -- str len )
+ \ move to the file name offset
+ 0 seek drop
+ \ read <buffer-size> bytes from that address
+ buffer @ buffer-size @ read drop
+ \ write a 0 to make sure it is a 0 terminated string
+ buffer-size @ 1 - buffer @ + 0 swap c!
+ buffer @ zcount ;
+
+: .print-info ( offset -- )
+ dup 2 spaces 6 0.r 2 spaces dup
+ 8 + 0 seek drop length 8 read drop
+ 6 length @ swap 0.r 2 spaces
+ 20 + .read-file-name type cr ;
+
+: .list-header cr
+ s" --offset---size-----file-name----" type cr ;
+
+: list
+ .list-header
+ 0 0 BEGIN + dup
+ .print-info dup 0 seek drop
+ next-file 8 read drop next-file @
+ dup 0= UNTIL 2drop ;
+
+: (find-file) ( name len -- offset | -1 )
+ 0 0 seek drop false found !
+ file-size ! file ! 0 0 BEGIN + dup
+ 20 + .read-file-name file @ file-size @
+ str= IF true found ! THEN
+ dup 0 seek drop
+ next-file 8 read drop next-file @
+ dup 0= found @ or UNTIL drop found @ 0=
+ IF drop -1 THEN ;
+
+: load ( addr -- size )
+ my-parent instance>args 2@ [char] \ left-parse-string 2drop
+ (find-file) dup -1 = IF 2drop 0 ELSE
+ \ got to the beginning
+ 0 0 seek drop
+ \ read the file size
+ dup 8 + 0 seek drop
+ here 8 read drop here @ ( dest-addr offset file-size )
+ \ read data start offset
+ over 18 + 0 seek drop
+ here 8 read drop here @ ( dest-addr offset file-size data-offset )
+ rot + 0 seek drop ( dest-addr file-size )
+ read
+ THEN
+;
diff --git a/slof/fs/packages/scsi.fs b/slof/fs/packages/scsi.fs
new file mode 100644
index 0000000..3d40700
--- /dev/null
+++ b/slof/fs/packages/scsi.fs
@@ -0,0 +1,183 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+s" scsi" device-name
+
+
+\ Standard Open Firmware method
+
+: open true ;
+
+
+\ Standard Open Firmware method
+
+: close ;
+
+
+\ Temporary pointer to SCSI command area
+
+0 VALUE command
+
+
+\ Temporary pointer to SCSI response Buffer
+
+0 VALUE response
+
+
+\ Builds SCSI READ command in the buffer
+\ This method will take starting Address as an input
+
+: build-read ( address lba #blocks -- )
+ 2 pick to command
+ command 0c erase
+ dup 7fff < IF
+ \ Use READ (10) command - understood by all devices
+ 28 command c! ( address lba #blocks )
+ command 7 + w! ( address lba ) \ Set transfer length
+ command 2 + l! ( address ) \ Set logical block address
+ ELSE
+ \ Use READ (12) command - needed for large #blocks
+ A8 command c! ( address lba #blocks )
+ command 2 + l! ( address lba ) \ Set transfer length
+ command 6 + l! ( address ) \ Set logical block address
+ THEN
+ drop
+;
+
+
+\ Builds SCSI MODE-SENSE command in the Buffer
+\ This method will take the starting address as an input
+
+: build-mode-sense ( address alloc-len page-code page-control -- )
+ 3 pick to command ( address alloc-len page-code page-control )
+ command 0c erase ( address alloc-len page-code page-control )
+ 6 lshift or command 2 + c! ( address alloc-len )
+ swap 7 + w! \ Configure allocation length
+;
+
+
+\ Builds READ CAPACITY command in the buffer
+
+: build-read-capacity ( address -- )
+ TO command
+ command 0c erase \ Clear buffer
+ 25 command c! \ set Opcode
+;
+
+
+\ Builds SCSI TEST-UNIT-READY command in the Buffer
+\ This method will take the starting address as an input
+
+: build-test-unit-ready ( address -- ) TO command command 0c erase ;
+
+
+\ Builds SCSI INQUIRY command in the Buffer
+\ This method will take the starting address as an input
+
+: build-inquiry ( address alloc-len -- )
+ swap TO command ( alloc-len )
+ command 0c erase ( alloc-len )
+ command 4 + c! \ Set allocation length
+ 12 command c! \ set Opcode
+;
+
+
+\ Analyse response of build-inquiry command
+
+: return-inquiry ( address -- verson peripheral-type )
+ TO response
+ response 3 + c@ 4 rshift ( version# ) \ SCSI version num
+ response c@ ( version# peripheral-device-type )
+;
+
+
+\ Builds SCSI REQUEST-SENSE command in the Buffer
+\ This method will take the starting address as an input
+
+: build-request-sense ( address alloc-len -- )
+ swap TO command ( alloc-len )
+ command 0c erase ( alloc-len )
+ 03 command c! ( alloc-len)
+ command 4 + c! \ Configure the allocation length
+;
+
+
+\ Analyse reply of REQUEST-SENSE command in the Buffer
+\ This method will take Starting address as an input
+
+: return-request-sense ( address -- false|ascq asc sense-key true )
+ TO response
+ response c@ 71
+ = response c@ 70 = or IF ( TRUE | FALSE )
+ response 0D + c@ ( ASCQ ) \ additional sense code qualifier
+ response 0c + c@ ( ASCQ ASC) \ additional sense code
+ response 2 + c@ ( ASCQ ASC sense-key ) \ sense key error descriptor
+ TRUE ( ASCQ ASC sense-key TRUE )
+ ELSE
+ FALSE ( FALSE )
+ THEN
+;
+
+
+\ Builds SCSI SEEK command in the Buffer
+\ This method will take the starting address as an input
+
+: build-seek ( address lba -- )
+ swap TO command ( lba )
+ command 0c erase ( lba )
+ 2b command c! ( lba ) \ Configure the Opcode
+ command 2 + l! \ Configure the logical block address
+;
+
+
+\ Builds SCSI LOAD command in the Buffer
+\ This method will take the starting address as an input
+
+\ : build-load ( address -- )
+\ TO command
+\ command 0c erase
+\ 1b command c! \ Cofigure opcode
+\ 03 command 4 + c! \ configure load bit and start bit
+\ ;
+
+
+\ Builds SCSI UNLOAD command in the Buffer
+\ This method will take the starting address as an input
+
+\ : build-unload ( address -- )
+\ to command
+\ command 0c erase
+\ 1b command c! \ Configure Opcode
+\ 02 command 4 + c! \ Configure unload bit and start bit
+\ ;
+
+
+\ Builds SCSI START command in the Buffer
+\ This method will take the starting address as an input
+
+: build-start ( address -- )
+ TO command
+ command 0c erase
+ 1b command c! \ Configure Opcode
+ 01 command 4 + c!
+;
+
+
+\ Builds SCSI STOP command in the Buffer
+\ This method will take the starting address as an input
+
+: build-stop ( address -- )
+ TO command
+ command 0c erase
+ 1b command c! \ Configure Opcode
+;
+
diff --git a/slof/fs/packages/sms.fs b/slof/fs/packages/sms.fs
new file mode 100644
index 0000000..7df46c0
--- /dev/null
+++ b/slof/fs/packages/sms.fs
@@ -0,0 +1,34 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" sms.fs" romfs-lookup [IF]
+ drop
+
+ s" /packages" find-device
+
+ new-device
+
+ s" sms" device-name
+
+ : open true ;
+
+ : close ;
+
+ \ The rest of methods is loaded dynamically from the romfs
+ \ on a first call to sms-start
+
+ finish-device
+
+ device-end
+[THEN]
+
diff --git a/slof/fs/pci-bridge.fs b/slof/fs/pci-bridge.fs
new file mode 100644
index 0000000..140f37a
--- /dev/null
+++ b/slof/fs/pci-bridge.fs
@@ -0,0 +1,62 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ get the PUID from the node above
+s" my-puid" $call-parent CONSTANT my-puid
+\ Save the bus number provided by this bridge
+pci-bus-number 1+ CONSTANT my-bus
+
+s" pci-config-bridge.fs" included
+
+\ generate the rom-fs filename from the vendor and device ID "pci-bridge_VENDORID_DEVICEID.fs"
+: filename ( -- str len )
+ s" pci-bridge_"
+ my-space pci-vendor@ 4 int2str $cat
+ s" _" $cat
+ my-space pci-device@ 4 int2str $cat
+ s" .fs" $cat
+;
+
+\ Set up the Bridge with either default or special settings
+: setup ( -- )
+ \ is there special handling for this device, given vendor and device id?
+ filename romfs-lookup ?dup
+ IF
+ \ give it a special treatment
+ evaluate
+ ELSE
+ \ no special handling for this device, attempt autoconfiguration
+ my-space pci-class-name type 2a emit cr
+ my-space pci-bridge-generic-setup
+ my-space pci-reset-2nd
+ THEN
+;
+
+\ Disable Bus Master, Memory Space and I/O Space for
+\ this device and so for the scanning for the devices behind
+pci-device-disable
+
+\ Enalbe #PERR and #SERR reporting
+pci-error-enable
+
+\ Print out device information
+my-space 42 pci-out \ config-addr ascii('B')
+
+\ and set up the bridge
+setup
+
+\ And enable Bus Master IO and MEM access again.
+\ we need that on bridges so that the devices behind
+\ can set their state on their own.
+pci-master-enable
+pci-mem-enable
+pci-io-enable
diff --git a/slof/fs/pci-class-code-names.fs b/slof/fs/pci-class-code-names.fs
new file mode 100644
index 0000000..a511c41
--- /dev/null
+++ b/slof/fs/pci-class-code-names.fs
@@ -0,0 +1,263 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: pci-class-name-00 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 01 OF s" display" ENDOF
+ dup OF s" unknown-legacy-device" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-01 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" scsi" ENDOF
+ 01 OF s" ide" ENDOF
+ 02 OF s" fdc" ENDOF
+ 03 OF s" ipi" ENDOF
+ 04 OF s" raid" ENDOF
+ 05 OF s" ata" ENDOF
+ 06 OF s" sata" ENDOF
+ 07 OF s" sas" ENDOF
+ dup OF s" mass-storage" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-02 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" ethernet" ENDOF
+ 01 OF s" token-ring" ENDOF
+ 02 OF s" fddi" ENDOF
+ 03 OF s" atm" ENDOF
+ 04 OF s" isdn" ENDOF
+ 05 OF s" worldfip" ENDOF
+ 05 OF s" picmg" ENDOF
+ dup OF s" network" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-03 ( addr -- str len )
+ pci-class@ FFFF and CASE
+ 0000 OF s" vga" ENDOF
+ 0001 OF s" 8514-compatible" ENDOF
+ 0100 OF s" xga" ENDOF
+ 0200 OF s" 3d-controller" ENDOF
+ dup OF s" display" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-04 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" video" ENDOF
+ 01 OF s" sound" ENDOF
+ 02 OF s" telephony" ENDOF
+ dup OF s" multimedia-device" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-05 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" memory" ENDOF
+ 01 OF s" flash" ENDOF
+ dup OF s" memory-controller" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-06 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" host" ENDOF
+ 01 OF s" isa" ENDOF
+ 02 OF s" eisa" ENDOF
+ 03 OF s" mca" ENDOF
+ 04 OF s" pci" ENDOF
+ 05 OF s" pcmcia" ENDOF
+ 06 OF s" nubus" ENDOF
+ 07 OF s" cardbus" ENDOF
+ 08 OF s" raceway" ENDOF
+ 09 OF s" semi-transparent-pci" ENDOF
+ 0A OF s" infiniband" ENDOF
+ dup OF s" unkown-bridge" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-07 ( addr -- str len )
+ pci-class@ FFFF and CASE
+ 0000 OF s" serial" ENDOF
+ 0001 OF s" 16450-serial" ENDOF
+ 0002 OF s" 16550-serial" ENDOF
+ 0003 OF s" 16650-serial" ENDOF
+ 0004 OF s" 16750-serial" ENDOF
+ 0005 OF s" 16850-serial" ENDOF
+ 0006 OF s" 16950-serial" ENDOF
+ 0100 OF s" parallel" ENDOF
+ 0101 OF s" bi-directional-parallel" ENDOF
+ 0102 OF s" ecp-1.x-parallel" ENDOF
+ 0103 OF s" ieee1284-controller" ENDOF
+ 01FE OF s" ieee1284-device" ENDOF
+ 0200 OF s" multiport-serial" ENDOF
+ 0300 OF s" modem" ENDOF
+ 0301 OF s" 16450-modem" ENDOF
+ 0302 OF s" 16550-modem" ENDOF
+ 0303 OF s" 16650-modem" ENDOF
+ 0304 OF s" 16750-modem" ENDOF
+ 0400 OF s" gpib" ENDOF
+ 0500 OF s" smart-card" ENDOF
+ dup OF s" communication-controller" ENDOF
+ ENDCASE
+;
+
+
+: pci-class-name-08 ( addr -- str len )
+ pci-class@ FFFF and CASE
+ 0000 OF s" interrupt-controller" ENDOF
+ 0001 OF s" isa-pic" ENDOF
+ 0002 OF s" eisa-pic" ENDOF
+ 0010 OF s" io-apic" ENDOF
+ 0020 OF s" iox-apic" ENDOF
+ 0100 OF s" dma-controller" ENDOF
+ 0101 OF s" isa-dma" ENDOF
+ 0102 OF s" eisa-dma" ENDOF
+ 0200 OF s" timer" ENDOF
+ 0201 OF s" isa-system-timer" ENDOF
+ 0202 OF s" eisa-system-timer" ENDOF
+ 0300 OF s" rtc" ENDOF
+ 0301 OF s" isa-rtc" ENDOF
+ 0400 OF s" hot-plug-controller" ENDOF
+ 0500 OF s" sd-host-conrtoller" ENDOF
+ dup OF s" system-periphal" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-09 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" keyboard" ENDOF
+ 01 OF s" pen" ENDOF
+ 02 OF s" mouse" ENDOF
+ 03 OF s" scanner" ENDOF
+ 04 OF s" gameport" ENDOF
+ dup OF s" input-controller" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-0A ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" dock" ENDOF
+ dup OF s" docking-station" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-0B ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" 386" ENDOF
+ 01 OF s" 486" ENDOF
+ 02 OF s" pentium" ENDOF
+ 10 OF s" alpha" ENDOF
+ 20 OF s" powerpc" ENDOF
+ 30 OF s" mips" ENDOF
+ 40 OF s" co-processor" ENDOF
+ dup OF s" cpu" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-0C ( addr -- str len )
+ pci-class@ FFFF and CASE
+ 0000 OF s" firewire" ENDOF
+ 0100 OF s" access-bus" ENDOF
+ 0200 OF s" ssa" ENDOF
+ 0300 OF s" usb-uhci" ENDOF
+ 0310 OF s" usb-ohci" ENDOF
+ 0320 OF s" usb-ehci" ENDOF
+ 0380 OF s" usb" ENDOF
+ 03FE OF s" usb-device" ENDOF
+ 0400 OF s" fibre-channel" ENDOF
+ 0500 OF s" smb" ENDOF
+ 0600 OF s" infiniband" ENDOF
+ 0700 OF s" ipmi-smic" ENDOF
+ 0701 OF s" ipmi-kbrd" ENDOF
+ 0702 OF s" ipmi-bltr" ENDOF
+ 0800 OF s" sercos" ENDOF
+ 0900 OF s" canbus" ENDOF
+ dup OF s" serial-bus" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-0D ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" irda" ENDOF
+ 01 OF s" consumer-ir" ENDOF
+ 10 OF s" rf-controller" ENDOF
+ 11 OF s" bluetooth" ENDOF
+ 12 OF s" broadband" ENDOF
+ 20 OF s" enet-802.11a" ENDOF
+ 21 OF s" enet-802.11b" ENDOF
+ dup OF s" wireless-controller" ENDOF
+ ENDCASE
+;
+
+
+: pci-class-name-0E ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ dup OF s" intelligent-io" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-0F ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 01 OF s" satelite-tv" ENDOF
+ 02 OF s" satelite-audio" ENDOF
+ 03 OF s" satelite-voice" ENDOF
+ 04 OF s" satelite-data" ENDOF
+ dup OF s" satelite-devoce" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-10 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" network-encryption" ENDOF
+ 01 OF s" entertainment-encryption" ENDOF
+ dup OF s" encryption" ENDOF
+ ENDCASE
+;
+
+: pci-class-name-11 ( addr -- str len )
+ pci-class@ 8 rshift FF and CASE
+ 00 OF s" dpio" ENDOF
+ 01 OF s" counter" ENDOF
+ 10 OF s" measurement" ENDOF
+ 20 OF s" managment-card" ENDOF
+ dup OF s" data-processing-controller" ENDOF
+ ENDCASE
+;
+
+\ create a string holding the predefined Class-Code-Names
+: pci-class-name ( addr -- str len )
+ dup pci-class@ 10 rshift CASE
+ 00 OF pci-class-name-00 ENDOF
+ 01 OF pci-class-name-01 ENDOF
+ 02 OF pci-class-name-02 ENDOF
+ 03 OF pci-class-name-03 ENDOF
+ 04 OF pci-class-name-04 ENDOF
+ 05 OF pci-class-name-05 ENDOF
+ 06 OF pci-class-name-06 ENDOF
+ 07 OF pci-class-name-07 ENDOF
+ 08 OF pci-class-name-08 ENDOF
+ 09 OF pci-class-name-09 ENDOF
+ 0A OF pci-class-name-0A ENDOF
+ 0B OF pci-class-name-0B ENDOF
+ 0C OF pci-class-name-0C ENDOF
+ 0C OF pci-class-name-0D ENDOF
+ 0C OF pci-class-name-0E ENDOF
+ 0C OF pci-class-name-0F ENDOF
+ 0C OF pci-class-name-10 ENDOF
+ 0C OF pci-class-name-11 ENDOF
+ dup OF drop s" unknown" ENDOF
+ ENDCASE
+;
diff --git a/slof/fs/pci-config-bridge.fs b/slof/fs/pci-config-bridge.fs
new file mode 100644
index 0000000..e8d1f49
--- /dev/null
+++ b/slof/fs/pci-config-bridge.fs
@@ -0,0 +1,85 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ define the config reads
+: config-b@ puid >r my-puid TO puid my-space + rtas-config-b@ r> TO puid ;
+: config-w@ puid >r my-puid TO puid my-space + rtas-config-w@ r> TO puid ;
+: config-l@ puid >r my-puid TO puid my-space + rtas-config-l@ r> TO puid ;
+
+\ define the config writes
+: config-b! puid >r my-puid TO puid my-space + rtas-config-b! r> TO puid ;
+: config-w! puid >r my-puid TO puid my-space + rtas-config-w! r> TO puid ;
+: config-l! puid >r my-puid TO puid my-space + rtas-config-l! r> TO puid ;
+
+\ for Debug purposes: dumps the whole config space
+: config-dump puid >r my-puid TO puid my-space pci-dump r> TO puid ;
+
+\ needed to find the right path in the device tree
+: decode-unit ( addr len -- phys.lo ... phys.hi )
+ 2 hex-decode-unit \ decode string
+ B lshift swap \ shift the devicenumber to the right spot
+ 8 lshift or \ add the functionnumber
+ my-bus 10 lshift or \ add the busnumber
+ 0 0 rot \ make phys.lo = 0 = phys.mid
+;
+
+\ needed to have the right unit address in the device tree listing
+\ phys.lo=phys.mid=0 , phys.hi=config-address
+: encode-unit ( phys.lo ... phys.hi -- unit-str unit-len )
+ nip nip \ forget the both zeros
+ dup 8 rshift 7 and swap \ calc Functionnumber
+ B rshift 1F and \ calc Devicenumber
+ over IF \ IF Function!=0
+ 2 hex-encode-unit \ | create string with DevNum,FnNum
+ ELSE \ ELSE
+ nip 1 hex-encode-unit \ | create string with only DevNum
+ THEN \ FI
+;
+
+: map-in ( phys.lo ... phys.hi size -- virt )
+ \ ." map-in called: " .s cr
+ 2drop drop
+;
+
+: map-out ( virt size -- )
+ \ ." map-out called: " .s cr
+ 2drop
+;
+
+: dma-alloc ( ... size -- virt )
+ \ ." dma-alloc called: " .s cr
+ alloc-mem
+;
+
+: dma-free ( virt size -- )
+ \ ." dma-free called: " .s cr
+ free-mem
+;
+
+: dma-map-in ( ... virt size cacheable? -- devaddr )
+ \ ." dma-map-in called: " .s cr
+ 2drop
+;
+
+: dma-map-out ( virt devaddr size -- )
+ \ ." dma-map-out called: " .s cr
+ 2drop drop
+;
+
+: dma-sync ( virt devaddr size -- )
+ \ XXX should we add at least a memory barrier here?
+ \ ." dma-sync called: " .s cr
+ 2drop drop
+;
+
+: open true ;
+: close ;
diff --git a/slof/fs/pci-device.fs b/slof/fs/pci-device.fs
new file mode 100644
index 0000000..c8b445e
--- /dev/null
+++ b/slof/fs/pci-device.fs
@@ -0,0 +1,101 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ get the PUID from the node above
+s" my-puid" $call-parent CONSTANT my-puid
+
+\ define the config reads
+: config-b@ puid >r my-puid TO puid my-space + rtas-config-b@ r> TO puid ;
+: config-w@ puid >r my-puid TO puid my-space + rtas-config-w@ r> TO puid ;
+: config-l@ puid >r my-puid TO puid my-space + rtas-config-l@ r> TO puid ;
+
+\ define the config writes
+: config-b! puid >r my-puid TO puid my-space + rtas-config-b! r> TO puid ;
+: config-w! puid >r my-puid TO puid my-space + rtas-config-w! r> TO puid ;
+: config-l! puid >r my-puid TO puid my-space + rtas-config-l! r> TO puid ;
+
+\ for Debug purposes: dumps the whole config space
+: config-dump puid >r my-puid TO puid my-space pci-dump r> TO puid ;
+
+\ prepare the device for subsequent use
+\ this word should be overloaded by the device file (if present)
+\ the device file can call this file before implementing
+\ its own open functionality
+: open
+ puid >r \ save the old puid
+ my-puid TO puid \ set up the puid to the devices Hostbridge
+ pci-master-enable \ And enable Bus Master, IO and MEM access again.
+ pci-mem-enable \ enable mem access
+ pci-io-enable \ enable io access
+ r> TO puid \ restore puid
+ true
+;
+
+\ close the previously opened device
+\ this word should be overloaded by the device file (if present)
+\ the device file can call this file after its implementation
+\ of own close functionality
+: close
+ puid >r \ save the old puid
+ my-puid TO puid \ set up the puid
+ pci-device-disable \ and disable the device
+ r> TO puid \ restore puid
+;
+
+\ generate the rom-fs filename from the vendor and device ID "pci-device_VENDORID_DEVICEID.fs"
+: devicefile ( -- str len )
+ s" pci-device_"
+ my-space pci-vendor@ 4 int2str $cat
+ s" _" $cat
+ my-space pci-device@ 4 int2str $cat
+ s" .fs" $cat
+;
+
+\ generate the rom-fs filename from the base-class id "pci-class_BASECLASS.fs"
+: classfile ( -- str len )
+ s" pci-class_"
+ my-space pci-class@ 10 rshift 2 int2str $cat
+ s" .fs" $cat
+;
+
+\ Set up the device with either default or special settings
+: setup ( -- )
+ \ is there special handling for this device, given vendor and device id?
+ devicefile romfs-lookup ?dup
+ IF
+ \ give it a special treatment
+ evaluate
+ ELSE
+ classfile romfs-lookup ?dup
+ IF
+ \ give it a pci-class related treatment
+ evaluate
+ ELSE
+ \ no special handling for this device, attempt autoconfiguration
+ my-space pci-class-name type 2a emit cr
+ my-space pci-device-generic-setup
+ THEN
+ THEN
+;
+
+\ Disable Bus Master, Memory Space and I/O Space for this device
+\ if Bus Master function is needed it should be enabled/disabled by open/close in the device driver code
+pci-device-disable
+
+\ Enalbe #PERR and #SERR reporting
+pci-error-enable
+
+\ Print out device information
+my-space 44 pci-out \ config-addr ascii('D')
+
+\ and set up the device
+setup
diff --git a/slof/fs/pci-properties.fs b/slof/fs/pci-properties.fs
new file mode 100644
index 0000000..aab8f13
--- /dev/null
+++ b/slof/fs/pci-properties.fs
@@ -0,0 +1,650 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+#include "pci-class-code-names.fs"
+
+\ read the various bar type sizes
+: pci-bar-size@ ( bar-addr -- bar-size ) -1 over rtas-config-l! rtas-config-l@ ;
+: pci-bar-size-mem@ ( bar-addr -- mem-size ) pci-bar-size@ -10 and invert 1+ FFFFFFFF and ;
+: pci-bar-size-io@ ( bar-addr -- io-size ) pci-bar-size@ -4 and invert 1+ FFFFFFFF and ;
+
+\ fetch raw bar size but keep original BAR value
+: pci-bar-size ( bar-addr -- bar-size-raw )
+ dup rtas-config-l@ swap \ fetch original Value ( bval baddr )
+ -1 over rtas-config-l! \ make BAR show size ( bval baddr )
+ dup rtas-config-l@ \ and fetch the size ( bval baddr bsize )
+ -rot rtas-config-l! \ restore Value
+;
+
+\ calc 32 bit MEM BAR size
+: pci-bar-size-mem32 ( bar-addr -- bar-size )
+ pci-bar-size \ fetch raw size
+ -10 and invert 1+ \ calc size
+ FFFFFFFF and \ keep lower 32 bits
+;
+
+\ calc 32 bit ROM BAR size
+: pci-bar-size-rom ( bar-addr -- bar-size )
+ pci-bar-size \ fetch raw size
+ FFFFF800 and invert 1+ \ calc size
+ FFFFFFFF and \ keep lower 32 bits
+;
+
+
+\ calc 64 bit MEM BAR size
+: pci-bar-size-mem64 ( bar-addr -- bar-size )
+ dup pci-bar-size \ fetch raw size lower 32 bits
+ swap 4 + pci-bar-size \ fetch raw size upper 32 bits
+ 20 lshift + \ and put them together
+ -10 and invert 1+ \ calc size
+;
+
+\ calc IO BAR size
+: pci-bar-size-io ( bar-addr -- bar-size )
+ pci-bar-size \ fetch raw size
+ -4 and invert 1+ \ calc size
+ FFFFFFFF and \ keep lower 32 bits
+;
+
+
+\ decode the Bar Type
+\ +----------------------------------------------------------------------------------------+
+\ | 3 2 1 0 |
+\ | +----------------------------+-+--+-+ |
+\ | MEM-BAR : | Base Address |P|TT|0| P - prefechtable ; TT - 00 : 32 Bit |
+\ | +----------------------------+-+--+-+ 10 : 64 Bit |
+\ | +-------------------------------+-+-+ |
+\ | IO-BAR : | Base Address |0|1| |
+\ | +-------------------------------+-+-+ |
+\ | That is: 0 - no encoded BarType |
+\ | 1 - IO - Bar |
+\ | 2 - Memory 32 Bit |
+\ | 3 - Memory 32 Bit prefetchable |
+\ | 4 - Memory 64 Bit |
+\ | 5 - Memory 64 Bit prefetchable |
+\ +----------------------------------------------------------------------------------------+
+: pci-bar-code@ ( bar-addr -- 0|1..4|5 )
+ rtas-config-l@ dup \ fetch the BaseAddressRegister
+ 1 and IF \ IO BAR ?
+ 2 and IF 0 ELSE 1 THEN \ only '01' is valid
+ ELSE \ Memory BAR ?
+ F and CASE
+ 0 OF 2 ENDOF \ Memory 32 Bit Non-Prefetchable
+ 8 OF 3 ENDOF \ Memory 32 Bit Prefetchable
+ 4 OF 4 ENDOF \ Memory 64 Bit Non-Prefetchable
+ C OF 5 ENDOF \ Memory 64 Bit Prefechtable
+ dup OF 0 ENDOF \ Not a valid BarType
+ ENDCASE
+ THEN
+;
+
+\ ***************************************************************************************
+\ Assigning the new Value to the BARs
+\ ***************************************************************************************
+\ align the current mem and set var to next mem
+\ align with a size of 0 returns 0 !!!
+: assign-var ( size var -- al-mem )
+ 2dup @ \ ( size var size cur-mem ) read current free mem
+ swap #aligned \ ( size var al-mem ) align the mem to the size
+ dup 2swap -rot + \ ( al-mem var new-mem ) add size to aligned mem
+ swap ! \ ( al-mem ) set variable to new mem
+;
+
+\ set bar to current free mem ( in variable ) and set variable to next free mem
+: assign-bar-value32 ( bar size var -- 4 )
+ over IF \ IF size > 0
+ assign-var \ | ( bar al-mem ) set variable to next mem
+ swap rtas-config-l! \ | ( -- ) set the bar to al-mem
+ ELSE \ ELSE
+ 2drop drop \ | clear stack
+ THEN \ FI
+ 4 \ size of the base-address-register
+;
+
+\ set bar to current free mem ( in variable ) and set variable to next free mem
+: assign-bar-value64 ( bar size var -- 8 )
+ over IF \ IF size > 0
+ assign-var \ | ( bar al-mem ) set variable to next mem
+ swap \ | ( al-mem addr ) calc config-addr of this bar
+ 2dup rtas-config-l! \ | ( al-mem addr ) set the Lower part of the bar to al-mem
+ 4 + swap 20 rshift \ | ( al-mem>>32 addr ) prepare the upper part of the al-mem
+ swap rtas-config-l! \ | ( -- ) and set the upper part of the bar
+ ELSE \ ELSE
+ 2drop drop \ | clear stack
+ THEN \ FI
+ 8 \ size of the base-address-register
+;
+
+\ Setup a prefetchable 64bit BAR and return its size
+: assign-mem64-bar ( bar-addr -- 8 )
+ dup pci-bar-size-mem64 \ fetch size
+ pci-next-mem \ var to change
+ assign-bar-value64 \ and set it all
+;
+
+\ Setup a prefetchable 32bit BAR and return its size
+: assign-mem32-bar ( bar-addr -- 4 )
+ dup pci-bar-size-mem32 \ fetch size
+ pci-next-mem \ var to change
+ assign-bar-value32 \ and set it all
+;
+
+\ Setup a non-prefetchable 64bit BAR and return its size
+: assign-mmio64-bar ( bar-addr -- 8 )
+ dup pci-bar-size-mem64 \ fetch size
+ pci-next-mmio \ var to change
+ assign-bar-value64 \ and set it all
+;
+
+\ Setup a non-prefetchable 32bit BAR and return its size
+: assign-mmio32-bar ( bar-addr -- 4 )
+ dup pci-bar-size-mem32 \ fetch size
+ pci-next-mmio \ var to change
+ assign-bar-value32 \ and set it all
+;
+
+\ Setup an IO-Bar and return the size of the base-address-register
+: assign-io-bar ( bar-addr -- 4 )
+ dup pci-bar-size-io \ fetch size
+ pci-next-io \ var to change
+ assign-bar-value32 \ and set it all
+;
+
+\ Setup an Expansion ROM bar
+: assign-rom-bar ( bar-addr -- )
+ dup pci-bar-size-rom \ fetch size
+ dup IF \ IF size > 0
+ over >r \ | save bar addr for enable
+ pci-next-mmio \ | var to change
+ assign-bar-value32 \ | and set it
+ drop \ | forget the BAR length
+ r@ rtas-config-l@ \ | fetch BAR
+ 1 or r> rtas-config-l! \ | and enable the ROM
+ ELSE \ ELSE
+ 2drop \ | clear stack
+ THEN
+;
+
+\ Setup the BAR due to its type and return the size of the register (4 or 8 Bytes ) used as increment for the BAR-Loop
+: assign-bar ( bar-addr -- reg-size )
+ dup pci-bar-code@ \ calc BAR type
+ dup IF \ IF >0
+ CASE \ | CASE Setup the right type
+ 1 OF assign-io-bar ENDOF \ | - set up an IO-Bar
+ 2 OF assign-mmio32-bar ENDOF \ | - set up an 32bit MMIO-Bar
+ 3 OF assign-mem32-bar ENDOF \ | - set up an 32bit MEM-Bar (prefetchable)
+ 4 OF assign-mmio64-bar ENDOF \ | - set up an 64bit MMIO-Bar
+ 5 OF assign-mem64-bar ENDOF \ | - set up an 64bit MEM-Bar (prefetchable)
+ ENDCASE \ | ESAC
+ ELSE \ ELSE
+ ABORT \ | Throw an exception
+ THEN \ FI
+;
+
+\ Setup all the bars of a pci device
+: assign-all-device-bars ( configaddr -- )
+ 28 10 DO \ BARs start at 10 and end at 27
+ dup i + \ calc config-addr of the BAR
+ assign-bar \ and set it up
+ +LOOP \ add 4 or 8 to the index and loop
+ 30 + assign-rom-bar \ set up the ROM if available
+;
+
+\ Setup all the bars of a pci device
+: assign-all-bridge-bars ( configaddr -- )
+ 18 10 DO \ BARs start at 10 and end at 17
+ dup i + \ calc config-addr of the BAR
+ assign-bar \ and set it up
+ +LOOP \ add 4 or 8 to the index and loop
+ 38 + assign-rom-bar \ set up the ROM if available
+;
+
+\ +---------------------------------------------------------------------------------------+
+\ | Numerical Representaton of a PCI address (PCI Bus Binding 2.2.1.1) |
+\ | |
+\ | 31 24 16 11 8 0 |
+\ | +--------+--------+-----+---+--------+ |
+\ | phys.hi: |npt000ss| bus | dev |fnc| reg | n - 0 relocatable |
+\ | +--------+--------+-----+---+--------+ p - 1 prefetchable |
+\ | t - 1 aliased or <1MB or <64KB |
+\ | ss - 00 Configuration Space |
+\ | 01 I/O Space |
+\ | 10 Memory Space 32bits |
+\ | 11 Memory Space 64bits |
+\ +---------------------------------------------------------------------------------------+
+
+\ ***************************************************************************************
+\ Generating the assigned-addresses property
+\ ***************************************************************************************
+\ generate assigned-addresses property for 64Bit MEM-BAR and return BAR-reg-size
+: gen-mem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
+ dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
+ over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size)
+ 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val )
+ 83000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 8 \ sizeof(BAR) = 8 Bytes
+;
+
+\ generate assigned-addresses property for prefetchable 64Bit MEM-BAR and return BAR-reg-size
+: gen-pmem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
+ dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
+ over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size)
+ 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val )
+ C3000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 8 \ sizeof(BAR) = 8 Bytes
+;
+
+\ generate assigned-addresses property for 32Bit MEM-BAR and return BAR-reg-size
+: gen-mem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
+ dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
+ -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
+ 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ sizeof(BAR) = 4 Bytes
+;
+
+\ generate assigned-addresses property for prefetchable 32Bit MEM-BAR and return BAR-reg-size
+: gen-pmem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
+ dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
+ -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
+ C2000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ sizeof(BAR) = 4 Bytes
+;
+
+\ generate assigned-addresses property for IO-BAR and return BAR-reg-size
+: gen-io-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
+ dup pci-bar-size-io \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
+ -4 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
+ 81000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ sizeof(BAR) = 4 Bytes
+;
+
+\ generate assigned-addresses property for ROM-BAR
+: gen-rom-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len )
+ dup pci-bar-size-rom \ fetch BAR Size ( paddr plen baddr bsize )
+ dup IF \ IF Size > 0
+ >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
+ FFFFF800 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
+ 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
+ r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
+ r> encode-64+ \ | Encode size ( paddr plen )
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+;
+
+\ add another BAR to the assigned addresses property and return the size of the encoded register
+: pci-add-assigned-address ( prop-addr prop-len bar-addr -- prop-addr prop-len bsize )
+ dup pci-bar-code@ \ calc BAR type ( paddr plen baddr btype)
+ CASE \ CASE for the BAR types ( paddr plen baddr )
+ 0 OF drop 4 ENDOF \ - not a valid type so do nothing
+ 1 OF gen-io-bar-prop ENDOF \ - IO-BAR
+ 2 OF gen-mem32-bar-prop ENDOF \ - MEM32
+ 3 OF gen-pmem32-bar-prop ENDOF \ - MEM32 prefetchable
+ 4 OF gen-mem64-bar-prop ENDOF \ - MEM64
+ 5 OF gen-pmem64-bar-prop ENDOF \ - MEM64 prefetchable
+ ENDCASE \ ESAC ( paddr plen bsize )
+;
+
+\ generate the assigned address property for a PCI device
+: pci-device-assigned-addresses-prop ( addr -- )
+ encode-start \ provide mem for property ( addr paddr plen )
+ 2 pick 30 + gen-rom-bar-prop \ assign the rom bar
+ 28 10 DO \ we have 6 possible BARs
+ 2 pick i + \ calc BAR address ( addr paddr plen bar-addr )
+ pci-add-assigned-address \ and generate the props for the BAR
+ +LOOP \ increase Index by returned len
+ s" assigned-addresses" property drop \ and write it into the device tree
+;
+
+\ generate the assigned address property for a PCI bridge
+: pci-bridge-assigned-addresses-prop ( addr -- )
+ encode-start \ provide mem for property
+ 2 pick 38 + gen-rom-bar-prop \ assign the rom bar
+ 18 10 DO \ we have 2 possible BARs
+ 2 pick i + \ ( addr paddr plen current-addr )
+ pci-add-assigned-address \ and generate the props for the BAR
+ +LOOP \ increase Index by returned len
+ s" assigned-addresses" property drop \ and write it into the device tree
+;
+
+\ check if the range is valid and if so encode it into
+\ child.hi child.mid child.lo parent.hi parent.mid parent.lo size.hi size.lo
+\ This is needed to translate the childrens addresses
+\ We implement only 1:1 mapping for all PCI bridges
+: pci-bridge-gen-range ( paddr plen base limit type -- paddr plen )
+ >r over - \ calc size ( paddr plen base size R:type )
+ dup 0< IF \ IF Size < 0 ( paddr plen base size R:type )
+ 2drop r> drop \ | forget values ( paddr plen )
+ ELSE \ ELSE
+ 1+ swap 2swap \ | adjust stack ( size base paddr plen R:type )
+ r@ encode-int+ \ | Child type ( size base paddr plen R:type )
+ 2 pick encode-64+ \ | Child address ( size base paddr plen R:type )
+ r> encode-int+ \ | Parent type ( size base paddr plen )
+ rot encode-64+ \ | Parent address ( size paddr plen )
+ rot encode-64+ \ | Encode size ( paddr plen )
+ THEN \ FI
+;
+
+
+\ generate an mmio space to the ranges property
+: pci-bridge-gen-mmio-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
+ 2 pick 20 + rtas-config-l@ \ fetch Value ( addr paddr plen val )
+ dup 0000FFF0 and 10 lshift \ calc base-address ( addr paddr plen val base )
+ swap 000FFFFF or \ calc limit-address ( addr paddr plen base limit )
+ 02000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
+;
+
+\ generate an mem space to the ranges property
+: pci-bridge-gen-mem-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
+ 2 pick 24 + rtas-config-l@ \ fetch Value ( addr paddr plen val )
+ dup 000FFFFF or \ calc limit Bits 31:0 ( addr paddr plen val limit.31:0 )
+ swap 0000FFF0 and 10 lshift \ calc base Bits 31:0 ( addr paddr plen limit.31:0 base.31:0 )
+ 4 pick 28 + rtas-config-l@ \ fetch upper Basebits ( addr paddr plen limit.31:0 base.31:0 base.63:32 )
+ 20 lshift or swap \ and calc Base ( addr paddr plen base.63:0 limit.31:0 )
+ 4 pick 2C + rtas-config-l@ \ fetch upper Limitbits ( addr paddr plen base.63:0 limit.31:0 limit.63:32 )
+ 20 lshift or \ and calc Limit ( addr paddr plen base.63:0 limit.63:0 )
+ 42000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
+;
+
+\ generate an io space to the ranges property
+: pci-bridge-gen-io-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
+ 2 pick 1C + rtas-config-l@ \ fetch Value ( addr paddr plen val )
+ dup 0000F000 and 00000FFF or \ calc Limit Bits 15:0 ( addr paddr plen val limit.15:0 )
+ swap 000000F0 and 8 lshift \ calc Base Bits 15:0 ( addr paddr plen limit.15:0 base.15:0 )
+ 4 pick 30 + rtas-config-l@ \ fetch upper Bits ( addr paddr plen limit.15:0 base.15:0 val )
+ dup FFFF and 10 lshift rot or \ calc Base ( addr paddr plen limit.15:0 val base.31:0 )
+ -rot FFFF0000 and or \ calc Limit ( addr paddr plen base.31:0 limit.31:0 )
+ 01000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
+;
+
+\ generate the ranges property for a PCI bridge
+: pci-bridge-range-props ( addr -- )
+ encode-start \ provide mem for property
+ pci-bridge-gen-mmio-range \ generate the non prefetchable Memory Entry
+ pci-bridge-gen-mem-range \ generate the prefetchable Memory Entry
+ pci-bridge-gen-io-range \ generate the IO Entry
+ dup IF \ IF any space present (propsize>0)
+ s" ranges" property \ | write it into the device tree
+ ELSE \ ELSE
+ 2drop \ | forget the properties
+ THEN \ FI
+ drop \ forget the address
+;
+
+\ create the interrupt map for this bridge
+: pci-bridge-interrupt-map ( -- )
+ encode-start \ create the property ( paddr plen )
+ get-node child \ find the first child ( paddr plen handle )
+ BEGIN dup WHILE \ Loop as long as the handle is non-zero ( paddr plen handle )
+ dup >r >space \ Get the my-space ( paddr plen addr R: handle )
+ pci-gen-irq-entry \ and Encode the interrupt settings ( paddr plen R: handle)
+ r> peer \ Get neighbour ( paddr plen handle )
+ REPEAT \ process next childe node ( paddr plen handle )
+ drop \ forget the null ( paddr plen )
+ s" interrupt-map" property \ and set it ( -- )
+ 1 encode-int s" #interrupt-cells" property \ encode the cell#
+ f800 encode-int 0 encode-int+ 0 encode-int+ \ encode the bit mask for config addr (Dev only)
+ 7 encode-int+ s" interrupt-map-mask" property \ encode IRQ#=7 and generate property
+;
+
+\ ***************************************************************************************
+\ Generating the reg property
+\ ***************************************************************************************
+\ reg = config-addr 0 0 0 0 [BAR-config-addr 0 0 size.high size.low]
+
+\ encode the reg prop for a nonprefetchable 32bit MEM-BAR
+: encode-mem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
+ dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR )
+ dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
+ >r 02000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | encode size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ BAR-Len = 4 (32Bit)
+;
+
+\ encode the reg prop for a prefetchable 32bit MEM-BAR
+: encode-pmem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
+ dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR )
+ dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
+ >r 42000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | encode size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ BAR-Len = 4 (32Bit)
+;
+
+\ encode the reg prop for a nonprefetchable 64bit MEM-BAR
+: encode-mem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
+ dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR )
+ dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
+ >r 03000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | encode size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 8 \ BAR-Len = 8 (64Bit)
+;
+
+\ encode the reg prop for a prefetchable 64bit MEM-BAR
+: encode-pmem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
+ dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR )
+ dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
+ >r 43000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | encode size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 8 \ BAR-Len = 8 (64Bit)
+;
+
+\ encode the reg prop for a ROM-BAR
+: encode-rom-bar ( prop-addr prop-len configaddr -- prop-addr prop-len )
+ dup pci-bar-size-rom \ fetch raw BAR-size
+ dup IF \ IF BAR is used
+ >r 02000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | calc and encode the size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+;
+
+\ encode the reg prop for an IO-BAR
+: encode-io-bar ( prop-addr prop-len BAR-addr BAR-value -- prop-addr prop-len 4 )
+ dup pci-bar-size-io \ calc BAR-size ( not changing the BAR )
+ dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
+ >r 01000000 or encode-int+ \ | save size and encode BAR addr
+ 0 encode-64+ \ | make mid and lo zero
+ r> encode-64+ \ | encode size
+ ELSE \ ELSE
+ 2drop \ | don't do anything
+ THEN \ FI
+ 4 \ BAR-Len = 4 (32Bit)
+;
+
+\ write the representation of this BAR into the reg property
+: encode-bar ( prop-addr prop-len bar-addr -- prop-addr prop-len bar-len )
+ dup pci-bar-code@ \ calc BAR type
+ CASE \ CASE for the BAR types ( paddr plen baddr val )
+ 0 OF drop 4 ENDOF \ - not a valid type so do nothing
+ 1 OF encode-io-bar ENDOF \ - IO-BAR
+ 2 OF encode-mem32-bar ENDOF \ - MEM32
+ 3 OF encode-pmem32-bar ENDOF \ - MEM32 prefetchable
+ 4 OF encode-mem64-bar ENDOF \ - MEM64
+ 5 OF encode-pmem64-bar ENDOF \ - MEM64 prefetchable
+ ENDCASE \ ESAC ( paddr plen blen )
+;
+
+\ Setup reg property
+\ first encode the configuration space address
+: pci-reg-props ( configaddr -- )
+ dup encode-int \ configuration space ( caddr paddr plen )
+ 0 encode-64+ \ make the rest 0
+ 0 encode-64+ \ encode the size as 0
+ 2 pick pci-htype@ \ fetch Header Type ( caddr paddr plen type )
+ 1 and IF \ IF Bridge ( caddr paddr plen )
+ 18 10 DO \ | loop over all BARs
+ 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr )
+ encode-bar \ | encode this BAR ( caddr paddr plen blen )
+ +LOOP \ | increase LoopIndex by the BARlen
+ 2 pick 38 + \ | calc ROM-BAR for a bridge ( caddr paddr plen baddr )
+ encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen )
+ ELSE \ ELSE ordinary device ( caddr paddr plen )
+ 28 10 DO \ | loop over all BARs
+ 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr )
+ encode-bar \ | encode this BAR ( caddr paddr plen blen )
+ +LOOP \ | increase LoopIndex by the BARlen
+ 2 pick 30 + \ | calc ROM-BAR for a device ( caddr paddr plen baddr )
+ encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen )
+ THEN \ FI ( caddr paddr plen )
+ s" reg" property \ and store it into the property
+ drop
+;
+
+\ ***************************************************************************************
+\ Generating common properties
+\ ***************************************************************************************
+\ set up common properties for devices and bridges
+: pci-common-props ( addr -- )
+ dup pci-class-name 2dup device-name device-type
+ dup pci-vendor@ encode-int s" vendor-id" property
+ dup pci-device@ encode-int s" device-id" property
+ dup pci-revision@ encode-int s" revision-id" property
+ dup pci-class@ encode-int s" class-code" property
+ 3 encode-int s" #address-cells" property
+ 2 encode-int s" #size-cells" property
+
+ dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN
+
+ dup pci-status@
+ dup 9 rshift 3 and encode-int s" devsel-speed" property
+ dup 7 rshift 1 and IF 0 0 s" fast-back-to-back" property THEN
+ dup 6 rshift 1 and IF 0 0 s" 66mhz-capable" property THEN
+ 5 rshift 1 and IF 0 0 s" udf-supported" property THEN
+ dup pci-cache@ ?dup IF encode-int s" cache-line-size" property THEN
+ pci-interrupt@ ?dup IF encode-int s" interrupts" property THEN
+;
+
+\ set up device only properties
+: pci-device-props ( addr -- )
+ \ FIXME no s" compatible" prop
+ \ FIXME no s" alternate-reg" prop
+ \ FIXME no s" fcode-rom-offset" prop
+ \ FIXME no s" power-consumption" prop
+ dup pci-common-props
+ dup pci-min-grant@ encode-int s" min-grant" property
+ dup pci-max-lat@ encode-int s" max-latency" property
+ dup pci-sub-device@ ?dup IF encode-int s" subsystem-id" property THEN
+ dup pci-sub-vendor@ ?dup IF encode-int s" subsystem-vendor-id" property THEN
+ dup pci-device-assigned-addresses-prop
+ pci-reg-props
+;
+
+\ set up bridge only properties
+: pci-bridge-props ( addr -- )
+ \ FIXME no s" slot-names" prop
+ \ FIXME no s" bus-master-capable" prop
+ \ FIXME no s" clock-frequency" prop
+ dup pci-bus@
+ encode-int s" primary-bus" property
+ encode-int s" secondary-bus" property
+ encode-int s" subordinate-bus" property
+ dup pci-bus@ drop encode-int rot encode-int+ s" bus-range" property
+ pci-device-slots encode-int s" slot-names" property
+ dup pci-bridge-range-props
+ dup pci-bridge-assigned-addresses-prop
+ pci-bridge-interrupt-map
+ pci-reg-props
+;
+
+\ FIXME still used in the device files slof/fs/devices/pci-device
+: assign-bar-mapping ( bar-offset size var -- )
+ rot my-unit-64 + -rot
+ assign-bar-value32 drop
+;
+
+\ FIXME this is still used by the devices in slof/fs/devices/pci-device_*
+: assigned-addresses-property ( -- )
+ my-unit-64
+ dup pci-common-props
+ pci-device-assigned-addresses-prop
+;
+
+\ used to set up all unknown Bridges.
+\ If a Bridge has no special handling for setup
+\ the device file (pci-bridge_VENDOR_DEVICE.fs) can call
+\ this word to setup busses and scan beyond.
+: pci-bridge-generic-setup ( addr -- )
+ pci-device-slots >r \ save the slot array on return stack
+ dup pci-common-props \ set the common properties before scanning the bus
+ s" pci" device-type \ the type is allways "pci"
+ dup pci-bridge-probe \ find all device connected to it
+ dup assign-all-bridge-bars \ set up all memory access BARs
+ dup pci-set-irq-line \ set the interrupt pin
+ dup pci-set-capabilities \ set up the capabilities
+ pci-bridge-props \ and generate all properties
+ r> TO pci-device-slots \ and reset the slot array
+;
+
+\ used for an gerneric device set up
+\ if a device has no special handling for setup
+\ the device file (pci-device_VENDOR_DEVICE.fs) can call
+\ this word to setup the device
+: pci-device-generic-setup ( config-addr -- )
+ dup assign-all-device-bars \ calc all BARs
+ dup pci-set-irq-line \ set the interrupt pin
+ dup pci-set-capabilities \ set up the capabilities
+ dup pci-device-props \ and generate all properties
+ drop \ forget the config-addr
+;
diff --git a/slof/fs/pci-scan.fs b/slof/fs/pci-scan.fs
new file mode 100644
index 0000000..e0cd813
--- /dev/null
+++ b/slof/fs/pci-scan.fs
@@ -0,0 +1,494 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ ----------------------------------------------------------
+\ ********** Variables to be set by host bridge **********
+\ ----------------------------------------------------------
+
+\ Values of the next free memory area
+VARIABLE pci-next-mem \ prefetchable memory mapped
+VARIABLE pci-max-mem
+VARIABLE pci-next-mmio \ non-prefetchable memory
+VARIABLE pci-max-mmio
+VARIABLE pci-next-io \ I/O space
+VARIABLE pci-max-io
+
+\ Counter of busses found
+0 VALUE pci-bus-number
+\ Counter of devices found
+0 VALUE pci-device-number
+\ bit field of devices plugged into this bridge
+0 VALUE pci-device-slots
+\ byte field holding the device-slot number vector of the current device
+\ the vector can be as deep as the max depth of bridges possible
+\ 3,4,5 means
+\ the 5th slot on the bus of the bridge in
+\ the 4th slot on the bus of the bridge in
+\ the 3rd slot on the HostBridge bus
+here 100 allot CONSTANT pci-device-vec
+0 VALUE pci-device-vec-len
+
+
+\ Fixme Glue to the pci-devices ... remove this later
+: next-pci-mem ( addr -- addr ) pci-next-mem ;
+: next-pci-mmio ( addr -- addr ) pci-next-mmio ;
+: next-pci-io ( addr -- addr ) pci-next-io ;
+
+\ ----------------------------------------------------------
+\ ****************** Helper functions ********************
+\ ----------------------------------------------------------
+
+\ convert an integer to string of len digits
+: int2str ( int len -- str len ) swap s>d rot <# 0 ?DO # LOOP #> ;
+
+\ convert addr to busnr
+: pci-addr2bus ( addr -- busnr ) 10 rshift FF and ;
+
+\ convert addr to devnr
+: pci-addr2dev ( addr -- dev ) B rshift 1F and ;
+
+\ convert addr to functionnumber
+: pci-addr2fn ( addr -- dev ) 8 rshift 7 and ;
+
+\ convert busnr devnr to addr
+: pci-bus2addr ( busnr devnr -- addr ) B lshift swap 10 lshift + ;
+
+\ print out a pci config addr
+: pci-addr-out ( addr -- ) dup pci-addr2bus 2 0.r space FFFF and 4 0.r ;
+
+\ Dump out the whole configspace
+: pci-dump ( addr -- )
+ 10 0 DO
+ dup
+ cr i 4 * +
+ dup pci-addr-out space
+ rtas-config-l@ 8 0.r
+ LOOP
+ drop cr
+;
+
+\ Dump out the pci device-slot vector
+: pci-vec ( -- )
+ cr s" device-vec(" type
+ pci-device-vec-len dup 2 0.r s" ):" type
+ 1+ 0 DO
+ pci-device-vec i + c@
+ space 2 0.r
+ LOOP
+ cr
+;
+
+\ prints out all relevant pci variables
+: var-out ( --)
+ s" mem:" type pci-next-mem @ 16 0.r cr
+ s" mmio:" type pci-next-mmio @ 16 0.r cr
+ s" io:" type pci-next-io @ 16 0.r cr
+;
+
+\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\ the following functions use l@ to fetch the data,
+\ that's because the pcie core on spider has some probs with w@ !!!
+\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\ read Vendor ID
+: pci-vendor@ ( addr -- id ) rtas-config-l@ FFFF and ;
+\ read Device ID
+: pci-device@ ( addr -- id ) rtas-config-l@ 10 rshift ;
+\ read Status
+: pci-status@ ( addr -- status ) 4 + rtas-config-l@ 10 rshift ;
+\ read Revision ID
+: pci-revision@ ( addr -- id ) 8 + rtas-config-b@ ;
+\ read Class Code
+: pci-class@ ( addr -- class ) 8 + rtas-config-l@ 8 rshift ;
+\ read Cache Line Size
+: pci-cache@ ( addr -- size ) C + rtas-config-b@ ;
+\ read Header Type
+: pci-htype@ ( addr -- type ) E + rtas-config-b@ ;
+\ read Sub Vendor ID
+: pci-sub-vendor@ ( addr -- sub-id ) 2C + rtas-config-l@ FFFF and ;
+\ read Sub Device ID
+: pci-sub-device@ ( addr -- sub-id ) 2C + rtas-config-l@ 10 rshift FFFF and ;
+\ read Interrupt Line
+: pci-interrupt@ ( addr -- interrupt ) 3D + rtas-config-b@ ;
+\ read Minimum Grant
+: pci-min-grant@ ( addr -- min-gnt ) 3E + rtas-config-b@ ;
+\ read Maximum Latency
+: pci-max-lat@ ( addr -- max-lat ) 3F + rtas-config-b@ ;
+\ Check if Capabilities are valid
+: pci-capabilities? ( addr -- 0|1 ) pci-status@ 4 rshift 1 and ;
+\ fetch the offset of the next capability
+: pci-cap-next ( cap-addr -- next-cap-off ) rtas-config-b@ FC and ;
+\ calc the address of the next capability
+: pci-cap-next-addr ( cap-addr -- next-cap-addr ) 1+ dup pci-cap-next dup IF swap -100 and + ELSE nip THEN ;
+
+\ Dump out all capabilities
+: pci-cap-dump ( addr -- )
+ cr
+ dup pci-capabilities? IF
+ 33 + BEGIN
+ pci-cap-next-addr dup 0<>
+ WHILE
+ dup pci-addr-out s" : " type
+ dup rtas-config-b@ 2 0.r cr
+ REPEAT
+ s" end found "
+ ELSE
+ s" capabilities not enabled!"
+ THEN
+ type cr drop
+;
+
+\ search the capability-list for this id
+: pci-cap-find ( addr id -- capp-addr|0 )
+ swap dup pci-capabilities? IF
+ 33 + BEGIN
+ pci-cap-next-addr dup 0<> IF
+ dup rtas-config-b@ 2 pick =
+ ELSE
+ true
+ THEN
+ UNTIL
+ nip
+ ELSE
+ 2drop 0
+ THEN
+;
+
+\ check wether this device is a pci-express device
+: pci-express? ( addr -- 0|1 ) 10 pci-cap-find 0<> ;
+
+\ check wether this device is a pci-express device
+: pci-x? ( addr -- 0|1 ) 07 pci-cap-find 0<> ;
+
+\ check wether this device has extended config space
+: pci-config-ext? ( addr -- 0|1 ) pci-express? ;
+
+\ set and fetch the interrupt Pin
+: pci-irq-line@ ( addr -- irq-pin ) 3C + rtas-config-b@ ;
+: pci-irq-line! ( pin addr -- ) 3C + rtas-config-b! ;
+
+\ set and fetch primary bus number
+: pci-bus-prim! ( nr addr -- ) 18 + dup rtas-config-l@ FFFFFF00 and rot + swap rtas-config-l! ;
+: pci-bus-prim@ ( addr -- nr ) 18 + rtas-config-l@ FF and ;
+
+\ set and fetch secondary bus number
+: pci-bus-scnd! ( nr addr -- ) 18 + dup rtas-config-l@ FFFF00FF and rot 8 lshift + swap rtas-config-l! ;
+: pci-bus-scnd@ ( addr -- nr ) 18 + rtas-config-l@ 8 rshift FF and ;
+
+\ set and fetch subordinate bus number
+: pci-bus-subo! ( nr addr -- ) 18 + dup rtas-config-l@ FF00FFFF and rot 10 lshift + swap rtas-config-l! ;
+: pci-bus-subo@ ( addr -- nr ) 18 + rtas-config-l@ 10 rshift FF and ;
+
+\ set and fetch primary, secondary and subordinate bus number
+: pci-bus! ( subo scnd prim addr -- ) swap rot 8 lshift + rot 10 lshift + swap 18 + dup rtas-config-l@ FF000000 and rot + swap rtas-config-l! ;
+: pci-bus@ ( addr -- subo scnd prim ) 18 + rtas-config-l@ dup 10 rshift FF and swap dup 8 rshift FF and swap FF and ;
+
+\ Reset secondary Status
+: pci-reset-2nd ( addr -- ) 1C + dup rtas-config-l@ FFFF0000 or swap rtas-config-l! ;
+
+\ Disable Bus Master, Memory Space and I/O Space for this device
+: pci-device-disable ( -- ) my-space 4 + dup rtas-config-l@ 7 invert and swap rtas-config-l! ;
+
+\ Enable Bus Master
+: pci-master-enable ( -- ) my-space 4 + dup rtas-config-l@ 4 or swap rtas-config-l! ;
+
+\ Disable Bus Master
+: pci-master-disable ( -- ) my-space 4 + dup rtas-config-l@ 4 invert and swap rtas-config-l! ;
+
+\ Enable response to mem accesses of pci device
+: pci-mem-enable ( -- ) my-space 4 + dup rtas-config-w@ 2 or swap rtas-config-w! ;
+: enable-mem-access ( -- ) pci-mem-enable ;
+
+\ Enable response to I/O accesses of pci-device
+: pci-io-enable ( -- ) my-space 4 + dup rtas-config-w@ 1 or swap rtas-config-w! ;
+: enable-io-access ( -- ) pci-io-enable ;
+
+\ Enable Bus Master, I/O and mem access
+: pci-enable ( -- ) my-space 4 + dup rtas-config-w@ 7 or swap rtas-config-w! ;
+
+\ Enable #PERR and #SERR errors of pci-device
+: pci-error-enable ( -- ) my-space 4 + dup rtas-config-w@ 140 or swap rtas-config-w! ;
+
+\ prints out the ScanInformation about a device
+\ char is a sign for device type e.g. D - device ; B - bridge
+: pci-out ( addr char -- )
+ 15 spaces
+ over pci-addr-out
+ s" (" type emit s" ) : " type
+ dup pci-vendor@ 4 0.r space
+ pci-device@ 4 0.r
+ 4 spaces
+;
+
+\ Update the device-slot number vector
+\ Set the bit of the DeviceSlot in the Slot array
+: pci-set-slot ( addr -- )
+ pci-addr2dev dup \ calc slot number
+ pci-device-vec-len \ the end of the vector
+ pci-device-vec + c! \ and update the vector
+ 80000000 swap rshift \ calc bit position of the device slot
+ pci-device-slots or \ set this bit
+ TO pci-device-slots \ and write it back
+;
+
+\ Update pci-next-mmio to be 1MB aligned and set the mmio-base register
+\ and set the Limit register to the maximum available address space
+\ needed for scanning possible devices behind the bridge
+: pci-bridge-set-mmio-base ( addr -- )
+ pci-next-mmio @ 100000 #aligned \ read the current Value and align to 1MB boundary
+ dup pci-next-mmio ! \ and write it back
+ 10 rshift \ mmio-base reg is only the upper 16 bits
+ pci-max-mmio @ FFFF0000 and or \ and Insert mmio Limit (set it to max)
+ swap 20 + rtas-config-l! \ and write it into the bridge
+;
+
+\ Update pci-next-mmio to be 1MB aligned and set the mmio-limit register
+\ The Limit Value is one less then the upper boundary
+\ If the limit is less than the base the mmio is disabled
+: pci-bridge-set-mmio-limit ( addr -- )
+ pci-next-mmio @ 100000 #aligned \ fetch current value and align to 1MB
+ dup pci-next-mmio ! \ and write it back
+ 1- FFFF0000 and \ make it one less and keep upper 16 bits
+ over 20 + rtas-config-l@ 0000FFFF and \ fetch original value
+ or swap 20 + rtas-config-l! \ and write it into the Reg
+;
+
+\ Update pci-next-mem to be 1MB aligned and set the mem-base and mem-base-upper register
+\ and set the Limit register to the maximum available address space
+\ needed for scanning possible devices behind the bridge
+: pci-bridge-set-mem-base ( addr -- )
+ pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary
+ dup pci-next-mem ! \ and write it back
+ over 24 + rtas-config-w@ \ check if 64bit support
+ 1 and IF \ IF 64 bit support
+ 2dup 20 rshift \ | keep upper 32 bits
+ swap 28 + rtas-config-l! \ | and write it into the Base-Upper32-bits
+ pci-max-mem @ 20 rshift \ | fetch max Limit address and keep upper 32 bits
+ 2 pick 2C + rtas-config-l! \ | and set the Limit
+ THEN \ FI
+ 10 rshift \ keep upper 16 bits
+ pci-max-mem @ FFFF0000 and or \ and Insert mmem Limit (set it to max)
+ swap 24 + rtas-config-l! \ and write it into the bridge
+;
+
+\ Update pci-next-mem to be 1MB aligned and set the mem-limit register
+\ The Limit Value is one less then the upper boundary
+\ If the limit is less than the base the mem is disabled
+: pci-bridge-set-mem-limit ( addr -- )
+ pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary
+ dup pci-next-mem ! \ and write it back
+ 1- \ make limit one less than boundary
+ over 24 + rtas-config-w@ \ check if 64bit support
+ 1 and IF \ IF 64 bit support
+ 2dup 20 rshift \ | keep upper 32 bits
+ swap 2C + rtas-config-l! \ | and write it into the Limit-Upper32-bits
+ THEN \ FI
+ FFFF0000 and \ keep upper 16 bits
+ over 24 + rtas-config-l@ 0000FFFF and \ fetch original Value
+ or swap 24 + rtas-config-l! \ and write it into the bridge
+;
+
+\ Update pci-next-io to be 4KB aligned and set the io-base and io-base-upper register
+\ and set the Limit register to the maximum available address space
+\ needed for scanning possible devices behind the bridge
+: pci-bridge-set-io-base ( addr -- )
+ pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary
+ dup pci-next-io ! \ and write it back
+ over 1C + rtas-config-l@ \ check if 32bit support
+ 1 and IF \ IF 32 bit support
+ 2dup 10 rshift \ | keep upper 16 bits
+ pci-max-io @ FFFF0000 and or \ | insert upper 16 bits of Max-Limit
+ swap 30 + rtas-config-l! \ | and write it into the Base-Upper16-bits
+ THEN \ FI
+ 8 rshift 000000FF and \ keep upper 8 bits
+ pci-max-io @ 0000FF00 and or \ insert upper 8 bits of Max-Limit
+ over rtas-config-l@ FFFF0000 and \ fetch original Value
+ or swap 1C + rtas-config-l! \ and write it into the bridge
+;
+
+\ Update pci-next-io to be 4KB aligned and set the io-limit register
+\ The Limit Value is one less then the upper boundary
+\ If the limit is less than the base the io is disabled
+: pci-bridge-set-io-limit ( addr -- )
+ pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary
+ dup pci-next-io ! \ and write it back
+ 1- \ make limit one less than boundary
+ over 1D + rtas-config-b@ \ check if 32bit support
+ 1 and IF \ IF 32 bit support
+ 2dup FFFF0000 and \ | keep upper 16 bits
+ over 30 + rtas-config-l@ \ | fetch original Value
+ or swap 30 + rtas-config-l! \ | and write it into the Limit-Upper16-bits
+ THEN \ FI
+ 0000FF00 and \ keep upper 8 bits
+ over 1C + rtas-config-l@ FFFF00FF and \ fetch original Value
+ or swap 1C + rtas-config-l! \ and write it into the bridge
+;
+
+\ set up all base registers to the current variable Values
+: pci-bridge-set-bases ( addr -- )
+ dup pci-bridge-set-mmio-base
+ dup pci-bridge-set-mem-base
+ pci-bridge-set-io-base
+;
+
+\ set up all limit registers to the current variable Values
+: pci-bridge-set-limits ( addr -- )
+ dup pci-bridge-set-mmio-limit
+ dup pci-bridge-set-mem-limit
+ pci-bridge-set-io-limit
+;
+
+\ ----------------------------------------------------------
+\ ****************** PCI Scan functions ******************
+\ ----------------------------------------------------------
+
+\ define function pointer as forward declaration of pci-probe-bus
+DEFER func-pci-probe-bus
+
+\ Setup the Base and Limits in the Bridge
+\ and scan the bus(es) beyond that Bridge
+: pci-bridge-probe ( addr -- )
+ dup pci-bridge-set-bases \ SetUp all Base Registers
+ pci-bus-number 1+ TO pci-bus-number \ increase number of busses found
+ pci-device-vec-len 1+ TO pci-device-vec-len \ increase the device-slot vector depth
+ dup \ stack config-addr for pci-bus!
+ FF swap \ Subordinate Bus Number ( for now to max to open all subbusses )
+ pci-bus-number swap \ Secondary Bus Number ( the new busnumber )
+ dup pci-addr2bus swap \ Primary Bus Number ( the current bus )
+ pci-bus! \ and set them into the bridge
+ pci-enable \ enable mem/IO transactions
+ dup pci-bus-scnd@ func-pci-probe-bus \ and probe the secondary bus
+ dup pci-bus-number swap pci-bus-subo! \ set SubOrdinate Bus Number to current number of busses
+ pci-device-vec-len 1- TO pci-device-vec-len \ decrease the device-slot vector depth
+ dup pci-bridge-set-limits \ SetUp all Limit Registers
+ drop \ forget the config-addr
+;
+
+\ set up the pci-device
+: pci-device-setup ( addr -- )
+ drop \ since the config-addr is coded in my-space, drop it here
+ s" pci-device.fs" included \ and setup the device as node in the device tree
+;
+
+\ set up the pci bridge
+: pci-bridge-setup ( addr -- )
+ drop \ since the config-addr is coded in my-space, drop it here
+ s" pci-bridge.fs" included \ and setup the bridge as node in the device tree
+;
+
+\ add the new found device/bridge to the device tree and set it up
+: pci-add-device ( addr -- )
+ new-device \ create a new device-tree node
+ dup set-space \ set the config addr for this device tree entry
+ dup pci-set-slot \ set the slot bit
+ dup pci-htype@ \ read HEADER-Type
+ 1 and IF \ IF BRIDGE
+ pci-bridge-setup \ | set up the bridge
+ ELSE \ ELSE
+ pci-device-setup \ | set up the device
+ THEN \ FI
+ finish-device \ and close the device-tree node
+;
+
+\ check for multifunction and for each function
+\ (dependig from header type) call device or bridge setup
+: pci-setup-device ( addr -- )
+ dup pci-htype@ \ read HEADER-Type
+ 80 and IF 8 ELSE 1 THEN \ check for multifunction
+ 0 DO \ LOOP over all possible functions (either 8 or only 1)
+ dup
+ i 8 lshift + \ calc device-function-config-addr
+ dup pci-vendor@ \ check if valid function
+ FFFF = IF
+ drop \ non-valid so forget the address
+ ELSE
+ pci-device-number 1+ \ increase the number of devices
+ TO pci-device-number \ and store it
+ pci-add-device \ and add the device to the device tree and set it up
+ THEN
+ LOOP \ next function
+ drop \ forget the device-addr
+;
+
+\ check if a device is plugged into this bus at this device number
+: pci-probe-device ( busnr devicenr -- )
+ pci-bus2addr \ calc pci-address
+ dup pci-vendor@ \ fetch Vendor-ID
+ FFFF = IF \ check if valid
+ drop \ if not forget it
+ ELSE
+ pci-setup-device \ if valid setup the device
+ THEN
+;
+
+\ walk through all 32 possible pci devices on this bus and probe them
+: pci-probe-bus ( busnr -- )
+ 0 TO pci-device-slots \ reset slot array to unpoppulated
+ 20 0 DO
+ dup
+ i pci-probe-device
+ LOOP
+ drop
+;
+
+\ setup the function pointer used in pci-bridge-setup
+' pci-probe-bus TO func-pci-probe-bus
+
+\ ----------------------------------------------------------
+\ ****************** System functions ********************
+\ ----------------------------------------------------------
+\ Setup the whole system for pci devices
+\ start with the bus-min and try all busses
+\ until at least 1 device was found
+\ ( needed for HostBridges that don't start with Bus 0 )
+: pci-probe-all ( bus-max bus-min -- ) \ Check all busses from bus-min up to bus-max if needed
+ 0 TO pci-device-vec-len \ reset the device-slot vector
+ DO
+ i TO pci-bus-number \ set current Busnumber
+ 0 TO pci-device-number \ reset Device Number
+ pci-bus-number pci-probe-bus \ and probe this bus
+ pci-device-number 0 > IF LEAVE THEN \ if we found a device we're done
+ LOOP \ else next bus
+;
+
+\ probe the hostbridge that is specified in my-puid
+\ for the mmio mem and io addresses:
+\ base is the least available address
+\ max is the highest available address
+: probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- )
+ puid >r TO puid \ save puid and set the new
+ pci-next-io ! \ save the next io-base address
+ pci-max-io ! \ save the max io-space address
+ pci-next-mem ! \ save the next mem-base address
+ pci-max-mem ! \ save the max mem-space address
+ pci-next-mmio ! \ save the next mmio-base address
+ pci-max-mmio ! \ save the max mmio-space address
+
+ 0d emit ." Adapters on " puid 10 0.r cr \ print the puid we're looking at
+ ( bus-max bus-min ) pci-probe-all \ and walk the bus
+ pci-device-number 0= IF \ IF no devices found
+ 15 spaces \ | indent the output
+ ." None" cr \ | tell the world our result
+ THEN \ FI
+ r> TO puid \ restore puid
+;
+
+\ provide the device-alias definition words
+#include <pci-aliases.fs>
+
+\ provide all words for the interrupts settings
+#include <pci-interrupts.fs>
+
+\ provide all words for the pci capabilities init
+#include <pci-capabilities.fs>
+
+\ provide all words needed to generate the properties and/or assign BAR values
+#include "pci-properties.fs"
diff --git a/slof/fs/preprocessor.fs b/slof/fs/preprocessor.fs
new file mode 100644
index 0000000..5bab531
--- /dev/null
+++ b/slof/fs/preprocessor.fs
@@ -0,0 +1,41 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: ([IF])
+ BEGIN
+ BEGIN parse-word dup 0= WHILE
+ 2drop refill
+ REPEAT
+
+ 2dup s" [IF]" str= IF 1 throw THEN
+ 2dup s" [ELSE]" str= IF 2 throw THEN
+ 2dup s" [THEN]" str= IF 3 throw THEN
+ s" \" str= IF linefeed parse 2drop THEN
+ AGAIN
+ ;
+
+: [IF] ( flag -- )
+ IF exit THEN
+ 1 BEGIN
+ ['] ([IF]) catch
+ CASE
+ 1 OF 1+ ENDOF
+ 2 OF dup 1 = if 1- then ENDOF
+ 3 OF 1- ENDOF
+ ENDCASE
+ dup 0 <=
+ UNTIL drop
+; immediate
+
+: [ELSE] 0 [COMPILE] [IF] ; immediate
+: [THEN] ; immediate
+
diff --git a/slof/fs/property.fs b/slof/fs/property.fs
index 16ea308..d8b97ac 100644
--- a/slof/fs/property.fs
+++ b/slof/fs/property.fs
@@ -1,29 +1,36 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
-
-\ Properties.
-
-\ Words on the property list for a package are actually executable words,
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Properties 5.3.5
+
+\ Words on the property list for a node are actually executable words,
\ that return the address and length of the property's data. Special
\ nodes like /options can have their properties use specialized code to
\ dynamically generate their data; most nodes just use a 2CONSTANT.
-: encode-int here swap lbsplit c, c, c, c, /l ;
-: encode-bytes dup >r here >r bounds ?DO i c@ c, LOOP r> r> ;
-: encode-string encode-bytes 0 c, char+ ;
+\ Put the type as byte before the property
+\ { int = 1, bytes = 2, string = 3 }
+\ This is used by .properties for pretty print
-: encode+ nip + ;
-: encode-int+ encode-int encode+ ;
+\ Flag for type encoding, encode-* resets, set-property set the flag
+true value encode-first?
+
+: decode-int over >r 4 /string r> 4c@ swap 2swap swap bljoin ;
+: decode-64 decode-int -rot decode-int -rot 2swap swap lxjoin ;
+: decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len )
+ dup 0= IF 2dup EXIT THEN \ string properties with zero lenght
+ over BEGIN dup c@ 0= IF 1+ -rot swap 2 pick over - rot over - -rot 1-
+ EXIT THEN 1+ AGAIN ;
\ Remove a word from a wordlist.
: (prune) ( name len head -- )
@@ -32,36 +39,151 @@
: prune ( name len -- ) last (prune) ;
: set-property ( data dlen name nlen phandle -- )
- get-current >r pkg>properties @ set-current
- 2dup prune $2CONSTANT r> set-current ;
-: property ( data dlen name nlen -- ) current-package @ set-property ;
-: get-property ( str len phandle -- false | data dlen true )
- pkg>properties @ voc-find dup IF link> execute true THEN ;
+ true to encode-first?
+ get-current >r node>properties @ set-current
+ 2dup prune $2CONSTANT r> set-current ;
+: delete-property ( name nlen -- )
+ get-node get-current >r node>properties @ set-current
+ prune r> set-current ;
+: property ( data dlen name nlen -- ) get-node set-property ;
+: get-property ( str len phandle -- true | data dlen false )
+ ?dup 0= IF cr cr cr ." get-property for " type ." on zero phandle"
+ cr cr true EXIT THEN
+ node>properties @ voc-find dup IF link> execute false ELSE drop true THEN ;
+: get-package-property ( str len phandle -- true | data dlen false )
+ get-property ;
+: get-my-property ( str len -- true | data dlen false )
+ my-self ihandle>phandle get-property ;
+: get-parent-property ( str len -- true | data dlen false )
+ my-parent ihandle>phandle get-property ;
+: get-inherited-property ( str len -- true | data dlen false )
+ my-self ihandle>phandle
+ BEGIN 3dup get-property 0=
+ IF \ Property found
+ rot drop rot drop rot drop false EXIT
+ THEN
+ parent 0=
+ IF
+ nip nip true EXIT
+ THEN
+ AGAIN ;
+
+\ Print out properties.
+
+20 CONSTANT indent-prop
+
+: .prop-int ( str len -- )
+ space
+ 400 min 0
+ ?DO
+ i over + dup ( str act-addr act-addr )
+ c@ 2 0.r 1+ dup c@ 2 0.r 1+ dup c@ 2 0.r 1+ c@ 2 0.r ( str )
+ i c and c = IF \ check for multipleof 16 bytes
+ cr indent @ indent-prop + 1+ 0 \ linefeed + indent
+ DO
+ space \ print spaces
+ LOOP
+ ELSE
+ space space \ print two spaces
+ THEN
+ 4 +LOOP
+ drop
+;
+
+: .prop-bytes ( str len -- )
+ 2dup -4 and .prop-int ( str len )
+
+ dup 3 and dup IF ( str len len%4 )
+ >r -4 and + r> ( str' len%4 )
+ bounds ( str' str'+len%4 )
+ DO
+ i c@ 2 0.r \ Print last 3 bytes
+ LOOP
+ ELSE
+ 3drop
+ THEN
+;
+
+: .prop-string ( str len )
+ 2dup space type
+ cr indent @ indent-prop + 0 DO space LOOP \ Linefeed
+ .prop-bytes
+;
-\ Print out properties. Just a hexdump, nothing fancy for strings etc.
: .propbytes ( xt -- )
- execute bounds ?DO space i c@ 2 0.r LOOP ;
+ execute dup
+ IF
+ over cell- @ execute
+ ELSE
+ 2drop
+ THEN
+;
: .property ( lfa -- )
- cr link> dup >name name>string type space .propbytes ;
+ cr indent @ 0
+ ?DO
+ space
+ LOOP
+ link> dup >name name>string 2dup type nip ( len )
+ indent-prop swap - ( xt 20-len )
+ dup 0< IF drop 0 THEN 0 ( xt number-of-space 0 )
+ ?DO
+ space
+ LOOP
+ .propbytes
+;
: (.properties) ( phandle -- )
- pkg>properties @ cell+ @ BEGIN dup WHILE dup .property @ REPEAT drop ;
+ node>properties @ cell+ @ BEGIN dup WHILE dup .property @ REPEAT drop ;
: .properties ( -- )
- current-package @ (.properties) ;
+ get-node (.properties) ;
: next-property ( str len phandle -- false | str' len' true )
?dup 0= IF device-tree @ THEN \ XXX: is this line required?
- pkg>properties @
+ node>properties @
>r 2dup 0= swap 0= or IF 2drop r> cell+ ELSE r> voc-find THEN
@ dup IF link>name name>string true THEN ;
+\ encode-* words and all helpers
+
+\ Start a encoded property string
+: encode-start ( -- prop 0 )
+ ['] .prop-int compile,
+ false to encode-first?
+ here 0
+;
+
+: encode-int ( val -- prop prop-len )
+ encode-first? IF
+ ['] .prop-int compile, \ Execution token for print
+ false to encode-first?
+ THEN
+ here swap lbsplit c, c, c, c, /l
+;
+: encode-bytes ( str len -- prop-addr prop-len )
+ encode-first? IF
+ ['] .prop-bytes compile, \ Execution token for print
+ false to encode-first?
+ THEN
+ here over 2dup 2>r allot swap move 2r>
+;
+: encode-string ( str len -- prop-addr prop-len )
+ encode-first? IF
+ ['] .prop-string compile, \ Execution token for print
+ false to encode-first?
+ THEN
+ encode-bytes 0 c, char+
+;
+
+: encode+ ( prop1-addr prop1-len prop2-addr prop2-len -- prop-addr prop-len )
+ nip + ;
+: encode-int+ encode-int encode+ ;
+: encode-64 xlsplit encode-int rot encode-int+ ;
+: encode-64+ encode-64 encode+ ;
+
+
\ Helpers for common nodes. Should perhaps remove "compatible", as it's
\ not typically a single string.
: device-name encode-string s" name" property ;
: device-type encode-string s" device_type" property ;
+: model encode-string s" model" property ;
: compatible encode-string s" compatible" property ;
-: full-name encode-string s" full_name" property ;
-
-\ Getting basic info about a package.
-: pkg>name dup >r s" name" rot get-property IF 1- r> drop ELSE r> (u.) THEN ;
-: pkg>path dup >r s" full_name" rot get-property drop 1- r> drop ;
diff --git a/slof/fs/quiesce.fs b/slof/fs/quiesce.fs
new file mode 100644
index 0000000..7521d1c
--- /dev/null
+++ b/slof/fs/quiesce.fs
@@ -0,0 +1,48 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+10 CONSTANT quiesce-xt#
+
+\ The array with the quiesce execution tokens:
+CREATE quiesce-xts quiesce-xt# cells allot
+quiesce-xts quiesce-xt# cells erase
+
+
+\ Add a token to the quiesce execution token array:
+: add-quiesce-xt ( xt -- )
+ quiesce-xt# 0 DO
+ quiesce-xts I cells + ( xt arrayptr )
+ dup @ 0= IF ( xt arrayptr )
+ ! UNLOOP EXIT
+ ELSE
+ drop ( xt )
+ THEN
+ LOOP
+ ." Warning: quiesce xt list is full." cr
+;
+
+
+\ The quiesce call asserts that the firmware and all hardware
+\ is in a sane state (e.g. assert that no background DMA is
+\ running anymore)
+: quiesce ( -- )
+ quiesce-xt# 0 DO
+ quiesce-xts I cells + ( arrayptr )
+ @ dup IF ( xt )
+ EXECUTE
+ ELSE
+ drop UNLOOP EXIT
+ THEN
+ LOOP
+;
+
diff --git a/slof/fs/rmove.fs b/slof/fs/rmove.fs
new file mode 100644
index 0000000..aafc2f6
--- /dev/null
+++ b/slof/fs/rmove.fs
@@ -0,0 +1,53 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+defer '(r@)
+defer '(r!)
+1 VALUE /(r)
+
+
+\ The rest of the code already implemented in prim.in
+\ In the end all of this should be moved over there and this file terminated
+
+: (rfill) ( addr size pattern 'r! /r -- )
+ to /(r) to '(r!) ff and
+ dup 8 lshift or dup 10 lshift or dup 20 lshift or
+ -rot bounds ?do dup i '(r!) /(r) +loop drop
+;
+
+: (fwrmove) ( src dest size -- )
+ >r 0 -rot r> bounds ?do + dup '(r@) i '(r!) /(r) dup +loop 2drop
+;
+
+\ Move from main to device memory
+: mrmove ( src dest size -- )
+ 3dup or or 7 AND CASE
+ 0 OF ['] x@ ['] rx! /x ENDOF
+ 4 OF ['] l@ ['] rl! /l ENDOF
+ 2 OF ['] w@ ['] rw! /w ENDOF
+ dup OF ['] c@ ['] rb! /c ENDOF
+ ENDCASE
+ ( We already know that source and destination do not overlap )
+ to /(r) to '(r!) to '(r@) (fwrmove)
+;
+
+: rfill ( addr size pattern -- )
+ 3dup drop or 7 AND CASE
+ 0 OF ['] rx! /x ENDOF
+ 4 OF ['] rl! /l ENDOF
+ 2 OF ['] rw! /w ENDOF
+ dup OF ['] rb! /c ENDOF
+ ENDCASE (rfill)
+;
+
+
+
diff --git a/slof/fs/romfs.fs b/slof/fs/romfs.fs
new file mode 100644
index 0000000..29fa80d
--- /dev/null
+++ b/slof/fs/romfs.fs
@@ -0,0 +1,123 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+eregs 10 8 * + @ CONSTANT romfs-base
+
+STRUCT
+ cell field romfs>file-header
+ cell field romfs>data
+ cell field romfs>data-size
+ cell field romfs>flags
+
+CONSTANT /romfs-lookup-control-block
+
+CREATE romfs-lookup-cb /romfs-lookup-control-block allot
+romfs-lookup-cb /romfs-lookup-control-block erase
+
+: create-filename ( string -- string\0 )
+ here >r dup 8 + allot
+ r@ over 8 + erase
+ r@ zplace r> ;
+
+: romfs-lookup ( fn-str fn-len -- data size | false )
+ create-filename romfs-base
+ romfs-lookup-cb romfs-lookup-entry call-c
+ 0= IF romfs-lookup-cb dup romfs>data @ swap romfs>data-size @ ELSE
+ false THEN ;
+
+: check-for-board-romfs ( -- true | false )
+ s" header" romfs-lookup drop @
+ 6d61676963313233 <> IF false ELSE true THEN ;
+
+: ibm,romfs-lookup ( fn-str fn-len -- data-high data-low size | 0 0 false )
+ romfs-lookup dup
+ 0= if drop 0 0 false else
+ swap dup 20 rshift swap ffffffff and then ;
+
+\ FIXME For a short time ...
+: romfs-lookup-client ibm,romfs-lookup ;
+
+\ Fixme temp implementation
+
+STRUCT
+ cell field romfs>next-off
+ cell field romfs>size
+ cell field romfs>flags
+ cell field romfs>data-off
+ cell field romfs>name
+
+CONSTANT /romfs-cb
+
+: romfs-map-file ( fn-str fn-len -- file-addr file-size )
+ romfs-base >r
+ BEGIN 2dup r@ romfs>name zcount string=ci not WHILE
+ ( fn-str fn-len ) ( R: rom-cb-file-addr )
+ r> romfs>next-off dup @ dup 0= IF 1 THROW THEN + >r REPEAT
+ ( fn-str fn-len ) ( R: rom-cb-file-addr )
+ 2drop r@ romfs>data-off @ r@ + r> romfs>size @ ;
+
+: flash-header ( -- address | false )
+ check-for-board-romfs 0= IF false ELSE
+ s" header" romfs-lookup 0= IF 0 THEN THEN ;
+
+CREATE bdate-str 10 allot
+: bdate2human ( -- addr len )
+ flash-header 40 + @ (.)
+ drop dup 0 + bdate-str 6 + 4 move
+ dup 4 + bdate-str 0 + 2 move
+ dup 6 + bdate-str 3 + 2 move
+ dup 8 + bdate-str b + 2 move
+ a + bdate-str e + 2 move
+ 2d bdate-str 2 + c!
+ 2d bdate-str 5 + c!
+ 20 bdate-str a + c!
+ 3a bdate-str d + c!
+ bdate-str 10
+;
+
+
+\ Look up a file in the ROM file system and evaluate it
+
+: included ( fn fn-len -- )
+ 2dup >r >r romfs-lookup dup IF
+ r> drop r> drop evaluate
+ ELSE
+ drop ." Cannot open file : " r> r> type cr
+ THEN
+;
+
+: include ( " fn " -- )
+ parse-word included
+;
+
+: ?include ( flag " fn " -- )
+ parse-word rot IF included ELSE 2drop THEN
+;
+
+: include? ( nargs flag " fn " -- )
+ parse-word rot IF
+ rot drop included
+ ELSE
+ 2drop 0 ?DO drop LOOP
+ THEN
+;
+
+
+\ List files in ROMfs
+
+: (print-romfs-file-info) ( file-addr -- )
+ 9 emit dup b 0.r 2 spaces dup 8 + @ 6 0.r 2 spaces 20 + zcount type cr
+;
+
+: romfs-list ( -- )
+ romfs-base 0 cr BEGIN + dup (print-romfs-file-info) dup @ dup 0= UNTIL 2drop
+;
diff --git a/slof/fs/root.fs b/slof/fs/root.fs
new file mode 100644
index 0000000..67df811
--- /dev/null
+++ b/slof/fs/root.fs
@@ -0,0 +1,57 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ this creates the root and common branches of the device tree
+
+defer (client-exec)
+defer client-exec
+
+\ defined in slof/fs/client.fs
+defer callback
+defer continue-client
+
+: set-chosen ( prop len name len -- )
+ s" /chosen" find-node set-property ;
+
+: get-chosen ( name len -- [ prop len ] success )
+ s" /chosen" find-node get-property 0= ;
+
+new-device
+ s" /" device-name
+ new-device
+ s" chosen" device-name
+ s" " encode-string s" bootargs" property
+ s" " encode-string s" bootpath" property
+ finish-device
+
+ new-device
+ s" aliases" device-name
+ finish-device
+
+ new-device
+ s" options" device-name
+ finish-device
+
+
+ new-device
+ s" openprom" device-name
+ s" BootROM" device-type
+ finish-device
+
+ new-device
+#include <packages.fs>
+ finish-device
+
+: open true ;
+: close ;
+
+finish-device
diff --git a/slof/fs/rtas/rtas-cpu.fs b/slof/fs/rtas/rtas-cpu.fs
new file mode 100644
index 0000000..54aac7b
--- /dev/null
+++ b/slof/fs/rtas/rtas-cpu.fs
@@ -0,0 +1,39 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: rtas-start-cpu ( pid loc r3 -- status )
+ [ s" start-cpu" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 3 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args2 l!
+ rtas-cb rtas>args1 l!
+ rtas-cb rtas>args0 l!
+ 0 rtas-cb rtas>args3 l!
+ enter-rtas
+ rtas-cb rtas>args3 l@
+;
+
+: rtas-freeze-timebase ( -- status )
+ [ s" freeze-time-base" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 0 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ enter-rtas
+ rtas-cb rtas>args0 l@
+;
+
+: rtas-thaw-timebase ( -- status )
+ [ s" thaw-time-base" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 0 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ enter-rtas
+ rtas-cb rtas>args0 l@
+;
diff --git a/slof/fs/rtas/rtas-flash.fs b/slof/fs/rtas/rtas-flash.fs
new file mode 100644
index 0000000..fb4bc6e
--- /dev/null
+++ b/slof/fs/rtas/rtas-flash.fs
@@ -0,0 +1,46 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: rtas-ibm-update-flash-64-and-reboot ( block-list -- status )
+ [ s" ibm,update-flash-64-and-reboot" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+: rtas-ibm-manage-flash-image ( image-to-commit -- status )
+ [ s" ibm,manage-flash-image" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+: rtas-set-flashside ( flashside -- status )
+ [ s" rtas-set-flashside" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 1 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
+
+: rtas-get-flashside ( -- status )
+ [ s" rtas-get-flashside" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 0 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ enter-rtas
+ rtas-cb rtas>args0 l@
+;
diff --git a/slof/fs/rtas/rtas-init.fs b/slof/fs/rtas/rtas-init.fs
new file mode 100644
index 0000000..c98fe6d
--- /dev/null
+++ b/slof/fs/rtas/rtas-init.fs
@@ -0,0 +1,121 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ (rtas-size) determines the size required for RTAS.
+\ It looks at the rtas binary in the flash and reads the rtas-size from
+\ its header at offset 8.
+: (rtas-size) ( -- rtas-size )
+ s" rtas" romfs-lookup dup 0=
+ ABORT" romfs-lookup for rtas failed"
+ drop 8 + @
+;
+
+(rtas-size) CONSTANT rtas-size
+
+: instantiate-rtas ( adr -- entry )
+ dup rtas-size erase
+ s" rtas" romfs-lookup 0=
+ ABORT" romfs-lookup for rtas failed"
+ hsprg1 swap start-rtas ;
+
+here fff + fffffffffffff000 and here - allot
+here rtas-size allot CONSTANT rtas-start-addr
+
+rtas-start-addr instantiate-rtas CONSTANT rtas-entry-point
+
+: drone-rtas
+ rtas-start-addr
+ dup rtas-size erase
+ 2000000 start-rtas to rtas-entry-point
+;
+
+
+\ ffffffffffffffff CONSTANT rtas-entry-point
+
+\ rtas control block
+
+STRUCT
+ /l field rtas>token
+ /l field rtas>nargs
+ /l field rtas>nret
+ /l field rtas>args0
+ /l field rtas>args1
+ /l field rtas>args2
+ /l field rtas>args3
+ /l field rtas>args4
+ /l field rtas>args5
+ /l field rtas>args6
+ /l field rtas>args7
+ /l C * field rtas>args
+ /l field rtas>bla
+
+CONSTANT /rtas-control-block
+
+CREATE rtas-cb /rtas-control-block allot
+rtas-cb /rtas-control-block erase
+
+\ call-c ( p0 p1 p2 entry -- ret )
+
+: enter-rtas ( -- )
+ rtas-cb rtas-start-addr 0 rtas-entry-point call-c drop ;
+
+
+\ This is the structure of the RTAS function jump table in the C code:
+STRUCT
+ cell FIELD rtasfunctab>name
+ cell FIELD rtasfunctab>func
+ cell FIELD rtasfunctab>flags
+CONSTANT rtasfunctab-size
+
+\ Create RTAS token properties by analyzing the jump table in the C code:
+: rtas-create-token-properties ( -- )
+ rtas-start-addr 10 + @ rtas-start-addr + \ Get pointer to jump table
+ rtas-start-addr 18 + @ rtas-start-addr + l@ \ Get the number of entries
+ 0 DO
+ dup rtasfunctab>func @ 0<> \ function pointer must not be NULL
+ over rtasfunctab>flags @ 1 and 0= \ Check the only-internal flag
+ and
+ IF
+ i 1+ encode-int \ Create the token value
+ 2 pick rtasfunctab>name @ zcount \ Create the token name string
+ property \ Create the property
+ THEN
+ rtasfunctab-size + \ Proceed to the next entry
+ LOOP
+ drop
+;
+
+\ Get the RTAS token that corresponds to an RTAS property name:
+: rtas-get-token ( str len -- token|0 )
+ rtas-start-addr 10 + @ rtas-start-addr + \ Get pointer to jump table
+ rtas-start-addr 18 + @ rtas-start-addr + l@ \ Get the number of entries
+ 0 DO
+ dup rtasfunctab>name @ \ Get pointer to function name
+ dup 0<> \ function name must not be NULL
+ over zcount 5 pick = nip and \ Check if both strings have same length
+ IF
+ 3 pick 3 pick \ Make a copy of the token name string
+ comp 0=
+ IF
+ drop 2drop
+ i 1+ \ If the name matched, return the token
+ UNLOOP EXIT
+ THEN
+ ELSE
+ drop
+ THEN
+ rtasfunctab-size + \ Proceed to the next entry
+ LOOP
+ drop
+ ." RTAS token not found: " type cr
+ 0
+;
diff --git a/slof/fs/rtas/rtas-reboot.fs b/slof/fs/rtas/rtas-reboot.fs
new file mode 100644
index 0000000..c20f80e
--- /dev/null
+++ b/slof/fs/rtas/rtas-reboot.fs
@@ -0,0 +1,33 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: rtas-power-off ( x y -- status )
+ [ s" power-off" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 2 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ rtas-cb rtas>args1 l!
+ enter-rtas
+ rtas-cb rtas>args2 l@
+;
+
+: power-off ( -- ) 0 0 rtas-power-off ;
+
+
+: rtas-system-reboot ( -- status )
+ [ s" system-reboot" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 0 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args1 l@
+;
diff --git a/slof/fs/rtas/rtas-vpd.fs b/slof/fs/rtas/rtas-vpd.fs
new file mode 100644
index 0000000..2191ee9
--- /dev/null
+++ b/slof/fs/rtas/rtas-vpd.fs
@@ -0,0 +1,33 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: rtas-read-vpd ( offset length data -- status )
+ [ s" msg-read-vpd" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 3 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args2 l!
+ rtas-cb rtas>args1 l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args3 l@
+;
+
+: rtas-write-vpd ( offset length data -- status )
+ [ s" msg-write-vpd" rtas-get-token ] LITERAL rtas-cb rtas>token l!
+ 3 rtas-cb rtas>nargs l!
+ 1 rtas-cb rtas>nret l!
+ rtas-cb rtas>args2 l!
+ rtas-cb rtas>args1 l!
+ rtas-cb rtas>args0 l!
+ enter-rtas
+ rtas-cb rtas>args3 l@
+;
diff --git a/slof/fs/search.fs b/slof/fs/search.fs
index bacf53b..2255636 100644
--- a/slof/fs/search.fs
+++ b/slof/fs/search.fs
@@ -1,17 +1,18 @@
-\ =============================================================================
-\ * Copyright (c) 2004, 2005 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ =============================================================================
-
-
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+\
\ Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
+\
+
\ stuff we should already have:
@@ -34,20 +35,22 @@ VARIABLE wordlists forth-wordlist wordlists !
\ \ \
10 CONSTANT max-in-search-order \ should define elsewhere
+\ CREATE search-order max-in-search-order cells allot \ stack of wids \ is in engine now
+\ search-order VALUE context \ top of stack \ is in engine now
: also ( -- ) clean-hash context dup cell+ dup to context >r @ r> ! ;
: previous ( -- ) clean-hash context cell- to context ;
-: only ( -- ) clean-hash search-order to context ;
+: only ( -- ) clean-hash search-order to context ( minimal-wordlist search-order ! ) ;
: seal ( -- ) clean-hash context @ search-order dup to context ! ;
: get-order ( -- wid_n .. wid_1 n )
- context >r search-order BEGIN dup r@ u<= WHILE
- dup @ swap cell+ REPEAT r> drop
- search-order - cell / ;
+ context >r search-order BEGIN dup r@ u<= WHILE
+ dup @ swap cell+ REPEAT r> drop
+ search-order - cell / ;
: set-order ( wid_n .. wid_1 n -- ) \ XXX: special cases for 0, -1
- clean-hash 1- cells search-order + dup to context
- BEGIN dup search-order u>= WHILE
- dup >r ! r> cell- REPEAT drop ;
+ clean-hash 1- cells search-order + dup to context
+ BEGIN dup search-order u>= WHILE
+ dup >r ! r> cell- REPEAT drop ;
\ \ \
@@ -64,24 +67,29 @@ VARIABLE wordlists forth-wordlist wordlists !
\ \ \ Vocabularies
\ \ \
-: VOCABULARY ( C: "name" -- ) ( -- ) CREATE wordlist drop
- DOES> clean-hash context ! ;
+: VOCABULARY ( C: "name" -- ) ( -- ) CREATE wordlist drop DOES> clean-hash context ! ;
\ : VOCABULARY ( C: "name" -- ) ( -- ) wordlist CREATE , DOES> @ context ! ;
+\ XXX we'd like to swap forth and forth-wordlist around (for .voc 's sake)
: FORTH ( -- ) clean-hash forth-wordlist context ! ;
-: >name ( xt -- nfa )
- BEGIN char- dup c@ UNTIL
- dup dup aligned - cell+ char-
- dup >r - BEGIN dup c@ r@ <> WHILE
- cell- r> cell+ >r REPEAT r> drop char- ;
-: .voc ( wid -- ) \ display name for wid
- dup cell- @ ['] vocabulary ['] forth within IF
- 2 cells - >name name>string type ELSE u. THEN space ;
+\ XXX this one needs to be elsewhere
+: >name ( xt -- nfa ) \ note: still has the "immediate" field!
+ BEGIN char- dup c@ UNTIL ( @lastchar )
+ dup dup aligned - cell+ char- ( @lastchar lenmodcell )
+ dup >r - BEGIN dup c@ r@ <> WHILE
+ cell- r> cell+ >r REPEAT r> drop char- ;
+: .voc ( wid -- ) \ display name for wid \ needs work ( body> or something like that )
+ dup cell- @ ['] vocabulary ['] forth within IF
+ 2 cells - >name name>string type ELSE u. THEN space ;
: vocs ( -- ) \ display all wordlist names
- cr wordlists BEGIN @ dup WHILE dup .voc REPEAT drop ;
+ cr wordlists BEGIN @ dup WHILE dup .voc REPEAT drop ;
: order ( -- )
- cr ." context: " get-order 0 ?DO .voc LOOP
- cr ." current: " get-current .voc ;
+ cr ." context: " get-order 0 ?DO .voc LOOP
+ cr ." current: " get-current .voc ;
+
+
+
-\ Find word in specific wordlist.
-: voc-find ( wid -- 0 | link ) clean-hash cell+ @ (find) clean-hash ;
+\ some handy helper
+: voc-find ( wid -- 0 | link )
+ clean-hash cell+ @ (find) clean-hash ;
diff --git a/slof/fs/sms/sms-load.fs b/slof/fs/sms/sms-load.fs
new file mode 100644
index 0000000..a5b2541
--- /dev/null
+++ b/slof/fs/sms/sms-load.fs
@@ -0,0 +1,50 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+false VALUE sms-loaded
+
+#include "packages/sms.fs"
+
+\ Dynamically load sms code from the romfs file
+\ Assumption is that skeleton sms package already exists
+\ but aside of open & close, all other methods are in a romfs file (sms.fs)
+\ Here we open the package and load the rest of the functionality
+
+\ After that, one needs to find-device and execute sms-start method
+\ The shorthand for that is given as (global) sms-start word
+
+: $sms-node s" /packages/sms" ;
+
+: (sms-init-package) ( -- true|false )
+ sms-loaded ?dup IF EXIT THEN
+ $sms-node ['] find-device catch IF 2drop false EXIT THEN
+ s" sms.fs" [COMPILE] included
+ device-end
+ true dup to sms-loaded
+;
+
+\ External wrapper for sms package method
+: sms-start ( -- )
+ (sms-init-package) not IF
+ cr ." SMS is not available." cr exit
+ THEN
+
+ s" Entering SMS ..." type
+ disable-watchdog
+ reset-dual-emit
+
+ \ if we only had execute-device-method...
+ $sms-node find-device
+ s" sms-start" evaluate
+ device-end
+;
+
diff --git a/slof/fs/stack.fs b/slof/fs/stack.fs
new file mode 100644
index 0000000..7bbdfb8
--- /dev/null
+++ b/slof/fs/stack.fs
@@ -0,0 +1,57 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ Example:
+\
+\ To get a 30 element stack, go:
+\
+\ 0 > 30 new-stack my-stack
+\ 0 > my-stack
+\ 0 > 20 push 30 push
+\ 0 > pop pop .s
+
+0 value current-stack
+
+: new-stack ( cells <>name -- )
+ create >r here ( here R: cells )
+ dup r@ 2 + cells ( here here bytes R: cells )
+ dup allot erase ( here R: cells)
+ cell+ r> ( here+1cell cells )
+ swap ! ( )
+ DOES> to current-stack
+;
+
+: reset-stack ( -- )
+ 0 current-stack !
+;
+
+: stack-depth ( -- depth )
+ current-stack @
+;
+
+: push ( value -- )
+ current-stack @
+ current-stack cell+ @ over <= ABORT" Stack overflow"
+ cells
+ 1 current-stack +!
+ current-stack 2 cells + + !
+;
+
+: pop ( -- value )
+ current-stack @ 0= ABORT" Stack underflow"
+ current-stack @ cells
+ current-stack + cell+ @
+ -1 current-stack +!
+;
+
+
diff --git a/slof/fs/start-up.fs b/slof/fs/start-up.fs
new file mode 100644
index 0000000..c36da13
--- /dev/null
+++ b/slof/fs/start-up.fs
@@ -0,0 +1,85 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: (boot) ( -- )
+ s" Executing following boot-command: "
+ boot-command $cat nvramlog-write-string-cr
+ s" boot-command" evaluate \ get boot command
+ ['] evaluate catch ?dup IF \ and execute it
+ ." boot attempt returned: "
+ abort"-str @ count type cr
+ nip nip \ drop string from 1st evaluate
+ throw
+ THEN
+;
+
+\ Note: The following ESC sequences has to be handled:
+\ 1B 4F 50
+\ 1B 5B 31 31 7E
+
+\ Reads and converts the function key.
+\ key = F1 -- n = 1
+: (function-key) ( -- n )
+ key? IF
+ key CASE
+ 50 OF 1 ENDOF
+ 7e OF 1 ENDOF
+ dup OF 0 ENDOF
+ ENDCASE
+ THEN
+;
+
+\ Checks if an ESC sequence occurs.
+: (esc-sequence) ( -- n )
+ key? IF
+ key CASE
+ 4f OF (function-key) ENDOF
+ 5b OF
+ key key drop (function-key) ENDOF
+ dup OF 0 ENDOF
+ ENDCASE
+ THEN
+;
+
+: (s-pressed) ( -- )
+ s" An 's' has been pressed. Entering Open Firmware Prompt"
+ nvramlog-write-string-cr
+;
+
+: (boot?) ( -- )
+ of-prompt? not auto-boot? and IF
+ (boot)
+ THEN
+;
+
+#include "sms/sms-load.fs"
+
+: start-it ( -- )
+ key? IF
+ key CASE
+ [char] s OF (s-pressed) ENDOF
+ 1b OF
+
+ (esc-sequence) CASE
+ 1 OF console-clean-fifo sms-start (boot) ENDOF
+ dup OF (boot?) ENDOF
+ ENDCASE
+
+ ENDOF
+ dup OF (boot?) ENDOF
+ ENDCASE
+ ELSE
+ (boot?)
+ THEN
+
+ disable-watchdog .banner
+;
diff --git a/slof/fs/term-io.fs b/slof/fs/term-io.fs
new file mode 100644
index 0000000..d352b9e
--- /dev/null
+++ b/slof/fs/term-io.fs
@@ -0,0 +1,57 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+: input ( dev-str dev-len -- )
+ open-dev ?dup IF
+ \ Close old stdin:
+ s" stdin" get-chosen IF
+ decode-int nip nip ?dup IF close-dev THEN
+ THEN
+ \ Now set the new stdin:
+ encode-int s" stdin" set-chosen
+ THEN
+;
+
+: output ( dev-str dev-len -- )
+ open-dev ?dup IF
+ \ Close old stdout:
+ s" stdout" get-chosen IF
+ decode-int nip nip ?dup IF close-dev THEN
+ THEN
+ \ Now set the new stdout:
+ encode-int s" stdout" set-chosen
+ THEN
+;
+
+: io ( dev-str dev-len -- )
+ 2dup input output
+;
+
+
+1 BUFFER: (term-io-char-buf)
+
+: term-io-key ( -- char )
+ s" stdin" get-chosen IF
+ decode-int nip nip dup 0= IF 0 EXIT THEN
+ >r BEGIN
+ (term-io-char-buf) 1 s" read" r@ $call-method
+ 0 >
+ UNTIL
+ (term-io-char-buf) c@
+ r> drop
+ THEN
+;
+
+' term-io-key to key
+
+\ TODO: Implement: ' term-io-key? to key?
diff --git a/slof/fs/terminal.fs b/slof/fs/terminal.fs
new file mode 100644
index 0000000..e1bf4b2
--- /dev/null
+++ b/slof/fs/terminal.fs
@@ -0,0 +1,196 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ \\\\\\\\\\\\\\ Global Data
+
+0 VALUE line#
+0 VALUE column#
+false VALUE inverse?
+false VALUE inverse-screen?
+18 VALUE #lines
+50 VALUE #columns
+
+false VALUE cursor
+false VALUE saved-cursor
+
+
+\ \\\\\\\\\\\\\\ Structure/Implementation Dependent Methods
+
+defer draw-character \ 2B inited by display driver
+defer reset-screen \ 2B inited by display driver
+defer toggle-cursor \ 2B inited by display driver
+defer erase-screen \ 2B inited by display driver
+defer blink-screen \ 2B inited by display driver
+defer invert-screen \ 2B inited by display driver
+defer insert-characters \ 2B inited by display driver
+defer delete-characters \ 2B inited by display driver
+defer insert-lines \ 2B inited by display driver
+defer delete-lines \ 2B inited by display driver
+defer draw-logo \ 2B inited by display driver
+
+: nop-toggle-cursor ( nop ) ;
+' nop-toggle-cursor to toggle-cursor
+
+\ \\\\\\\\\\\\\\ Implementation Independent Methods (Depend on Previous)
+\ *
+\ *
+: (cursor-off) ( -- ) cursor dup to saved-cursor
+ IF toggle-cursor false to cursor THEN ;
+: (cursor-on) ( -- ) cursor dup to saved-cursor
+ 0= IF toggle-cursor true to cursor THEN ;
+: restore-cursor ( -- ) saved-cursor dup cursor
+ <> IF toggle-cursor to cursor ELSE drop THEN ;
+
+' (cursor-off) to cursor-off
+' (cursor-on) to cursor-on
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ Generic device methods:
+\ *
+
+
+\ \\\\\\\\\\\\\\ Exported Interface:
+\ *
+\ *
+
+false VALUE esc-on
+false VALUE csi-on
+defer esc-process
+0 VALUE esc-num-parm
+0 VALUE esc-num-parm2
+0 VALUE saved-line#
+0 VALUE saved-column#
+
+: get-esc-parm ( default -- value )
+ esc-num-parm dup 0> IF nip ELSE drop THEN 0 to esc-num-parm ;
+: get-esc-parm2 ( default -- value )
+ esc-num-parm2 dup 0> IF nip ELSE drop THEN 0 to esc-num-parm2 ;
+: set-esc-parm ( newdigit -- ) [char] 0 - esc-num-parm a * + to esc-num-parm ;
+
+: reverse-cursor ( oldpos -- newpos) dup IF 1 get-esc-parm - THEN ;
+: advance-cursor ( bound oldpos -- newpos) tuck > IF 1 get-esc-parm + THEN ;
+: erase-in-line #columns column# - dup 0> IF delete-characters ELSE drop THEN ;
+
+: terminal-line++ ( -- )
+ line# 1+ dup #lines = IF 1- 0 to line# 1 delete-lines THEN
+ to line#
+;
+
+0 VALUE dang
+0 VALUE blipp
+
+: ansi-esc ( char -- )
+ csi-on IF
+ dup [char] 0 [char] 9 between IF set-esc-parm
+ ELSE CASE
+ [char] A OF line# reverse-cursor to line# ENDOF
+ [char] B OF #lines line# advance-cursor to line# ENDOF
+ [char] C OF #columns column# advance-cursor to column# ENDOF
+ [char] D OF column# reverse-cursor to column# ENDOF
+ [char] E OF ( FIXME: Cursor Next Line - No idea what does it mean )
+ #lines line# advance-cursor to line#
+ ENDOF
+ [char] f OF
+ 1 get-esc-parm2 to line# column# get-esc-parm to column#
+ ENDOF
+ [char] H OF
+ 1 get-esc-parm2 to line# column# get-esc-parm to column#
+ ENDOF
+ ( second parameter delimiter for f and H commands )
+ [char] ; OF 0 get-esc-parm to esc-num-parm2 ENDOF
+ [char] J OF
+ #lines line# - dup 0> IF
+ line# 1+ to line# delete-lines line# 1- to line#
+ ELSE drop THEN
+ erase-in-line
+ ENDOF
+ [char] K OF erase-in-line ENDOF
+ [char] L OF 1 get-esc-parm insert-lines ENDOF
+ [char] M OF 1 get-esc-parm delete-lines ENDOF
+ [char] @ OF 1 get-esc-parm insert-characters ENDOF
+ [char] P OF 1 get-esc-parm delete-characters ENDOF
+ [char] m OF 0 get-esc-parm 0<> to inverse? ENDOF
+ ( These are non-ANSI commands recommended by OpenBoot )
+ [char] p OF inverse-screen? IF false to inverse-screen?
+ inverse? 0= to inverse? invert-screen
+ THEN
+ ENDOF
+ [char] q OF inverse-screen? 0= IF true to inverse-screen?
+ inverse? 0= to inverse? invert-screen
+ THEN
+ ENDOF
+\ [char] s OF reset-screen ENDOF ( FIXME: this conflicts w. ANSI )
+\ [char] s OF line# to saved-line# column# to saved-column# ENDOF
+ [char] u OF saved-line# to line# saved-column# to column# ENDOF
+ dup dup to dang OF blink-screen ENDOF
+ ENDCASE false to csi-on
+ false to esc-on 0 to esc-num-parm 0 to esc-num-parm2
+ THEN
+ ELSE CASE
+ ( DEV VT compatibility stuff used by accept.fs )
+ [char] 7 OF line# to saved-line# column# to saved-column# ENDOF
+ [char] 8 OF saved-line# to line# saved-column# to column# ENDOF
+ [char] [ OF true to csi-on ENDOF
+ dup dup OF false to esc-on to blipp ENDOF
+ ENDCASE
+ csi-on 0= IF false to esc-on THEN 0 to esc-num-parm 0 to esc-num-parm2
+ THEN
+;
+
+' ansi-esc to esc-process
+CREATE twtracebuf 4000 allot twtracebuf 4000 erase
+twtracebuf VALUE twbp
+0 VALUE twbc
+
+: twtrace
+ twbc 4000 = IF 0 to twbc twtracebuf to twbp THEN
+ dup twbp c! twbp 1+ to twbp twbc 1+ to twbc
+;
+
+: terminal-write ( addr len -- actual-len )
+ cursor-off
+ tuck bounds ?DO i c@
+ twtrace
+ esc-on IF esc-process
+ ELSE CASE
+ 1B OF true to esc-on ENDOF
+ carret OF 0 to column# ENDOF
+ linefeed OF terminal-line++ ENDOF
+ bell OF blink-screen ENDOF
+ 9 ( TAB ) OF column# 7 + -8 and dup #columns < IF
+ to column#
+ ELSE drop THEN
+ ENDOF
+ B ( VT ) OF line# ?dup IF 1- to line# THEN ENDOF
+ C ( FF ) OF 0 to line# 0 to column# erase-screen ENDOF
+ bs OF column# 1- dup 0< IF
+ line# IF
+ line# 1- to line#
+ drop #columns 1-
+ ELSE drop column#
+ THEN
+ THEN
+ to column# ( bl draw-character )
+ ENDOF
+ dup OF
+ i c@ draw-character
+ column# 1+ dup #columns >= IF
+ drop 0 terminal-line++
+ THEN
+ to column#
+ ENDOF
+ ENDCASE
+ THEN
+ LOOP
+ restore-cursor
+;
diff --git a/slof/fs/timebase.fs b/slof/fs/timebase.fs
new file mode 100644
index 0000000..2184587
--- /dev/null
+++ b/slof/fs/timebase.fs
@@ -0,0 +1,19 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+\ Define all timebase related words
+
+: milliseconds ( -- ms ) tbl@ d# 1000 * tb-frequency / ;
+: microseconds ( -- us ) tbl@ d# 1000000 * tb-frequency / ;
+
+: ms ( ms-to-wait -- ) milliseconds + BEGIN milliseconds over >= UNTIL drop ;
+: get-msecs ( -- n ) milliseconds ;
+: us ( us-to-wait -- ) microseconds + BEGIN microseconds over >= UNTIL drop ;
diff --git a/slof/fs/translate.fs b/slof/fs/translate.fs
new file mode 100644
index 0000000..954acc1
--- /dev/null
+++ b/slof/fs/translate.fs
@@ -0,0 +1,152 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ this is a C-to-Forth translation from the translate
+\ address code in the client
+\ with extensions to handle different sizes of #size-cells
+
+\ this tries to figure out if it is a PCI device what kind of
+\ translation is wanted
+\ if prop_type is 0, "reg" property is used, otherwise "assigned-addresses"
+: pci-address-type ( node address prop_type -- type )
+ -rot 2 pick ( prop_type node address prop_type )
+ 0= IF
+ swap s" reg" rot get-property ( prop_type address data dlen false )
+ ELSE
+ swap s" assigned-addresses" rot get-property ( prop_type address data dlen false )
+ THEN
+ IF 2drop -1 EXIT THEN 4 / 5 /
+ \ advance (phys-addr(3) size(2)) steps
+ 0 DO
+ \ BARs and Expansion ROM must be in assigned-addresses...
+ \ so if prop_type is 0 ("reg") and a config space offset is set
+ \ we skip this entry...
+ dup l@ FF AND 0<> ( prop_type address data cfgspace_offset? )
+ 3 pick 0= ( prop_type address data cfgspace_offset? reg_prop? )
+ AND NOT IF
+ 2dup 8 + ( prop_type address data address data' )
+ 2dup l@ 2 pick 8 + l@ + <= -rot l@ >= and IF
+ l@ 03000000 and 18 rshift nip
+ \ no 64bit translations supported pretend it is 32bit
+ dup 3 = IF 1- THEN
+ ( prop_type type )
+ swap drop ( type )
+ UNLOOP EXIT
+ THEN
+ THEN
+ \ advance in 4 byte steps and (phys-addr(3) size(2)) steps
+ 4 5 * +
+ LOOP
+ 3drop -1
+;
+
+: (range-read-cells) ( range-addr #cells -- range-value )
+ \ if number of cells != 1; do 64bit read; else a 32bit read
+ 1 = IF l@ ELSE @ THEN
+;
+
+\ this functions tries to find a mapping for the given address
+\ it assumes that if we have #address-cells == 3 that we are trying
+\ to do a PCI translation
+
+\ nac - #address-cells
+\ nsc - #size-cells
+\ pnac - parent #address-cells
+
+: (map-one-range) ( type range pnac nsc nac address -- address true | address false )
+ \ only check for the type if nac == 3 (PCI)
+ over 3 = 5 pick l@ 3000000 and 18 rshift 7 pick <> and IF
+ >r 2drop 3drop r> false EXIT
+ THEN
+ \ get size
+ 4 pick 4 pick 3 pick + 4 * +
+ \ get nsc
+ 3 pick
+ \ read size
+ ( type range pnac nsc nac address range nsc )
+ (range-read-cells)
+ ( type range pnac nsc nac address size )
+ \ skip type if PCI
+ 5 pick 3 pick 3 = IF
+ 4 +
+ THEN
+ \ get nac
+ 3 pick
+ ( type range pnac nsc nac address size range nac )
+ \ read child-mapping
+ (range-read-cells)
+ ( type range pnac nsc nac address size child-mapping )
+ dup >r dup 3 pick > >r + over <= r> or IF
+ \ address is not inside the mapping range
+ >r 2drop 3drop r> r> drop false EXIT
+ THEN
+ dup r> -
+ ( type range pnac nsc nac address offset )
+ \ add the offset on the parent mapping
+ 5 pick 5 pick 3 = IF
+ \ skip type if PCI
+ 4 +
+ THEN
+ 3 pick 4 * +
+ ( type range pnac nsc nac address offset parent-mapping-address )
+ \ get pnac
+ 5 pick
+ \ read parent mapping
+ (range-read-cells)
+ ( type range pnac nsc nac address offset parent-mapping )
+ + >r 3drop 3drop r> true
+;
+
+\ this word translates the given address starting from the node specified
+\ in node; the word will return to the node it was started from
+: translate-address ( node address -- address )
+ \ check for address type in "assigned-addresses"
+ 2dup 1 pci-address-type ( node address type )
+ dup -1 = IF
+ \ not found in "assigned-addresses", check in "reg"
+ drop 2dup 0 pci-address-type ( node address type )
+ THEN
+ rot parent BEGIN
+ \ check if it is the root node
+ dup parent 0= IF 2drop EXIT THEN
+ ( address type parent )
+ s" #address-cells" 2 pick get-property 2drop l@ >r \ nac
+ s" #size-cells" 2 pick get-property 2drop l@ >r \ nsc
+ s" #address-cells" 2 pick parent get-property 2drop l@ >r \ pnac
+ -rot ( node address type )
+ s" ranges" 4 pick get-property IF
+ 3drop
+ ABORT" no ranges property; not translatable"
+ THEN
+ r> r> r> 3 roll
+ ( node address type ranges pnac nsc nac length )
+ 4 / >r 3dup + + >r 5 roll r> r> swap / 0 ?DO
+ ( node type ranges pnac nsc nac address )
+ 6dup (map-one-range) IF
+ nip leave
+ THEN
+ nip
+ \ advance ranges
+ 4 roll
+ ( node type pnac nsc nac address ranges )
+ 4 pick 4 pick 4 pick + + 4 * + 4 -roll
+ LOOP
+ >r 2drop 2drop r> ( node type address )
+ swap rot parent ( address type node )
+ dup 0=
+ UNTIL
+;
+
+\ this words translates the given address starting from the current node
+: translate-my-address ( address -- address' )
+ get-node swap translate-address
+;
diff --git a/slof/fs/update_flash.fs b/slof/fs/update_flash.fs
new file mode 100644
index 0000000..7461440
--- /dev/null
+++ b/slof/fs/update_flash.fs
@@ -0,0 +1,101 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ Set by update-flash -f to true, preventing update-flash -c
+false value flash-new
+
+: update-flash-help ( -- )
+ cr ." update-flash tool to flash host FW " cr
+ ." -f <filename> : Flash from file (e.g. net:\boot_rom.bin)" cr
+ ." -l : Flash from load-base" cr
+ ." -d : Flash from old load base (used by drone)" cr
+ ." -c : Flash from temp to perm" cr
+ ." -r : Flash from perm to temp" cr
+;
+
+: flash-read-temp ( -- success? )
+ get-flashside 1 = IF flash-addr load-base over flash-image-size move true
+ ELSE
+ false
+ THEN
+;
+
+: flash-read-perm ( -- success? )
+ get-flashside 0= IF flash-addr load-base over flash-image-size move true
+ ELSE
+ false
+ THEN
+;
+
+: flash-switch-side ( side -- success? )
+ set-flashside 0<> IF
+ s" Cannot change flashside" type cr false
+ ELSE
+ true
+ THEN
+;
+
+: flash-ensure-temp ( -- success? )
+ get-flashside 0= IF
+ cr ." Cannot flash perm! Switching to temp side!"
+ 1 flash-switch-side
+ ELSE
+ true
+ THEN
+ ;
+
+\ update-flash -f <filename>
+\ -l
+\ -c
+\ -r
+
+: update-flash ( "text" )
+ get-flashside >r \ Save old flashside
+ parse-word ( str len ) \ Parse first string
+ drop dup c@ ( str first-char )
+ [char] - <> IF
+ update-flash-help r> 2drop EXIT
+ THEN
+
+ 1+ c@ ( second-char )
+ CASE
+ [char] f OF parse-word cr s" do-load" evaluate
+ flash-ensure-temp TO flash-new
+ ENDOF
+ [char] l OF flash-ensure-temp
+ ENDOF
+ [char] d OF flash-load-base load-base 200000 move
+ flash-ensure-temp
+ ENDOF
+ [char] c OF flash-read-temp 0= flash-new or IF
+ ." Cannot commit temp, need to boot on temp first " cr false
+ ELSE
+ 0 flash-switch-side
+ THEN
+ ENDOF
+ [char] r OF flash-read-perm 0= IF
+ ." Cannot commit perm, need to boot on perm first " cr false
+ ELSE
+ 1 flash-switch-side
+ THEN
+ ENDOF
+ dup OF false ENDOF
+ ENDCASE
+
+ ( true| false )
+ 0= IF
+ update-flash-help r> drop EXIT
+ THEN
+
+ load-base flash-write 0= IF ." Flash write failed !! " cr THEN
+ r> set-flashside drop \ Restore old flashside
+;
diff --git a/slof/fs/usb/usb-enumerate.fs b/slof/fs/usb/usb-enumerate.fs
new file mode 100644
index 0000000..a027ec5
--- /dev/null
+++ b/slof/fs/usb/usb-enumerate.fs
@@ -0,0 +1,257 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ create the device tree for hub
+
+: (hub-create) ( -- )
+ mps port-number new-device-address port-number
+ ( mps port-number usb-address port-number )
+ new-device set-space ( mps port-number usb-address )
+ encode-int s" USB-ADDRESS" property ( mps port-number )
+ s" Address Set" usb-debug-print
+ encode-int s" reg" property ( mps )
+ s" Port Number Set" usb-debug-print
+ encode-int s" MPS-DCP" property
+ s" MPS Set" usb-debug-print
+ s" usb-hub.fs" INCLUDED
+ s" Driver Included" usb-debug-print
+ finish-device
+;
+
+
+\ encode properties for scsi or atapi device
+
+: (atapi-scsi-property-set) ( -- )
+ dd-buffer @ e + c@ ( Manuf )
+ dd-buffer @ f + c@ ( Manuf Prod )
+ dd-buffer @ 10 + c@ ( Manuf Prod Serial-Num )
+ cd-buffer @ 16 + w@-le ( Manuf Prod Serial-Num ep-mps )
+ cd-buffer @ 14 + c@ ( Manuf Prod Serial-Num ep-mps ep-addr )
+ cd-buffer @ 1d + w@-le ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps )
+ cd-buffer @ 1b + c@ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr )
+ mps port-number new-device-address port-number
+ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr
+ mps port-num usb-addr port-num )
+ new-device set-space
+ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr
+ mps port-num usb-addr )
+ encode-int s" USB-ADDRESS" property
+ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr
+ mps port-num )
+ encode-int s" reg" property
+ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr
+ mps )
+ encode-int s" MPS-DCP" property
+ ( Manuf Prod Serial-Num ep-mps ep-addr ep-mps ep-addr )
+ 2 0 DO
+ dup 80 and IF
+ 7f and encode-int
+ s" BULK-IN-EP-ADDR" property
+ encode-int s" MPS-BULKIN" property
+ ELSE
+ encode-int s" BULK-OUT-EP-ADDR" property
+ encode-int s" MPS-BULKOUT" property
+ THEN
+ LOOP ( Manuf Prod Serial-Num )
+ encode-int s" iSerialNumber" property ( Manuf Prod )
+ encode-int s" iProduct" property ( Manuf )
+ encode-int s" iManufacturer" property
+;
+
+
+\ To classify device as hub/atapi/scsi/HID device
+
+: (device-classify)
+ ( -- Interface-protocol Interface-subclass Interface-class TRUE|FALSE )
+ cd-buffer @ BULK-CONFIG-DESCRIPTOR-LEN erase
+ cd-buffer @ BULK-CONFIG-DESCRIPTOR-LEN mps new-device-address
+ ( buffer descp-len mps usb-address )
+ control-std-get-configuration-descriptor
+ IF
+ cd-buffer @ 1+ c@ ( Descriptor-type )
+ 2 = IF
+ cd-buffer @ 10 + c@ ( protocol )
+ cd-buffer @ f + c@ ( protocol subclass )
+ cd-buffer @ e + c@ ( protocol subclass class )
+ TRUE
+ ELSE
+ s" Not a valid configuration descriptor!!" usb-debug-print
+ FALSE
+ THEN
+ ELSE
+ s" Unable to read configuration descriptor!!" usb-debug-print
+ FALSE
+ THEN
+;
+
+
+\ create device tree for Atapi SFF-8020 device
+
+: (atapi-8020-create) ( -- )
+ (atapi-scsi-property-set)
+ s" usb-storage.fs" INCLUDED
+ finish-device
+;
+
+\ create device tree for Atapi SFF-8070 device
+
+: (atapi-8070-create) ( -- )
+ (atapi-scsi-property-set)
+ s" usb-storage.fs" INCLUDED
+ \ s" storage" device-name
+ finish-device
+;
+
+
+\ create device tree for SCSI device
+
+: (scsi-create) ( -- )
+ mps new-device-address 0 ch-buffer 1 control-std-get-maxlun ( TRUE|FALSE )
+ IF
+ s" GET-MAX-LUN IS WORKING :" usb-debug-print
+ ELSE
+ s" ERROR in GET-MAX-LUN " usb-debug-print
+ cd-buffer @ 5 + c@ to temp1
+ temp1 new-device-address control-std-set-configuration drop
+ THEN
+ \ FIXME: an IBM external HDD reported a number of 127 LUNs which could
+ \ not be set up. We need to understand how to set up the device
+ \ to report the correct number of LUNs.
+ \ The USB Massbulk Standard 1.0 defines a maximum of 15 mult. LUNs.
+ \ Workaround: Devices that might report a higher number are treated
+ \ as having exactly one LUN. Without this workaround the
+ \ USB scan hangs during the setup of non-available LUNs.
+ ch-buffer c@ dup 0= swap f > or IF
+ s" + LUN: " ch-buffer c@ usb-debug-print-val
+ (atapi-scsi-property-set)
+ s" usb-storage.fs" INCLUDED
+ finish-device
+
+ ELSE
+ s" - LUN: " ch-buffer c@ usb-debug-print-val
+ (atapi-scsi-property-set)
+ s" usb-storage-wrapper.fs" INCLUDED
+ finish-device
+
+ THEN
+;
+
+
+\ Classify USB storage device by sub-class code
+
+: (classify-storage) ( interface-protocol interface-subclass -- )
+ s" USB: Mass Storage Device Found!" usb-debug-print
+ swap 50 <> IF
+ s" USB storage: Protocol is not 50." usb-debug-print
+ drop EXIT
+ THEN
+ ( interface-subclass )
+ CASE
+ 02 OF (atapi-8020-create) s" 2 ATAPI " usb-debug-print ENDOF
+ 05 OF (atapi-8070-create) s" 5 ATAPI " usb-debug-print ENDOF
+ 06 OF (scsi-create) s" 6 SCSI " usb-debug-print ENDOF
+ dup OF s" USB storage: Unsupported sub-class code." usb-debug-print ENDOF
+ ENDCASE
+;
+
+
+\ create keyboard device tree
+
+: (keyboard-create) ( -- )
+ cd-buffer @ 1f + c@ ( ep-mps )
+ cd-buffer @ 1d + c@ ( ep-mps ep-addr )
+ mps port-number new-device-address port-number
+ ( ep-mps ep-addr mps port-num usb-addr port-num )
+ new-device set-space ( ep-mps ep-addr mps port-num usb-addr )
+ encode-int s" USB-ADDRESS" property ( ep-mps ep-addr mps port-num )
+ encode-int s" reg" property ( ep-mps ep-addr mps )
+ encode-int s" MPS-DCP" property ( ep-mps ep-addr )
+ 7f and encode-int s" INT-IN-EP-ADDR" property
+ encode-int s" MPS-INTIN" property
+ new-device-address \ device-speed
+ s" usb-keyboard.fs" INCLUDED
+ finish-device
+;
+
+: (mouse-create) ( -- )
+ mps port-number new-device-address port-number
+ ( mps port-num usb-addr port-num )
+ new-device set-space ( mps port-num usb-addr )
+ encode-int s" USB-ADDRESS" property ( mps port-num )
+ encode-int s" reg" property ( mps )
+ encode-int s" MPS-DCP" property
+ s" usb-mouse.fs" INCLUDED
+ finish-device
+;
+
+
+\ Classify by interface class code
+
+: (classify-by-interface) ( -- )
+ (device-classify) IF
+ ( Interface-protocol Interface-subclass Interface-class )
+ CASE
+ 08 OF
+ ( Interface-protocol Interface-subclass )
+ (classify-storage)
+ ENDOF
+ 03 OF
+ ( Interface-protocol Interface-subclass )
+ s" USB: HID Found!" usb-debug-print
+ 01 = IF
+ case
+ 01 of
+ s" USB keyboard!" usb-debug-print
+ (keyboard-create)
+ endof
+ 02 of
+ s" USB mouse!" usb-debug-print
+ (mouse-create)
+ endof
+ dup of
+ s" USB: unsupported HID!" usb-debug-print
+ endof
+ endcase
+ ELSE
+ s" USB: unsupported HID!" usb-debug-print
+ THEN
+ ENDOF
+ dup OF
+ ( Interface-protocol Interface-subclass )
+ s" USB: unsupported interface type." usb-debug-print
+ 2drop
+ ENDOF
+ ENDCASE
+ THEN
+;
+
+
+\ create usb device tree depending upon classification of the device
+\ after encoding apt properties
+
+: create-usb-device-tree ( -- )
+ dd-buffer @ DEVICE-DESCRIPTOR-DEVCLASS-OFFSET + c@ ( Device-class )
+ CASE
+ HUB-DEVICE-CLASS OF s" USB: HUB found" usb-debug-print
+ (hub-create)
+ ENDOF
+ NO-CLASS OF
+ \ In this case, the INTERFACE descriptor
+ \ tells you whats what -- Refer USB spec.
+ (classify-by-interface)
+ ENDOF
+ DUP OF
+ s" USB: Unknown device found." usb-debug-print
+ ENDOF
+ ENDCASE
+;
diff --git a/slof/fs/usb/usb-hub.fs b/slof/fs/usb/usb-hub.fs
new file mode 100644
index 0000000..ac0ae66
--- /dev/null
+++ b/slof/fs/usb/usb-hub.fs
@@ -0,0 +1,468 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ ----------------------------------------------------------------------------
+\ On detection of a hub after reading the device descriptor this package has to
+\ be called so that the hub enumeration is done to idenitify the down stream
+\ device
+\ --------------------------------------------------------------------------
+\ OF properties
+\ --------------------------------------------------------------------------
+
+
+s" hub" device-name
+s" usb" device-type
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+\ converts physical address to text unit string
+
+
+: encode-unit ( port-addr -- unit-str unit-len ) 1 hex-encode-unit ;
+
+
+\ Converts text unit string to phyical address
+
+
+: decode-unit ( addr len -- port-addr ) 1 hex-decode-unit ;
+
+0 VALUE new-device-address
+0 VALUE port-number
+0 VALUE MPS-DCP
+0 VALUE mps
+0 VALUE my-usb-address
+
+00 value device-speed
+
+
+\ Get parameters passed from the parent.
+
+: mps-property-set ( -- )
+ s" HUB Compiling mps-property-set " usb-debug-print
+ s" USB-ADDRESS" get-my-property ( TRUE | prop-addr prop-len FALSE )
+ IF
+ s" notpossible" usb-debug-print
+ ELSE
+ decode-int nip nip to my-usb-address
+ THEN
+ s" MPS-DCP" get-my-property ( TRUE | prop-addr prop-len FALSE )
+ IF
+ s" MPS-DCP property not found Assuming 8 as MAX PACKET SIZE" ( str len )
+ usb-debug-print
+ s" for the default control pipe" usb-debug-print
+ 8 to MPS-DCP
+ ELSE
+ s" MPS-DCP property found!!" usb-debug-print ( prop-addr prop-len FALSE )
+ decode-int nip nip to MPS-DCP
+ THEN
+;
+
+
+\ --------------------------------------------------------------------------
+\ Constant declarations
+\ --------------------------------------------------------------------------
+
+
+2303080000000000 CONSTANT hppwr-set
+2301080000000000 CONSTANT hppwr-clear
+2303040000000000 CONSTANT hprst-set
+A300000000000400 CONSTANT hpsta-get
+2303010000000000 CONSTANT hpena-set
+A006002900000000 CONSTANT hubds-get
+8 CONSTANT DEFAULT-CONTROL-MPS
+12 CONSTANT DEVICE-DESCRIPTOR-LEN
+9 CONSTANT CONFIG-DESCRIPTOR-LEN
+20 CONSTANT BULK-CONFIG-DESCRIPTOR-LEN
+
+
+\ TODO:
+\ CONFIG-DESCRIPTOR-LEN should be only 9. The interface
+\ and endpoint descriptors returned along with config
+\ descriptor are variable and 0x19 is a very wrong VALUE
+\ to specify for this #define.
+
+
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE-OFFSET
+4 CONSTANT DEVICE-DESCRIPTOR-DEVCLASS-OFFSET
+7 CONSTANT DEVICE-DESCRIPTOR-MPS-OFFSET
+9 CONSTANT HUB-DEVICE-CLASS
+0 CONSTANT NO-CLASS
+
+
+\ --------------------------------------------------------------------------
+\ Temporary Variable declarations
+\ --------------------------------------------------------------------------
+
+00 VALUE temp1
+00 VALUE temp2
+00 VALUE temp3
+00 VALUE po2pg \ Power On to Power Good
+
+
+\ --------------------------------------------------------------------------
+\ Buffer allocations
+\ --------------------------------------------------------------------------
+
+
+VARIABLE setup-packet \ 8 bytes for setup packet
+VARIABLE ch-buffer \ 1 byte character buffer
+
+INSTANCE VARIABLE dd-buffer
+INSTANCE VARIABLE cd-buffer
+
+\ TODO:
+\ Should arrive a proper value for the size of the "cd-buffer"
+
+8 chars alloc-mem VALUE status-buffer
+9 chars alloc-mem VALUE hd-buffer
+
+
+: (allocate-mem) ( -- )
+ DEVICE-DESCRIPTOR-LEN chars alloc-mem dd-buffer !
+ BULK-CONFIG-DESCRIPTOR-LEN chars alloc-mem cd-buffer !
+;
+
+
+: (de-allocate-mem) ( -- )
+ dd-buffer @ ?dup IF
+ DEVICE-DESCRIPTOR-LEN free-mem
+ 0 dd-buffer !
+ THEN
+ cd-buffer @ ?dup IF
+ BULK-CONFIG-DESCRIPTOR-LEN free-mem
+ 0 cd-buffer !
+ THEN
+;
+
+
+\ standard open firmware methods
+
+: open ( -- TRUE )
+ (allocate-mem)
+ TRUE
+;
+
+: close ( -- )
+ (de-allocate-mem)
+;
+
+
+\ --------------------------------------------------------------------------
+\ Parent's method
+\ --------------------------------------------------------------------------
+
+
+: controlxfer ( dir addr dlen setup-packet MPS ep-fun -- TRUE|FALSE )
+ s" controlxfer" $call-parent
+;
+
+: control-std-set-address ( speedbit -- usb-address TRUE|FALSE )
+ s" control-std-set-address" $call-parent
+;
+
+: control-std-get-device-descriptor
+ ( data-buffer data-len MPS funcAddr -- TRUE|FALSE )
+ s" control-std-get-device-descriptor" $call-parent
+;
+
+: control-std-get-configuration-descriptor
+ ( data-buffer data-len MPS funcAddr -- TRUE|FALSE )
+ s" control-std-get-configuration-descriptor" $call-parent
+;
+
+: control-std-get-maxlun
+ ( MPS fun-addr dir data-buff data-len -- TRUE|FALSE)
+ s" control-std-get-maxlun" $call-parent
+;
+
+: control-std-set-configuration
+ ( configvalue FuncAddr -- TRUE|FALSE )
+ s" control-std-set-configuration" $call-parent
+;
+
+: control-std-get-string-descriptor
+ ( StringIndex data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
+ s" control-std-get-string-descriptor" $call-parent
+;
+
+: rw-endpoint
+ ( pt ed-type toggle buffer length mps address -- toggle TRUE|toggle FALSE )
+ s" rw-endpoint" $call-parent
+;
+
+: debug-td ( -- )
+ s" debug-td" $call-parent
+;
+
+
+\ --------------------------------------------------------------------------
+\ HUB specific methods
+\ --------------------------------------------------------------------------
+\ To bring on the power on a valid port of a hub with a valid USB address
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-power-set ( port# -- TRUE|FALSE )
+ hppwr-set setup-packet ! ( port#)
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE | FALSE )
+;
+
+
+\ --------------------------------------------------------------------------
+\ To put power off on ports where device detection or enumeration has failed
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-power-clear ( port#-- TRUE|FALSE )
+ hppwr-clear setup-packet ! ( port#)
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To reset a valid port of a hub with a valid USB
+\ address
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-reset-set ( port# -- TRUE|FALSE )
+ hprst-set setup-packet ! ( port# )
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To enable a particular valid port of a hub with a valid USB address
+\ -------------------------------------------------------------------------
+
+
+: control-hub-port-enable ( port# -- TRUE|FALSE )
+ hpena-set setup-packet ! ( port# )
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To get the status of a valid port of a hub with
+\ a valid USB address
+\ -------------------------------------------------------------------------
+
+
+: control-hub-port-status-get ( buffer port# -- TRUE|FALSE )
+ hpsta-get setup-packet ! ( buffer port# )
+ setup-packet 4 + c! ( buffer )
+ 0 swap 4 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ --------------------------------------------------------------------------
+\ To get the hub descriptor to understand how many ports are vailable and the
+\ specs of those ports
+\ ---------------------------------------------------------------------------
+
+
+: control-get-hub-descriptor ( buffer buffer-length -- TRUE|FALSE )
+ hubds-get setup-packet !
+ dup setup-packet 6 + w!-le ( buffer buffer-length )
+ 0 -rot setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+s" usb-enumerate.fs" INCLUDED
+
+
+: hub-configure-port ( port# -- )
+
+ \ Step 1: set the Port Power
+ usb-test-flag
+ IF
+ ." Port: " dup . cr
+ 150 ms \ wait for bad devices
+ THEN
+
+ dup control-hub-port-power-set drop ( port# )
+ BEGIN ( port# )
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 102 and 0= ( port# TRUE|FALSE )
+ WHILE ( port# )
+ REPEAT ( port# )
+ po2pg 3 * ms \ wait for bPwrOn2PwrGood*3 ms
+
+ usb-test-flag
+ IF
+ 150 ms
+ THEN
+ \ STEP 2: Reset the port.
+
+ dup control-hub-port-reset-set drop ( port# )
+ BEGIN ( port# )
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 10 and ( port# TRUE|FALSE )
+ usb-test-flag
+ IF
+ s" Port Satus: " status-buffer w@-le usb-debug-print-val
+ THEN
+ WHILE ( port# )
+ REPEAT ( port# )
+
+ \ after reset set port enable -important-
+ dup control-hub-port-enable drop ( port# )
+
+ usb-test-flag
+ IF
+ 10 ms
+ THEN
+
+ \ STEP 3: Check if a device is connected to the
+ \ port.
+
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 103 and 103 <> ( port# TRUE|FALSE )
+ s" Port status bits: " status-buffer w@-le usb-debug-print-val
+ IF ( port# )
+ drop
+ s" Connect status: No device connected " usb-debug-print
+ EXIT
+ THEN
+
+ \ New addition: Sometimes the port status returns connected
+ \ but Set address was failing. Analysis showed that such
+ \ ports do not set this bit to 1.
+
+ status-buffer 2 + w@-le 1 and 1 <> ( port# )
+ IF ( port# )
+ drop
+ s" No device connected to port- set addresss failed" usb-debug-print
+ EXIT
+ THEN
+ s" HUB: New device found!!!" usb-debug-print
+\ s" HUB: Status buffer first word -> " usb-debug-print
+\ s" HUB: Status buffer second word -> " usb-debug-print
+
+ \ STEP 4: Assign an address to this device.
+
+ status-buffer w@-le 200 and 4 lshift \ get speed bit
+ dup to device-speed \ store speed bit
+ ( port# speedbit )
+ control-std-set-address ( port# usb-addr TRUE|FALSE )
+ 50 ms ( port# usb-addr TRUE|FALSE )
+ debug-td ( port# usb-addr TRUE|FALSE )
+ IF ( port# usb-addr )
+ device-speed or ( port# usb-addr+speedbit )
+ to new-device-address ( port# )
+ to port-number
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN erase
+ dd-buffer @ DEFAULT-CONTROL-MPS DEFAULT-CONTROL-MPS new-device-address
+ ( buffer mps mps usb-addr )
+ control-std-get-device-descriptor ( TRUE|FALSE )
+ IF
+ dd-buffer @ DEVICE-DESCRIPTOR-TYPE-OFFSET + c@ ( descriptor-type )
+ DEVICE-DESCRIPTOR-TYPE <> ( TRUE|FALSE )
+ IF
+ s" HUB: ERROR!! Invalid Device Descriptor for the new device"
+ usb-debug-print
+ ELSE
+ dd-buffer @ DEVICE-DESCRIPTOR-MPS-OFFSET + c@ to mps
+
+ \ Re-read the device descriptor again with the known MPS.
+
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN erase
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN mps new-device-address
+ ( buffer descp-len mps usb-addr )
+ \ s" DEVICE DESCRIPTOR: " usb-debug-print
+ control-std-get-device-descriptor drop
+ \ dd-buffer usb-debug-print-val
+ create-usb-device-tree
+ THEN
+ ELSE
+ s" ERROR!! Failed to get device descriptor" usb-debug-print
+ THEN
+ ELSE ( port# )
+ s" USB Set Adddress failed!!" usb-debug-print ( port# )
+ s" Clearing Port Power..." usb-debug-print ( port# )
+ control-hub-port-power-clear ( TRUE|FALSE )
+ IF
+ s" Port power down " usb-debug-print
+ ELSE
+ s" Unable to clear port power!!!" usb-debug-print
+ THEN
+ THEN
+;
+
+
+\ ---------------------------------------------------------------------------
+\ To enumerate all the valid ports of hub
+\ TODO:
+\ 1. Remove hardcoded constants.
+\ 2. Remove Endian Dependencies.
+\ 3. Return values of controlxfer should be checked.
+\ ---------------------------------------------------------------------------
+
+: hub-enumerate ( -- )
+ cd-buffer @ CONFIG-DESCRIPTOR-LEN erase
+
+ \ Get HUB configuration and SET the configuration
+ \ note: remove hard-coded constants.
+
+ cd-buffer @ CONFIG-DESCRIPTOR-LEN MPS-DCP my-usb-address
+ ( buffer descp-len mps usb-address )
+ control-std-get-configuration-descriptor drop
+ cd-buffer @ 1+ c@ 2 <> IF
+ s" Unable to read configuration descriptor" usb-debug-print
+ EXIT
+ THEN
+ cd-buffer @ 4 + c@ 1 <> IF
+ s" Not a valid HUB config descriptor" usb-debug-print
+ EXIT
+ THEN
+
+ \ TODO: Do further checkings on the returned Configuration descriptor
+ \ before proceeding to accept it.
+
+ cd-buffer @ 5 + c@ to temp1 \ Store the configuration in temp1
+ temp1 my-usb-address control-std-set-configuration drop
+ my-usb-address to temp1
+ hd-buffer 9 erase
+ hd-buffer 9 control-get-hub-descriptor drop
+
+ \ PENDING: 1. Check Return value.
+ \ 2. HUB descriptor size is variable. Currently we r hardcoding
+ \ a value of 9.
+
+ hd-buffer 2 + c@ to temp2
+ s" HUB: Found " usb-debug-print \ temp2 .
+ s" number of downstream hub ports! : " temp2 usb-debug-print-val
+ hd-buffer 5 + c@ to po2pg \ get bPwrOn2PwrGood
+ temp2 1+ 1 DO
+ I hub-configure-port
+ LOOP
+;
+
+
+\ --------------------------------------------------------------------------
+\ To initialize hub
+\ --------------------------------------------------------------------------
+
+(allocate-mem)
+mps-property-set
+hub-enumerate
+(de-allocate-mem)
+
diff --git a/slof/fs/usb/usb-kbd-device-support.fs b/slof/fs/usb/usb-kbd-device-support.fs
new file mode 100644
index 0000000..ccf1b42
--- /dev/null
+++ b/slof/fs/usb/usb-kbd-device-support.fs
@@ -0,0 +1,105 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+00 value kbd-addr
+to kbd-addr
+8 alloc-mem to kbd-report
+4 chars alloc-mem value kbd-data
+
+: rw-endpoint
+ s" rw-endpoint" $call-parent ;
+
+: controlxfer
+ s" controlxfer" $call-parent ;
+
+: control-std-get-device-descriptor
+ s" control-std-get-device-descriptor" $call-parent ;
+
+: control-std-get-configuration-descriptor
+ s" control-std-get-configuration-descriptor" $call-parent ;
+
+: control-std-set-configuration
+ s" control-std-set-configuration" $call-parent ;
+
+: control-cls-set-protocol ( reportvalue FuncAddr -- TRUE|FALSE )
+ to temp1
+ to temp2
+ 210b000000000100 setup-packet !
+ temp2 kbd-data l!-le
+ 1 kbd-data 1 setup-packet DEFAULT-CONTROL-MPS temp1 controlxfer
+;
+
+: control-cls-set-idle ( reportvalue FuncAddr -- TRUE|FALSE )
+ to temp1
+ to temp2
+ 210a000000000000 setup-packet !
+ temp2 kbd-data l!-le
+ 0 kbd-data 0 setup-packet DEFAULT-CONTROL-MPS temp1 controlxfer
+;
+
+: control-std-get-report-descriptor ( data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
+ to temp1
+ to temp2
+ to temp3
+ 8106002200000000 setup-packet !
+ temp3 setup-packet 6 + w!-le
+ 0 swap temp3 setup-packet temp2 temp1 controlxfer
+;
+
+: kbd-init
+ s" Starting to initialize keyboard" usb-debug-print
+ s" MPS-INTIN" get-my-property
+ if
+ s" not possible" usb-debug-print
+ else
+ decode-int nip nip to mps-int-in
+ then
+ s" INT-IN-EP-ADDR" get-my-property
+ if
+ s" not possible" usb-debug-print
+ else
+ decode-int nip nip to int-in-ep
+ then
+
+ 7f alloc-mem to cfg-buffer
+ s" Allocated buffers!!" usb-debug-print
+
+ cfg-buffer 12 8 kbd-addr \ get device descriptor
+ control-std-get-device-descriptor
+ drop
+ \ s" dev_desc=" type cfg-buffer 12 dump cr
+
+ cfg-buffer 9 8 kbd-addr \ get config descriptor
+ control-std-get-configuration-descriptor
+ drop
+ \ s" cfg_desc=" type cfg-buffer 9 dump cr
+
+ cfg-buffer 5 + c@ kbd-addr \ set configuration
+ control-std-set-configuration
+ drop
+ s" KBDS: Set config returned" usb-debug-print
+
+ 0 kbd-addr control-cls-set-protocol drop \ set protocol=boot mode
+ s" KBDS: Set protocol returned" usb-debug-print
+
+ 0 kbd-addr control-cls-set-idle drop \ set idle
+ s" KBDS: Set idle returned" usb-debug-print
+
+ cfg-buffer 40 8 kbd-addr \ get report descriptor
+ control-std-get-report-descriptor
+ drop
+ \ s" report_desc=" type cfg-buffer 40 dump cr
+
+ s" Finished initializing keyboard" usb-debug-print
+;
+
diff --git a/slof/fs/usb/usb-keyboard.fs b/slof/fs/usb/usb-keyboard.fs
new file mode 100644
index 0000000..b0c4be9
--- /dev/null
+++ b/slof/fs/usb/usb-keyboard.fs
@@ -0,0 +1,345 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" keyboard" device-name
+s" keyboard" device-type
+
+3 encode-int s" assigned-addresses" property
+1 encode-int s" reg" property
+1 encode-int s" configuration#" property
+s" EN" encode-string s" language" property
+
+1 constant NumLk
+2 constant CapsLk
+4 constant ScrLk
+
+00 value kbd-addr
+to kbd-addr \ save speed bit
+8 value mps-dcp
+8 constant DEFAULT-CONTROL-MPS
+8 chars alloc-mem value setup-packet
+8 chars alloc-mem value kbd-report
+4 chars alloc-mem value multi-key
+0 value cfg-buffer
+0 value led-state
+0 value temp1
+0 value temp2
+0 value temp3
+0 value ret
+0 value scancode
+0 value kbd-shift
+0 value kbd-scan
+0 value key-old
+0 value expire-ms
+0 value mps-int-in
+0 value int-in-ep
+0 value int-in-toggle
+
+kbd-addr \ give speed bit to include file
+s" usb-kbd-device-support.fs" included
+
+: control-cls-set-report ( reportvalue FuncAddr -- TRUE|FALSE )
+ to temp1
+ to temp2
+ 2109000200000100 setup-packet !
+ temp2 kbd-data l!-le
+ 1 kbd-data 1 setup-packet DEFAULT-CONTROL-MPS temp1 controlxfer
+;
+
+: control-cls-get-report ( data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
+ to temp1
+ to temp2
+ to temp3
+ a101000100000000 setup-packet !
+ temp3 setup-packet 6 + w!-le
+ 0 swap temp3 setup-packet temp2 temp1 controlxfer
+;
+
+: int-get-report ( -- ) \ get report for interrupt transfer
+ 0 2 int-in-toggle kbd-report 8 mps-int-in
+ kbd-addr int-in-ep 7 lshift or rw-endpoint \ get report
+ swap to int-in-toggle if
+ kbd-report @ ff00000000000000 and 38 rshift to kbd-shift \ store shift status
+ kbd-report @ 0000ffffffffffff and to kbd-scan \ store scan codes
+ else
+ 0 to kbd-shift \ clear shift status
+ 0 to kbd-scan \ clear scan code buffer
+ then
+;
+
+: ctl-get-report ( -- ) \ get report for control transfer
+ kbd-report 8 8 kbd-addr control-cls-get-report if \ get report
+ kbd-report @ ff00000000000000 and 38 rshift to kbd-shift \ store shift status
+ kbd-report @ 0000ffffffffffff and to kbd-scan \ store scan codes
+ else
+ 0 to kbd-shift \ clear shift status
+ 0 to kbd-scan \ clear scan code buffer
+ then
+;
+
+: open ( -- true )
+ true
+;
+
+: close ;
+
+: set-led ( led -- )
+ dup to led-state
+ kbd-addr control-cls-set-report drop
+;
+
+: is-shift ( -- true|false )
+ kbd-shift 22 and if
+ true
+ else
+ false
+ then
+;
+
+: is-alt ( -- true|false )
+ kbd-shift 44 and if
+ true
+ else
+ false
+ then
+;
+
+: is-ctrl ( -- true|false )
+ kbd-shift 11 and if
+ true
+ else
+ false
+ then
+;
+
+: ctrl_alt_del_key ( char -- )
+ is-ctrl if \ ctrl is pressed?
+ is-alt if \ alt is pressed?
+ 4c = if \ del is pressed?
+ s" reboot.... " usb-debug-print
+ \ reset-all \ reboot
+ drop false \ invalidate del key on top of stack
+ then
+ false \ dummy for last drop
+ then
+ then
+ drop \ clear stack
+;
+
+: get-ukbd-char ( ScanCode -- char|false )
+ dup ctrl_alt_del_key \ check ctrl+alt+del
+ dup to scancode \ store scan code
+ case \ translate scan code --> char
+ 04 of [char] a endof
+ 05 of [char] b endof
+ 06 of [char] c endof
+ 07 of [char] d endof
+ 08 of [char] e endof
+ 09 of [char] f endof
+ 0a of [char] g endof
+ 0b of [char] h endof
+ 0c of [char] i endof
+ 0d of [char] j endof
+ 0e of [char] k endof
+ 0f of [char] l endof
+ 10 of [char] m endof
+ 11 of [char] n endof
+ 12 of [char] o endof
+ 13 of [char] p endof
+ 14 of [char] q endof
+ 15 of [char] r endof
+ 16 of [char] s endof
+ 17 of [char] t endof
+ 18 of [char] u endof
+ 19 of [char] v endof
+ 1a of [char] w endof
+ 1b of [char] x endof
+ 1c of [char] y endof
+ 1d of [char] z endof
+ 1e of [char] 1 endof
+ 1f of [char] 2 endof
+ 20 of [char] 3 endof
+ 21 of [char] 4 endof
+ 22 of [char] 5 endof
+ 23 of [char] 6 endof
+ 24 of [char] 7 endof
+ 25 of [char] 8 endof
+ 26 of [char] 9 endof
+ 27 of [char] 0 endof
+ 28 of 0d endof \ Enter
+ 29 of 1b endof \ ESC
+ 2a of 08 endof \ Backsace
+ 2b of 09 endof \ Tab
+ 2c of 20 endof \ Space
+ 2d of [char] - endof
+ 2e of [char] = endof
+ 2f of [char] [ endof
+ 30 of [char] ] endof
+ 31 of [char] \ endof
+ 33 of [char] ; endof
+ 34 of [char] ' endof
+ 35 of [char] ` endof
+ 36 of [char] , endof
+ 37 of [char] . endof
+ 38 of [char] / endof
+ 39 of led-state CapsLk xor set-led false endof \ CapsLk
+ 3a of 1b 7e31315b to multi-key endof \ F1
+ 3b of 1b 7e32315b to multi-key endof \ F2
+ 3c of 1b 7e33315b to multi-key endof \ F3
+ 3d of 1b 7e34315b to multi-key endof \ F4
+ 3e of 1b 7e35315b to multi-key endof \ F5
+ 3f of 1b 7e37315b to multi-key endof \ F6
+ 40 of 1b 7e38315b to multi-key endof \ F7
+ 41 of 1b 7e39315b to multi-key endof \ F8
+ 42 of 1b 7e30315b to multi-key endof \ F9
+ 43 of 1b 7e31315b to multi-key endof \ F10
+ 44 of 1b 7e33315b to multi-key endof \ F11
+ 45 of 1b 7e34315b to multi-key endof \ F12
+ 47 of led-state ScrLk xor set-led false endof \ ScrLk
+ 49 of 1b 7e315b to multi-key endof \ Ins
+ 4a of 1b 7e325b to multi-key endof \ Home
+ 4b of 1b 7e335b to multi-key endof \ PgUp
+ 4c of 1b 7e345b to multi-key endof \ Del
+ 4d of 1b 7e355b to multi-key endof \ End
+ 4e of 1b 7e365b to multi-key endof \ PgDn
+ 4f of 1b 435b to multi-key endof \ R-arrow
+ 50 of 1b 445b to multi-key endof \ L-arrow
+ 51 of 1b 425b to multi-key endof \ D-arrow
+ 52 of 1b 415b to multi-key endof \ U-arrow
+ 53 of led-state NumLk xor set-led false endof \ NumLk
+ 54 of [char] / endof \ keypad /
+ 55 of [char] * endof \ keypad *
+ 56 of [char] - endof \ keypad -
+ 57 of [char] + endof \ keypad +
+ 58 of 0d endof \ keypad Enter
+ 89 of [char] \ endof \ japanese yen
+ dup of false endof \ other keys are false
+ endcase
+ to ret \ store char
+ led-state CapsLk and 0 <> if \ if CapsLk is on
+ scancode 03 > if \ from a to z ?
+ scancode 1e < if
+ ret 20 - to ret \ to Upper case
+ then
+ then
+ then
+ is-shift if \ if shift is on
+ scancode 03 > if \ from a to z ?
+ scancode 1e < if
+ ret 20 - to ret \ to Upper case
+ else
+ scancode
+ case \ translate scan code --> char
+ 1e of [char] ! endof
+ 1f of [char] @ endof
+ 20 of [char] # endof
+ 21 of [char] $ endof
+ 22 of [char] % endof
+ 23 of [char] ^ endof
+ 24 of [char] & endof
+ 25 of [char] * endof
+ 26 of [char] ( endof
+ 27 of [char] ) endof
+ 2d of [char] _ endof
+ 2e of [char] + endof
+ 2f of [char] { endof
+ 30 of [char] } endof
+ 31 of [char] | endof
+ 33 of [char] : endof
+ 34 of [char] " endof
+ 35 of [char] ~ endof
+ 36 of [char] < endof
+ 37 of [char] > endof
+ 38 of [char] ? endof
+ dup of ret endof \ other keys are no change
+ endcase
+ to ret \ overwrite new char
+ then
+ then
+ then
+ led-state NumLk and 0 <> if \ if NumLk is on
+ scancode
+ case \ translate scan code --> char
+ 59 of [char] 1 endof
+ 5a of [char] 2 endof
+ 5b of [char] 3 endof
+ 5c of [char] 4 endof
+ 5d of [char] 5 endof
+ 5e of [char] 6 endof
+ 5f of [char] 7 endof
+ 60 of [char] 8 endof
+ 61 of [char] 9 endof
+ 62 of [char] 0 endof
+ 63 of [char] . endof \ keypad .
+ dup of ret endof \ other keys are no change
+ endcase
+ to ret \ overwirte new char
+ then
+ ret \ return char
+;
+
+: usb-kread ( -- char|false ) \ usb key read for control transfer
+ multi-key 0 <> if \ if multi scan code key is pressed
+ multi-key ff and \ read one byte from buffer
+ multi-key 8 rshift to multi-key \ move to next byte
+ else \ normal key check
+ \ if interrupt transfer
+ int-get-report \ read report (interrupt transfer)
+ \ else control transfer
+ \ ctl-get-report \ read report (control transfer)
+ \ end of interrupt/control switch
+ kbd-scan 0 <> if \ scan code exist?
+ begin kbd-scan ff and dup 00 = while \ get a last scancode in report buffer
+ kbd-scan 8 rshift to kbd-scan \ This algorithm is wrong --> must be fixed!
+ drop \ KBD doesn't set scancode in pressed order!!!
+ repeat
+ dup key-old <> if \ if the scancode is new
+ dup to key-old \ save current scan code
+ get-ukbd-char \ translate scan code --> char
+ milliseconds fa + to expire-ms \ set typematic delay 250ms
+ else \ scan code is not changed
+ milliseconds expire-ms > if \ if timer is expired ... should be considered timer carry over
+ get-ukbd-char \ translate scan code --> char
+ milliseconds 21 + to expire-ms \ set typematic rate 30cps
+ else \ timer is not expired
+ drop false \ do nothing
+ then
+ then
+ else
+ 0 to key-old \ clear privious key
+ false \ no scan code --> return false
+ then
+ then
+;
+
+
+: key-read ( -- char )
+ 0 begin drop usb-kread dup 0 <> until \ read key input (Interrupt transfer)
+;
+
+
+: read ( addr len -- actual )
+ 0= IF drop 0 EXIT THEN
+ usb-kread ?dup IF swap c! 1 ELSE 0 swap c! -2 THEN
+;
+
+
+kbd-init \ keyboard initialize
+milliseconds to expire-ms \ Timer initialize
+0 to multi-key \ multi key buffer clear
+7 set-led \ flash leds
+250 ms
+0 set-led
+
+s" keyboard" get-node node>path set-alias
+
diff --git a/slof/fs/usb/usb-mouse.fs b/slof/fs/usb/usb-mouse.fs
new file mode 100644
index 0000000..1703196
--- /dev/null
+++ b/slof/fs/usb/usb-mouse.fs
@@ -0,0 +1,26 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+s" mouse" device-name
+s" mouse" device-type
+
+1 encode-int s" configuration#" property
+2 encode-int s" #buttons" property
+4 encode-int s" assigned-addresses" property
+2 encode-int s" reg" property
+
+: open true ;
+: close ;
+: get-event ( msec -- pos.x pos.y buttons true|false )
+;
+
diff --git a/slof/fs/usb/usb-ohci.fs b/slof/fs/usb/usb-ohci.fs
new file mode 100644
index 0000000..5b71d56
--- /dev/null
+++ b/slof/fs/usb/usb-ohci.fs
@@ -0,0 +1,1109 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ We expect to base address of the OHCI controller on the stack:
+
+CONSTANT baseaddrs
+
+s" OHCI base address = " baseaddrs usb-debug-print-val
+
+
+\ Open Firmware Properties
+
+
+s" usb" 2dup device-name device-type
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+
+\ converts physical address to text unit string
+
+
+: encode-unit ( port -- unit-str unit-len ) 1 hex-encode-unit ;
+
+
+\ Converts text unit string to phyical address
+
+
+: decode-unit ( addr len -- port ) 1 hex-decode-unit ;
+
+
+\ Data Structure Definitions
+\ OHCI Task Descriptor Structure.
+
+
+STRUCT
+ /l field td>tattr
+ /l field td>cbptr
+ /l field td>ntd
+ /l field td>bfrend
+CONSTANT /tdlen
+
+
+\ OHCI Endpoint Descriptor Structure.
+
+
+STRUCT
+ /l field ed>eattr
+ /l field ed>tdqtp
+ /l field ed>tdqhp
+ /l field ed>ned
+CONSTANT /edlen
+
+
+\ HCCA Done queue location packaged as a structure for ease OF use.
+
+
+STRUCT
+ /l field hc>hcattr
+ /l field hc>hcdone
+CONSTANT /hclen
+
+
+\ OHCI Memory Mapped Registers
+
+
+\ : get-base-address ( -- baseaddr )
+\ s" assigned-addresses" get-my-property IF
+\ s" not possible" usb-debug-print
+\ -1
+\ ELSE ( addr len )
+\ decode-int drop ( addr len )
+\ decode-int drop ( addr len )
+\ decode-int nip nip ( n )
+\ THEN
+\ \ TODO: Use translate-address here
+\ ;
+
+\ get-base-address CONSTANT baseaddrs
+
+baseaddrs 4 + CONSTANT hccontrol
+baseaddrs 8 + CONSTANT hccomstat
+baseaddrs 0c + CONSTANT hcintstat
+baseaddrs 14 + CONSTANT hcintdsbl
+baseaddrs 18 + CONSTANT hchccareg
+baseaddrs 20 + CONSTANT hcctrhead
+baseaddrs 24 + CONSTANT hccurcont
+baseaddrs 28 + CONSTANT hcbulkhead
+baseaddrs 2c + CONSTANT hccurbulk
+baseaddrs 30 + CONSTANT hcdnehead
+baseaddrs 34 + CONSTANT hcintrval
+baseaddrs 48 + CONSTANT hcrhdescA
+baseaddrs 54 + CONSTANT hcrhpstat
+
+
+\ Constants for COMSTAT register
+
+
+2 CONSTANT CLF
+
+\ Constants for INTSTAT register
+
+2 CONSTANT WDH
+
+\ Constants for RH Port Status Register
+
+1 CONSTANT RHP-CCS
+2 CONSTANT RHP-PES
+10 CONSTANT RHP-PRS
+100 CONSTANT RHP-PPS
+100000 CONSTANT RHP-PRSC
+
+\ Constants for OHCI
+
+0 CONSTANT OHCI-DP-SETUP
+1 CONSTANT OHCI-DP-OUT
+2 CONSTANT OHCI-DP-IN
+3 CONSTANT OHCI-DP-INVALID
+
+\ 8-byte Standard Device Requests + Hub class specific requests.
+
+8006000100001200 CONSTANT get-ddescp
+8006000200000900 CONSTANT get-cdescp
+8006000400000900 CONSTANT get-idescp
+8006000500000700 CONSTANT get-edescp
+A006000000001000 CONSTANT get-hdescp
+0009010000000000 CONSTANT set-cdescp
+2303010004000000 CONSTANT hpenable-set
+2303040001000000 CONSTANT hp1rst-set
+2303040002000000 CONSTANT hp2rst-set
+2303040003000000 CONSTANT hp3rst-set
+2303040004000000 CONSTANT hp4rst-set
+2303080001000000 CONSTANT hp1pwr-set
+2303080002000000 CONSTANT hp2pwr-set
+2303080003000000 CONSTANT hp3pwr-set
+2303080004000000 CONSTANT hp4pwr-set
+A003000000000400 CONSTANT hstatus-get
+A300000001000400 CONSTANT hp1sta-get
+A300000002000400 CONSTANT hp2sta-get
+A300000003000400 CONSTANT hp3sta-get
+A300000004000400 CONSTANT hp4sta-get
+8008000000000100 CONSTANT get-config
+
+A1FE000000000100 CONSTANT GET-MAX-LUN
+
+2 18 lshift CONSTANT DATA0-TOGGLE
+3 18 lshift CONSTANT DATA1-TOGGLE
+0f 1c lshift CONSTANT CC-FRESH-TD
+8 CONSTANT STD-REQUEST-SETUP-SIZE
+0 13 lshift CONSTANT TD-DP-SETUP
+1 13 lshift CONSTANT TD-DP-OUT
+2 13 lshift CONSTANT TD-DP-IN
+
+400001 CONSTANT ed-cntatr
+400002 CONSTANT ed-cntatr1
+80081 CONSTANT ed-hubatr
+80000 CONSTANT ed-defatr
+0f0e40000 CONSTANT td-attr
+00 VALUE ptr
+
+
+\ TD Management constants and Data structures.
+
+
+200 CONSTANT MAX-TDS
+0 VALUE td-freelist-head
+0 VALUE td-freelist-tail
+0 VALUE num-free-tds
+
+INSTANCE VARIABLE td-list-region
+
+\ ED Management constants
+
+
+14 CONSTANT MAX-EDS
+0 VALUE ed-freelist-head
+0 VALUE num-free-eds
+INSTANCE VARIABLE ed-list-region
+0 VALUE usb-address
+0 VALUE initial-hub-address
+0 VALUE new-device-address
+0 VALUE mps
+0 VALUE DEBUG-TDS
+0 VALUE case-failed \ available for general use to see IF a CASE statement
+ \ failed or not.
+0 VALUE WHILE-failed \ available for general use to see IF a WHILE LOOP
+ \ failed in the middle. Used to break from the
+ \ WHILE LOOP
+
+8 CONSTANT DEFAULT-CONTROL-MPS
+12 CONSTANT DEVICE-DESCRIPTOR-LEN
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE-OFFSET
+4 CONSTANT DEVICE-DESCRIPTOR-DEVCLASS-OFFSET
+7 CONSTANT DEVICE-DESCRIPTOR-MPS-OFFSET
+
+20 CONSTANT BULK-CONFIG-DESCRIPTOR-LEN
+
+9 CONSTANT HUB-DEVICE-CLASS
+0 CONSTANT NO-CLASS
+
+VARIABLE setup-packet \ 8 bytes for setup packet
+VARIABLE ch-buffer \ 1 byte character buffer
+
+INSTANCE VARIABLE dd-buffer
+INSTANCE VARIABLE cd-buffer
+
+
+\ Temporary variables for functions. These variables have to be initialized
+\ before usage in functions and their values assume significance only during
+\ the function's execution time. Should be used like local variables.
+\ CAUTION:
+\ If you are calling functions that destroy contents OF these variables, be
+\ smart enuf to save the values before calling them.
+\ It is recommended that these temporary variables are used only amidst normal
+\ FORTH words -- not among the vicinity OF any OF the functions OF this node.
+
+
+0 VALUE temp1
+0 VALUE temp2
+0 VALUE temp3
+0 VALUE extra-bytes
+0 VALUE num-td
+0 VALUE current
+
+0 VALUE device-speed
+
+
+\ Debug functions for displaying ED, TD and their combo list.
+
+: display-ed ( ED-ADDRESS -- )
+ TO temp1
+ usb-debug-flag IF
+ s" Dump OF ED " type temp1 u. cr
+ s" eattr : " type temp1 ed>eattr l@-le u. cr
+ s" tdqhp : " type temp1 ed>tdqhp l@-le u. cr
+ s" tdqtp : " type temp1 ed>tdqtp l@-le u. cr
+ s" ned : " type temp1 ed>ned l@-le u. cr
+ THEN
+;
+
+
+\ Displays the transfer descriptors
+
+: display-td ( TD-ADDRESS -- )
+ TO temp1
+ usb-debug-flag IF
+ s" TD " type temp1 u. s" dump: " type cr
+ s" td>tattr : " type temp1 td>tattr l@-le u. cr
+ s" td>cbptr : " type temp1 td>cbptr l@-le u. cr
+ s" td>ntd : " type temp1 td>ntd l@-le u. cr
+ s" td>bfrend : " type temp1 td>bfrend l@-le u. cr
+ THEN
+;
+
+
+\ display's the descriptors
+
+
+: display-descriptors ( ED-ADDRESS -- )
+ 10 1- not and ( ED-ADDRESS~ )
+ dup display-ed ed>tdqhp l@-le BEGIN ( ED-ADDRESS~ )
+ 10 1- not and ( ED-ADDRESS~ )
+ dup 0<> ( ED-ADDRESS~ TRUE | FALSE )
+ WHILE
+ dup display-td td>ntd l@-le ( ED-ADDRESS~ )
+ REPEAT
+ drop
+;
+
+
+\ ---------------------------------------------------------------------------
+\ TD LIST MANAGEMENT WORDS
+\ ------------------------
+\ The following are WORDS internal to this node. They are supposed to
+\ be used by other WORDS inside this device node.
+\ The first three WORDS below form the interface. The fourth and fifth
+\ word is a helper function and is not exposed to other portions OF this
+\ device node.
+\ a) initialize-td-free-list
+\ b) allocate-td-list
+\ c) (free-td-list)
+\ d) find-td-list-tail-and-size
+\ e) zero-out-a-td-except-link
+\ ----------------------------------------------------------------------------
+
+
+: zero-out-a-td-except-link ( td -- )
+
+
+ \ There r definitely smarter ways to DO it especially
+ \ on a 64-bit machine.
+
+ \ Optimization, Portability:
+ \ --------------------------
+ \ Replace the following code by two "!" OF zeroes. Since
+ \ we know that an "td" is actually 16 bytes and that we
+ \ will be executing on a 64-bit machine, we can finish OFf
+ \ with 2 stores. But that WONT be portable.
+
+
+ dup 0 swap td>tattr l!-le ( td )
+ dup 0 swap td>cbptr l!-le ( td )
+ dup 0 swap td>bfrend l!-le ( td )
+ drop
+;
+
+
+\ COLON DEFINITION: initialize-td-free-list - Internal Function
+
+\ Initialize the TD Free List Region and create a linked list OF successive
+\ TDs. Note that the NEXT pointers are all in little-endian and they
+\ can be directly used for HC purposes.
+
+
+: initialize-td-free-list ( -- )
+ MAX-TDS 0= IF EXIT THEN
+ td-list-region @ 0= IF EXIT THEN
+ td-list-region @ TO temp1
+ 0 TO temp2 BEGIN
+ temp1 zero-out-a-td-except-link
+ temp1 /tdlen + dup temp1 td>ntd l!-le TO temp1
+ temp2 1+ TO temp2
+ temp2 MAX-TDS = ( TRUE | FALSE )
+ UNTIL
+ temp1 /tdlen - dup 0 swap td>ntd l!-le TO td-freelist-tail
+ td-list-region @ TO td-freelist-head
+ MAX-TDS TO num-free-tds
+;
+
+
+\ COLON DEFINITION: allocate-td-list -- Internal function
+\ Argument:
+\ The function accepts a non-negative number and allocates
+\ a TD-LIST containing that many TDs. A TD-LIST is a list
+\ OF TDs that are linked by the next-td field. The next-td
+\ field is in little-endian mode so that the TD list can
+\ be directly re-used by the HC.
+\ Return value:
+\ The function returns "head" and "tail" OF the allocated
+\ TD-LIST. If for any reason, the function cannot allocate
+\ the TD-LIST, the function returns 2 NULL pointers in the
+\ stack indicating that the allocation failed.
+
+\ Note that the TD list returned is NULL terminated. i.e
+\ the nextTd field OF the tail is NULL.
+
+
+
+: allocate-td-list ( n -- head tail )
+ dup 0= IF drop 0 0 EXIT THEN ( 0 0 )
+ dup num-free-tds > IF drop 0 0 EXIT THEN ( 0 0 )
+ dup num-free-tds = IF ( n )
+ drop td-freelist-head td-freelist-tail ( td-freelist-head td-freelist-tail )
+ 0 TO td-freelist-head ( td-freelist-head td-freelist-tail )
+ 0 TO td-freelist-tail ( td-freelist-head td-freelist-tail )
+ 0 TO num-free-tds ( td-freelist-head td-freelist-tail )
+ EXIT
+ THEN
+
+ \ If we are here THEN we know that the requested number OF TDs is less
+ \ than what we actually have. We need TO traverse the list and find the
+ \ new Head pointer position and THEN update the head pointer accordingly.
+ \ Update num-free-tds
+
+ dup num-free-tds swap - TO num-free-tds ( n )
+
+ \ Traverse through the Free list to identify the element that exists after
+ \ "n" TDs. Use the info to return the head and tail pointer and update
+ \ the new td-list-head
+
+ td-freelist-head ( n td-list-head )
+ dup TO temp1 ( n td-list-head )
+ swap ( td-list-head n )
+ 0 DO ( td-list-head )
+ temp1 TO temp2 ( td-list-head )
+ temp1 td>ntd l@-le TO temp1 ( td-list-head )
+ LOOP ( td-list-head )
+ temp2 ( td-list-head td-list-tail )
+ dup td>ntd 0 swap l!-le ( td-list-head td-list-tail )
+ temp1 TO td-freelist-head ( td-list-head td-list-tail )
+;
+
+
+\ COLON DEFINITION: find-td-list-tail-and-size
+\ This function counts the number OF TD elements
+\ in the given list. It also returns the last tail
+\ TD OF the TD list.
+
+\ ASSUMPTION:
+\ A NULL terminated TD list is assumed. A not-well formed
+\ list can result in in-determinate behaviour.
+
+\ ROOM FOR ENHANCEMENT:
+\ We could arrive at a generic function for counting
+\ list elements to which the next-ptr OFfset can also
+\ be passed as an argument (in this case it is >ntd)
+\ This function can THEN be changed to call the
+\ function with "0 >ntd" as an additional argument
+\ (apart from head and tail)
+
+
+: find-td-list-tail-and-size ( head -- tail n )
+ TO temp1
+ 0 TO temp2
+ 0 TO temp3
+ DEBUG-TDS IF
+ s" BEGIN find-td-list-tail-and-size: " usb-debug-print
+ THEN
+ BEGIN
+ temp1 0<> ( TRUE|FALSE )
+ WHILE
+ DEBUG-TDS IF
+ temp1 u. cr
+ THEN
+ temp1 TO temp3
+ temp1 td>ntd l@-le TO temp1
+ temp2 1+ TO temp2
+ REPEAT
+ temp3 temp2 ( tail n )
+ DEBUG-TDS IF
+ s" END find-td-list-tail-and-size" usb-debug-print
+ THEN
+;
+
+
+\ COLON DEFINITION: (free-td-list)
+
+\ Arguments: (head --)
+\ The "head" pointer OF the TD-LIST to be freed is passed as
+\ an argument to this function. The function merely adds the list to the
+\ already existing TD-LIST
+
+\ Assumptions:
+\ The function assumes that the TD-LIST passed as argument is a well-formed
+\ list. The function does not DO any check on it.
+\ But since, the "TD-LIST" is generally freed from the DONE-QUEUE which is
+\ a well-formed list, the interface makes much sense.
+
+\ Return values:
+\ Nothing is returned. The arguments passed are popped OFf.
+
+
+: (free-td-list) ( head -- )
+
+ \ Enhancement:
+ \ We could zero-out-a-td-except-link for the TD list that is being freed.
+ \ This way, we could prevent some nasty repercussions OF bugs (that r yet
+ \ to be discovered). but we can include this enhancement during the testing
+ \ phase.
+
+ dup find-td-list-tail-and-size num-free-tds + TO num-free-tds ( head tail )
+ td-freelist-tail 0= IF ( head tail )
+ dup TO td-freelist-tail ( head tail )
+ THEN ( head tail )
+ td>ntd td-freelist-head swap l!-le ( head )
+ TO td-freelist-head
+;
+
+
+\ END OF TD LIST MANAGEMENT WORDS
+\ ED Management section BEGINs
+\ ----------------------------
+
+
+: zero-out-an-ed-except-link ( ed -- )
+
+ \ There are definitely smarter ways to do it especially
+ \ on a 64-bit machine.
+
+ \ Optimization, Portability:
+ \ --------------------------
+ \ Replace by a "!" and "l!". we know that an "ed" is
+ \ actually 16 bytes and that we will be executing on
+ \ a 64-bit machine, we can finish OFf with 2 stores.
+ \ But that WONT be portable.
+
+ dup 0 swap ed>eattr l!-le ( ed )
+ dup 0 swap ed>tdqtp l!-le ( ed )
+ dup 0 swap ed>tdqhp l!-le ( ed )
+ drop
+;
+
+\ Intialises ed-list afresh
+
+: initialize-ed-free-list ( -- )
+ MAX-EDS 0= IF EXIT THEN
+ ed-list-region @ 0= IF
+ s" init-ed-list: ed-list-region is not allocated!" usb-debug-print
+ EXIT
+ THEN
+ ed-list-region @ TO temp1
+ 0 TO temp2 BEGIN
+ temp1 zero-out-an-ed-except-link
+ temp1 /edlen + dup temp1 ed>ned l!-le TO temp1
+ temp2 1+ TO temp2
+ temp2 MAX-EDS =
+ UNTIL
+ temp1 /edlen - ed>ned 0 swap l!-le
+ ed-list-region @ TO ed-freelist-head
+ MAX-EDS TO num-free-eds
+;
+
+
+\ allocate an ed and return ed address
+
+
+: allocate-ed ( -- ed-ptr )
+ num-free-eds 0= IF 0 EXIT THEN
+ ed-freelist-head ( ed-freelist-head )
+ ed-freelist-head ed>ned l@-le TO ed-freelist-head ( ed-freelist-head )
+ num-free-eds 1- TO num-free-eds ( ed-freelist-head )
+ dup ed>ned 0 swap l!-le \ Terminate the Link. ( ed-freelist-head )
+;
+
+
+\ free the given ed pointer
+
+: free-ed ( ed-ptr -- )
+ dup zero-out-an-ed-except-link ( ed-ptr )
+ dup ed>ned ed-freelist-head swap l!-le ( ed-ptr )
+ TO ed-freelist-head
+ num-free-eds 1+ TO num-free-eds
+;
+
+
+\ Buffer allocations
+\ ------------------
+\ Note:
+\ -----
+\ 1. What should we DO IF alloc-mem fails ?
+\ 2. alloc-mem must return aligned memory addresses.
+\ 3. alloc-mem must return DMAable memory!
+
+\ Memory for the HCCA - must stay allocated as long as the HC is operational!
+100 alloc-mem VALUE hchcca
+hchcca ff and IF
+ \ This should never happen - alloc-mem always aligns
+ s" Warning: hchcca not aligned!" usb-debug-print
+THEN
+
+84 hchcca + CONSTANT hchccadneq
+
+
+: (allocate-mem) ( -- )
+ /tdlen MAX-TDS * 10 + alloc-mem dup td-list-region ! ( td-list-region-ptr )
+ f and IF
+ s" Warning: td-list-region not aligned!" usb-debug-print
+ THEN
+ initialize-td-free-list
+
+ /edlen MAX-EDS * 10 + alloc-mem dup ed-list-region ! ( ed-list-region-ptr )
+ f and IF
+ s" Warning: ed-list-region not aligned!" usb-debug-print
+ THEN
+ initialize-ed-free-list
+
+ DEVICE-DESCRIPTOR-LEN chars alloc-mem dd-buffer !
+ BULK-CONFIG-DESCRIPTOR-LEN chars alloc-mem cd-buffer !
+;
+
+
+\ The method makes sure that when the host node is closed all
+\ associated buffer allocations made for data-structures as
+\ well as data-buffers are freed
+
+: (de-allocate-mem) ( -- )
+ td-list-region @ ?dup IF
+ /tdlen MAX-TDS * 10 + free-mem
+ 0 td-list-region !
+ THEN
+ ed-list-region @ ?dup IF
+ /edlen MAX-EDS * 10 + free-mem
+ 0 ed-list-region !
+ THEN
+ dd-buffer @ ?dup IF
+ DEVICE-DESCRIPTOR-LEN free-mem
+ 0 dd-buffer !
+ THEN
+ cd-buffer @ ?dup IF
+ BULK-CONFIG-DESCRIPTOR-LEN free-mem
+ 0 cd-buffer !
+ THEN
+;
+
+
+\ Suspend hostcontroller (and the bus).
+\ This method must be called before the operating system starts.
+\ It prevents the HC from doing DMA in the background during boot
+\ (e.g. updating its frame number counter in the HCCA)
+
+: hc-suspend ( -- )
+ \ s" USB HC suspend with hccontrol=" type hccontrol . cr
+ 00C3 hccontrol rl!-le \ Suspend USB host controller
+;
+
+
+\ OF methods
+
+: open ( -- TRUE|FALSE )
+ (allocate-mem)
+ TRUE
+;
+
+: close ( -- )
+ (de-allocate-mem)
+;
+
+
+\ COLON DEFINITION: HC-enable-control-list-processing
+\ Enables USB HC transactions on control list.
+
+: HC-enable-control-list-processing ( -- )
+ hccomstat dup rl@-le 02 or swap rl!-le
+ hccontrol dup rl@-le 10 or swap rl!-le
+;
+
+
+\ COLON DEFINTION: HC-enable-bulk-list-processing
+\ PENDING: Remove Hard coded constants.
+
+: HC-enable-bulk-list-processing ( -- )
+ hccomstat dup rl@-le 04 or swap rl!-le
+ hccontrol dup rl@-le 20 or swap rl!-le
+;
+
+
+: HC-enable-interrupt-list-processing ( -- )
+ hccontrol dup rl@-le 04 or swap rl!-le
+;
+
+
+\ Clearing WDH to allow HC to write into DOne queue again
+
+: (HC-ACK-WDH) ( -- ) WDH hcintstat rl!-le ;
+
+\ Checking whether anything has been written into DOne queue
+
+: (HC-CHECK-WDH) ( -- ) hcintstat rl@-le WDH and 0<> ;
+
+
+\ Disable USB transaction and keep it ready
+
+: disable-control-list-processing ( -- )
+ hccontrol dup rl@-le ffffffef and swap rl!-le
+ hccomstat dup rl@-le fffffffd and swap rl!-le
+;
+
+: disable-bulk-list-processing ( -- )
+ hccontrol dup rl@-le ffffffdf and swap rl!-le
+ hccomstat dup rl@-le fffffffb and swap rl!-le
+;
+
+
+: disable-interrupt-list-processing ( -- )
+ hccontrol dup rl@-le fffffffb and swap rl!-le
+;
+
+
+\ COLON DEFINITION: fill-TD-list
+
+\ This function accepts a TD list and a data-buffer and
+\ distributes this data buffer over the TD list depending
+\ on the Max Packet Size.
+
+\ Arguments:
+\ ----------
+\ (from bottom OF stack)
+\ 1. addr -- Address OF the data buffer
+\ 2. dlen -- Length OF the data buffer above.
+\ 3. dir -- Tells whether the TDs r for an IN or
+\ OUT transaction.
+\ 4. MPS -- Maximum Packet Size associated with the endpoint
+\ that will use this TD list.
+\ 5. TD-List-Head - Head pointer OF the List OF TDs.
+\ This list is NOT expected to be NULL terminated.
+
+\ Assumptions:
+\ -----------
+\ 1. TD-List for data is well-formed and has sufficient entries
+\ to hold "dlen".
+\ 2. The TDs toggle field is assumed to be taken from the endpoint
+\ descriptor's "toggle carry" field.
+\ 3. Assumes that the caller specifies the correct start-toggle.
+\ If the caller specifies a wrong data toggle OF 1 for a SETUP
+\ PACKET, this method will not find it out.
+
+\ COLON DEFINTION: (toggle-current-toggle)
+\ Scope: Internal to fill-TD-list
+\ Functionality:
+\ Toggles the "T" field that is passed as argument.
+\ "T" as in the "T" field OF the TD.
+
+0 VALUE current-toggle
+: fill-TD-list ( start-toggle addr dlen dp MPS TD-List-Head -- )
+ TO temp1 ( start-toggle addr dlen dp MPS )
+ TO temp2 ( start-toggle addr dlen dp )
+ CASE ( start-toggle addr dlen )
+ OHCI-DP-SETUP OF TD-DP-SETUP TO temp3 ENDOF ( start-toggle addr dlen )
+ OHCI-DP-IN OF TD-DP-IN TO temp3 ENDOF ( start-toggle addr dlen )
+ OHCI-DP-OUT OF TD-DP-OUT TO temp3 ENDOF ( start-toggle addr dlen )
+ dup OF -1 TO temp3 ( start-toggle addr dlen )
+ s" fill-TD-list: Invalid DP specified" usb-debug-print
+ ENDOF
+ ENDCASE
+ temp3 -1 = IF EXIT THEN ( start-toggle addr dlen )
+
+
+\ temp1 -- TD-List-Head
+\ temp2 -- Max Packet Size
+\ temp3 -- TD-DP-IN or TD-DP-OUT or TD-DP-SETUP
+
+ rot ( addr dlen start-toggle )
+ TO current-toggle swap ( dlen addr )
+ BEGIN
+ over temp2 >= ( dlen addr TRUE|FALSE )
+ WHILE ( dlen addr )
+ dup temp1 td>cbptr l!-le ( dlen addr )
+ current-toggle 18 lshift ( dlen addr current-toggle~ )
+ DATA0-TOGGLE ( dlen addr current-toggle~ toggle )
+ CC-FRESH-TD temp3 or or or ( dlen addr or-result )
+ temp1 td>tattr l!-le ( dlen addr~ )
+ dup temp2 1- + temp1 td>bfrend l!-le ( dlen addr~ )
+ temp2 + ( dlen next-addr )
+ swap temp2 - swap
+ temp1 td>ntd l@-le TO temp1 ( dlen next-addr)
+ current-toggle ( dlen next-addr current-toggle )
+ CASE
+ 0 OF 1 TO current-toggle ENDOF
+ 1 OF 0 TO current-toggle ENDOF
+ ENDCASE
+ REPEAT ( dlen addr )
+ over 0<> IF
+ dup temp1 td>cbptr l!-le ( dlen addr )
+ current-toggle 18 lshift ( dlen addr curent-toggle~ )
+ DATA0-TOGGLE ( dlen addr curent-toggle~ toggle )
+ CC-FRESH-TD temp3 or or or ( dlen addr or-result )
+ temp1 td>tattr l!-le ( dlen addr )
+ + 1- temp1 td>bfrend l!-le
+ ELSE
+ 2drop
+ THEN
+;
+
+
+\ COLON DEFINITION: (td-list-status )
+\ FUNCTIONALITY:
+\ To traverse the TD list to check for a TD carrying non-zero CC return the
+\ respective TD address and CC ELSE 0
+\ SCOPE:
+\ Internal method
+
+: (td-list-status) ( PointerToTDlist -- failingTD CCode TRUE | 0 )
+ BEGIN ( PointerToTDlist )
+ dup 0<> ( PointerToTDlist TRUE|FALSE )
+ IF ( PointerToTDlist )
+ dup td>tattr l@-le f0000000 and 1c rshift dup 0= TRUE swap
+ ( PointerToTDlist CCode TRUE TRUE|FALSE )
+ ELSE
+ drop FALSE dup ( FALSE )
+ THEN
+ WHILE
+ drop drop td>ntd l@-le
+ REPEAT
+;
+
+
+\ ==================================================================
+\ COLON DEFINITION: (wait-for-done-q)
+\ FUNCTIONALITY:
+\ To DO a timed polling OF the DOne queue and acknowledge and return
+\ the address OF the last retired Td list
+\ SCOPE:
+\ Internal method
+\ ==================================================================
+
+
+: (wait-for-done-q) ( timeout -- TD-list TRUE | FALSE )
+ BEGIN ( timeout )
+ dup 0<> ( timeout TRUE|FALSE )
+ WHILE ( timeout )
+ (HC-CHECK-WDH) ( timeout TRUE|FALSE )
+ IF ( timeout )
+ drop 0 ( 0 )
+ ELSE ( timeout )
+ 1- ( timeout )
+ 1 ms ( timeout )
+ THEN ( timeout )
+
+ \ Wait for 1 milli-second.
+ \ PENDING: There should be a better way.
+
+ REPEAT ( timeout )
+ drop
+ hchccadneq rl@-le dup 0<> IF ( td-list )
+ TRUE ( td-list TRUE )
+ 0 hchccadneq rl!-le ( td-list TRUE )
+ (HC-ACK-WDH) ( td-list TRUE )
+ ELSE FALSE ( td-list FALSE )
+ THEN ( td-list TRUE|FALSE )
+;
+
+
+\ displays free tds
+
+
+: debug-td ( -- )
+ s" Num Free TDs = " num-free-tds usb-debug-print-val
+;
+
+
+\ display content of frame counter
+
+\ : debug-frame-counter ( -- )
+\ 40 1 DO
+\ ." Frame ct at HCCA at end OF enumeration = "
+\ hchcca 80 + rl@-le .
+\ LOOP
+\ ;
+
+\ ============================================================================
+\ COLON DEFINITION: HC-reset
+\ This routine should be the first to be executed.
+\ This routine will reset the HC and will bring it to Operational
+\ state.
+\ PENDING:
+\ Arrive at the right value OF FrameInterval. Currently we are hardcoding
+\ it.
+\ ==========================================================================
+
+
+: HC-reset ( -- )
+ 00 hccontrol rl!-le
+ hccomstat dup rl@-le 01 or swap rl!-le
+ BEGIN
+ hccomstat rl@-le 01 and 0<>
+ WHILE
+ REPEAT
+ hchcca hchccareg rl!-le
+ 0000 hcctrhead rl!-le
+ 0ffff hcintdsbl rl!-le
+ 0000 hcbulkhead rl!-le
+ 0083 hccontrol rl!-le
+ 23f02edf hcintrval rl!-le
+;
+
+
+: error-recovery ( -- )
+ initialize-td-free-list
+ initialize-ed-free-list
+ HC-reset
+;
+
+\ ================================================================
+: store-initial-usb-hub-address ( -- )
+ usb-address TO initial-hub-address
+;
+
+: reset-to-initial-usb-hub-address ( -- )
+ initial-hub-address TO usb-address
+;
+
+\ allocate-usb-address:
+\ Function allocates an USB address.
+\ See RISK below.
+
+
+: allocate-usb-address ( -- usb-address )
+ usb-address 7f <> ( TRUE|FALSE )
+ IF
+ usb-address 1+ TO usb-address \ RISK: Check to see IF it overflows 127
+ usb-address ( usb-address )
+ THEN ( usb-address )
+;
+
+s" usb-support.fs" INCLUDED
+
+
+
+\ =====================================================================
+\ COLON DEFINTION: control-std-set-address
+\ INTERFACE FUNCTION
+\ Function allocates an USB addrss and uses it to send SET-ADDRESS packet
+\ to the default USB address.
+\ This is an interface function available to child nodes.
+
+: control-std-set-address ( speedbit -- usb-address TRUE | FALSE )
+ >r ( R: speedbit )
+ 0005000000000000 setup-packet !
+ allocate-usb-address dup setup-packet 2 + c! ( usb-addr R: speedbit )
+ s" USB set-address: " 2 pick usb-debug-print-val ( usb-addr R: speedbit )
+ 0 0 0 setup-packet 8 r> controlxfer ( usb-addr TRUE | FALSE )
+ IF ( TRUE | FALSE )
+ TRUE ( TRUE )
+ ELSE
+ drop FALSE \ PENDING: Return the allocated address back. ( FALSE )
+ THEN ( TRUE | FALSE )
+;
+
+
+\ Fetches the device decriptor of the usb-device
+
+
+: control-std-get-device-descriptor
+ ( data-buffer data-len MPS fa -- TRUE|FALSE )
+ 8006000100000000 setup-packet !
+ 2 pick setup-packet 6 + w!-le
+ ( data-buffer data-len MPS fa )
+ setup-packet -rot ( data-buffer data-len setup-packet MPS fa )
+ >r >r >r >r >r 0 r> r> r> r> r>
+ ( 0 data-buffer data-len setup-packet MPS fa )
+ controlxfer ( TRUE | FALSE )
+;
+
+
+\ ==================================================================
+\ To retrieve the configuration descriptor OF a device
+\ with a valid USB address
+
+
+: control-std-get-configuration-descriptor
+ ( data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
+ TO temp1 ( data-buffer data-len MPS )
+ TO temp2 ( data-buffer data-len )
+ TO temp3 ( data-buffer )
+ 8006000200000000 setup-packet !
+ temp3 setup-packet 6 + w!-le
+ 0 swap temp3 setup-packet temp2 temp1 controlxfer
+;
+
+\ Fectes num of logical units available for a device
+: control-std-get-maxlun ( MPS fun-addr dir data-buff data-len -- TRUE | FALSE )
+ GET-MAX-LUN setup-packet ! ( MPS fun-addr dir data-buff data-len )
+ setup-packet 5 pick 5 pick
+ ( MPS fun-addr dir data-buff data-len setup-packet MPS fun-addr )
+ controlxfer ( MPS fun-addr TRUE | FALSE )
+ nip nip ( TRUE | FALSE )
+;
+
+\ get the string descriptor of the usb device
+
+
+: control-std-get-string-descriptor
+ ( StringIndex data-buffer data-len MPS FuncAddr -- TRUE | FALSE )
+ TO temp1 ( StringIndex data-buffer data-len MPS )
+ TO temp2 ( StringIndex data-buffer data-len )
+ TO temp3 ( StringIndex )
+ 8006000300000000 setup-packet !
+ temp3 setup-packet 6 + w!-le
+ 409 setup-packet 4 + w!-le \ US English Language code.
+ swap ( data buffer StringIndex )
+ setup-packet 2 + c! ( data-buffer )
+ 0 swap temp3 setup-packet temp2 temp1 controlxfer ( TRUE | FALSE )
+;
+
+\ sets a valid usb configaration for a device
+
+: control-std-set-configuration ( configvalue FuncAddr -- TRUE|FALSE )
+ TO temp1 ( configvalue )
+ TO temp2
+ 0009000000000000 setup-packet ! \ RISK: Endian and 64-bit assumptions
+ temp2 setup-packet 2 + w!-le
+ 0 0 0 setup-packet DEFAULT-CONTROL-MPS temp1 controlxfer
+
+ \ NOTE: We could use DEFAULT-CONTROL-MPS because there is no data phase
+ \ associated with this control xfer. Its a dont care.
+;
+
+
+\ To set the device address retrive the device descriptor and build the
+\ usb device tree by passing device class
+
+
+0 VALUE port-number
+
+s" usb-enumerate.fs" INCLUDED
+
+: rhport-enumerate ( port-num -- )
+ TO port-number
+ device-speed control-std-set-address ( usb-addr TRUE | FALSE )
+ IF
+ device-speed or ( usb-addr+speedbit )
+ TO new-device-address
+ dd-buffer @ 8 erase
+
+ \ Read Device Descriptor - First 8 bytes.
+
+ dd-buffer @ DEFAULT-CONTROL-MPS DEFAULT-CONTROL-MPS ( buffer mps mps )
+ new-device-address control-std-get-device-descriptor ( TRUE | FALSE )
+ IF
+ ELSE
+ s" USB: Read Dev Descriptor failed" usb-debug-print EXIT
+
+ \ NOTE: Tomorrow, IF there is a LOOP here,we may need to UNLOOP before
+ \ "EXIT"ing. Beware. Much depends on what LOOPing construct is used.
+
+ THEN
+
+ \ Read the Descriptor Type and check IF we have read correctly.
+
+ dd-buffer @ DEVICE-DESCRIPTOR-TYPE-OFFSET + c@ ( Descriptor-type )
+ DEVICE-DESCRIPTOR-TYPE <> IF
+ s" USB: Error Reading Device Descriptor" usb-debug-print
+ s" Read descriptor is not OF the right type" usb-debug-print
+ s" Aborting enumeration" usb-debug-print
+ EXIT
+ \ NOTE: Tomorrow, IF u have a LOOP here THEN we may need to
+ \ UNLOOP before EXITing. Depends on what type OF LOOPing construct
+ \ is used. Beware.
+
+ THEN
+
+ \ Read the MPS and store it.
+
+ dd-buffer @ DEVICE-DESCRIPTOR-MPS-OFFSET + c@ TO mps
+
+ \ NOTE: Probably, we could check MPS for only 8/16/32/64
+ \ hmm.. not now...
+
+ \ Read the device class to see what type OF device it is and create an
+ \ appropriate child node here.
+ create-usb-device-tree
+ ELSE
+ s" Set address failed on port " port-number usb-debug-print-val
+ s" Aborting Enumeration." usb-debug-print
+ EXIT
+
+ \ NOTE: Tomorrow , IF u have a LOOP here THEN we may need to
+ \ UNLOOP before EXITing. Depends on what type OF LOOPing construct
+ \ is used. Beware.
+
+ THEN
+;
+
+
+\ =========================================================================
+\ PROTOTYPE FUNCTION: "rhport-initialize"
+\ Detect Device, reset and enable the respective port.
+\ COLON Definition rhport-initialize accepts the total number OF root hub
+\ ports as an argument and probes every available root hub port and initiates
+\ the build OF the USB devie sub-tree so is effectively the mother OF all
+\ USB device nodes that are to be detected and instantiated.
+\ ==========================================================================
+
+
+VARIABLE total-rh-ports
+0 VALUE current-stat
+
+: rhport-initialize ( total-rh-ports -- )
+ total-rh-ports !
+ hcrhpstat TO current-stat
+ total-rh-ports @ 1+ 1 DO
+ hcrhdescA rl@-le 0300 and 0100 = ( TRUE|FALSE )
+ IF
+ 100 current-stat rl!-le
+ hcrhdescA 3 + rb@ 2 * ms
+ THEN
+ current-stat rl@-le RHP-CCS and 0<> ( TRUE|FALSE )
+ IF
+ s" Device at this port!" usb-debug-print
+ RHP-PPS current-stat rl!-le \ port power on
+ hcrhdescA 3 + rb@ 2 * ms \ wait for POTPGT*2 ms
+ RHP-PES current-stat rl!-le \ port enable
+ 50 ms
+ RHP-PRS current-stat rl!-le \ port reset
+ 50 ms
+ \ RHP-PRSC current-stat rl!-le
+
+ current-stat rl@-le 200 and 4 lshift
+ to device-speed \ store speed bit
+
+ I ['] rhport-enumerate CATCH IF \ Scan port
+ s" USB scan failed on root hub port: " rot usb-debug-print-val
+ reset-to-initial-usb-hub-address
+ THEN
+ ELSE
+ s" No device detected at this port." usb-debug-print
+ THEN
+ current-stat 4 + TO current-stat
+ LOOP
+;
+
+
+\ ===================================================
+\ Enumeration at Host level
+\ ===================================================
+
+: enumerate ( -- )
+ HC-reset
+ ['] hc-suspend add-quiesce-xt \ Assert that HC will be supsended
+ hcrhdescA rl@-le 000000ff and ( total-rh-ports )
+ store-initial-usb-hub-address
+ rhport-initialize \ Probe all available RH ports
+ reset-to-initial-usb-hub-address
+;
+
+
+\ Create an alias for this controller:
+set-ohci-alias
+
diff --git a/slof/fs/usb/usb-static.fs b/slof/fs/usb/usb-static.fs
new file mode 100644
index 0000000..0067549
--- /dev/null
+++ b/slof/fs/usb/usb-static.fs
@@ -0,0 +1,85 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ Set usb-debug flag to TRUE for debugging output:
+0 VALUE usb-debug-flag
+0 VALUE usb-test-flag
+
+\ Print a debug message when usb-debug-flag is set
+: usb-debug-print ( str len -- )
+ usb-debug-flag IF type cr ELSE 2drop THEN
+;
+
+\ Print a debug message with corresponding value when usb-debug-flag is set
+: usb-debug-print-val ( str len val -- )
+ usb-debug-flag IF -ROT type . cr ELSE drop 2drop THEN
+;
+
+
+0 VALUE ohci-alias-num
+
+\ create a new ohci device alias for the current node:
+: set-ohci-alias ( -- )
+ ohci-alias-num dup 1+ TO ohci-alias-num ( num )
+ s" ohci" rot $cathex strdup \ create alias name
+ get-node node>path \ get path string
+ set-alias \ and set the alias
+;
+
+0 VALUE cdrom-alias-num
+
+\ create a new ohci device alias for the current node:
+: set-cdrom-alias ( -- )
+ cdrom-alias-num dup 1+ TO cdrom-alias-num ( num )
+ s" cdrom" rot $cathex strdup \ create alias name
+ get-node node>path \ get path string
+ set-alias \ and set the alias
+;
+
+: usb-create-alias-name ( num -- str len )
+ >r s" ohciX" 2dup + 1- ( str len last-char-ptr R: num )
+ r> [char] 0 + swap c! ( str len R: )
+;
+
+\ Scan all USB host controllers for attached devices:
+: usb-scan
+ \ Scan all OHCI chips:
+ ." Scan USB... " cr
+ 0 >r \ Counter for alias
+ BEGIN
+ r@ usb-create-alias-name
+ find-alias ?dup ( false | str len len R: num )
+ WHILE
+ usb-debug-flag IF
+ ." * Scanning hub " 2dup type ." ..." cr
+ THEN
+ open-dev ?dup IF ( ihandle R: num )
+ dup to my-self
+ dup ihandle>phandle dup set-node
+ child ?dup IF
+ delete-node s" Deleting node" usb-debug-print
+ THEN
+ >r s" enumerate" r@ $call-method \ Scan host controller
+ r> close-dev 0 set-node 0 to my-self
+ THEN ( R: num )
+ r> 1+ >r ( R: num+1 )
+ REPEAT r> drop
+ 0 TO ohci-alias-num
+ 0 TO cdrom-alias-num
+ s" cdrom0" find-alias ( false | dev-path len )
+ dup IF
+ s" cdrom" 2swap ( alias-name len' dev-path len )
+ set-alias ( -- )
+ ELSE
+ drop ( -- )
+ THEN
+;
diff --git a/slof/fs/usb/usb-storage-support.fs b/slof/fs/usb/usb-storage-support.fs
new file mode 100644
index 0000000..5013c2c
--- /dev/null
+++ b/slof/fs/usb/usb-storage-support.fs
@@ -0,0 +1,222 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ ---------------------------------------------------------------------------
+\ Parent methods
+\ ---------------------------------------------------------------------------
+
+: rw-endpoint
+ ( pt ed-type toggle buffer length mps addres -- toggle TRUE | toggle FALSE )
+ s" rw-endpoint" $call-parent
+ ( toggle TRUE | toggle FALSE )
+;
+
+: controlxfer ( dir addr dlen setup-packet MPS ep-fun --- TRUE|FALSE )
+ s" controlxfer" $call-parent
+ ( TRUE | FALSE )
+;
+
+: control-std-get-configuration-descriptor
+ ( data-buffer data-len MPS FuncAddr -- TRUE | FALSE )
+ s" control-std-get-configuration-descriptor" $call-parent
+ ( TRUE | FALSE )
+;
+
+: control-std-set-configuration ( configvalue FuncAddr -- TRUE | FALSE )
+ s" control-std-set-configuration" $call-parent ( TRUE | FALSE )
+;
+
+: bulk-reset-recovery-procedure ( bulk-out-endp bulk-in-endp usb-addr -- )
+ s" bulk-reset-recovery-procedure" $call-parent
+;
+
+
+\ ---------------------------------------------------------------------------
+\ Bulk support package methods
+\ ---------------------------------------------------------------------------
+
+: build-cbw ( address tag transfer-len direction lun command-len -- )
+ s" build-cbw" ihandle-bulk @ $call-method
+;
+
+: analyze-csw ( address -- residue tag TRUE | reason FALSE )
+ s" analyze-csw" ihandle-bulk @ $call-method
+ ( residue tag TRUE | reason FALSE )
+;
+
+
+\ ---------------------------------------------------------------------------
+\ SCSI support package methods
+\ ---------------------------------------------------------------------------
+
+: build-read ( address lba #blocks -- )
+ s" build-read" ihandle-scsi @ $call-method
+;
+
+: build-inquiry ( address alloc-len -- )
+ s" build-inquiry" ihandle-scsi @ $call-method
+;
+
+: return-inquiry ( address -- version# peripheral-device-type )
+ s" return-inquiry" ihandle-scsi @ $call-method
+ ( version# peripheral-device-type )
+;
+
+: build-mode-sense ( address alloc-len page-code page-control -- )
+ s" build-mode-sense" ihandle-scsi @ $call-method
+;
+
+: build-read-capacity ( address -- )
+ s" build-read-capacity" ihandle-scsi @ $call-method
+;
+
+: build-seek ( address lba -- )
+ s" build-seek" ihandle-scsi @ $call-method
+;
+
+: build-start ( address -- )
+ s" build-start" ihandle-scsi @ $call-method
+;
+
+: build-stop ( address -- )
+ s" build-stop" ihandle-scsi @ $call-method
+;
+
+\ : build-load ( address -- )
+\ s" build-load" ihandle-scsi @ $call-method
+\ ;
+
+\ : build-unload ( address -- )
+\ s" build-unload" ihandle-scsi @ $call-method
+\ ;
+
+: build-test-unit-ready ( address -- )
+ s" build-test-unit-ready" ihandle-scsi @ $call-method
+;
+
+: return-test-unit-ready ( address -- status )
+ s" return-unit-ready" ihandle-scsi @ $call-method ( status )
+;
+
+: build-read-toc ( address session# alloc-len -- )
+ s" build-read-toc" ihandle-scsi @ $call-method
+;
+
+: build-request-sense ( address alloc-len -- )
+ s" build-request-sense" ihandle-scsi @ $call-method
+;
+
+: return-request-sense ( address -- FALSE | ASCQ ASC sense-key TRUE )
+ s" return-request-sense" ihandle-scsi @ $call-method
+ ( FALSE | ASCQ ASC sense-key TRUE )
+;
+
+
+\ =======================================================
+\ NATIVE METHODS USED EITHER AT PROBE TIME OR TIME
+\ WHEN INSTANCE IS CREATED
+\ =======================================================
+
+
+\ --------------------------------------------------------
+\ COLON DEFINITION: the method is a probe-time method
+\ used to:
+\ 1. decode the properties and store in variables
+\ 2. allocat buffers required for the device and
+\ 3. set the right configuration after extracting the
+\ configuration descriptor
+\ --------------------------------------------------------
+
+: device-init ( -- )
+ s" Starting to initialize usb-storage device" usb-debug-print
+ s" USB-ADDRESS" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to my-usb-address
+ THEN
+ s" MPS-BULKOUT" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to mps-bulk-out
+ THEN
+ s" MPS-BULKIN" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to mps-bulk-in
+ THEN
+ s" BULK-IN-EP-ADDR" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to bulk-in-ep
+ THEN
+ s" BULK-OUT-EP-ADDR" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to bulk-out-ep
+ THEN
+ s" MPS-DCP" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" Not possible" usb-debug-print
+ ELSE
+ decode-int nip nip to mps-dcp
+ THEN
+ s" LUN" get-my-property ( TRUE | propaddr proplen FALSE )
+ IF
+ s" NOT Possible to extract LUN" usb-debug-print
+ ELSE
+ decode-int nip nip to lun
+ THEN
+ s" Extracted properties inherited from parent." usb-debug-print
+
+ \ PENDING:
+ \ Do some return value check here...
+
+ 40 alloc-mem to command-buffer
+ 80 alloc-mem to response-buffer
+ 10 alloc-mem to csw-buffer
+ 8 alloc-mem to cfg-buffer
+ s" Allocated buffers." usb-debug-print
+ cfg-buffer 8 mps-dcp my-usb-address ( buffer len mps fun-addr )
+ control-std-get-configuration-descriptor ( TRUE | FALSE )
+ drop
+ s" Configuration descriptor extracted." usb-debug-print
+ cfg-buffer 5 + c@ my-usb-address ( configvalue fun-addr )
+ control-std-set-configuration ( TRUE | FALSE )
+ s" usb-storage: Set config returned: " rot usb-debug-print-val
+;
+
+
+\ ----------------------------------------------------
+\ Internal methods
+\ ----------------------------------------------------
+
+
+: (open-package) ( ihandle-var name-str name-len -- )
+ find-package IF ( ihandle-var phandle )
+ 0 0 rot open-package ( ihandle-var ihandle )
+ swap !
+ ELSE
+ s" Support package not found" usb-debug-print
+ THEN
+;
+
+: (close-package) ( ihandle-var -- )
+ dup @ close-package
+ 0 swap !
+;
+
diff --git a/slof/fs/usb/usb-storage-wrapper.fs b/slof/fs/usb/usb-storage-wrapper.fs
new file mode 100644
index 0000000..eb3d547
--- /dev/null
+++ b/slof/fs/usb/usb-storage-wrapper.fs
@@ -0,0 +1,181 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ -----------------------------------------------------------
+\ OF properties
+\ -----------------------------------------------------------
+
+s" scsi" device-name
+s" block-type" device-type
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+
+: encode-unit 1 hex-encode-unit ;
+
+: decode-unit 1 hex-decode-unit ;
+
+
+\ -----------------------------------------------------------
+\ Specific properties
+\ -----------------------------------------------------------
+
+1 chars alloc-mem VALUE ch-buffer
+8 VALUE mps-dcp
+0 VALUE port-number
+0 VALUE my-usb-address
+
+
+: control-std-get-maxlun
+ ( MPS fun-addr dir data-buff data-len -- TRUE | FALSE )
+ s" control-std-get-maxlun" $call-parent
+;
+
+
+: control-std-get-configuration-descriptor
+ ( data-buffer data-len MPS funcAddr -- TRUE|FALSE )
+ s" control-std-get-configuration-descriptor" $call-parent
+;
+
+: rw-endpoint
+ ( pt ed-type toggle buffer length mps address -- toggle TRUE|toggle FALSE )
+ s" rw-endpoint" $call-parent
+;
+
+: controlxfer ( dir addr dlen setup-packet MPS ep-fun -- TRUE|FALSE )
+ s" controlxfer" $call-parent
+;
+
+: control-std-set-configuration
+ ( configvalue FuncAddr -- TRUE|FALSE )
+ s" control-std-set-configuration" $call-parent
+;
+
+\ This method is used for extracting the properties from it's parent and
+\ storing these value to temporary variable so that they can used later.
+
+: extract-properties ( -- )
+ s" USB-ADDRESS" get-inherited-property ( prop-addr prop-len FALSE | TRUE )
+ IF
+ s" notpossible" usb-debug-print
+ ELSE
+ decode-int nip nip to my-usb-address
+ THEN
+ s" MPS-DCP" get-inherited-property ( prop-addr prop-len FALSE | TRUE )
+ IF
+ s" MPS-DCP property not found.Assume 8 as MAX PACKET SIZE" usb-debug-print
+ s" for the default control pipe" usb-debug-print
+ 8 to mps-dcp
+ ELSE
+ s" MPS-DCP property found!!" usb-debug-print
+ decode-int nip nip to mps-dcp
+ THEN
+ s" reg" get-inherited-property ( prop-addr prop-len FLASE | TRUE )
+ IF
+ s" notpossible" usb-debug-print
+ ELSE
+ decode-int nip nip to port-number
+ THEN
+;
+
+
+\ This method is used for creating the child nodes for every Logical unit
+\ available in the device, this method will call control-std-get-maxlun for
+\ for finding the maximum Logical units supported by the device and along with
+\ the creation of nodes this method encodes the properties of the node also.
+
+: create-tree ( -- )
+ mps-dcp my-usb-address 0 ch-buffer 1 ( MPS fun-addr dir data-buff data-len )
+ control-std-get-maxlun ( TRUE | FALSE )
+
+ \ This method extracts the maximum number of Logical Units Supported by
+ \ the Device . if no Logical Units are present then 0 will be taken as the
+ \ max logical units. if the device doesn't support the GET-MAX-LUN command
+ \ then the device may can be stalled as a temporary fix to come out from
+ \ the stalling situations we can issue the control-std-set-configuration with
+ \ appropriate arguments
+
+
+ IF
+ s" GET-MAX-LUN IS WORKING :" usb-debug-print
+ ELSE
+ s" ERROR in GET-MAX-LUN " usb-debug-print
+ THEN
+ ch-buffer c@ 1 + 0 ( max-lun+1 0 )
+ DO
+ s" iManufacturer" get-inherited-property drop ( prop-addr prop-len TRUE )
+ decode-int nip nip ( iManu )
+ s" iProduct" get-inherited-property drop
+ ( iManu prop-addr prop-len TRUE | FALSE )
+ decode-int nip nip ( iManu iProd )
+ s" iSerialNumber" get-inherited-property drop
+ ( iManu iProd prop-addr prop-len TRUE | FALSE )
+ decode-int nip nip ( iManu iProd iSerNum )
+ s" MPS-BULKOUT" get-inherited-property drop
+ ( iManu iProd iSerNum prop-len prop-addr TRUE | FALSE )
+ decode-int nip nip ( iManu iProd iSerNum MPS-BULKOUT )
+ s" BULK-OUT-EP-ADDR" get-inherited-property drop
+ ( iManu iProd iSerNum MPS-BULKOUT prop-addr prop-len TRUE|FALSE )
+ decode-int nip nip ( iManu iProd iSerNum MPS-BULKOUT BULK-OUT-EP-ADDR )
+ s" MPS-BULKIN" get-inherited-property drop
+ ( iManu iProd iSerNum MPS-BULKOUT BULK-OUT-EP-ADDR prop-addr prop-len
+ TRUE | FALSE )
+ decode-int nip nip
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN )
+ s" BULK-IN-EP-ADDR" get-inherited-property drop
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN prop-addr
+ prop-len TRUE | FALSE )
+ decode-int nip nip
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR )
+ mps-dcp port-number my-usb-address I
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR mps-dcp port-address my-usb-address lun-number )
+ new-device
+
+ \ creates new device child node, doesn't consume any argument from stack
+
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR mps-dcp port-address my-usb-address lun-number )
+
+ set-space
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR mps-dcp port-number my-usb-address )
+ encode-int s" USB-ADDRESS" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR mps-dcp port-number )
+ encode-int s" reg" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN )
+ ( BULKIN-EP-ADDR mps-dcp port-number )
+ encode-int s" MPS-DCP" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR )
+ I encode-int s" LUN" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN
+ BULKIN-EP-ADDR )
+ encode-int s" BULK-IN-EP-ADDR" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR MPS-BULKIN )
+ encode-int s" MPS-BULKIN" property
+ ( iManu iProd iSernum MPS-BULKOUT BULK-OUT-EP-ADDR )
+ encode-int s" BULK-OUT-EP-ADDR" property
+ ( iManu iProd iSernum MPS-BULKOUT )
+ encode-int s" MPS-BULKOUT" property ( iManu iProd iSerNum )
+ encode-int s" iSerialNumber" property ( iManu iProd )
+ encode-int s" iProduct" property ( iManu )
+ encode-int s" iManufacturer" property ( -- )
+ s" usb-storage.fs" INCLUDED
+ finish-device
+ LOOP
+;
+
+extract-properties \ Extract the properties from parent
+create-tree \ this method creates the node for every lun with properties
diff --git a/slof/fs/usb/usb-storage.fs b/slof/fs/usb/usb-storage.fs
new file mode 100644
index 0000000..642e46a
--- /dev/null
+++ b/slof/fs/usb/usb-storage.fs
@@ -0,0 +1,464 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ -----------------------------------------------------------
+\ OF properties
+\ -----------------------------------------------------------
+
+s" storage" device-name
+s" block" device-type
+
+2 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+
+\ -----------------------------------------------------------
+\ Specific properties
+\ -----------------------------------------------------------
+
+8 VALUE mps-bulk-out
+8 VALUE mps-bulk-in
+8 VALUE mps-dcp
+0 VALUE bulk-in-ep
+0 VALUE bulk-out-ep
+0 VALUE bulk-in-toggle
+0 VALUE bulk-out-toggle
+0 VALUE lun
+0 VALUE my-usb-address
+
+
+\ ----------------------------------------------------------
+\ Instance specific values
+\ ----------------------------------------------------------
+
+0 VALUE csw-buffer
+0e VALUE cfg-buffer
+0 VALUE response-buffer
+0 VALUE command-buffer
+0 VALUE resp-size
+0 VALUE resp-buffer
+INSTANCE VARIABLE ihandle-bulk
+INSTANCE VARIABLE ihandle-scsi
+INSTANCE VARIABLE ihandle-deblocker
+INSTANCE VARIABLE flag
+INSTANCE VARIABLE count
+0 VALUE max-transfer
+0 VALUE block-size
+
+
+\ -------------------------------------------------------
+\ General Constants
+\ -------------------------------------------------------
+
+0f CONSTANT SCSI-COMMAND-OFFSET
+
+
+\ -------------------------------------------------------
+\ All support methods inherited from parent or imported
+\ from support packages are included here. Also included
+\ are the internal methods
+\ -------------------------------------------------------
+
+s" usb-storage-support.fs" INCLUDED
+
+\ ---------------------------------------------------------------
+\ COLON Definitions: Implementation of Standard SCSI commands
+\ over USB OHCI
+\ ---------------------------------------------------------------
+
+
+\ to use the general bulk command a lot of global variables
+\ must be set. See for example the inquiry command.
+0 VALUE bulk-cnt
+: do-bulk-command ( resp-buffer resp-size -- TRUE | FALSE )
+ TO resp-size
+ TO resp-buffer
+ 2 TO bulk-cnt
+ FALSE dup
+ BEGIN 0= WHILE
+ drop
+ \ prepare and send bulk CBW
+ 1 1 bulk-out-toggle command-buffer 1f mps-bulk-out
+ ( pt ed-type toggle buffer length mps-bulk-out )
+ my-usb-address bulk-out-ep 7 lshift or
+ ( pt ed-type toggle buffer length mps address )
+ rw-endpoint swap ( TRUE toggle | FALSE toggle )
+ to bulk-out-toggle ( TRUE | FALSE )
+ IF
+ resp-size 0<> IF \ do we need a response ?!
+ \ read the bulk response
+ 0 1 bulk-in-toggle resp-buffer resp-size mps-bulk-in
+ ( pt ed-type toggle buffer length mps-bulk-in )
+ my-usb-address bulk-in-ep 7 lshift or
+ ( pt ed-type toggle buffer length mps address )
+ rw-endpoint swap ( TRUE toggle | FALSE toggle )
+ to bulk-in-toggle ( TRUE | FALSE )
+ ELSE
+ TRUE
+ THEN
+ IF
+ \ read the bulk CSW
+ 0 1 bulk-in-toggle csw-buffer D mps-bulk-in
+ ( pt ed-type toggle buffer length mps-bulk-in )
+ my-usb-address bulk-in-ep 7 lshift or
+ ( pt ed-type toggle buffer length mps address )
+ rw-endpoint swap ( TRUE toggle | FALSE toggle )
+ to bulk-in-toggle ( TRUE | FALSE )
+ IF
+ s" Command successful." usb-debug-print
+ TRUE dup
+ ELSE
+ s" Command failed in CSW stage" usb-debug-print
+ FALSE dup
+ THEN
+ ELSE
+ s" Command failed while receiving DATA... read CSW..." usb-debug-print
+ \ STALLED: Get CSW to send the CBW again
+ 0 1 bulk-in-toggle csw-buffer D mps-bulk-in
+ ( pt ed-type toggle buffer length mps-bulk-in )
+ my-usb-address bulk-in-ep 7 lshift or
+ ( pt ed-type toggle buffer length mps address )
+ rw-endpoint swap ( TRUE toggle | FALSE toggle )
+ to bulk-in-toggle ( TRUE | FALSE )
+ IF
+ s" OK evaluate the CSW ..." usb-debug-print
+ csw-buffer c + l@-le
+ 2 = IF \ Phase Error
+ s" do a bulk reset-recovery ..." usb-debug-print
+ bulk-out-ep bulk-in-ep my-usb-address
+ bulk-reset-recovery-procedure
+ THEN
+ \ ELSE
+ \ don't abort if the read fails.
+ THEN
+ FALSE dup
+ THEN
+ ELSE
+ s" Command failed while Sending CBW ..." usb-debug-print
+ FALSE dup
+ THEN
+ bulk-cnt 1 - TO bulk-cnt
+ bulk-cnt 0= IF
+ 2drop FALSE dup
+ THEN
+ REPEAT
+;
+
+\ ---------------------------------------------------------------
+\ Method to 1. Send the INQUIRY command 2. Recieve and analyse
+\ (pending) INQUIRY data
+\ ---------------------------------------------------------------
+
+: inquiry ( -- )
+ s" usb-storage: inquiry" usb-debug-print
+ command-buffer 1 20 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + 20 ( address alloc-len )
+ build-inquiry
+ response-buffer 20
+ do-bulk-command
+ IF
+ s" Successfully read INQUIRY data" usb-debug-print
+ s" Inquiry data for 0x20 bytes availabe in Response buffer"
+ usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (inquiry)"
+ 5040 error" (USB) Device transaction error. (inquiry)"
+ ABORT
+ THEN
+;
+
+\ ---------------------------------------------------------------
+\ Method to 1. Send the READ CAPACITY command
+\ 2. Recieve and analyse the response data
+\ ---------------------------------------------------------------
+
+: read-capacity ( -- )
+ s" usb-storage: read-capacity" usb-debug-print
+ command-buffer 1 8 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + ( address )
+ build-read-capacity
+ response-buffer 8 do-bulk-command
+ IF
+ s" Successfully read READ CAPACITY data" usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (capacity)"
+ 5040 error" (USB) Device transaction error. (capacity)"
+ ABORT
+ THEN
+;
+
+
+\ --------------------------------------------------------------------
+\ Method to 1. Send TEST UNIT READY command 2. Analyse the status
+\ of the response
+\ -------------------------------------------------------------------
+
+: test-unit-ready ( -- TRUE | FALSE )
+ command-buffer 1 0 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + ( address )
+ build-test-unit-ready
+ response-buffer 0 do-bulk-command
+ IF
+ s" Successfully read test unit ready data" usb-debug-print
+ s" Test Unit STATUS availabe in csw-buffer" usb-debug-print
+ csw-buffer 0c + c@ 0= IF
+ s" Test Unit Command Successfully Executed" usb-debug-print
+ TRUE ( TRUE )
+ ELSE
+ s" Test Unit Command Failed to execute" usb-debug-print
+ FALSE ( FALSE )
+ THEN
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (test-unit-ready)"
+ 5040 error" (USB) Device transaction error. (test-unit-ready)"
+ ABORT
+ THEN
+;
+
+\ -------------------------------------------------
+\ Method to 1. read sense data 2. analyse sesnse
+\ data(pending)
+\ ------------------------------------------------
+
+: request-sense ( -- )
+ s" request-sense: Command ready." usb-debug-print
+ command-buffer 1 12 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + 12 ( address alloc-len )
+ build-request-sense
+ response-buffer 12 do-bulk-command
+ IF
+ s" Read Sense data successfully" usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (request-sense)"
+ 5040 error" (USB) Device transaction error. (request-sense)"
+ ABORT
+ THEN
+;
+
+: start ( -- )
+ command-buffer 1 0 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + ( address )
+ build-start
+ response-buffer 0 do-bulk-command
+ IF
+ s" Start successfully" usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (start)"
+ 5040 error" (USB) Device transaction error. (start)"
+ ABORT
+ THEN
+;
+
+
+\ To transmit SCSI Stop command
+
+: stop ( -- )
+ command-buffer 1 0 80 lun 0c
+ ( address tag transfer-len direction lun command-len )
+ build-cbw
+ command-buffer SCSI-COMMAND-OFFSET + ( address )
+ build-stop
+ response-buffer 0 do-bulk-command
+ IF
+ s" Stop successfully" usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (stop)"
+ 5040 error" (USB) Device transaction error. (stop)"
+ ABORT
+ THEN
+;
+
+
+0 VALUE temp1
+0 VALUE temp2
+0 VALUE temp3
+
+
+\ -------------------------------------------------------------
+\ block device's seek
+\ -------------------------------------------------------------
+
+: seek ( pos-hi pos-lo -- status )
+ s" seek" ihandle-deblocker @ $call-method
+;
+
+
+\ -------------------------------------------------------------
+\ block device's read
+\ -------------------------------------------------------------
+
+: read ( address length -- actual )
+ s" read" ihandle-deblocker @ $call-method
+;
+
+
+\ -------------------------------------------------------------
+\ read-blocks to be used by deblocker
+\ -------------------------------------------------------------
+: read-blocks ( address block# #blocks -- #read-blocks )
+ block-size * command-buffer ( address block# transfer-len command-buffer )
+ 1 2 pick 80 lun 0c build-cbw ( address block# transfer-len )
+ dup to temp1 ( address block# transfer-len)
+ block-size / ( address block# #blocks )
+ command-buffer ( address block# #block command-addr )
+ SCSI-COMMAND-OFFSET + -rot ( address command-addr block# #blocks )
+ build-read ( address )
+ temp1 do-bulk-command
+ IF
+ s" Read Sense data successfully" usb-debug-print
+ ELSE
+ \ TRUE ABORT" USB device transaction error. (read-blocks)"
+ 5040 error" (USB) Device transaction error. (read-blocks)"
+ ABORT
+ THEN
+ temp1 block-size / ( #read-blocks )
+;
+
+\ ------------------------------------------------
+\ To bring the the media to seekable and readable
+\ condition.
+\ ------------------------------------------------
+
+0 VALUE temp1
+0 VALUE temp2
+0 VALUE temp3
+d# 800 CONSTANT media-ready-retry
+
+: make-media-ready ( -- )
+ s" usb-storage: make-media-ready" usb-debug-print
+ 0 flag !
+ 0 count !
+ BEGIN
+ flag @ 0=
+ WHILE
+ test-unit-ready IF
+ s" Media ready for access." usb-debug-print
+ 1 flag !
+ ELSE
+ count @ 1 + count !
+ count @ media-ready-retry = IF
+ 1 flag !
+ 5000 error" (USB) Media or drive not ready for this blade."
+ ABORT
+ THEN
+ request-sense
+ response-buffer return-request-sense
+ ( FALSE | ascq asc sense-key TRUE )
+ IF
+ to temp1 ( ascq asc )
+ to temp2 ( ascq )
+ to temp3
+ temp1 2 = temp2 3a = and ( TRUE | FALSE )
+ IF
+ 5010 error" (USB) No Media found! Check for the drawer/inserted media."
+ ABORT
+ THEN
+ temp1 2 = temp2 06 = and ( TRUE | FALSE )
+ IF
+ 5020 error" (USB) Unknown media format."
+ ABORT
+ THEN
+ temp1 0<> temp2 4 = temp3 2 = and and ( TRUE | FALSE )
+ IF
+ start stop
+ THEN
+ THEN
+ THEN
+ d# 10 ms
+ REPEAT
+ usb-debug-flag IF
+ ." make-media-ready finished after "
+ count @ decimal . hex ." tries." cr
+ THEN
+;
+
+
+\ Set up the block-size of the device, using the READ CAPACITY command.
+\ Note: Media must be ready (=> make-media-ready) or READ CAPACITY
+\ might fail!
+
+: (init-block-size)
+ read-capacity
+ response-buffer 4 +
+ l@ to block-size
+ s" usb-storage: block-size=" block-size usb-debug-print-val
+;
+
+
+\ Standard OF methods
+
+: open ( -- TRUE )
+ s" usb-storage: open" usb-debug-print
+ ihandle-bulk s" bulk" (open-package)
+ ihandle-scsi s" scsi" (open-package)
+
+ make-media-ready
+ (init-block-size) \ Init block-size before opening the deblocker
+
+ ihandle-deblocker s" deblocker" (open-package)
+
+ s" disk-label" find-package IF ( phandle )
+ usb-debug-flag IF ." my-args for disk-label = " my-args swap . . cr THEN
+ my-args rot interpose
+ THEN
+ TRUE ( TRUE )
+;
+
+
+: close ( -- )
+ ihandle-deblocker (close-package)
+ ihandle-scsi (close-package)
+ ihandle-bulk (close-package)
+;
+
+
+\ Set device name according to type
+
+: (init-device-name) ( -- )
+ inquiry
+ response-buffer c@
+ CASE
+ 1 OF s" tape" device-name ENDOF
+ 5 OF s" cdrom" device-name ENDOF
+ \ dup OF s" storage" device-name ENDOF
+ ENDCASE
+;
+
+
+\ Initial device node setup
+
+: (initial-setup)
+ ihandle-bulk s" bulk" (open-package)
+ ihandle-scsi s" scsi" (open-package)
+
+ device-init
+ (init-device-name)
+ set-cdrom-alias
+ 200 to block-size \ Default block-size, will be overwritten in "open"
+ 10000 to max-transfer
+
+ ihandle-bulk (close-package)
+ ihandle-scsi (close-package)
+;
+
+(initial-setup)
diff --git a/slof/fs/usb/usb-support.fs b/slof/fs/usb/usb-support.fs
new file mode 100644
index 0000000..1326a04
--- /dev/null
+++ b/slof/fs/usb/usb-support.fs
@@ -0,0 +1,628 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+0 value NEXT-TD
+
+0 VALUE num-tds
+0 VALUE td-retire-count
+0 VALUE saved-tail
+0 VALUE poll-timer
+VARIABLE controlxfer-cmd
+
+\ Allocate an ED and populate it
+
+: (ed-prepare) ( dir addr dlen setup-packet MPS ep-fun --
+ FALSE | dir addr dlen ed-ptr setup-ptr )
+ allocate-ed dup 0= IF ( dir addr dlen setup-packet MPS ep-fun ed-ptr )
+ drop 3drop 2drop FALSE EXIT ( FALSE )
+ THEN
+ TO temp1 ( dir addr dlen setup-packet MPS ep-fun )
+ \ s" controlxfer: Allocated ED: " temp1 usb-debug-print-val
+ temp1 zero-out-an-ed-except-link ( dir addr dlen setup-packet MPS ep-fun )
+ temp1 ed>eattr l@-le or temp1 ed>eattr l!-le ( dir addr dlen setup-ptr MPS )
+ dup TO temp2 10 lshift temp1 ed>eattr l@-le or temp1 ed>eattr l!-le
+ ( dir addr dlen setup-packet-address )
+ temp1 swap TRUE ( dir addr dlen ed-ptr setup-ptr TRUE )
+;
+
+
+\ Allocate TD list
+
+
+: (td-prepare) ( dir addr dlen ed-ptr setup-ptr --
+ dir FALSE | dir addr dlen ed-ptr setup-ptr td-head td-tail )
+ 2 pick ( dir addr dlen ed-ptr setup-ptr dlen )
+ temp2 ( dir addr dlen ed-ptr setup-ptr dlen MPS )
+ /mod ( dir addr dlen ed-ptr setup-ptr rem quo )
+ swap 0<> IF ( dir addr dlen ed-ptr setup-ptr quo )
+ 1+
+ THEN
+ 2+
+ dup TO num-tds ( dir addr dlen ed-ptr setup-ptr quo+2 )
+ allocate-td-list dup 0= IF ( dir addr dlen ed-ptr setup-ptr quo+2 )
+ 2drop ( dir addr dlen ed-ptr setup-ptr )
+ drop ( dir addr dlen ed-ptr )
+ free-ed ( dir addr dlen )
+ 2drop ( dir )
+ FALSE ( dir FALSE )
+ EXIT
+ THEN TRUE
+;
+
+
+\ Fill in the ED structure completely.
+
+
+: (td-ready) ( dir addr dlen ed-ptr setup-ptr td-head td-tail -- )
+ ( dir addr dlen ed-ptr setup-ptr )
+ 3 pick ( dir addr dlen ed-ptr setup-ptr td-head td-tail ed-ptr )
+ tuck ( dir addr dlen ed-ptr setup-ptr td-head ed-ptr td-tail ed-ptr )
+ ed>tdqtp l!-le ( dir addr dlen ed-ptr setup-ptr td-head ed-ptr )
+ ed>tdqhp l!-le ( dir addr dlen ed-ptr setup-ptr )
+ over ed>ned 0 swap l!-le ( dir addr dlen ed-ptr setup-ptr )
+;
+
+
+\ Initialize the HEAD and TAIL TDs for SETUP and
+\ STATUS phase respectively.
+
+
+: (td-setup-status) ( dir addr dlen ed-ptr setup-ptr -- dir addr dlen ed-ptr )
+ over ed>tdqhp l@-le ( dir addr dlen ed-ptr setup-ptr td-head )
+ dup zero-out-a-td-except-link ( dir addr dlen ed-ptr setup-ptr td-head )
+ dup td>tattr DATA0-TOGGLE CC-FRESH-TD or swap l!-le
+ ( dir addr dlen ed-ptr setup-ptr td-head )
+ 2dup td>cbptr l!-le ( dir addr dlen ed-ptr setup-ptr td-head )
+ 2dup td>bfrend swap STD-REQUEST-SETUP-SIZE 1- + swap l!-le
+ ( dir addr dlen ed-ptr setup-ptr td-head )
+ 2drop ( dir addr dlen ed-ptr )
+;
+
+\ Initialize the TD TAIL pointer.
+
+
+: (td-tailpointer) ( dir addr dlen ed-ptr -- dir addr dlen ed-ptr )
+ dup ed>tdqtp l@-le ( dir addr dlen ed-ptr td-tail )
+ dup zero-out-a-td-except-link ( dir addr dlen ed-ptr td-tail )
+ dup td>tattr dup l@-le DATA1-TOGGLE CC-FRESH-TD or or swap l!-le
+ ( dir addr dlen ed-ptr td-tail )
+ 4 pick 0= ( dir addr dlen ed-ptr td-tail flag )
+ 3 pick 0<> ( dir addr dlen ed-ptr td-tail flag flag )
+ and IF ( dir addr dlen ed-ptr td-tail )
+ dup td>tattr dup l@-le TD-DP-OUT or swap l!-le
+ ( dir addr dlen ed-ptr td-tail )
+ ELSE
+ dup td>tattr dup l@-le TD-DP-IN or swap l!-le
+ ( dir addr dlen ed-ptr td-tail )
+ THEN
+ drop ( dir addr dlen ed-ptr )
+;
+
+\ Initialize the Data TDs.
+
+
+: (td-data) ( dir addr dlen ed-ptr -- ed-ptr )
+ -rot ( dir ed-ptr addr dlen )
+ dup 0<> IF ( dir ed-ptr addr dlen )
+ >r >r >r TO temp1 r> r> r> temp1 ( ed-ptr addr dlen dir )
+ 3 pick ( ed-ptr addr dlen dir ed-ptr )
+ ed>tdqhp l@-le td>ntd l@-le ( ed-ptr addr dlen dir td-datahead )
+ 4 pick ( ed-ptr addr dlen dir td-datahead ed-ptr )
+ td>tattr l@-le 10 rshift ( ed-ptr addr dlen dir td-head-data MPS )
+ swap ( ed-ptr addr dlen dir MPS td-head-data )
+ >r >r >r >r >r 1 r> r> r> r> r>
+ ( ed-ptr 1 addr dlen dir MPS td-head-data )
+ >r >r 0= IF ( ed-ptr 1 addr dlen dir )
+ OHCI-DP-IN ( ed-ptr 1 addr dlen dir OHCI-DP-IN )
+ ELSE
+ OHCI-DP-OUT ( ed-ptr 1 addr dlen dir OHCI-DP-OUT )
+ THEN
+ r> r> ( ed-ptr 1 addr dlen dir OHCI-DP- MPS td-head-data )
+ fill-TD-list
+ ELSE
+ 2drop nip ( ed-ptr )
+ THEN
+;
+
+
+\ Program the HC with the ed-ptr value and wait for status to
+\ from the HC.
+\ Free the ED and TDs associated with it.
+\ PENDING: Above said.
+
+
+: (transfer-wait-for-doneq) ( ed-ptr -- TRUE | FALSE )
+ dup ( ed-ptr ed-ptr )
+ hcctrhead rl!-le ( ed-ptr )
+ HC-enable-control-list-processing ( ed-ptr )
+ 0 TO td-retire-count ( ed-ptr )
+ 0 TO poll-timer BEGIN ( ed-ptr )
+ td-retire-count num-tds <> ( ed-ptr TRUE | FALSE )
+ poll-timer d# 5000 < and ( ed-ptr TRUE | FALSE )
+ WHILE
+ (HC-CHECK-WDH) IF ( ed-ptr )
+ hchccadneq rl@-le find-td-list-tail-and-size nip ( ed-ptr n )
+ td-retire-count + TO td-retire-count ( ed-ptr )
+ hchccadneq rl@-le dup ( ed-ptr done-td done-td )
+ (td-list-status) IF ( ed-ptr done-td failed-td CCcode )
+ \ keep condition code of TD on return stack
+ dup >r
+ s" (transfer-wait-for-doneq: USB device communication error."
+ usb-debug-print ( ed-ptr done-td failed-td CCcode R: CCcode )
+ dup 4 = swap dup 5 = rot or IF ( ed-ptr done-td failed-td CCcode R: CCcode )
+ d# 5000 TO poll-timer ( ed-ptr done-td failed-td CCcode R: CCcode )
+ THEN
+ ( ed-ptr done-td failed-td CCcode R: CCcode)
+ usb-debug-flag IF
+ s" CC code ->" type . cr
+ s" Failing TD contents:" type cr display-td
+ ELSE
+ 2drop
+ THEN ( ed-ptr done-td R: CCcode)
+ controlxfer-cmd @ GET-MAX-LUN = r> 4 = and IF
+ s" (transfer-wait-for-doneq): GET-MAX-LUN ControlXfer STALLed"
+ usb-debug-print
+ \ Condition Code = 4 means that the device does not support multiple LUNS
+ \ see USB Massbulk 1.0 Standard
+ ELSE
+ drop
+ 5030 error" (USB) Device communication error."
+ ABORT
+ \ FIXME: ABORTing here might leave the HC in an unusable state.
+ \ We should maybe rather ABORT at the end of this Forth
+ \ word, when clean-up has been done (or not ABORT at all)
+ THEN
+ THEN ( ed-ptr done-td )
+ (free-td-list) ( ed-ptr )
+ 0 hchccadneq rl!-le ( ed-ptr )
+ (HC-ACK-WDH) \ TDs were written to DOne queue. ACK the HC.
+ \ s" Retired = " td-retire-count usb-debug-print-val
+ \ s" Total = " num-tds usb-debug-print-val
+ THEN
+ poll-timer 1+ TO poll-timer
+ 1 ms
+ REPEAT ( ed-ptr )
+ disable-control-list-processing ( ed-ptr )
+ td-retire-count num-tds <> IF ( ed-ptr )
+ dup display-descriptors ( ed-ptr )
+ THEN
+ free-ed
+ td-retire-count num-tds <> IF
+ FALSE ( FALSE )
+ ELSE
+ TRUE ( TRUE )
+ THEN
+;
+
+
+\ COLON DEFINITION: controlxfer
+\ INTERFACE FUNCTION
+
+\ ARGUMENTS:
+\ (from the bottom OF stack)
+\ 1. dir -- This is the direction OF data transfer associated with
+\ the DATA STAGE OF the control xfer.
+\ If there is no data transfer (argument dlen is zero)
+\ THEN this argument DOes not matter, nonethless it has
+\ to be passed.
+\ A "0" represents an IN and "1" represents an "OUT".
+\ 2. addr -- If therez a data stage associated with the transfer,
+\ THEN, this argument holds the address OF the data buffer
+\ 3. dlen -- This arg holds the length OF the data buffer discussed
+\ in previous step (addr)
+\ 4. setup-packet -- This holds the pointer to the setup packet that
+\ will be transmitted during the SETUP stage OF
+\ the control xfer. The function assumes the length
+\ OF the status packet to be 8 bytes.
+\ 5. MPS -- This is the MAX PACKET SIZE OF the endpoint.
+\ 6. ep-fun -- This is the 11-bit value that holds the Endpoint and
+\ the function address. bit 7 to bit 10 holds the Endpoint
+\ address. Bits 0 to Bit 6 holds the Function Address.
+\ The BIT numbering followed : The left most bit is referred
+\ as bit 0. (not the one followed by PPC)
+\ Bit 13 must be set for low-speed devices.
+
+\ RETURN VALUE:
+\ Returns TRUE | FALSE depending on the success OF the transaction.
+
+\ ASSUMPTIONS:
+\ 1. Function assumes that the setup packet is 8-bytes in length.
+\ If in future, IF we need to add a new argument, we need to change
+\ the function in lot OF places.
+
+\ RISKS:
+\ 1. If for some reason, the USB controller DOes not retire all the TDs
+\ THEN, the status checking part OF this "word" can spin forever.
+
+
+: controlxfer ( dir addr dlen setup-packet MPS ep-fun -- TRUE | FALSE )
+ 2 pick @ controlxfer-cmd !
+ (ed-prepare) ( FALSE | dir addr dlen ed-ptr setup-ptr )
+ invert IF FALSE EXIT THEN
+ (td-prepare) ( pt ed-type toggle buffer length mps head )
+ invert IF FALSE EXIT THEN
+ (td-ready) ( dir addr dlen ed-ptr setup-ptr )
+ (td-setup-status) ( dir addr dlen ed-ptr )
+ (td-tailpointer) ( dir addr dlen ed-ptr )
+ (td-data) ( ed-ptr )
+
+
+ \ FIXME:
+ \ Clear the TAIL pointer in ED. This has got sthg to DO with how
+ \ the HC finds an EMPTY queue condition. Refer spec.
+
+
+ dup ed>tdqtp l@-le TO saved-tail ( ed-ptr )
+ dup ed>tdqtp 0 swap l!-le ( ed-ptr )
+ (transfer-wait-for-doneq) ( TRUE | FALSE )
+;
+
+0201000000000000 CONSTANT CLEARHALTFEATURE
+0 VALUE endpt-num
+0 VALUE usb-addr-contr-req
+: control-std-clear-feature ( endpoint-nr usb-addr -- TRUE|FALSE )
+ TO usb-addr-contr-req \ usb address
+ TO endpt-num \ endpoint number
+ CLEARHALTFEATURE setup-packet !
+ endpt-num setup-packet 4 + c! \ endpoint number
+ 0 0 0 setup-packet DEFAULT-CONTROL-MPS usb-addr-contr-req controlxfer
+ ( TRUE|FALSE )
+;
+
+\ It resets the usb bulk-device
+21FF000000000000 CONSTANT BULK-RESET
+: control-std-bulk-reset ( usb-addr -- TRUE|FALSE )
+ TO usb-addr-contr-req
+ BULK-RESET setup-packet !
+ 0 0 0 setup-packet DEFAULT-CONTROL-MPS usb-addr-contr-req controlxfer
+ ( TRUE|FALSE )
+;
+
+: bulk-reset-recovery-procedure ( bulk-out-endp bulk-in-endp usb-addr -- )
+ >r ( bulk-out-endp bulk-in-endp R: usb-addr )
+ \ perform a bulk reset
+ r@ control-std-bulk-reset
+ IF s" bulk reset OK"
+ ELSE s" bulk reset failed"
+ THEN usb-debug-print
+
+ \ clear bulk-in endpoint ( bulk-out-endp bulk-in-endp R: usb-addr )
+ 80 or r@ control-std-clear-feature
+ IF s" control-std-clear IN endpoint OK"
+ ELSE s" control-std-clear-IN endpoint failed"
+ THEN usb-debug-print
+
+ \ clear bulk-out endpoint ( bulk-out-endp R: usb-addr )
+ r@ control-std-clear-feature
+ IF s" control-std-clear OUT endpoint OK"
+ ELSE s" control-std-clear-OUT endpoint failed"
+ THEN usb-debug-print
+ r> drop
+;
+
+0 VALUE saved-rw-ed
+0 VALUE num-rw-tds
+0 VALUE num-rw-retired-tds
+0 VALUE saved-rw-start-toggle
+0 VALUE saved-list-type
+
+\ Allocate an ED and populate what you can.
+
+
+: (ed-prepare-rw)
+ ( pt ed-type toggle buffer length mps address ed-ptr --
+ FALSE | pt ed-type toggle buffer length mps )
+ allocate-ed dup 0= IF
+ ( pt ed-type toggle buffer length mps address ed-ptr )
+ drop 2drop 2drop 2drop drop
+ saved-rw-start-toggle FALSE EXIT ( toggle FALSE )
+ THEN
+ TO saved-rw-ed ( pt ed-type toggle buffer length mps address )
+ saved-rw-ed zero-out-an-ed-except-link
+ ( pt ed-type toggle buffer length mps address )
+ saved-rw-ed ed>eattr l!-le ( pt ed-type toggle buffer length mps )
+ dup 10 lshift saved-rw-ed ed>eattr l@-le or
+ ( pt ed-type toggle buffer length mps mps~ )
+ saved-rw-ed ed>eattr l!-le TRUE ( pt ed-type toggle buffer length mps TRUE )
+;
+
+
+\ Allocate TD List
+
+
+: (td-prepare-rw)
+ ( pt ed-type toggle buffer length mps --
+ FALSE | pt ed-type toggle buffer length mps head )
+ 2dup ( pt ed-type toggle buffer length mps length mps )
+ /mod ( pt ed-type toggle buffer length mps num-tds rem )
+ swap 0<> IF ( pt ed-type toggle buffer length mps num-tds )
+ 1+ ( pt ed-type toggle buffer length mps num-tds+1 )
+ THEN
+ dup TO num-rw-tds ( pt ed-type toggle buffer length mps num-tds )
+ allocate-td-list ( pt ed-type toggle buffer length mps head tail )
+ dup 0= IF
+ 2drop 2drop 2drop 2drop
+ saved-rw-ed free-ed
+ ." rw-endpoint: TD list allocation failed" cr
+ saved-rw-start-toggle FALSE ( FALSE )
+ EXIT
+ THEN
+ drop TRUE ( pt ed-type toggle buffer length mps head TRUE )
+;
+
+
+\ Populate TD list with data buffers and toggle info.
+
+
+: (td-data-rw)
+ ( pt ed-type toggle buffer length mps head -- FALSE | pt et head )
+ 6 pick ( pt ed-type toggle buffer length mps head pt )
+ FALSE TO case-failed CASE
+ 0 OF OHCI-DP-IN ENDOF
+ 1 OF OHCI-DP-OUT ENDOF
+ 2 OF OHCI-DP-SETUP ENDOF
+ dup OF TRUE TO case-failed
+ ." rw-endpoint: Invalid Packet Type!" cr
+ ENDOF
+ ENDCASE ( pt ed-type toggle buffer length mps head dp )
+ case-failed IF
+ saved-rw-ed free-ed ( pt ed-type toggle buffer length mps head dp )
+ drop (free-td-list) ( pt ed-type toggle buffer length mps head )
+ 2drop 2drop 2drop
+ saved-rw-start-toggle FALSE ( FALSE )
+ EXIT ( FALSE )
+ THEN
+ -rot ( pt ed-type toggle buffer length dp mps head )
+ dup >r ( pt ed-type toggle buffer length dp mps head )
+ fill-TD-list r> TRUE ( pt et head TRUE )
+;
+
+
+\ Enqueue the ED with the appropriate list
+
+
+: (ed-ready-rw) ( pt et -- - | toggle FALSE )
+ nip ( et )
+ FALSE TO case-failed CASE
+ 0 OF \ Control List. Queue the ED to control list
+ 0 TO saved-list-type
+ saved-rw-ed hcctrhead rl!-le
+ HC-enable-control-list-processing
+ ENDOF
+ 1 OF \ Bulk List. Queue the ED to bulk list
+ 1 TO saved-list-type
+ saved-rw-ed hcbulkhead rl!-le
+ HC-enable-bulk-list-processing
+ ENDOF
+ 2 OF \ Interrupt List.
+ 2 TO saved-list-type
+ saved-rw-ed hchccareg rl@-le rl!-le
+ HC-enable-interrupt-list-processing
+ ENDOF
+ dup OF
+ saved-rw-ed ed>tdqhp l@-le (free-td-list)
+ saved-rw-ed free-ed
+ TRUE TO case-failed
+ ENDOF
+ ENDCASE
+ case-failed IF
+ saved-rw-start-toggle FALSE ( toggle FALSE )
+ EXIT
+ THEN
+ TRUE ( TRUE )
+;
+
+\ Wait for TDs to return to the Done Q.
+
+: (wait-td-retire) ( -- )
+ 0 TO num-rw-retired-tds
+ FALSE TO while-failed BEGIN
+ num-rw-retired-tds num-rw-tds < ( TRUE | FALSE )
+ while-failed FALSE = and ( TRUE | FALSE )
+ WHILE
+ d# 5000 (wait-for-DOne-q) IF ( TD-list )
+ dup find-td-list-tail-and-size nip ( td-list size )
+ num-rw-retired-tds + TO num-rw-retired-tds ( td-list )
+ dup (td-list-status) IF ( td-list failed-TD CC )
+ dup 4 = IF
+ saved-list-type CASE
+ 0 OF 0 0 control-std-clear-feature
+ ENDOF
+ 1 OF \ clean bulk stalled
+ disable-bulk-list-processing \ disable procesing
+ saved-rw-ed ed>eattr l@-le dup \ extract
+ 780 and 7 rshift 80 or \ endpoint and
+ swap 7f and \ usb addr
+ control-std-clear-feature
+ ENDOF
+ 2 OF 0 saved-rw-ed ed>eattr l@-le
+ control-std-clear-feature ENDOF
+ ENDCASE
+ ELSE
+ usb-debug-flag IF
+ s" TD failed with CC code: " type . cr
+ THEN
+ drop drop
+ \ TRUE ABORT" USB device transaction error."
+ 5040 error" (USB) device transaction error."
+ ABORT
+ THEN
+ 2drop drop
+ TRUE TO while-failed \ transaction failed
+ NEXT-TD 0<> IF \ clean the TD if we
+ NEXT-TD (free-td-list) \ had a stalled
+ THEN
+ THEN
+ (free-td-list)
+ ELSE
+ drop \ drop td-list pointer
+ TRUE TO while-failed
+ THEN
+ REPEAT
+;
+
+
+\ Process retired TDs
+
+
+: (process-retired-td) ( -- TRUE | FALSE )
+ saved-list-type CASE
+ 0 OF disable-control-list-processing ENDOF
+ 1 OF disable-bulk-list-processing ENDOF
+ 2 OF disable-interrupt-list-processing ENDOF
+ ENDCASE
+ saved-rw-ed ed>tdqhp l@-le 2 and 0<> IF
+ 1
+ ELSE
+ 0
+ THEN
+ WHILE-failed IF
+ FALSE ( FALSE )
+ ELSE
+ TRUE ( TRUE )
+ THEN
+ saved-rw-ed free-ed
+;
+
+
+\ (DO-rw-endpoint): T1 12 80 0 0chis method is an privately visible function
+\ to be used by the "rw-endpoint" the required
+\ number OF times based on the actual length
+\ to be transferred
+
+\ Arguments:
+\ pt: Packet type
+\ 0 -> IN
+\ 1 -> OUT
+\ 2 -> SETUP
+\ et: Endpoint type
+\ 0 -> Control
+\ 1 -> Bulk
+\ toggle: Starting toggle for this transfer
+\ buffer length: Data buffer associated with the transfer limited
+\ accordingly by the "rw-endpoint" method to the
+\ value OF max packet size
+\ mps: Max Packet Size.
+\ address: Address OF endpoint. 11-bit address. The lower 7-bits represent
+\ the USB addres and the upper 4-bits represent the Endpoint
+\ number.
+
+
+
+: (do-rw-endpoint)
+ ( pt ed-type toggle buffer length mps address -- toggle TRUE|toggle FALSE )
+ 4 pick ( pt ed-type toggle buffer length mps address toggle )
+ TO saved-rw-start-toggle ( pt ed-type toggle buffer length mps address)
+ (ed-prepare-rw) ( FALSE | pt ed-type toggle buffer length mps )
+ invert IF FALSE EXIT THEN
+ (td-prepare-rw) ( FALSE | pt ed-type toggle buffer length mps head )
+ invert IF FALSE EXIT THEN
+ (td-data-rw) ( FALSE | pt et head )
+ invert IF FALSE EXIT THEN
+ saved-rw-ed ed>tdqhp l!-le ( pt et )
+ saved-rw-ed ed>tdqhp l@-le td>ntd l@-le TO NEXT-TD \ save for a stalled
+ (ed-ready-rw)
+ invert IF FALSE EXIT THEN
+ (wait-td-retire)
+ (process-retired-td) ( TRUE | FALSE )
+;
+
+
+\ rw-endpoint: The method is an externally visible method to be exported
+\ to the child nodes. It uses the internal method
+\ "(DO-rw-endpoint)", the required number OF times based on the
+\ actual length OF transfer, so that the limitataion OF MAX-TDS
+\ DO not hinder the transfer.
+
+\ Arguments:
+\ pt: Packet type
+\ 0 -> IN
+\ 1 -> OUT
+\ 2 -> SETUP
+\ et: Endpoint type
+\ 0 -> Control
+\ 1 -> Bulk
+\ toggle: Starting toggle for this transfer
+\ buffer length: Data buffer associated with the transfer
+\ mps: Max Packet Size.
+\ address: Address OF endpoint. 11-bit address. The lower 7-bits represent
+\ the USB addres and the upper 4-bits represent the Endpoint
+\ number.
+
+
+0 VALUE transfer-len
+0 VALUE mps-current
+0 VALUE addr-current
+0 VALUE usb-addr
+0 VALUE toggle-current
+0 VALUE type-current
+0 VALUE pt-current
+0 VALUE read-status
+0 VALUE counter
+0 VALUE residue
+
+
+: rw-endpoint
+ ( pt ed-type toggle buffer length mps address -- )
+ ( toggle TRUE |toggle FALSE )
+
+ \ a single transfer descriptor can point to a buffer OF
+ \ 8192 bytes a block on the CDROM has 2048 bytes
+ \ but a single transfer is constrained by the MPS
+
+ 2 pick TO transfer-len ( pt ed-type toggle buffer length mps address )
+ 1 pick TO mps-current ( pt ed-type toggle buffer length mps address )
+ TRUE TO read-status ( pt ed-type toggle buffer length mps address )
+ transfer-len mps-current num-free-tds * <= IF
+ (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
+ TO read-status ( toggle )
+ TO toggle-current
+ ELSE
+ TO usb-addr ( pt ed-type toggle buffer length mps )
+ 2drop ( pt ed-type toggle buffer )
+ TO addr-current ( pt ed-type toggle )
+ TO toggle-current ( pt ed-type )
+ TO type-current ( pt )
+ TO pt-current
+ transfer-len mps-current num-free-tds * /mod ( residue count )
+ ( remainder=residue quotient=count )
+ TO counter ( residue )
+ TO residue
+ mps-current num-free-tds * TO transfer-len BEGIN
+ counter 0 > ( TRUE | FALSE )
+ read-status TRUE = and ( TRUE | FALSE )
+ WHILE
+ pt-current type-current toggle-current ( pt ed-type toggle )
+ addr-current transfer-len ( pt ed-type toggle buffer length )
+ mps-current ( pt ed-type toggle buffer length mps )
+ usb-addr (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
+ TO read-status ( toggle )
+ TO toggle-current
+ addr-current transfer-len + TO addr-current
+ counter 1- TO counter
+ REPEAT
+ residue 0<> ( TRUE |FALSE )
+ read-status TRUE = and IF
+ residue TO transfer-len
+ pt-current type-current toggle-current ( pt ed-type toggle )
+ addr-current transfer-len ( pt ed-type toggle buffer length )
+ mps-current ( pt ed-type toggle buffer length mps )
+ usb-addr (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
+ TO read-status
+ TO toggle-current
+ THEN
+ THEN
+ read-status invert IF
+ THEN
+ toggle-current ( toggle )
+ read-status ( TRUE | FALSE )
+;
diff --git a/slof/fs/vpd-bootlist.fs b/slof/fs/vpd-bootlist.fs
new file mode 100644
index 0000000..50c3cac
--- /dev/null
+++ b/slof/fs/vpd-bootlist.fs
@@ -0,0 +1,83 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+: check-bootlist ( -- true | false )
+ vpd-bootlist l@
+ dup 0= IF
+ ( bootlist == 0 means that probably nothing from vpd has been received )
+ s" Boot list could not be read from VPD" log-string cr
+ s" Boot watchdog has been rearmed" log-string cr
+ 2 set-watchdog
+ exit THEN
+ FFFFFFFF = IF
+ ( bootlist all FFs means that the vpd has no useful information )
+ .banner
+ -6b boot-exception-handler
+ \ The next message is duplicate, but sent w. log-string
+ s" Boot list successfully read from VPD but no useful information received" log-string cr
+ s" Please specify the boot device in the management module" log-string cr
+ s" Specified Boot Sequence not valid" mm-log-warning
+ false ELSE true THEN ;
+
+\ the following words are necessary for vpd-boot-import
+defer set-boot-device
+defer add-boot-device
+defer bootdevice
+
+\ Import boot device list from VPD
+\ If none, keep the existing list in NVRAM
+\ This word can be used to overwrite read-bootlist if wanted
+
+: vpd-boot-import ( -- )
+ 0 0 set-boot-device
+ vpd-read-bootlist
+ check-bootlist IF
+ 4 0 DO vpd-bootlist i + c@
+ CASE
+ 6 OF \ cr s" 2B Booting from Network" log-string cr
+ s" net" furnish-boot-file $cat strdup add-boot-device
+ ENDOF
+
+ \ 7 OF cr s" Booting from no device not supported" 2dup mm-log-warning log-string cr
+ \ 7 OF cr s" 2B Booting from NVRAM boot-device list: " boot-device $cat
+ \ log-string cr
+ \ boot-device add-boot-device ENDOF
+
+ 8 OF \ cr s" 2B Booting from disk0" log-string cr
+ s" disk disk0" add-boot-device ENDOF
+
+ 9 OF \ cr s" 2B Booting from disk1" log-string cr
+ s" disk1" add-boot-device ENDOF
+
+ A OF \ cr s" 2B Booting from disk2" log-string cr
+ s" disk2" add-boot-device ENDOF
+
+ B OF \ cr s" 2B Booting from disk3" log-string cr
+ s" disk3" add-boot-device ENDOF
+
+ C OF \ cr s" 2B Booting from CDROM" log-string cr
+ s" cdrom" add-boot-device ENDOF
+
+ E OF \ cr s" 2B Booting from disk4" log-string cr
+ s" disk4" add-boot-device ENDOF
+
+ F OF \ cr s" 2B Booting from SAS - w. Timeout" log-string cr
+ s" sas" add-boot-device ENDOF
+ 10 OF \ cr s" 2B Booting from SAS - Continuous Retry" log-string cr
+ s" sas" add-boot-device ENDOF
+ ENDCASE
+ LOOP
+ bootdevice 2@ dup >r s" boot-device" $setenv
+ r> IF 0 ELSE -6b THEN
+ ELSE -6a THEN
+ boot-exception-handler
+;
diff --git a/slof/lowmem.S b/slof/lowmem.S
new file mode 100644
index 0000000..024e78f
--- /dev/null
+++ b/slof/lowmem.S
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
+#include <xvect.h>
+
+ .globl _start
+ /* All exception vectors *******************/
+_start:
+ .org 0x100
+ /* check if Master / Slave *****************/
+ /* Master will go to XVECT_M_HANDLER */
+ /* Slave will go to XVECT_S_HANDLER */
+ ld r3,XVECT_S_HANDLER(0)
+ mfspr r0, PIR
+ cmpwi r0, 0
+ bne 0f
+ ld r3,XVECT_M_HANDLER(0)
+0:
+ mtctr r3
+ li r0,0x100
+ bctr
+
+ /* FIXME: Also need 0280, 0380, 0f20, etc. */
+
+ .irp i, 0x0200,0x0280,0x0300,0x0380,0x0400,0x0480,0x0500,0x0600,0x0700, \
+ 0x0800,0x0900,0x0a00,0x0b00,0x0c00,0x0d00,0x0e00,0x0f00, \
+ 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, \
+ 0x1800,0x1900,0x1a00,0x1b00,0x1c00,0x1d00,0x1e00,0x1f00, \
+ 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, \
+ 0x2800,0x2900,0x2a00,0x2b00,0x2c00,0x2d00,0x2e00,0x2f00
+ .org \i
+
+ /* enable this if you get exceptions before the console works */
+ /* this will allow using the hardware debugger to see where */
+ /* it traps, and with what register values etc. */
+ // b $
+
+ mtsprg 0, r0
+ mfctr r0
+ mtsprg 2,r0
+ mflr r0
+ mtsprg 3,r0
+ ld r0, XVECT_M_HANDLER(0)
+ mtctr r0
+ li r0, \i
+ bctr
+ .endr
+
+
+ .org XVECT_M_HANDLER
+ .quad 0
+
+ .org XVECT_S_HANDLER
+ .quad 0
+
+ .org XVECT_TOPADDR
+ .byte 0x36 # to fill out to exactly 16kB
diff --git a/slof/ofw.S b/slof/ofw.S
index a0e3e80..38b447a 100644
--- a/slof/ofw.S
+++ b/slof/ofw.S
@@ -1,88 +1,112 @@
-# =============================================================================
-# * Copyright (c) 2004, 2005 IBM Corporation
-# * All rights reserved.
-# * This program and the accompanying materials
-# * are made available under the terms of the BSD License
-# * which accompanies this distribution, and is available at
-# * http://www.opensource.org/licenses/bsd-license.php
-# *
-# * Contributors:
-# * IBM Corporation - initial implementation
-# =============================================================================
-
-
-#
-# The loader. This is position-independent code.
-#
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
.section ".slof.loader","ax"
-. = 0
-
- # Get our address.
-
- bcl 20,31,$+4
- mflr 31
-
- # Copy exception vectors.
-
- addi 1,31,0x200-4-8
- li 0,0x3f00/8
- mtctr 0
- li 2,0x100-8
+ # get our address
+
+.base:
+ bcl 20,31,0f
+ .align 3
+.st: .quad _slof_text-.base
+.stl: .quad _slof_text_size
+.sd: .quad _slof_data-.base
+.sdl: .quad _slof_data_size
+.sbl: .quad _slof_bss_size
+0:
+ mr r16,r3 # ROM Base
+ mfspr r17, HSPRG1 # Fixme, will be done in pcd
+ mflr r31
+ subi r31,r31,4
+
+ # copy paflof text
+
+ ld r3,.st-.base(r31)
+ add r3,r3,r31
+ lis r4,_slof_text@h # Addr of engine code
+ ori r4,r4,_slof_text@l
+ ld r5,.stl-.base(31)
+ bl .copy
+
+ lis r3,_slof_text@h # Addr of engine code
+ ori r3,r3,_slof_text@l
+ ld r4,.stl-.base(r31)
+ bl .flush
+
+ # copy paflof data
+
+ ld r3,.sd-.base(31)
+ add r3,r3,r31
+ lis r4,_slof_data@h # Addr of engine data
+ ori r4,r4,_slof_data@l
+ ld r5,.sdl-.base(r31)
+ bl .copy
+
+ lis r3,_slof_data@h # Addr of engine data
+ ori r3,r3,_slof_data@l
+ ld r4,.sdl-.base(r31)
+ bl .flush
+
+ # zero paflof bss
+
+ lis r3,_slof_bss@h # Addr of engine bss
+ ori r3,r3,_slof_bss@l
+ ld r4,.sbl-.base(r31)
+ bl .zero
+
+ lis r3,_slof_bss@h # Addr of engine bss
+ ori r3,r3,_slof_bss@l
+ ld r4,.sbl-.base(r31)
+ bl .flush
+
+ # fill in handler address
+
+ lis r3,_slof_text@h
+ ori r3,r3,_slof_text@l
+ ld r3,0(r3)
+ std r3,0x2ff0(0)
+
+ # GO!
+
+ ba 0x100
+
+
+.zero: # zero from r3 size r4
+ subi r3,r3,8
+ addi r4,r4,7
+ srwi r4,r4,3
+ mtctr r4
+ li r5,0
0:
- ldu 0,8(1)
- stdu 0,8(2)
- bdnz 0b
+ stdu r5,8(r3)
+ bdnz 0b
- # Copy Paflof text.
+ blr
- addi 1,31,0x4100-4-8
- li 0,0x2000/8
- mtctr 0
- lis 2,0x111
- subi 2,2,8
+.copy: # copy from 3 to 4 size 5
+ subi r3,r3,8
+ subi r4,r4,8
+ addi r5,r5,7
+ srwi r5,r5,3
+ mtctr r5
0:
- ldu 0,8(1)
- stdu 0,8(2)
- bdnz 0b
-
- # Copy paflof data.
-
- addi 1,31,0x6100-4-8
- lis 0,1
- mtctr 0
- lis 2,0x112
- subi 2,2,8
-0:
- ldu 0,8(1)
- stdu 0,8(2)
- bdnz 0b
-
- # Flush L1-D cache.
-
- sync
-
- # Flush L1-I cache for Paflof and exception vector code.
-
- li 0,0x4000/128
- mtctr 0
- li 1,0
-0:
- icbi 0,1
- addi 1,1,128
- bdnz 0b
-
- li 0,0x2000/128
- mtctr 0
- lis 1,0x111
-0:
- icbi 0,1
- addi 1,1,128
- bdnz 0b
-
- isync
+ ldu r5,8(r3)
+ stdu r5,8(r4)
+ bdnz 0b
- # Go!
+ blr
- ba 0x100
+.flush: # flush at 3 size 4
+ FLUSH_CACHE(r3, r4)
+ blr
diff --git a/slof/paflof.c b/slof/paflof.c
index 3f193da..b25f294 100644
--- a/slof/paflof.c
+++ b/slof/paflof.c
@@ -1,20 +1,19 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
-
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
//
// Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
//
+
#define XSTR(x) #x
#define ISTR(x,y) XSTR(x.y)
#undef unix
@@ -22,22 +21,38 @@
#include "paflof.h"
#include ISTR(TARG,h)
-void engine(long error)
+#define LAST_ELEMENT(x) x[sizeof x / sizeof x[0] - 1]
+
+#include ISTR(TARG,c)
+
+
+void engine(long error, long reason)
{
cell *restrict dp;
cell *restrict rp;
cell *restrict ip;
cell *restrict cfa;
- cell handler_stack[16];
+ cell handler_stack[160];
- #include "prim.h"
+ #include "prep.h"
#include "dict.xt"
+ static int init_lw = 0;
+ if (init_lw == 0) {
+ init_lw = 1;
+ LAST_ELEMENT(xt_FORTH_X2d_WORDLIST).a = xt_LASTWORD;
+ }
+
dp = the_data_stack;
rp = handler_stack - 1;
+ if (error != 0x100) {
+ dp->n = reason;
+ dp++;
+ }
dp->n = error;
ip = xt_SYSTHROW;
#include "prim.code"
+ #include "board.code"
#include ISTR(TARG,code)
}
diff --git a/slof/paflof.h b/slof/paflof.h
index ea6dbfc..cf2f07f 100644
--- a/slof/paflof.h
+++ b/slof/paflof.h
@@ -1,53 +1,18 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
-
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
//
// Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
//
-#include "types.h"
#define TIBSIZE 256
#define POCKETSIZE 256
-
-// Where we put the exception save areas, and the stacks.
-// Stacks grow upwards, just like in real life. You should see my desk.
-#define the_exception_frame ((cell *)0x1100000)
-#define the_client_frame ((cell *)0x1100400)
-#define the_data_stack ((cell *)0x1102000)
-#define the_return_stack ((cell *)0x1104000)
-#define the_system_stack ((cell *)0x1106000)
-
-// These buffers are allocated in C code to ease implementation.
-#define the_tib ((cell *)0x1108000)
-#define the_pockets ((cell *)0x1109000)
-
-// This is where the run-time data space starts.
-#define the_mem ((cell *)0x1200000)
-
-
-// Some binary blob that is linked in to the image. Use an ELF file
-// for example; we can execute that as a client program, then.
-// You could use yaboot or a (small enough) Linux kernel, for example.
-extern char _binary_payload_start[];
-
-// Assembler glue routine for switching context between the client
-// program and SLOF itself.
-extern void client_entry_point();
-extern unsigned long call_client(cell);
-
-// Magic function to perform stuff that we don't give source for.
-extern type_u oco(cell, cell);
-
-// Synchronize instruction cache with data cache.
-extern void flush_cache (void*, long);
diff --git a/slof/ppc64.c b/slof/ppc64.c
new file mode 100644
index 0000000..6fdad05
--- /dev/null
+++ b/slof/ppc64.c
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <cpu.h>
+
+static unsigned long __attribute__((noinline))
+call_c(cell arg0, cell arg1, cell arg2, cell entry)
+{
+ register unsigned long r3 asm("r3") = arg0.u;
+ register unsigned long r4 asm("r4") = arg1.u;
+ register unsigned long r5 asm("r5") = arg2.u;
+ register unsigned long r6 = entry.u ;
+
+ asm volatile("mflr 31 ; mtctr %4 ; bctrl ; mtlr 31"
+ : "=r"(r3)
+ : "r"(r3), "r"(r4), "r"(r5), "r"(r6)
+ : "ctr", "r31");
+
+ return r3;
+}
+
+long
+writeLogByte_wrapper(long x, long y)
+{
+ unsigned long result;
+ set_ci();
+ result = writeLogByte(x, y);
+ clr_ci();
+ return result;
+}
diff --git a/slof/ppc64.code b/slof/ppc64.code
index 1fe1d2f..e2866fb 100644
--- a/slof/ppc64.code
+++ b/slof/ppc64.code
@@ -1,34 +1,19 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
// This file contains the implementation of the Forth code words specific
// to PowerPC64. Some of this is 970-only.
-// Set and clear the RM_CI bit in HID4. Needed for all I/O accesses.
-#define SET_CI do { \
- unsigned long hid4; \
- asm volatile("mfspr %0,1012" : "=r"(hid4)); \
- hid4 |= 0x0000010000000000UL; \
- asm volatile("slbia ; sync ; mtspr 1012,%0 ; isync" : "+r"(hid4)); \
-} while (0)
-
-#define CLR_CI do { \
- unsigned long hid4; \
- asm volatile("mfspr %0,1012" : "=r"(hid4)); \
- hid4 &= ~0x0000010000000000UL; \
- asm volatile("sync ; mtspr 1012,%0 ; isync" : "+r"(hid4)); \
-} while (0)
-
// The I/O accesses themselves.
PRIM(RB_X40) GET_CHAR1; SET_CI; GET_CHAR2; CLR_CI; GET_CHAR3; MIRP
PRIM(RB_X21) PUT_CHAR1; SET_CI; PUT_CHAR2; CLR_CI; MIRP
@@ -36,6 +21,8 @@ PRIM(RW_X40) GET_WORD1; SET_CI; GET_WORD2; CLR_CI; GET_WORD3; MIRP
PRIM(RW_X21) PUT_WORD1; SET_CI; PUT_WORD2; CLR_CI; MIRP
PRIM(RL_X40) GET_LONG1; SET_CI; GET_LONG2; CLR_CI; GET_LONG3; MIRP
PRIM(RL_X21) PUT_LONG1; SET_CI; PUT_LONG2; CLR_CI; MIRP
+PRIM(RX_X40) GET_XONG1; SET_CI; GET_XONG2; CLR_CI; GET_XONG3; MIRP
+PRIM(RX_X21) PUT_XONG1; SET_CI; PUT_XONG2; CLR_CI; MIRP
// 970-specific CPU registers.
PRIM(HID0_X21)
@@ -51,7 +38,7 @@ MIRP
PRIM(HID1_X21)
unsigned long hid1 = TOS.u;
- asm volatile("mtspr 1009,%0 ; mtspr 1009,%0 ; isync" : "+r"(hid1));
+ asm volatile("mtspr 1009,%0 ; mtspr 1009,%0 ; isync" : : "r"(hid1));
POP;
MIRP
@@ -62,7 +49,7 @@ MIRP
PRIM(HID4_X21)
unsigned long hid4 = TOS.u;
- asm volatile("sync ; mtspr 1012,%0 ; isync" : "+r"(hid4));
+ asm volatile("sync ; mtspr 1012,%0 ; isync" : : "r"(hid4));
POP;
MIRP
@@ -73,7 +60,7 @@ MIRP
PRIM(HID5_X21)
unsigned long hid5 = TOS.u;
- asm volatile("mtspr 1014,%0" : "+r"(hid5));
+ asm volatile("mtspr 1014,%0" : : "r"(hid5));
POP;
MIRP
@@ -85,7 +72,7 @@ MIRP
// PowerPC special registers.
PRIM(MSR_X21)
unsigned long msr = TOS.u;
- asm volatile("mtmsrd %0" : "+r"(msr));
+ asm volatile("mtmsrd %0" : : "r"(msr));
POP;
MIRP
@@ -96,7 +83,7 @@ MIRP
PRIM(SDR1_X21)
unsigned long sdr1 = TOS.u;
- asm volatile("mtsdr1 %0" : "+r"(sdr1));
+ asm volatile("mtsdr1 %0" : : "r"(sdr1));
POP;
MIRP
@@ -127,7 +114,7 @@ MIRP
PRIM(DABR_X21)
unsigned long dabr = TOS.u;
- asm volatile("mtspr 1013,%0" : "+r"(dabr));
+ asm volatile("mtspr 1013,%0" : : "r"(dabr));
POP;
MIRP
@@ -138,7 +125,7 @@ MIRP
PRIM(HIOR_X21)
unsigned long dabr = TOS.u;
- asm volatile("mtspr 311,%0" : "+r"(dabr));
+ asm volatile("mtspr 311,%0" : : "r"(dabr));
POP;
MIRP
@@ -147,9 +134,78 @@ PRIM(HIOR_X40)
asm volatile("mfspr %0,311" : "=r"(TOS));
MIRP
+
+
+PRIM(SPRG0_X21)
+ unsigned long sprg0 = TOS.u;
+ asm volatile("mtsprg0 %0" : "+r"(sprg0));
+ POP;
+MIRP
+
+PRIM(SPRG0_X40)
+ PUSH;
+ asm volatile("mfsprg0 %0" : "=r"(TOS));
+MIRP
+
+PRIM(SPRG1_X21)
+ unsigned long sprg1 = TOS.u;
+ asm volatile("mtsprg1 %0" : "+r"(sprg1));
+ POP;
+MIRP
+
+PRIM(SPRG1_X40)
+ PUSH;
+ asm volatile("mfsprg1 %0" : "=r"(TOS));
+MIRP
+
+PRIM(SPRG2_X21)
+ unsigned long sprg2 = TOS.u;
+ asm volatile("mtsprg2 %0" : "+r"(sprg2));
+ POP;
+MIRP
+
+PRIM(SPRG2_X40)
+ PUSH;
+ asm volatile("mfsprg2 %0" : "=r"(TOS));
+MIRP
+
+PRIM(SPRG3_X21)
+ unsigned long sprg3 = TOS.u;
+ asm volatile("mtsprg3 %0" : "+r"(sprg3));
+ POP;
+MIRP
+
+PRIM(SPRG3_X40)
+ PUSH;
+ asm volatile("mfsprg3 %0" : "=r"(TOS));
+MIRP
+
+PRIM(HSPRG0_X21)
+ unsigned long hsprg0 = TOS.u;
+ asm volatile("mtspr 304,%0" : "+r"(hsprg0));
+ POP;
+MIRP
+
+PRIM(HSPRG0_X40)
+ PUSH;
+ asm volatile("mfspr %0,304" : "=r"(TOS));
+MIRP
+
+PRIM(HSPRG1_X21)
+ unsigned long hsprg1 = TOS.u;
+ asm volatile("mtspr 305,%0" : "+r"(hsprg1));
+ POP;
+MIRP
+
+PRIM(HSPRG1_X40)
+ PUSH;
+ asm volatile("mfspr %0,305" : "=r"(TOS));
+MIRP
+
+
PRIM(MMCR0_X21)
unsigned long mmcr0 = TOS.u;
- asm volatile("sync ; mtspr 795,%0 ; isync" : "+r"(mmcr0));
+ asm volatile("sync ; mtspr 795,%0 ; isync" : : "r"(mmcr0));
POP;
MIRP
@@ -158,20 +214,50 @@ PRIM(PMC1_X40)
asm volatile("sync ; mfspr %0,787" : "=r"(TOS));
MIRP
+PRIM(ICBI)
+ asm volatile("dcbst 0,%0 ; sync ; icbi 0,%0 ; sync ; isync" : : "r"(TOS));
+ POP;
+MIRP
// Call into the client program.
PRIM(JUMP_X2d_CLIENT)
TOS.u = call_client(TOS);
MIRP
-// Call an object-code only routine.
-PRIM(OCO)
- cell p0 = TOS; POP;
- cell p1 = TOS;
- TOS.u = oco(p0, p1);
-MIRP
// Hang. Useful for debugging, believe it or not.
PRIM(CRASH)
for (;;) ;
MIRP
+
+PRIM(START_X2d_RTAS)
+ cell e = TOS; POP;
+ cell p1 = TOS; POP;
+ cell p0 = TOS;
+ TOS.u = call_c(p0, p1, (cell)0UL, e);
+MIRP
+
+PRIM(CALL_X2d_C)
+ cell e = TOS; POP;
+ cell p2 = TOS; POP;
+ cell p1 = TOS; POP;
+ cell p0 = TOS;
+ TOS.u = call_c(p0, p1, p2, e);
+MIRP
+
+PRIM(FLUSHCACHE)
+ type_u n = TOS.u; POP;
+ unsigned char* p = TOS.a; POP;
+ flush_cache(p, n);
+MIRP
+
+PRIM(DEC_X21)
+ unsigned long dec = TOS.u;
+ asm volatile("mtdec %0" : "+r"(dec));
+ POP;
+MIRP
+
+PRIM(DEC_X40)
+ PUSH;
+ asm volatile("mfdec %0" : "=r"(TOS));
+MIRP
diff --git a/slof/ppc64.h b/slof/ppc64.h
index fa1d10d..eff7383 100644
--- a/slof/ppc64.h
+++ b/slof/ppc64.h
@@ -1,18 +1,52 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+#include <cpu.h>
+#include "types.h"
+
+#define SET_CI set_ci()
+#define CLR_CI clr_ci()
// The big Forth source file that contains everything but the core engine.
// We include it as a hunk of data into the C part of SLOF; at startup
// time, this will be EVALUATE'd.
-extern char _binary_ppc64_fs_start[], _binary_ppc64_fs_end[];
+extern char _slof_start[];
+extern char _slof_here_start[];
+
+#define the_exception_frame ((cell *) (_slof_start))
+#define the_client_frame ((cell *) (_slof_start+0x400))
+#define the_data_stack ((cell *) (_slof_start+0x2000))
+#define the_return_stack ((cell *) (_slof_start+0x4000))
+#define the_system_stack ((cell *) (_slof_start+0x6000))
+
+// these two really need to be implemented as a plain
+// normal BUFFER: in the data space
+#define the_tib ((cell *) (_slof_start+0x8000))
+#define the_pockets ((cell *) (_slof_start+0x9000))
+#define the_comp_buffer ((cell *) (_slof_start+0xA000))
+#define the_client_stack ((cell *) (_slof_start+0xBf00))
+
+// wasteful, but who cares. 14MB should be enough.
+#define the_mem ((cell *) (_slof_here_start))
+
+#define the_heap_start ((cell *) (_slof_start+0x700000))
+#define the_heap_end ((cell *) (_slof_start+0x700000+0x800000))
+
+
+extern char _binary_OF_fsi_start[], _binary_OF_fsi_end[];
+//extern char _binary_vmlinux_start[], _binary_vmlinux_end[];
+void client_entry_point();
+
+extern unsigned long call_client(cell);
+extern long c_romfs_lookup(long, long, void *);
+extern long writeLogByte(long, long);
diff --git a/slof/ppc64.in b/slof/ppc64.in
index 993f096..d7da086 100644
--- a/slof/ppc64.in
+++ b/slof/ppc64.in
@@ -1,15 +1,14 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
// The Forth code words (primitives) that are specific to PowerPC64.
@@ -20,6 +19,8 @@ cod(RW@)
cod(RW!)
cod(RL@)
cod(RL!)
+cod(RX@)
+cod(RX!)
// CPU register accesses.
cod(HID0!)
@@ -42,29 +43,61 @@ cod(DABR@)
cod(DABR!)
cod(HIOR@)
cod(HIOR!)
+cod(SPRG0@)
+cod(SPRG0!)
+cod(SPRG1@)
+cod(SPRG1!)
+cod(SPRG2@)
+cod(SPRG2!)
+cod(SPRG3@)
+cod(SPRG3!)
+cod(HSPRG0@)
+cod(HSPRG0!)
+cod(HSPRG1@)
+cod(HSPRG1!)
+cod(DEC@)
+cod(DEC!)
cod(MMCR0!)
cod(PMC1@)
+cod(ICBI)
+
// The start address of a binary payload.
-con(PAYLOAD (type_u)_binary_payload_start)
+//con(PAYLOAD (type_u)_binary_payload_start)
// Calling the client program.
con(CLIENT-ENTRY-POINT (type_u)client_entry_point)
cod(JUMP-CLIENT)
dfr(CLIENTINTERFACE)
-// Calling binary-only code.
-cod(OCO)
+
+con(ROMFS-LOOKUP-ENTRY (type_u) c_romfs_lookup)
+
+// not very elegant... but the only way it works for me
+con(.WRITE-LOG-BYTE-ENTRY (type_u) writeLogByte_wrapper)
+col(WRITE-LOG-BYTE-ENTRY .WRITE-LOG-BYTE-ENTRY @)
+
+cod(CALL-C)
+cod(START-RTAS)
+
+
+cod(FLUSHCACHE)
+
// Hang.
cod(CRASH)
-var(DAAR 0x10000000)
+var(DAAR 0x00f00000)
col(DUMBER DAAR @ C! LIT(1) DAAR +!)
-// Engine startup.
-col(NICEINIT DOTICK DUMBER DOTO EMIT DOTICK ((FIND)) DOTO (FIND) DOTICK 2DROP DOTO (REVEAL) LIT((type_u)_binary_ppc64_fs_start) LIT((type_u)_binary_ppc64_fs_end) OVER - DOTICK EVALUATE CATCH ?DUP 0BRANCH(2) PRINT-STATUS CLEAR)
-static cell xt_SYSTHROW[] = { DUP LIT(0x100) _X3d _0BRANCH(3) DROP NICEINIT QUIT PRINT_X2d_STATUS QUIT };
+dfr(BOOT-EXCEPTION-HANDLER)
+
+col(NICEINIT DOTICK DROP DOTO EMIT DOTICK ((FIND)) DOTO (FIND) DOTICK 2DROP DOTO (REVEAL) LIT((type_u)_binary_OF_fsi_start) LIT((type_u)_binary_OF_fsi_end) OVER - DOTICK EVALUATE CATCH BOOT-EXCEPTION-HANDLER)
+
+static cell xt_SYSTHROW[] = { _0 RDEPTH_X21 DUP LIT(0x100) _X3d _0BRANCH(3) NICEINIT BRANCH(7) DUP LIT(0x3800) _X3d _0BRANCH(1) CLIENTINTERFACE PRINT_X2d_STATUS QUIT };
+
+// sentinel, leave it here!
col(LASTWORD )
+
diff --git a/slof/prep.h b/slof/prep.h
index 1fc7486..e020b6b 100644
--- a/slof/prep.h
+++ b/slof/prep.h
@@ -1,20 +1,19 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
-
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
//
// Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
//
+
#define _N(_n) { .n = _n },
#define _O(_n) { .n = CELLSIZE * (_n) },
#define _C(_c) { .c = _c },
@@ -36,7 +35,7 @@
#define DOBUFFER_X3a lab(DOBUFFER_X3a)
#define cod(_xt) def(lab(_xt))
-#define col(_xt, _def...) def(DOCOL _def EXIT)
+#define col(_xt, _def...) def(DOCOL _def SEMICOLON)
#define con(_xt, _def) def(DOCON _N(_def))
#define dfr(_xt) def(DODEFER _N(0))
#define val(_xt, _def) def(DOVAL _N(_def))
diff --git a/slof/prim.code b/slof/prim.code
index 7df46fa..c97706a 100644
--- a/slof/prim.code
+++ b/slof/prim.code
@@ -1,13 +1,15 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
// ============================================================================
@@ -15,6 +17,7 @@
// Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
//
+
#define NEXT00 goto *cfa->a
#define NEXT0 cfa = ip->a; NEXT00
#define NEXT ip++; NEXT0
@@ -51,6 +54,22 @@ PRIM(TIB) PUSH; TOS.a = the_tib; MIRP
// For pockets (temporary string buffers).
PRIM(POCKETS) PUSH; TOS.a = the_pockets; MIRP
+// exception register area
+PRIM(EREGS) PUSH; TOS.a = the_exception_frame; MIRP
+
+// client register area
+PRIM(CIREGS) PUSH; TOS.a = the_client_frame; MIRP
+
+// Client stack
+PRIM(CISTACK) PUSH; TOS.a = the_client_stack; MIRP
+
+// compile-in-interpret buffer
+PRIM(COMP_X2d_BUFFER) PUSH; TOS.a = the_comp_buffer; MIRP
+
+// Heap pointers
+PRIM(HEAP_X2d_START) PUSH; TOS.a = the_heap_start; MIRP
+PRIM(HEAP_X2d_END) PUSH; TOS.a = the_heap_end; MIRP
+
// Codefields.
@@ -68,12 +87,21 @@ code_DODOES:
NEXT0;
}
code_DODEFER:
+ {
+ cfa = (cfa + 1)->a;
+ NEXT00;
+ }
code_DOALIAS:
{
cfa = (cfa + 1)->a;
NEXT00;
}
code_DOCON:
+ {
+ PUSH;
+ TOS = *(cfa + 1);
+ NEXT;
+ }
code_DOVAL:
{
PUSH;
@@ -86,6 +114,10 @@ code_DOFIELD:
NEXT;
}
code_DOVAR:
+ {
+ (++dp)->a = cfa + 1;
+ NEXT;
+ }
code_DOBUFFER_X3a:
{
(++dp)->a = cfa + 1;
@@ -112,10 +144,22 @@ code_0BRANCH:
NEXT;
}
+// Jump to "defer BP"
+code_BREAKPOINT:
+ {
+ RPUSH; RTOS.a = ip;
+ ip = (cell * ) xt_BP+2;
+ NEXT;
+ }
// literals
code_LIT:
+ {
+ PUSH;
+ TOS = *++ip;
+ NEXT;
+ }
code_DOTICK:
{
PUSH;
@@ -146,6 +190,7 @@ PRIM(DEPTH) PUSH; TOS.u = dp - the_data_stack; MIRP
PRIM(DEPTH_X21) dp = the_data_stack + TOS.u - 1; MIRP
PRIM(RDEPTH) PUSH; TOS.u = rp - the_return_stack + 1; MIRP
PRIM(RDEPTH_X21) rp = the_return_stack + TOS.u - 1; POP; MIRP
+PRIM(RPICK) TOS = *(rp - TOS.n); MIRP
// 2.1
PRIM(_X2b) NOS.u += TOS.u; POP; MIRP
@@ -319,6 +364,13 @@ code_EXIT:
ip = (rp--)->a;
NEXT;
}
+
+code_SEMICOLON:
+ {
+ ip = (rp--)->a;
+ NEXT;
+ }
+
code_EXECUTE: // don't need this as prim
{
cfa = (dp--)->a;
@@ -329,21 +381,149 @@ code_EXECUTE: // don't need this as prim
// 3.1
+#define _FWMOVE(s, d, size, t) \
+ { t *s1=(t *)s, *d1=(t *)d; \
+ while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } }
+
+#define _BWMOVE(s, d, size, t) { \
+ t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); \
+ while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
+}
+
+#define _FWOVERLAP(s, d, size) ((d >= s) && ((type_u)d < ((type_u)s + size)))
+
+#define _MOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWMOVE(s, d, size, t) else _FWMOVE(s, d, size, t)
+
+#define _FASTMOVE(s, d, size) \
+ switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
+ case 0: _MOVE(s, d, size, type_u); break; \
+ case sizeof(type_l): _MOVE(s, d, size, type_l); break; \
+ case sizeof(type_w): _MOVE(s, d, size, type_w); break; \
+ default: _MOVE(s, d, size, type_c); break; \
+ }
+
PRIM(MOVE)
type_u n = TOS.u; POP;
unsigned char *q = TOS.a; POP;
unsigned char *p = TOS.a; POP;
- if (p >= q || q >= p + n)
- for (p--, q--; n--; )
- *++q = *++p;
- else
- for (p += n, q += n ; n--; )
- *--q = *--p;
+
+ _FASTMOVE(p, q, n);
MIRP
+code_FILL:
+ {
+ unsigned char c = (dp--)->u;
+ int size = ((dp--)->n);
+ unsigned char *d = (unsigned char *)((dp--)->u);
+ type_u fill_v=c | c <<8;
+
+ fill_v |= fill_v << 16;
+ switch (((type_u)d | (type_u)size) & (sizeof(type_u)-1)) {
+ case 0: {
+ type_u *up = (type_u *)d;
+#ifndef UNIX
+ fill_v |= fill_v << 32;
+#endif
+ while ((size-=sizeof(type_u)) >= 0)
+ *up++ = fill_v;
+ }
+ case sizeof(type_l): {
+ type_l *lp = (type_l *)d;
+
+ while ((size-=sizeof(type_l)) >= 0)
+ *lp++ = (type_l)fill_v;
+ }
+ case sizeof(type_w): {
+ type_w *wp = (type_w *)d;
+
+ while ((size-=sizeof(type_w)) >= 0)
+ *wp++ = (type_w)fill_v;
+ }
+ default:
+ while (size-- > 0)
+ *d++ = (unsigned char)c;
+ }
+ NEXT;
+ }
-PRIM(FLUSHCACHE)
- type_u n = TOS.u; POP;
- unsigned char* p = TOS.a; POP;
- flush_cache(p, n);
+code_COMP:
+ {
+ int len = ((dp--)->n);
+ unsigned char *addr2 = (unsigned char *)((dp--)->u);
+ unsigned char *addr1 = (unsigned char *)((dp--)->u);
+
+ while (len-- > 0) {
+ if (*addr1 > *addr2) {
+ (++dp)->n = 1;
+ NEXT;
+ }
+ else if (*addr1 < *addr2) {
+ (++dp)->n = -1;
+ NEXT;
+ }
+ addr1 += 1;
+ addr2 += 1;
+ }
+ (++dp)->n = 0;
+ NEXT;
+ }
+
+// Device IO block data helpers
+#define _FWRMOVE(s, d, size, t) \
+ { t *s1=(t *)s, *d1=(t *)d; SET_CI; \
+ while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } \
+ CLR_CI; \
+}
+
+#define _BWRMOVE(s, d, size, t) { \
+ t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); SET_CI; \
+ while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
+ CLR_CI; \
+}
+
+#define _RMOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWRMOVE(s, d, size, t) else _FWRMOVE(s, d, size, t)
+
+#define _FASTRMOVE(s, d, size) \
+ switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
+ case 0: _RMOVE(s, d, size, type_u); break; \
+ case sizeof(type_l): _RMOVE(s, d, size, type_l); break; \
+ case sizeof(type_w): _RMOVE(s, d, size, type_w); break; \
+ default: _RMOVE(s, d, size, type_c); break; \
+ }
+
+code_RMOVE:
+ {
+ type_u size = ((dp--)->u);
+ type_u *d = (type_u *)((dp--)->u);
+ type_u *s = (type_u *)((dp--)->u);
+
+ _FASTRMOVE(s, d, size);
+ NEXT;
+ }
+
+
+// String compare, case insensitive:
+// : string=ci ( str1 len1 str2 len2 -- equal? )
+PRIM(STRING_X3d_CI)
+ type_u l2 = TOS.u; POP;
+ unsigned char *p2 = TOS.a; POP;
+ type_u l1 = TOS.u; POP;
+ unsigned char *p1 = TOS.a;
+ extern int toupper(int c);
+
+ if (l1 == l2) {
+ TOS.n = -1; /* Default to TRUE */
+ while (l1 > 0) {
+ if (toupper(*p1) != toupper(*p2)) {
+ TOS.n = 0;
+ break;
+ }
+ ++p1; ++p2;
+ --l1;
+ }
+ }
+ else {
+ TOS.n = 0;
+ }
MIRP
+
diff --git a/slof/prim.in b/slof/prim.in
index ff39f95..6da069f 100644
--- a/slof/prim.in
+++ b/slof/prim.in
@@ -1,13 +1,15 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
// ============================================================================
@@ -17,9 +19,19 @@
cod(TIB)
cod(POCKETS)
+cod(EREGS)
+cod(CIREGS)
+cod(CISTACK)
+// compile buffer for the "structure words in interpret mode" OF extension
+cod(COMP-BUFFER)
+
+cod(HEAP-START)
+cod(HEAP-END)
cod(BRANCH) _ADDING _O
cod(0BRANCH) _ADDING _O
+dfr(BP)
+cod(BREAKPOINT)
cod(LIT) _ADDING _N
cod(DOTICK)
@@ -33,6 +45,7 @@ cod(SWAP)
cod(>R)
cod(R>)
cod(R@)
+cod(RPICK)
cod(DEPTH)
cod(DEPTH!)
@@ -74,8 +87,13 @@ cod(DOLEAVE) _ADDING _O
cod(DO?LEAVE) _ADDING _O
cod(EXIT)
+cod(SEMICOLON)
cod(EXECUTE)
cod(MOVE)
+// cod(RMOVE64)
+cod(RMOVE)
+
+
+
-cod(FLUSHCACHE)
diff --git a/slof/ref.pl b/slof/ref.pl
index 0cfe10a..61f7a88 100644
--- a/slof/ref.pl
+++ b/slof/ref.pl
@@ -1,33 +1,45 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
#!/usr/bin/perl
-# =============================================================================
-# * Copyright (c) 2004, 2005 IBM Corporation
-# * All rights reserved.
-# * This program and the accompanying materials
-# * are made available under the terms of the BSD License
-# * which accompanies this distribution, and is available at
-# * http://www.opensource.org/licenses/bsd-license.php
-# *
-# * Contributors:
-# * IBM Corporation - initial implementation
-# =============================================================================
#
# Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
#
+
+use Getopt::Std;
use Data::Dumper;
$CELLSIZE = length(sprintf "%x", ~0) / 2;
-$CELLSIZE = 8; # Hard code for cross-compiling to a different size ABI.
+$CELLSIZE = 8;
+$DEBUG = 0;
+
+sub usage
+{
+ printf STDERR "Usage: ref.pl [ -s 32|64 ] [ -d ] \n";
+ printf STDERR " ref.pl -h\n";
+ exit 0;
+}
sub string
{
my ($s, $extra) = @_;
+ $DEBUG and printf STDERR "\nstring:[%s][%02x]\n", $s, ord $extra;
$s = sprintf "%s%c%s", $extra, length($s), $s;
@s = ($s =~ /(.{1,$CELLSIZE})/gs);
do { s/([\x00-\x1f\x22\x5c\x7f-\xff])/sprintf "\\%03o", ord $1/egs } for @s;
my @reut = ("{ .c = \"" . (join "\" }, { .c = \"", @s) . "\" },", scalar @s);
+ # $DEBUG and print STDERR Dumper \@reut;
return @reut;
}
@@ -36,6 +48,7 @@ sub forth_to_c_name
($_, my $numeric) = @_;
s/([^a-zA-Z0-9])/sprintf("_X%02x_", ord($1))/ge;
s/__/_/g;
+# s/^_//;
s/_$//;
s/^(\d)/_$1/ if $numeric;
return $_;
@@ -45,23 +58,41 @@ sub special_forth_to_c_name
{
($_, my $numeric) = @_;
+ $DEBUG and print STDERR "\tasked for $_ [[numeric is $numeric]]\n";
my ($name, $arg) = (/^([^(]+)(.*)$/);
+ # $DEBUG and print STDERR "\tname is $name -- arg is $arg\n";
if ($special{$name} == 1) {
$_ = forth_to_c_name($name, $numeric) . $arg;
} elsif ($special{$name} != 2) {
$_ = forth_to_c_name($_, $numeric);
}
+ # $DEBUG and print STDERR "\tmaking it $_\n";
return $_;
}
+getopts('dhs:') or die "Invalid option!\n";
+
+$opt_h and usage();
+$opt_d and $DEBUG=1;
+$opt_s and $opt_s != 32 and $opt_s != 64 and die("Only -s32 or -s64 allowed");
+
+$opt_s and $opt_s == 32 and $CELLSIZE=4;
+
+$DEBUG and printf STDERR "Cell size set to $CELLSIZE;\n";
+
$link = "0";
%special = ( _N => 2, _O => 2, _C => 2, _A => 2 );
+$DEBUG and print STDERR "Compiling:";
while ($line = <>) {
if ($line =~ /^([a-z]{3})\(([^ ]+)./) {
$typ = $1;
$name = $2;
+
+ $DEBUG and print STDERR "\n\t\t$name###\n";
+
$name =~ s/\)$// if $line =~ /\)\s+_ADDING.*$/;
+ # $DEBUG and print STDERR " $name";
$cname = forth_to_c_name($name, 1);
$par = '';
$add = '';
@@ -70,8 +101,13 @@ while ($line = <>) {
$typ = "col";
$extra = "\1";
}
+# if ($typ eq "com") {
+# $typ = "col";
+# $extra = "\3";
+# }
($str, $strcells) = (string $name, $extra);
if ($line =~ /^str\([^"]*"([^"]*)"/) {
+ # $DEBUG and print STDERR "[[[$1]]]\n";
($s) = (string $1);
$line =~ s/"[^"]*"/$s/;
}
@@ -84,15 +120,20 @@ while ($line = <>) {
$add = join " ", map { $count++; "$_(_x$count)" } @typ;
$line =~ s/\s+_ADDING.*$//;
}
+ # $DEBUG and print STDERR $line;
($body) = ($line =~ /^...\((.*)\)$/);
@body = split " ", $body;
+ # $DEBUG and print STDERR "\n";
+ # $DEBUG and print STDERR "BODY WAS: ", (join " ", @body), "\n";
if ($typ ne "str" and $typ ne "con") {
@body = map { special_forth_to_c_name($_, $typ eq "col") } @body;
} else {
$body[0] = special_forth_to_c_name($body[0]);
}
+ # $DEBUG and print STDERR "BODY IS: ", (join " ", @body), "\n";
$body = join " ", @body;
$body =~ s/ /, /;
+ # $DEBUG and print STDERR "===> $body\n";
print "header($cname, { .a = $link }, $str) ";
$link = "xt_$cname";
@@ -104,3 +145,4 @@ while ($line = <>) {
print $line;
}
}
+$DEBUG and print STDERR "\n";
diff --git a/slof/types.h b/slof/types.h
index 7cb2c8d..6f5d146 100644
--- a/slof/types.h
+++ b/slof/types.h
@@ -1,20 +1,19 @@
-// ============================================================================
-// * Copyright (c) 2004, 2005 IBM Corporation
-// * All rights reserved.
-// * This program and the accompanying materials
-// * are made available under the terms of the BSD License
-// * which accompanies this distribution, and is available at
-// * http://www.opensource.org/licenses/bsd-license.php
-// *
-// * Contributors:
-// * IBM Corporation - initial implementation
-// ============================================================================
-
-
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
//
// Copyright 2002,2003,2004 Segher Boessenkool <segher@kernel.crashing.org>
//
+
#ifndef _TYPES_H
#define _TYPES_H
@@ -34,6 +33,7 @@ typedef long type_n; // cell size
typedef unsigned long type_u; // cell size
#endif
+//#define CELLSIZE (sizeof(type_u) / sizeof(type_c))
#define CELLSIZE sizeof(type_u)
typedef union cell {
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..9c31a9d
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,33 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+include ../make.rules
+
+all: gen_reloc_table
+
+%.o: %.c
+ $(HOSTCC) -W $(HOSTCFLAGS) -c $^
+
+elf2tst: elf2tst.o
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
+
+gen_reloc_table: gen_reloc_table.o
+ $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
+
+clean_here:
+ rm -f elf2tst *.o gen_reloc_table
+
+clean: clean_here
+
+
+distclean: clean_here
+
diff --git a/tools/create_reloc_table.sh b/tools/create_reloc_table.sh
new file mode 100755
index 0000000..b7ebb5f
--- /dev/null
+++ b/tools/create_reloc_table.sh
@@ -0,0 +1,60 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2007 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+#!/bin/sh
+
+
+CROSSTMP=`grep ^CROSS $(dirname $0)/../make.rules | cut -d\ -f2`
+
+CROSS=${CROSS-$CROSSTMP}
+
+# Set defaults:
+LD="${CROSS}ld"
+LDFLAGS="-nostdlib"
+LDSFILE=""
+OBJCOPY="${CROSS}objcopy"
+
+DIRNAME=`dirname $0`
+
+# Parse parameters:
+while [ $# -gt 0 ] ; do
+ case "$1" in
+ --ld) LD=$2 ; shift 2 ;;
+ --ldflags) LDFLAGS=$2 ; shift 2 ;;
+ --lds) LDSFILE=$2 ; shift 2 ;;
+ --objcopy) OBJCOPY=$2 ; shift 2 ;;
+ *.o|*.a|-l*|-L*) OBJFILES="$OBJFILES $1" ; shift ;;
+ *) echo "$0:" ; echo " Unsupported argument: $1"; exit -1 ;;
+ esac
+done
+
+if [ -z $LDSFILE ]; then
+ echo "Please specifiy an lds file with the --lds option"
+ exit 42
+fi
+
+TMP1=`mktemp`
+TMP2=`mktemp`
+
+# Now create the two object files:
+$LD $LDFLAGS -T $LDSFILE -o $TMP1.o $OBJFILES || exit -1
+$LD $LDFLAGS -T $LDSFILE -o $TMP2.o $OBJFILES --section-start .text=0x4000000000000000 || exit -1
+
+$OBJCOPY -O binary $TMP1.o $TMP1.bin || exit -1
+$OBJCOPY -O binary $TMP2.o $TMP2.bin || exit -1
+
+# Create the relocation table with gen_reloc_table:
+$DIRNAME/gen_reloc_table $TMP1.bin $TMP2.bin reloc_table.bin
+
+$LD -o reloc_table.o -bbinary reloc_table.bin -e0 || exit -1
+$OBJCOPY --rename-section .data=.reloc reloc_table.o reloc_table.o || exit -1
+
+rm -f $TMP1.o $TMP2.o $TMP1.bin $TMP2.bin reloc_table.bin
diff --git a/tools/gen_reloc_table.c b/tools/gen_reloc_table.c
new file mode 100644
index 0000000..17c06f9
--- /dev/null
+++ b/tools/gen_reloc_table.c
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int reloc_64_cnt;
+
+static int reloc_64[4096];
+
+static void
+output_int(FILE *output_file, int i)
+{
+ fputc((i>>24) & 0xff, output_file);
+ fputc((i>>16) & 0xff, output_file);
+ fputc((i>>8) & 0xff, output_file);
+ fputc(i & 0xff, output_file);
+}
+
+static void
+output_reloc_table(FILE * output_file, int reloc_cnt, int reloc[])
+{
+ int i;
+ for (i=0; i < reloc_cnt; i++)
+ {
+#ifdef DEBUG
+ printf ("reloc %x\n", reloc[i]);
+#endif
+ output_int (output_file, reloc[i]);
+ }
+ if ((reloc_cnt & 1) == 0)
+ output_int (output_file, 0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cnt_a, cnt_b, offset = -1;
+ unsigned char a, b;
+ FILE *orig, *other, *output_file;
+
+ if (argc != 4)
+ {
+ fprintf (stderr, "reloc_diff orig_file other_file output_file\n");
+ exit(-1);
+ }
+
+ orig = fopen(argv[1], "rb");
+ other = fopen(argv[2], "rb");
+ output_file = fopen(argv[3], "wb");
+ if(orig == NULL || other == NULL || output_file == NULL) {
+ printf("Could not open file.\n");
+ return -1;
+ }
+
+ while (1)
+ {
+ cnt_a = fread(&a, 1, 1, orig);
+ cnt_b = fread(&b, 1, 1, other);
+ offset ++;
+ if (cnt_a != cnt_b)
+ {
+ fprintf (stderr, "Files >%s< and >%s< have not the same lenght\n",argv[1],argv[2]);
+ exit(-1);
+ }
+
+ if (cnt_a == 0)
+ break;
+
+ if (a == b) continue;
+
+ if (a + 0x40 == b)
+ {
+ reloc_64[reloc_64_cnt++] = offset;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown relocation");
+ fprintf(stderr, "Offset %x: %02x %02x\n", offset, a, b);
+ break;
+ }
+ }
+
+ output_reloc_table(output_file, reloc_64_cnt, reloc_64);
+ return 0;
+}